vincentiusyoshuac commited on
Commit
0c2193f
·
verified ·
1 Parent(s): cc3875f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -107
app.py CHANGED
@@ -1,6 +1,5 @@
1
  import streamlit as st
2
  import pandas as pd
3
- import numpy as np
4
  from datetime import datetime, timedelta
5
  import networkx as nx
6
  import plotly.graph_objs as go
@@ -8,49 +7,42 @@ import plotly.graph_objs as go
8
  class TaskDependencyManager:
9
  def __init__(self):
10
  self.dependency_graph = nx.DiGraph()
11
-
12
- def add_task_dependency(self, tasks_df, task_name, predecessor=None, successor=None):
13
  """
14
- Tambahkan dependency antar tugas dengan validasi komprehensif
15
  """
16
- # Validasi input
17
- if not task_name or task_name.strip() == '':
18
- return False
19
 
20
  # Tambahkan node tugas ke graph
21
  if task_name not in self.dependency_graph.nodes():
22
  self.dependency_graph.add_node(task_name)
23
-
24
  # Tambahkan dependency predecessor
25
- if predecessor and predecessor != '':
 
26
  if predecessor not in self.dependency_graph.nodes():
27
  self.dependency_graph.add_node(predecessor)
28
-
29
- # Cegah dependency siklik
30
  if not self._is_cyclic_dependency(predecessor, task_name):
31
  self.dependency_graph.add_edge(predecessor, task_name)
32
-
33
  # Tambahkan dependency successor
34
- if successor and successor != '':
 
35
  if successor not in self.dependency_graph.nodes():
36
  self.dependency_graph.add_node(successor)
37
-
38
- # Cegah dependency siklik
39
  if not self._is_cyclic_dependency(task_name, successor):
40
  self.dependency_graph.add_edge(task_name, successor)
41
-
42
- return True
43
-
44
  def _is_cyclic_dependency(self, source, target):
45
  """
46
  Cek apakah menambahkan edge akan menciptakan siklus dalam graph
47
  """
48
  try:
49
- # Coba cek apakah path sudah ada dari target ke source
50
  return nx.has_path(self.dependency_graph, target, source)
51
  except nx.NetworkXError:
52
  return False
53
-
54
  def get_task_dependencies(self, task_name):
55
  """
56
  Dapatkan predecessor dan successor suatu tugas
@@ -58,7 +50,6 @@ class TaskDependencyManager:
58
  try:
59
  predecessors = list(self.dependency_graph.predecessors(task_name))
60
  successors = list(self.dependency_graph.successors(task_name))
61
-
62
  return {
63
  'predecessors': ', '.join(predecessors) if predecessors else '-',
64
  'successors': ', '.join(successors) if successors else '-'
@@ -68,49 +59,20 @@ class TaskDependencyManager:
68
  'predecessors': '-',
69
  'successors': '-'
70
  }
71
-
72
- def update_task_dependencies(self, tasks_df):
73
- """
74
- Update dependency untuk seluruh task di dataframe
75
- """
76
- # Reset graph
77
- self.dependency_graph = nx.DiGraph()
78
-
79
- # Tambahkan dependency untuk setiap task
80
- for _, task in tasks_df.iterrows():
81
- task_name = task['Task Name']
82
- predecessor = task['Predecessor']
83
- successor = task['Successor']
84
-
85
- # Tambahkan node
86
- if task_name not in self.dependency_graph.nodes():
87
- self.dependency_graph.add_node(task_name)
88
-
89
- # Tambahkan predecessor
90
- if predecessor and predecessor != '-':
91
- if predecessor not in self.dependency_graph.nodes():
92
- self.dependency_graph.add_node(predecessor)
93
- self.dependency_graph.add_edge(predecessor, task_name)
94
-
95
- # Tambahkan successor
96
- if successor and successor != '-':
97
- if successor not in self.dependency_graph.nodes():
98
- self.dependency_graph.add_node(successor)
99
- self.dependency_graph.add_edge(task_name, successor)
100
-
101
  def create_dependency_visualization(self):
102
  """
103
  Buat visualisasi graph dependency dengan posisi node yang optimal
