AjaykumarPilla commited on
Commit
563cd8f
·
verified ·
1 Parent(s): 647c06f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +91 -19
app.py CHANGED
@@ -2,8 +2,9 @@ import streamlit as st
2
  import streamlit.components.v1 as components
3
  import pandas as pd
4
  import matplotlib.pyplot as plt
 
5
  import os
6
- from datetime import datetime
7
  import json
8
  import requests
9
  import base64
@@ -68,7 +69,7 @@ if 'weather_data' not in st.session_state:
68
  def fetch_weather_data(project_location, date):
69
  if not WEATHER_API_KEY:
70
  logger.error("WEATHER_API_KEY not set")
71
- return None, "Weather API key not set. Please provide a valid API key."
72
  try:
73
  params = {
74
  "q": project_location,
@@ -79,7 +80,7 @@ def fetch_weather_data(project_location, date):
79
  response.raise_for_status()
80
  data = response.json()
81
 
82
- # Find the closest forecast to the specified date
83
  target_date = datetime.strptime(date, "%Y-%m-%d")
84
  closest_forecast = None
85
  min_time_diff = float('inf')
@@ -92,31 +93,30 @@ def fetch_weather_data(project_location, date):
92
  closest_forecast = forecast
93
 
94
  if not closest_forecast:
95
- return None, "No forecast available for the specified date."
96
 
97
  # Map weather conditions to impact score
98
- weather_main = closest_forecast['weather'][0]['main'].lower()
 
99
  if 'clear' in weather_main:
100
  impact_score = 10
101
  elif 'clouds' in weather_main:
102
- impact_score = 30 if closest_forecast['clouds']['all'] < 50 else 50
103
  elif 'rain' in weather_main:
104
- impact_score = 70 if closest_forecast['rain'].get('3h', 0) < 2.5 else 85
105
  elif 'storm' in weather_main or 'thunderstorm' in weather_main:
106
  impact_score = 90
107
- else:
108
- impact_score = 50 # Default for other conditions (e.g., fog, snow)
109
 
110
  weather_condition = get_weather_condition(impact_score)
111
  return {
112
  "weather_impact_score": impact_score,
113
  "weather_condition": weather_condition,
114
- "temperature": closest_forecast['main']['temp'],
115
- "humidity": closest_forecast['main']['humidity']
116
  }, None
117
  except Exception as e:
118
  logger.error(f"Failed to fetch weather data: {str(e)}")
119
- return None, f"Failed to fetch weather data for {project_location}: {str(e)}"
120
 
121
  # Function to format high_risk_phases with flag and alert
122
  def format_high_risk_phases(high_risk_phases):
@@ -127,8 +127,57 @@ def format_high_risk_phases(high_risk_phases):
127
  formatted.append(f"{flag} {phase['phase']}: {phase['task']} (Risk: {phase['risk']:.1f}%) {alert}")
128
  return formatted
129
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  # Function to generate PDF
131
- def generate_pdf(input_data, prediction, heatmap_fig):
132
  buffer = BytesIO()
133
  doc = SimpleDocTemplate(buffer, pagesize=letter)
134
  styles = getSampleStyleSheet()
@@ -186,17 +235,33 @@ def generate_pdf(input_data, prediction, heatmap_fig):
186
  heatmap_fig.savefig(img_buffer, format='png', bbox_inches='tight')
187
  img_buffer.seek(0)
188
  story.append(Image(img_buffer, width=6*inch, height=2*inch))
189
- plt.close(heatmap_fig)
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
  doc.build(story)
192
  buffer.seek(0)
193
  return buffer
194
 
195
- # Function to save data to Salesforce, including PDF
196
  def save_to_salesforce(input_data, prediction, pdf_buffer):
197
  if sf is None:
198
  return "Salesforce connection not established."
199
  try:
 
 
 
200
  # Prepare data for Delay_Predictor__c object
201
  sf_data = {
202
  "Project_Name__c": input_data["project_name"],
@@ -214,7 +279,8 @@ def save_to_salesforce(input_data, prediction, pdf_buffer):
214
  "Project_Location__c": input_data["project_location"],
215
  "Delay_Probability__c": prediction["delay_probability"],
216
  "AI_Insights__c": prediction["ai_insights"],
217
- "High_Risk_Phases__c": "; ".join(format_high_risk_phases(prediction["high_risk_phases"]))
 
218
  }
219
  logger.info(f"Attempting to save to Salesforce Delay_Predictor__c: {sf_data}")
220
 
@@ -324,8 +390,8 @@ if submit_button:
324
  if project_location and weather_forecast_date:
325
  weather_data, weather_error = fetch_weather_data(project_location, input_data["weather_forecast_date"])
326
  if weather_error:
327
- st.error(weather_error)
328
- logger.error(weather_error)
329
  input_data["weather_impact_score"] = 50 # Fallback value
330
  input_data["weather_condition"] = "Unknown"
331
  else:
@@ -399,7 +465,13 @@ if submit_button:
399
  ax.set_title("Delay Risk Heatmap")
400
  plt.tight_layout()
401
 
402
- pdf_buffer = generate_pdf(input_data, prediction, fig)
 
 
 
 
 
 
403
  plt.close(fig)
404
  st.download_button(
405
  label="Download Prediction Report (PDF)",
 
2
  import streamlit.components.v1 as components
3
  import pandas as pd
4
  import matplotlib.pyplot as plt
5
+ import plotly.figure_factory as ff
6
  import os
7
+ from datetime import datetime, timedelta
8
  import json
9
  import requests
10
  import base64
 
69
  def fetch_weather_data(project_location, date):
70
  if not WEATHER_API_KEY:
71
  logger.error("WEATHER_API_KEY not set")
72
+ return None, {"error": "Weather API key not set. Please provide a valid API key."}
73
  try:
74
  params = {
75
  "q": project_location,
 
80
  response.raise_for_status()
81
  data = response.json()
82
 
83
+ # Find the closest forecast to the target date
84
  target_date = datetime.strptime(date, "%Y-%m-%d")
85
  closest_forecast = None
86
  min_time_diff = float('inf')
 
93
  closest_forecast = forecast
94
 
95
  if not closest_forecast:
96
+ return None, {"error": "No forecast available for the specified date."}
97
 
98
  # Map weather conditions to impact score
99
+ weather_main = forecast['weather'][0]['main'].lower()
100
+ impact_score = 50 # Default
101
  if 'clear' in weather_main:
102
  impact_score = 10
103
  elif 'clouds' in weather_main:
104
+ impact_score = 30 if forecast['clouds']['all'] < 50 else 50
105
  elif 'rain' in weather_main:
106
+ impact_score = 70 if forecast['rain'].get('3h', 0) < 2.5 else 85
107
  elif 'storm' in weather_main or 'thunderstorm' in weather_main:
108
  impact_score = 90
 
 
109
 
110
  weather_condition = get_weather_condition(impact_score)
111
  return {
112
  "weather_impact_score": impact_score,
113
  "weather_condition": weather_condition,
114
+ "temperature": forecast['main']['temp'],
115
+ "humidity": forecast['main']['humidity']
116
  }, None
117
  except Exception as e:
118
  logger.error(f"Failed to fetch weather data: {str(e)}")
119
+ return None, {"error": f"Failed to fetch weather data for {project_location}: {str(e)}"}
120
 
121
  # Function to format high_risk_phases with flag and alert
122
  def format_high_risk_phases(high_risk_phases):
 
127
  formatted.append(f"{flag} {phase['phase']}: {phase['task']} (Risk: {phase['risk']:.1f}%) {alert}")
128
  return formatted
129
 
130
+ # Function to generate Gantt chart
131
+ def generate_gantt_chart(input_data, prediction):
132
+ try:
133
+ phase = input_data["phase"]
134
+ task = input_data["task"]
135
+ expected_duration = input_data["task_expected_duration"]
136
+ actual_duration = input_data["task_actual_duration"]
137
+ forecast_date = datetime.strptime(input_data["weather_forecast_date"], "%Y-%m-%d")
138
+ delay_risk = prediction["delay_probability"]
139
+
140
+ # Calculate start and end dates
141
+ start_date = forecast_date - timedelta(days=max(expected_duration, actual_duration))
142
+ expected_end = start_date + timedelta(days=expected_duration)
143
+ actual_end = start_date + timedelta(days=actual_duration) if actual_duration > 0 else expected_end
144
+
145
+ # Prepare Gantt chart data
146
+ df = [
147
+ dict(Task=f"{phase}: {task} (Expected)", Start=start_date.strftime("%Y-%m-%d"), Finish=expected_end.strftime("%Y-%m-%d"), Resource="Expected", Risk=delay_risk),
148
+ dict(Task=f"{phase}: {task} (Actual)", Start=start_date.strftime("%Y-%m-%d"), Finish=actual_end.strftime("%Y-%m-%d"), Resource="Actual", Risk=delay_risk)
149
+ ]
150
+
151
+ # Color based on delay risk
152
+ colors = {
153
+ "Expected": "rgb(0, 255, 0)" if delay_risk <= 50 else "rgb(255, 255, 0)" if delay_risk <= 75 else "rgb(255, 0, 0)",
154
+ "Actual": "rgb(0, 200, 0)" if delay_risk <= 50 else "rgb(200, 200, 0)" if delay_risk <= 75 else "rgb(200, 0, 0)"
155
+ }
156
+
157
+ # Create Gantt chart
158
+ fig = ff.create_gantt(
159
+ df,
160
+ colors=colors,
161
+ index_col="Resource",
162
+ title=f"Gantt Chart for {phase}: {task}",
163
+ show_colorbar=True,
164
+ bar_width=0.4,
165
+ showgrid_x=True,
166
+ showgrid_y=True
167
+ )
168
+ fig.update_layout(
169
+ xaxis_title="Timeline",
170
+ yaxis_title="Task",
171
+ height=300,
172
+ margin=dict(l=150)
173
+ )
174
+ return fig
175
+ except Exception as e:
176
+ logger.error(f"Failed to generate Gantt chart: {str(e)}")
177
+ return None
178
+
179
  # Function to generate PDF
180
+ def generate_pdf(input_data, prediction, heatmap_fig, gantt_fig):
181
  buffer = BytesIO()
182
  doc = SimpleDocTemplate(buffer, pagesize=letter)
183
  styles = getSampleStyleSheet()
 
235
  heatmap_fig.savefig(img_buffer, format='png', bbox_inches='tight')
236
  img_buffer.seek(0)
237
  story.append(Image(img_buffer, width=6*inch, height=2*inch))
238
+ story.append(Spacer(1, 12))
239
+
240
+ # Gantt Chart
241
+ if gantt_fig:
242
+ story.append(Paragraph("Gantt Chart", styles['Heading2']))
243
+ gantt_buffer = BytesIO()
244
+ try:
245
+ gantt_fig.write_image(gantt_buffer, format='PNG')
246
+ gantt_buffer.seek(0)
247
+ story.append(Image(gantt_buffer, width=6*inch, height=3*inch))
248
+ except Exception as e:
249
+ logger.error(f"Failed to include Gantt chart in PDF: {str(e)}")
250
+ story.append(Paragraph("Gantt Chart unavailable due to rendering issues.", styles['Normal']))
251
+ story.append(Spacer(1, 12))
252
 
253
  doc.build(story)
254
  buffer.seek(0)
255
  return buffer
256
 
257
+ # Function to save data to Salesforce, including PDF and Status__c
258
  def save_to_salesforce(input_data, prediction, pdf_buffer):
259
  if sf is None:
260
  return "Salesforce connection not established."
261
  try:
262
+ # Determine Status__c based on delay probability
263
+ status = "Flagged" if prediction["delay_probability"] > 75 else "Running"
264
+
265
  # Prepare data for Delay_Predictor__c object
266
  sf_data = {
267
  "Project_Name__c": input_data["project_name"],
 
279
  "Project_Location__c": input_data["project_location"],
280
  "Delay_Probability__c": prediction["delay_probability"],
281
  "AI_Insights__c": prediction["ai_insights"],
282
+ "High_Risk_Phases__c": "; ".join(format_high_risk_phases(prediction["high_risk_phases"])),
283
+ "Status__c": status
284
  }
285
  logger.info(f"Attempting to save to Salesforce Delay_Predictor__c: {sf_data}")
286
 
 
390
  if project_location and weather_forecast_date:
391
  weather_data, weather_error = fetch_weather_data(project_location, input_data["weather_forecast_date"])
392
  if weather_error:
393
+ st.error(weather_error.get("error", "Unknown weather error"))
394
+ logger.error(weather_error.get("error", "Unknown weather error"))
395
  input_data["weather_impact_score"] = 50 # Fallback value
396
  input_data["weather_condition"] = "Unknown"
397
  else:
 
465
  ax.set_title("Delay Risk Heatmap")
466
  plt.tight_layout()
467
 
468
+ # Generate Gantt chart
469
+ gantt_fig = generate_gantt_chart(input_data, prediction)
470
+ if gantt_fig:
471
+ st.plotly_chart(gantt_fig, use_container_width=True)
472
+ logger.info("Gantt chart rendered")
473
+
474
+ pdf_buffer = generate_pdf(input_data, prediction, fig, gantt_fig)
475
  plt.close(fig)
476
  st.download_button(
477
  label="Download Prediction Report (PDF)",