tbaig1605 commited on
Commit
86de5e1
ยท
verified ยท
1 Parent(s): 195d9aa

Update app.py

Browse files

import streamlit as st
import pandas as pd
import networkx as nx

st.title("๐Ÿ“… Project Scheduler & Critical Path (Days Based)")

project_type = st.selectbox("Select Project Type", ["Building", "Bridge", "Road", "Other"])

st.markdown("### ๐Ÿ“‹ Task Details")
st.markdown("""
Each row: `TaskID, Duration (in days), Dependency, Relationship Type (FS/SS/FF/SF), Lag (optional)`
- Example: `A,5,,,`\n
- Example: `B,3,A,FS,0`\n
- Example: `C,2,A,SS,1`
""")

task_data = st.text_area("Paste your task data here:")

if st.button("๐Ÿงฎ Calculate Critical Path"):
tasks = {}
dependencies = []

# Parse input data
for line in task_data.strip().split("\n"):
parts = [p.strip() for p in line.split(",")]
task_id, duration = parts[0], int(parts[1])
dep = parts[2] if len(parts) > 2 and parts[2] else None
rel_type = parts[3] if len(parts) > 3 and parts[3] else "FS"
lag = int(parts[4]) if len(parts) > 4 and parts[4] else 0
tasks[task_id] = duration
if dep:
dependencies.append((dep, task_id, rel_type.upper(), lag))

# Build directed graph
G = nx.DiGraph()
for task_id in tasks:
G.add_node(task_id, duration=tasks[task_id])
for from_task, to_task, rel, lag in dependencies:
G.add_edge(from_task, to_task, type=rel, lag=lag)

# Initialize earliest and latest start/finish times
es = {} # Earliest start times
ef = {} # Earliest finish times
ls = {} # Latest start times
lf = {} # Latest finish times

# Topological order to ensure we process tasks in correct order
top_order = list(nx.topological_sort(G))

# Forward pass to calculate ES and EF
for task in top_order:
preds = list(G.predecessors(task))
if not preds:
es[task] = 0
else:
max_start = 0
for pred in preds:
edge = G.edges[pred, task]
pred_type = edge.get("type", "FS")
lag = edge.get("lag", 0)
if pred_type == "FS":
start_time = ef[pred] + lag
elif pred_type == "SS":
start_time = es[pred] + lag
elif pred_type == "FF":
start_time = ef[pred] - tasks[task] + lag
elif pred_type == "SF":
start_time = es[pred] - tasks[task] + lag
max_start = max(max_start, start_time)
es[task] = max_start
ef[task] = es[task] + tasks[task]

# Backward pass to calculate LS and LF
for task in reversed(top_order):
succs = list(G.successors(task))
if not succs:
lf[task] = ef[task]
else:
min_finish = min(ls[succ] for succ in succs)
lf[task] = min_finish
ls[task] = lf[task] - tasks[task]

# Critical path calculation: Task is critical if ES == LS
critical_path = [t for t in top_order if es[t] == ls[t]]

st.success(f"Critical Path: {' โž '.join(critical_path)}")
st.info(f"Total Project Duration: {max(ef.values())} days")

Files changed (1) hide show
  1. app.py +0 -108
app.py CHANGED
@@ -1,112 +1,4 @@
1
- import streamlit as st
2
- import pandas as pd
3
- import networkx as nx
4
- import plotly.figure_factory as ff
5
 
6
- st.title("๐Ÿ“… Project Scheduler & Critical Path (Days Based)")
7
-
8
- project_type = st.selectbox("Select Project Type", ["Building", "Bridge", "Road", "Other"])
9
-
10
- st.markdown("### ๐Ÿ“‹ Task Details")
11
- st.markdown("""
12
- Each row: `TaskID, Duration (in days), Dependency, Relationship Type (FS/SS/FF/SF), Lag (optional)`
13
- - Example: `A,5,,,`\n
14
- - Example: `B,3,A,FS,0`\n
15
- - Example: `C,2,A,SS,1`
16
- """)
17
-
18
- task_data = st.text_area("Paste your task data here:")
19
-
20
- if st.button("๐Ÿงฎ Calculate Critical Path"):
21
- tasks = {}
22
- dependencies = []
23
-
24
- for line in task_data.strip().split("\n"):
25
- parts = [p.strip() for p in line.split(",")]
26
- task_id, duration = parts[0], int(parts[1])
27
- dep = parts[2] if len(parts) > 2 and parts[2] else None
28
- rel_type = parts[3] if len(parts) > 3 and parts[3] else "FS"
29
- lag = int(parts[4]) if len(parts) > 4 and parts[4] else 0
30
- tasks[task_id] = duration
31
- if dep:
32
- dependencies.append((dep, task_id, rel_type.upper(), lag))
33
-
34
- # Build graph
35
- G = nx.DiGraph()
36
- for task_id in tasks:
37
- G.add_node(task_id, duration=tasks[task_id])
38
- for from_task, to_task, rel, lag in dependencies:
39
- G.add_edge(from_task, to_task, type=rel, lag=lag)
40
-
41
- # CPM calculation (simplified for FS and SS, other types handled properly now)
42
- es = {}
43
- ef = {}
44
- top_order = list(nx.topological_sort(G))
45
-
46
- for task in top_order:
47
- preds = list(G.predecessors(task))
48
- if not preds:
49
- es[task] = 0
50
- else:
51
- max_start = 0
52
- for pred in preds:
53
- edge = G.edges[pred, task]
54
- pred_type = edge.get("type", "FS")
55
- lag = edge.get("lag", 0)
56
- pred_duration = G.nodes[pred]["duration"]
57
- if pred_type == "FS":
58
- start_time = ef[pred] + lag
59
- elif pred_type == "SS":
60
- start_time = es[pred] + lag
61
- elif pred_type == "FF":
62
- start_time = ef[pred] - tasks[task] + lag
63
- elif pred_type == "SF":
64
- start_time = es[pred] - tasks[task] + lag
65
- else:
66
- start_time = ef[pred] + lag
67
- max_start = max(max_start, start_time)
68
- es[task] = max_start
69
- ef[task] = es[task] + tasks[task]
70
-
71
- # Backward pass
72
- lf = {}
73
- ls = {}
74
- for task in reversed(top_order):
75
- succs = list(G.successors(task))
76
- if not succs:
77
- lf[task] = ef[task]
78
- else:
79
- min_finish = min(ls[succ] for succ in succs)
80
- lf[task] = min_finish
81
- ls[task] = lf[task] - tasks[task]
82
-
83
- critical_path = [t for t in top_order if es[t] == ls[t]]
84
-
85
- st.success(f"Critical Path: {' โž '.join(critical_path)}")
86
- st.info(f"Total Project Duration: {max(ef.values())} days")
87
-
88
- # Gantt chart (adjusted to handle display properly)
89
- df = pd.DataFrame([
90
- {
91
- "Task": t,
92
- "Start": f"Day {es[t]}",
93
- "Finish": f"Day {ef[t]}",
94
- "Start_day": es[t],
95
- "Finish_day": ef[t],
96
- "Resource": "Critical" if t in critical_path else "Non-Critical"
97
- }
98
- for t in top_order
99
- ])
100
-
101
- fig = ff.create_gantt(
102
- df,
103
- index_col="Resource",
104
- show_colorbar=True,
105
- group_tasks=True,
106
- showgrid_x=True,
107
- showgrid_y=True
108
- )
109
- st.plotly_chart(fig, use_container_width=True)
110
 
111
 
112
 
 
 
 
 
 
1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
 
4