104
  """
105
  if not self.dependency_graph.nodes():
106
  return None
107
-
108
  # Layout untuk positioning node
109
  try:
110
  pos = nx.kamada_kawai_layout(self.dependency_graph)
111
  except:
112
  pos = nx.spring_layout(self.dependency_graph, k=0.5, seed=42)
113
-
114
  # Trace untuk edges
115
  edge_x, edge_y = [], []
116
  for edge in self.dependency_graph.edges():
@@ -118,23 +80,23 @@ class TaskDependencyManager:
118
  x1, y1 = pos[edge[1]]
119
  edge_x.extend([x0, x1, None])
120
  edge_y.extend([y0, y1, None])
121
-
122
  edge_trace = go.Scatter(
123
  x=edge_x, y=edge_y,
124
  line=dict(width=1.5, color='#888', dash='dot'),
125
  hoverinfo='none',
126
  mode='lines')
127
-
128
  # Trace untuk nodes
129
  node_x, node_y, node_text = [], [], []
130
  node_degrees = dict(self.dependency_graph.degree())
131
-
132
  for node in self.dependency_graph.nodes():
133
  x, y = pos[node]
134
  node_x.append(x)
135
  node_y.append(y)
136
  node_text.append(f"{node} (Koneksi: {node_degrees[node]})")
137
-
138
  node_trace = go.Scatter(
139
  x=node_x, y=node_y,
140
  text=node_text,
@@ -154,62 +116,56 @@ class TaskDependencyManager:
154
  line_width=2
155
  )
156
  )
157
-
158
  layout = go.Layout(
159
  title='Graph Dependency Proyek',
160
  titlefont_size=16,
161
  showlegend=False,
162
  hovermode='closest',
163
- margin=dict(b=20,l=5,r=5,t=40),
164
  xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
165
  yaxis=dict(showgrid=False, zeroline=False, showticklabels=False)
166
  )
167
-
168
  return go.Figure(data=[edge_trace, node_trace], layout=layout)
169
 
170
  class StreamlitAdvancedProjectApp:
171
  def __init__(self):
172
- if 'dependency_manager' not in st.session_state:
173
- st.session_state.dependency_manager = TaskDependencyManager()
174
- self.dependency_manager = st.session_state.dependency_manager
175
-
 
 
 
 
176
  def run(self):
177
  st.set_page_config(page_title="Project Dependency Optimizer", page_icon="🚀")
178
-
179
  st.title("🚀 Advanced Project Dependency Optimizer")
180
-
181
  # Sidebar untuk input tugas
182
  st.sidebar.header("Input Tugas Terperinci")
183
-
184
- # Inisialisasi session state untuk tasks
185
- if 'tasks' not in st.session_state:
186
- st.session_state.tasks = pd.DataFrame(columns=[
187
- 'Task Name', 'Start Date', 'End Date',
188
- 'Duration', 'Complexity', 'Predecessor', 'Successor',
189
- 'Progress', 'Cost'
190
- ])
191
-
192
- # Form input tugas
193
  with st.sidebar.form("task_input"):
194
- task_name = st.text_input("Nama Tugas", key="task_name_input")
195
- start_date = st.date_input("Tanggal Mulai", key="start_date_input")
196
- duration = st.number_input("Durasi (Hari)", min_value=1, value=5, key="duration_input")
197
- complexity = st.selectbox("Kompleksitas", ['Low', 'Medium', 'High'], key="complexity_input")
198
-
199
  # Pilih predecessor dan successor dari tugas yang sudah ada
200
  existing_tasks = [''] + list(st.session_state.tasks['Task Name'])
201
- predecessor = st.selectbox("Predecessor (Opsional)", existing_tasks, index=0, key="predecessor_input")
202
- successor = st.selectbox("Successor (Opsional)", existing_tasks, index=0, key="successor_input")
203
-
204
  submit = st.form_submit_button("Tambah Tugas")
205
-
206
  if submit and task_name:
207
  # Cek duplikasi nama tugas
208
  if task_name in st.session_state.tasks['Task Name'].values:
209
  st.sidebar.error("Tugas dengan nama ini sudah ada!")
210
  else:
211
  # Siapkan data tugas baru
212
- new_task = pd.DataFrame([{
213
  'Task Name': task_name,
214
  'Start Date': start_date,
215
  'End Date': start_date + timedelta(days=duration),
@@ -219,47 +175,36 @@ class StreamlitAdvancedProjectApp:
219
  'Successor': successor if successor else '-',
220
  'Progress': 0,
221
  'Cost': duration * 500
222
- }])
223
-
224
- # Tambahkan ke dataframe
225
- st.session_state.tasks = pd.concat([
226
- st.session_state.tasks,
227
- new_task
228
- ], ignore_index=True)
229
-
230
- # Update dependency graph
231
- self.dependency_manager.update_task_dependencies(st.session_state.tasks)
232
-
233
  # Tampilkan daftar tugas
234
  if not st.session_state.tasks.empty:
235
  st.subheader("Daftar Tugas")
236
- tasks_display = st.session_state.tasks.copy()
237
- st.dataframe(tasks_display)
238
-
239
  # Analisis Dependency
240
  st.subheader("Analisis Hubungan Tugas")
241
  selected_task = st.selectbox(
242
- "Pilih Tugas untuk Melihat Dependency",
243
- tasks_display['Task Name']
244
  )
245
-
246
  if selected_task:
247
  dependencies = self.dependency_manager.get_task_dependencies(selected_task)
248
-
249
  col1, col2 = st.columns(2)
250
  with col1:
251
  st.write("Predecessor:")
252
  st.code(dependencies['predecessors'])
253
-
254
  with col2:
255
  st.write("Successor:")
256
  st.code(dependencies['successors'])
257
-
258
  # Visualisasi Graph Dependency
259
  st.subheader("Visualisasi Graph Dependency")
260
  try:
261
  dependency_graph_fig = self.dependency_manager.create_dependency_visualization()
262
-
263
  if dependency_graph_fig:
264
  st.plotly_chart(dependency_graph_fig, use_container_width=True)
265
  else:
 
1
  import streamlit as st
2
  import pandas as pd
 
3
  from datetime import datetime, timedelta
4
  import networkx as nx
5
  import plotly.graph_objs as go
 
7
  class TaskDependencyManager:
8
  def __init__(self):
9
  self.dependency_graph = nx.DiGraph()
10
+
11
+ def add_task(self, task_data):
12
  """
13
+ Tambahkan tugas baru ke dalam graph dependency
14
  """
15
+ task_name = task_data['Task Name']
 
 
16
 
17
  # Tambahkan node tugas ke graph
18
  if task_name not in self.dependency_graph.nodes():
19
  self.dependency_graph.add_node(task_name)
20
+
21
  # Tambahkan dependency predecessor
22
+ predecessor = task_data['Predecessor']
23
+ if predecessor and predecessor != '-':
24
  if predecessor not in self.dependency_graph.nodes():
25
  self.dependency_graph.add_node(predecessor)
 
 
26
  if not self._is_cyclic_dependency(predecessor, task_name):
27
  self.dependency_graph.add_edge(predecessor, task_name)
28
+
29
  # Tambahkan dependency successor
30
+ successor = task_data['Successor']
31
+ if successor and successor != '-':
32
  if successor not in self.dependency_graph.nodes():
33
  self.dependency_graph.add_node(successor)
 
 
34
  if not self._is_cyclic_dependency(task_name, successor):
35
  self.dependency_graph.add_edge(task_name, successor)
36
+
 
 
37
  def _is_cyclic_dependency(self, source, target):
38
  """
39
  Cek apakah menambahkan edge akan menciptakan siklus dalam graph
40
  """
41
  try:
 
42
  return nx.has_path(self.dependency_graph, target, source)
43
  except nx.NetworkXError:
44
  return False
45
+
46
  def get_task_dependencies(self, task_name):
47
  """
48
  Dapatkan predecessor dan successor suatu tugas
 
50
  try:
51
  predecessors = list(self.dependency_graph.predecessors(task_name))
52
  successors = list(self.dependency_graph.successors(task_name))
 
53
  return {
54
  'predecessors': ', '.join(predecessors) if predecessors else '-',
55
  'successors': ', '.join(successors) if successors else '-'
 
59
  'predecessors': '-',
60
  'successors': '-'
61
  }
62
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  def create_dependency_visualization(self):
64
  """
65
  Buat visualisasi graph dependency dengan posisi node yang optimal
66
  """
67
  if not self.dependency_graph.nodes():
68
  return None
69
+
70
  # Layout untuk positioning node
71
  try:
72
  pos = nx.kamada_kawai_layout(self.dependency_graph)
73
  except:
74
  pos = nx.spring_layout(self.dependency_graph, k=0.5, seed=42)
75
+
76
  # Trace untuk edges
77
  edge_x, edge_y = [], []
78
  for edge in self.dependency_graph.edges():
 
80
  x1, y1 = pos[edge[1]]
81
  edge_x.extend([x0, x1, None])
82
  edge_y.extend([y0, y1, None])
83
+
84
  edge_trace = go.Scatter(
85
  x=edge_x, y=edge_y,
86
  line=dict(width=1.5, color='#888', dash='dot'),
87
  hoverinfo='none',
88
  mode='lines')
89
+
90
  # Trace untuk nodes
91
  node_x, node_y, node_text = [], [], []
92
  node_degrees = dict(self.dependency_graph.degree())
93
+
94
  for node in self.dependency_graph.nodes():
95
  x, y = pos[node]
96
  node_x.append(x)
97
  node_y.append(y)
98
  node_text.append(f"{node} (Koneksi: {node_degrees[node]})")
99
+
100
  node_trace = go.Scatter(
101
  x=node_x, y=node_y,
102
  text=node_text,
 
116
  line_width=2
117
  )
118
  )
119
+
120
  layout = go.Layout(
121
  title='Graph Dependency Proyek',
122
  titlefont_size=16,
123
  showlegend=False,
124
  hovermode='closest',
125
+ margin=dict(b=20, l=5, r=5, t=40),
126
  xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
127
  yaxis=dict(showgrid=False, zeroline=False, showticklabels=False)
128
  )
129
+
130
  return go.Figure(data=[edge_trace, node_trace], layout=layout)
131
 
132
  class StreamlitAdvancedProjectApp:
133
  def __init__(self):
134
+ if 'tasks' not in st.session_state:
135
+ st.session_state.tasks = pd.DataFrame(columns=[
136
+ 'Task Name', 'Start Date', 'End Date',
137
+ 'Duration', 'Complexity', 'Predecessor', 'Successor',
138
+ 'Progress', 'Cost'
139
+ ])
140
+ self.dependency_manager = TaskDependencyManager()
141
+
142
  def run(self):
143
  st.set_page_config(page_title="Project Dependency Optimizer", page_icon="🚀")
 
144
  st.title("🚀 Advanced Project Dependency Optimizer")
145
+
146
  # Sidebar untuk input tugas
147
  st.sidebar.header("Input Tugas Terperinci")
148
+
 
 
 
 
 
 
 
 
 
149
  with st.sidebar.form("task_input"):
150
+ task_name = st.text_input("Nama Tugas")
151
+ start_date = st.date_input("Tanggal Mulai")
152
+ duration = st.number_input("Durasi (Hari)", min_value=1, value=5)
153
+ complexity = st.selectbox("Kompleksitas", ['Low', 'Medium', 'High'])
154
+
155
  # Pilih predecessor dan successor dari tugas yang sudah ada
156
  existing_tasks = [''] + list(st.session_state.tasks['Task Name'])
157
+ predecessor = st.selectbox("Predecessor (Opsional)", existing_tasks, index=0)
158
+ successor = st.selectbox("Successor (Opsional)", existing_tasks, index=0)
159
+
160
  submit = st.form_submit_button("Tambah Tugas")
161
+
162
  if submit and task_name:
163
  # Cek duplikasi nama tugas
164
  if task_name in st.session_state.tasks['Task Name'].values:
165
  st.sidebar.error("Tugas dengan nama ini sudah ada!")
166
  else:
167
  # Siapkan data tugas baru
168
+ new_task = {
169
  'Task Name': task_name,
170
  'Start Date': start_date,
171
  'End Date': start_date + timedelta(days=duration),
 
175
  'Successor': successor if successor else '-',
176
  'Progress': 0,
177
  'Cost': duration * 500
178
+ }
179
+ st.session_state.tasks = st.session_state.tasks.append(new_task, ignore_index=True)
180
+ self.dependency_manager.add_task(new_task)
181
+
 
 
 
 
 
 
 
182
  # Tampilkan daftar tugas
183
  if not st.session_state.tasks.empty:
184
  st.subheader("Daftar Tugas")
185
+ st.dataframe(st.session_state.tasks, use_container_width=True)
186
+
 
187
  # Analisis Dependency
188
  st.subheader("Analisis Hubungan Tugas")
189
  selected_task = st.selectbox(
190
+ "Pilih Tugas untuk Melihat Dependency",
191
+ st.session_state.tasks['Task Name']
192
  )
193
+
194
  if selected_task:
195
  dependencies = self.dependency_manager.get_task_dependencies(selected_task)
 
196
  col1, col2 = st.columns(2)
197
  with col1:
198
  st.write("Predecessor:")
199
  st.code(dependencies['predecessors'])
 
200
  with col2:
201
  st.write("Successor:")
202
  st.code(dependencies['successors'])
203
+
204
  # Visualisasi Graph Dependency
205
  st.subheader("Visualisasi Graph Dependency")
206
  try:
207
  dependency_graph_fig = self.dependency_manager.create_dependency_visualization()
 
208
  if dependency_graph_fig:
209
  st.plotly_chart(dependency_graph_fig, use_container_width=True)
210
  else: