Spaces:
Sleeping
Sleeping
Rajan Sharma
commited on
Update response_formatter.py
Browse files- response_formatter.py +260 -149
response_formatter.py
CHANGED
|
@@ -13,45 +13,61 @@ class ResponseFormatter:
|
|
| 13 |
response += "\n\n"
|
| 14 |
|
| 15 |
# Data Preparation
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
|
|
|
| 19 |
|
| 20 |
-
# Analysis
|
| 21 |
if "facility_distribution" in analysis_results:
|
| 22 |
response += "## 2. Facility Distribution Analysis\n\n"
|
| 23 |
response += ResponseFormatter._format_facility_distribution(analysis_results["facility_distribution"])
|
| 24 |
response += "\n\n"
|
| 25 |
|
|
|
|
| 26 |
if "capacity_analysis" in analysis_results:
|
| 27 |
response += "## 3. Capacity Analysis\n\n"
|
| 28 |
response += ResponseFormatter._format_capacity_analysis(analysis_results["capacity_analysis"])
|
| 29 |
response += "\n\n"
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
if "resource_allocation" in analysis_results:
|
| 32 |
-
response += "##
|
| 33 |
response += ResponseFormatter._format_resource_allocation(analysis_results["resource_allocation"])
|
| 34 |
response += "\n\n"
|
| 35 |
|
|
|
|
| 36 |
if "trends" in analysis_results:
|
| 37 |
-
response += "##
|
| 38 |
response += ResponseFormatter._format_trends(analysis_results["trends"])
|
| 39 |
response += "\n\n"
|
| 40 |
|
| 41 |
-
# Recommendations
|
| 42 |
if "recommendations" in analysis_results:
|
| 43 |
-
response += "##
|
| 44 |
response += ResponseFormatter._format_recommendations(analysis_results["recommendations"])
|
| 45 |
response += "\n\n"
|
| 46 |
|
| 47 |
# Future Integration
|
| 48 |
if "future_integration" in analysis_results:
|
| 49 |
-
response += "##
|
| 50 |
response += ResponseFormatter._format_integration_opportunities(analysis_results["future_integration"])
|
| 51 |
response += "\n\n"
|
| 52 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
# Provenance
|
| 54 |
-
response += "##
|
| 55 |
response += "This analysis is based on:\n"
|
| 56 |
response += "- Scenario description provided by the user\n"
|
| 57 |
response += "- Uploaded data files\n"
|
|
@@ -83,6 +99,10 @@ class ResponseFormatter:
|
|
| 83 |
if high_priority:
|
| 84 |
summary.append(f"{len(high_priority)} high-priority recommendations identified")
|
| 85 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
return " | ".join(summary) if summary else "No key metrics identified"
|
| 87 |
|
| 88 |
@staticmethod
|
|
@@ -112,6 +132,90 @@ class ResponseFormatter:
|
|
| 112 |
response += "\nData quality checks and transformations were applied to ensure accuracy and consistency."
|
| 113 |
return response
|
| 114 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
@staticmethod
|
| 116 |
def _format_facility_distribution(dist_results: Dict[str, Any]) -> str:
|
| 117 |
"""Format facility distribution analysis results"""
|
|
@@ -200,173 +304,180 @@ class ResponseFormatter:
|
|
| 200 |
|
| 201 |
if "capacity_growth_rate" in capacity_results:
|
| 202 |
growth = capacity_results["capacity_growth_rate"]
|
| 203 |
-
response += f"**
|
| 204 |
-
|
| 205 |
-
if "zone_summary" in capacity_results:
|
| 206 |
-
response += "### Bed Capacity by Zone\n\n"
|
| 207 |
-
response += "| Zone | Current Beds | Previous Beds | Absolute Change | Percentage Change |\n"
|
| 208 |
-
response += "|------|--------------|---------------|-----------------|-------------------|\n"
|
| 209 |
-
|
| 210 |
-
for zone_data in capacity_results["zone_summary"]:
|
| 211 |
-
# Extract zone name - try different possible keys
|
| 212 |
-
zone_name = "Unknown"
|
| 213 |
-
for key in ["zone", "Zone", "ZONE", "region", "Region", "REGION"]:
|
| 214 |
-
if key in zone_data:
|
| 215 |
-
zone_name = zone_data[key]
|
| 216 |
-
break
|
| 217 |
-
|
| 218 |
-
# Extract bed counts
|
| 219 |
-
current_beds = zone_data.get("beds_current", zone_data.get("current", "N/A"))
|
| 220 |
-
prev_beds = zone_data.get("beds_prev", zone_data.get("previous", "N/A"))
|
| 221 |
-
abs_change = zone_data.get("bed_change", "N/A")
|
| 222 |
-
pct_change = zone_data.get("percent_change", "N/A")
|
| 223 |
-
|
| 224 |
-
response += f"| {zone_name} | {current_beds} | {prev_beds} | {abs_change} | {pct_change:.1f}% |\n"
|
| 225 |
-
|
| 226 |
-
response += "\n"
|
| 227 |
-
|
| 228 |
-
if "max_absolute_decrease" in capacity_results and isinstance(capacity_results["max_absolute_decrease"], dict):
|
| 229 |
-
response += "### Zone with Largest Absolute Decrease\n\n"
|
| 230 |
-
max_abs = capacity_results["max_absolute_decrease"]
|
| 231 |
-
|
| 232 |
-
# Extract zone name
|
| 233 |
-
zone_name = "Unknown"
|
| 234 |
-
for key in ["zone", "Zone", "ZONE", "region", "Region", "REGION"]:
|
| 235 |
-
if key in max_abs:
|
| 236 |
-
zone_name = max_abs[key]
|
| 237 |
-
break
|
| 238 |
-
|
| 239 |
-
# Extract values
|
| 240 |
-
abs_change = max_abs.get("bed_change", "N/A")
|
| 241 |
-
pct_change = max_abs.get("percent_change", "N/A")
|
| 242 |
-
|
| 243 |
-
response += f"**Zone**: {zone_name}\n"
|
| 244 |
-
response += f"**Absolute Decrease**: {abs_change} beds\n"
|
| 245 |
-
response += f"**Percentage Decrease**: {pct_change:.1f}%\n\n"
|
| 246 |
-
|
| 247 |
-
if "max_percentage_decrease" in capacity_results and isinstance(capacity_results["max_percentage_decrease"], dict):
|
| 248 |
-
response += "### Zone with Largest Percentage Decrease\n\n"
|
| 249 |
-
max_pct = capacity_results["max_percentage_decrease"]
|
| 250 |
-
|
| 251 |
-
# Extract zone name
|
| 252 |
-
zone_name = "Unknown"
|
| 253 |
-
for key in ["zone", "Zone", "ZONE", "region", "Region", "REGION"]:
|
| 254 |
-
if key in max_pct:
|
| 255 |
-
zone_name = max_pct[key]
|
| 256 |
-
break
|
| 257 |
-
|
| 258 |
-
# Extract values
|
| 259 |
-
abs_change = max_pct.get("bed_change", "N/A")
|
| 260 |
-
pct_change = max_pct.get("percent_change", "N/A")
|
| 261 |
-
|
| 262 |
-
response += f"**Zone**: {zone_name}\n"
|
| 263 |
-
response += f"**Absolute Decrease**: {abs_change} beds\n"
|
| 264 |
-
response += f"**Percentage Decrease**: {pct_change:.1f}%\n\n"
|
| 265 |
-
|
| 266 |
-
if "facilities_with_largest_declines" in capacity_results:
|
| 267 |
-
response += "### Facilities with Largest Bed Declines\n\n"
|
| 268 |
-
response += "| Facility | Zone | Teaching Status | Beds Lost |\n"
|
| 269 |
-
response += "|----------|------|----------------|-----------|\n"
|
| 270 |
-
|
| 271 |
-
for facility in capacity_results["facilities_with_largest_declines"]:
|
| 272 |
-
name = facility.get("facility_name", "N/A")
|
| 273 |
-
|
| 274 |
-
# Extract zone name
|
| 275 |
-
zone_name = "Unknown"
|
| 276 |
-
for key in ["zone", "Zone", "ZONE", "region", "Region", "REGION"]:
|
| 277 |
-
if key in facility:
|
| 278 |
-
zone_name = facility[key]
|
| 279 |
-
break
|
| 280 |
-
|
| 281 |
-
teaching = facility.get("teaching_status", "N/A")
|
| 282 |
-
change = facility.get("bed_change", "N/A")
|
| 283 |
-
|
| 284 |
-
response += f"| {name} | {zone_name} | {teaching} | {change} |\n"
|
| 285 |
-
|
| 286 |
-
response += "\n"
|
| 287 |
|
| 288 |
-
return response if response else "No capacity data available"
|
| 289 |
|
| 290 |
@staticmethod
|
| 291 |
-
def _format_resource_allocation(
|
| 292 |
-
"""Format resource allocation results"""
|
| 293 |
response = ""
|
| 294 |
|
| 295 |
-
if "
|
| 296 |
-
response += f"**Total
|
| 297 |
|
| 298 |
-
if "
|
| 299 |
-
|
| 300 |
-
response +=
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 304 |
|
| 305 |
-
if "
|
| 306 |
-
response += "###
|
| 307 |
-
|
| 308 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 309 |
response += "\n"
|
| 310 |
|
| 311 |
return response if response else "No resource allocation data available"
|
| 312 |
|
| 313 |
@staticmethod
|
| 314 |
-
def _format_trends(
|
| 315 |
"""Format trend analysis results"""
|
| 316 |
response = ""
|
| 317 |
|
| 318 |
-
if "
|
| 319 |
-
response += "
|
| 320 |
-
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
|
| 324 |
-
|
| 325 |
-
|
| 326 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 327 |
response += "\n"
|
| 328 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 329 |
return response if response else "No trend data available"
|
| 330 |
|
| 331 |
@staticmethod
|
| 332 |
-
def _format_recommendations(
|
| 333 |
"""Format operational recommendations"""
|
| 334 |
-
if not recommendations:
|
| 335 |
-
return "No specific recommendations generated"
|
| 336 |
-
|
| 337 |
response = ""
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 343 |
|
| 344 |
return response
|
| 345 |
|
| 346 |
@staticmethod
|
| 347 |
-
def _format_integration_opportunities(
|
| 348 |
"""Format future integration opportunities"""
|
| 349 |
response = ""
|
| 350 |
|
| 351 |
-
if "
|
| 352 |
-
response += "
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
|
| 370 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 371 |
|
| 372 |
return response if response else "No integration opportunities identified"
|
|
|
|
| 13 |
response += "\n\n"
|
| 14 |
|
| 15 |
# Data Preparation
|
| 16 |
+
if "data_preparation" in analysis_results:
|
| 17 |
+
response += "## 1. Data Preparation\n\n"
|
| 18 |
+
response += ResponseFormatter._format_data_preparation(analysis_results["data_preparation"])
|
| 19 |
+
response += "\n\n"
|
| 20 |
|
| 21 |
+
# Facility Distribution Analysis
|
| 22 |
if "facility_distribution" in analysis_results:
|
| 23 |
response += "## 2. Facility Distribution Analysis\n\n"
|
| 24 |
response += ResponseFormatter._format_facility_distribution(analysis_results["facility_distribution"])
|
| 25 |
response += "\n\n"
|
| 26 |
|
| 27 |
+
# Capacity Analysis
|
| 28 |
if "capacity_analysis" in analysis_results:
|
| 29 |
response += "## 3. Capacity Analysis\n\n"
|
| 30 |
response += ResponseFormatter._format_capacity_analysis(analysis_results["capacity_analysis"])
|
| 31 |
response += "\n\n"
|
| 32 |
|
| 33 |
+
# Long-Term Care Assessment
|
| 34 |
+
if "long_term_care_assessment" in analysis_results:
|
| 35 |
+
response += "## 4. Long-Term Care Capacity Assessment\n\n"
|
| 36 |
+
response += ResponseFormatter._format_long_term_care_assessment(analysis_results["long_term_care_assessment"])
|
| 37 |
+
response += "\n\n"
|
| 38 |
+
|
| 39 |
+
# Resource Allocation Analysis
|
| 40 |
if "resource_allocation" in analysis_results:
|
| 41 |
+
response += "## 5. Resource Allocation Analysis\n\n"
|
| 42 |
response += ResponseFormatter._format_resource_allocation(analysis_results["resource_allocation"])
|
| 43 |
response += "\n\n"
|
| 44 |
|
| 45 |
+
# Trend Analysis
|
| 46 |
if "trends" in analysis_results:
|
| 47 |
+
response += "## 6. Trend Analysis\n\n"
|
| 48 |
response += ResponseFormatter._format_trends(analysis_results["trends"])
|
| 49 |
response += "\n\n"
|
| 50 |
|
| 51 |
+
# Operational Recommendations
|
| 52 |
if "recommendations" in analysis_results:
|
| 53 |
+
response += "## 7. Operational Recommendations\n\n"
|
| 54 |
response += ResponseFormatter._format_recommendations(analysis_results["recommendations"])
|
| 55 |
response += "\n\n"
|
| 56 |
|
| 57 |
# Future Integration
|
| 58 |
if "future_integration" in analysis_results:
|
| 59 |
+
response += "## 8. Future Integration Opportunities\n\n"
|
| 60 |
response += ResponseFormatter._format_integration_opportunities(analysis_results["future_integration"])
|
| 61 |
response += "\n\n"
|
| 62 |
|
| 63 |
+
# Validation Results
|
| 64 |
+
if "validation" in analysis_results:
|
| 65 |
+
response += "## 9. Analysis Validation\n\n"
|
| 66 |
+
response += ResponseFormatter._format_validation_results(analysis_results["validation"])
|
| 67 |
+
response += "\n\n"
|
| 68 |
+
|
| 69 |
# Provenance
|
| 70 |
+
response += "## 10. Provenance\n\n"
|
| 71 |
response += "This analysis is based on:\n"
|
| 72 |
response += "- Scenario description provided by the user\n"
|
| 73 |
response += "- Uploaded data files\n"
|
|
|
|
| 99 |
if high_priority:
|
| 100 |
summary.append(f"{len(high_priority)} high-priority recommendations identified")
|
| 101 |
|
| 102 |
+
if "validation" in results:
|
| 103 |
+
completion_rate = results["validation"].get("completion_rate", 0)
|
| 104 |
+
summary.append(f"Analysis completion rate: {completion_rate:.1%}")
|
| 105 |
+
|
| 106 |
return " | ".join(summary) if summary else "No key metrics identified"
|
| 107 |
|
| 108 |
@staticmethod
|
|
|
|
| 132 |
response += "\nData quality checks and transformations were applied to ensure accuracy and consistency."
|
| 133 |
return response
|
| 134 |
|
| 135 |
+
@staticmethod
|
| 136 |
+
def _format_data_preparation(data_prep_results: Dict[str, Any]) -> str:
|
| 137 |
+
"""Format data preparation results"""
|
| 138 |
+
response = ""
|
| 139 |
+
|
| 140 |
+
if "total_facilities" in data_prep_results:
|
| 141 |
+
response += f"**Total Facilities Analyzed**: {data_prep_results['total_facilities']:,}\n\n"
|
| 142 |
+
|
| 143 |
+
if "facility_type_frequency" in data_prep_results:
|
| 144 |
+
response += "### Facility Type Frequency\n\n"
|
| 145 |
+
response += "| Facility Type | Count |\n"
|
| 146 |
+
response += "|---------------|-------|\n"
|
| 147 |
+
for ftype, count in data_prep_results["facility_type_frequency"].items():
|
| 148 |
+
response += f"| {ftype} | {count} |\n"
|
| 149 |
+
response += "\n"
|
| 150 |
+
|
| 151 |
+
if "top_cities" in data_prep_results and "city_facility_breakdown" in data_prep_results:
|
| 152 |
+
response += "### Top Cities by Facility Count\n\n"
|
| 153 |
+
response += "| City | Hospitals | Nursing/Residential | Ambulatory | Total |\n"
|
| 154 |
+
response += "|------|-----------|-------------------|------------|-------|\n"
|
| 155 |
+
|
| 156 |
+
for city in data_prep_results["top_cities"]:
|
| 157 |
+
if city in data_prep_results["city_facility_breakdown"]:
|
| 158 |
+
breakdown = data_prep_results["city_facility_breakdown"][city]
|
| 159 |
+
hospitals = breakdown.get("Hospitals", 0)
|
| 160 |
+
nursing = breakdown.get("Nursing and residential care facilities", 0)
|
| 161 |
+
ambulatory = breakdown.get("Ambulatory health care services", 0)
|
| 162 |
+
total = hospitals + nursing + ambulatory
|
| 163 |
+
response += f"| {city} | {hospitals} | {nursing} | {ambulatory} | {total} |\n"
|
| 164 |
+
|
| 165 |
+
response += "\n"
|
| 166 |
+
|
| 167 |
+
return response if response else "No data preparation results available"
|
| 168 |
+
|
| 169 |
+
@staticmethod
|
| 170 |
+
def _format_long_term_care_assessment(ltc_results: Dict[str, Any]) -> str:
|
| 171 |
+
"""Format long-term care assessment results"""
|
| 172 |
+
response = ""
|
| 173 |
+
|
| 174 |
+
if "zone_with_largest_decrease" in ltc_results:
|
| 175 |
+
response += f"**Zone with Largest Percentage Decrease**: {ltc_results['zone_with_largest_decrease']}\n\n"
|
| 176 |
+
|
| 177 |
+
if "major_city" in ltc_results:
|
| 178 |
+
response += f"**Major City in Zone**: {ltc_results['major_city']}\n\n"
|
| 179 |
+
|
| 180 |
+
if "facility_counts" in ltc_results:
|
| 181 |
+
counts = ltc_results["facility_counts"]
|
| 182 |
+
response += "### Facility Counts in Major City\n\n"
|
| 183 |
+
response += f"- Hospitals: {counts['hospitals']}\n"
|
| 184 |
+
response += f"- Nursing/Residential Care Facilities: {counts['nursing_residential_care']}\n"
|
| 185 |
+
response += f"- Ambulatory Health Services: {counts['ambulatory']}\n\n"
|
| 186 |
+
|
| 187 |
+
if "nursing_to_hospital_ratio" in ltc_results:
|
| 188 |
+
ratio = ltc_results["nursing_to_hospital_ratio"]
|
| 189 |
+
response += f"**Nursing/Residential to Hospital Ratio**: {ratio:.2f}\n\n"
|
| 190 |
+
|
| 191 |
+
if "capacity_assessment" in ltc_results:
|
| 192 |
+
assessment = ltc_results["capacity_assessment"]
|
| 193 |
+
response += f"**Long-Term Care Capacity Assessment**: {assessment.upper()}\n\n"
|
| 194 |
+
|
| 195 |
+
if assessment == "insufficient":
|
| 196 |
+
response += "The ratio of nursing/residential care facilities to hospitals is below the recommended threshold of 1.5. "
|
| 197 |
+
response += "This indicates insufficient long-term care capacity to support the healthcare system in this area.\n\n"
|
| 198 |
+
else:
|
| 199 |
+
response += "The ratio of nursing/residential care facilities to hospitals meets or exceeds the recommended threshold. "
|
| 200 |
+
response += "This indicates sufficient long-term care capacity.\n\n"
|
| 201 |
+
|
| 202 |
+
return response if response else "No long-term care assessment results available"
|
| 203 |
+
|
| 204 |
+
@staticmethod
|
| 205 |
+
def _format_validation_results(validation: Dict[str, Any]) -> str:
|
| 206 |
+
"""Format validation results"""
|
| 207 |
+
response = f"**Analysis Completion Rate**: {validation['completion_rate']:.1%}\n\n"
|
| 208 |
+
|
| 209 |
+
if validation["all_tasks_completed"]:
|
| 210 |
+
response += "✅ All required tasks were completed successfully.\n\n"
|
| 211 |
+
else:
|
| 212 |
+
response += "⚠️ The following tasks were not completed:\n\n"
|
| 213 |
+
for task in validation["missing_tasks"]:
|
| 214 |
+
response += f"- {task}\n"
|
| 215 |
+
response += "\n"
|
| 216 |
+
|
| 217 |
+
return response
|
| 218 |
+
|
| 219 |
@staticmethod
|
| 220 |
def _format_facility_distribution(dist_results: Dict[str, Any]) -> str:
|
| 221 |
"""Format facility distribution analysis results"""
|
|
|
|
| 304 |
|
| 305 |
if "capacity_growth_rate" in capacity_results:
|
| 306 |
growth = capacity_results["capacity_growth_rate"]
|
| 307 |
+
response += f"**Annual Growth Rate**: {growth:.1%}\n\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 308 |
|
| 309 |
+
return response if response else "No capacity analysis data available"
|
| 310 |
|
| 311 |
@staticmethod
|
| 312 |
+
def _format_resource_allocation(allocation_results: Dict[str, Any]) -> str:
|
| 313 |
+
"""Format resource allocation analysis results"""
|
| 314 |
response = ""
|
| 315 |
|
| 316 |
+
if "total_resources" in allocation_results:
|
| 317 |
+
response += f"**Total Resources**: {allocation_results['total_resources']:,} units\n\n"
|
| 318 |
|
| 319 |
+
if "allocation_by_facility" in allocation_results:
|
| 320 |
+
response += "### Allocation by Facility Type\n\n"
|
| 321 |
+
response += "| Facility Type | Resource Count | Percentage |\n"
|
| 322 |
+
response += "|---------------|----------------|------------|\n"
|
| 323 |
+
for ftype, count in allocation_results["allocation_by_facility"].items():
|
| 324 |
+
percentage = count / allocation_results.get("total_resources", 1) * 100
|
| 325 |
+
response += f"| {ftype} | {count:,} | {percentage:.1f}% |\n"
|
| 326 |
+
response += "\n"
|
| 327 |
+
|
| 328 |
+
if "allocation_by_region" in allocation_results:
|
| 329 |
+
response += "### Allocation by Region\n\n"
|
| 330 |
+
response += "| Region | Resource Count | Percentage |\n"
|
| 331 |
+
response += "|--------|----------------|------------|\n"
|
| 332 |
+
for region, count in allocation_results["allocation_by_region"].items():
|
| 333 |
+
percentage = count / allocation_results.get("total_resources", 1) * 100
|
| 334 |
+
response += f"| {region} | {count:,} | {percentage:.1f}% |\n"
|
| 335 |
+
response += "\n"
|
| 336 |
|
| 337 |
+
if "efficiency_metrics" in allocation_results:
|
| 338 |
+
response += "### Efficiency Metrics\n\n"
|
| 339 |
+
response += "| Metric | Value |\n"
|
| 340 |
+
response += "|--------|-------|\n"
|
| 341 |
+
for metric, value in allocation_results["efficiency_metrics"].items():
|
| 342 |
+
if isinstance(value, float):
|
| 343 |
+
response += f"| {metric} | {value:.2f} |\n"
|
| 344 |
+
else:
|
| 345 |
+
response += f"| {metric} | {value} |\n"
|
| 346 |
response += "\n"
|
| 347 |
|
| 348 |
return response if response else "No resource allocation data available"
|
| 349 |
|
| 350 |
@staticmethod
|
| 351 |
+
def _format_trends(trends_results: Dict[str, Any]) -> str:
|
| 352 |
"""Format trend analysis results"""
|
| 353 |
response = ""
|
| 354 |
|
| 355 |
+
if "summary" in trends_results:
|
| 356 |
+
response += f"**Trend Summary**: {trends_results['summary']}\n\n"
|
| 357 |
+
|
| 358 |
+
if "facility_growth" in trends_results:
|
| 359 |
+
response += "### Facility Growth Trends\n\n"
|
| 360 |
+
response += "| Year | Facility Count | Growth Rate |\n"
|
| 361 |
+
response += "|------|----------------|-------------|\n"
|
| 362 |
+
prev_count = None
|
| 363 |
+
for year, count in trends_results["facility_growth"].items():
|
| 364 |
+
if prev_count is not None:
|
| 365 |
+
growth_rate = (count - prev_count) / prev_count
|
| 366 |
+
response += f"| {year} | {count:,} | {growth_rate:.1%} |\n"
|
| 367 |
+
else:
|
| 368 |
+
response += f"| {year} | {count:,} | N/A |\n"
|
| 369 |
+
prev_count = count
|
| 370 |
response += "\n"
|
| 371 |
|
| 372 |
+
if "capacity_trends" in trends_results:
|
| 373 |
+
response += "### Capacity Trends\n\n"
|
| 374 |
+
response += "| Year | Total Capacity | Growth Rate |\n"
|
| 375 |
+
response += "|------|----------------|-------------|\n"
|
| 376 |
+
prev_capacity = None
|
| 377 |
+
for year, capacity in trends_results["capacity_trends"].items():
|
| 378 |
+
if prev_capacity is not None:
|
| 379 |
+
growth_rate = (capacity - prev_capacity) / prev_capacity
|
| 380 |
+
response += f"| {year} | {capacity:,} | {growth_rate:.1%} |\n"
|
| 381 |
+
else:
|
| 382 |
+
response += f"| {year} | {capacity:,} | N/A |\n"
|
| 383 |
+
prev_capacity = capacity
|
| 384 |
+
response += "\n"
|
| 385 |
+
|
| 386 |
+
if "utilization_trends" in trends_results:
|
| 387 |
+
response += "### Utilization Trends\n\n"
|
| 388 |
+
response += "| Year | Average Utilization |\n"
|
| 389 |
+
response += "|------|---------------------|\n"
|
| 390 |
+
for year, utilization in trends_results["utilization_trends"].items():
|
| 391 |
+
response += f"| {year} | {utilization:.1%} |\n"
|
| 392 |
+
response += "\n"
|
| 393 |
+
|
| 394 |
+
if "forecast" in trends_results:
|
| 395 |
+
response += "### Forecast\n\n"
|
| 396 |
+
response += trends_results["forecast"] + "\n\n"
|
| 397 |
+
|
| 398 |
return response if response else "No trend data available"
|
| 399 |
|
| 400 |
@staticmethod
|
| 401 |
+
def _format_recommendations(recommendations_results: List[Dict[str, Any]]) -> str:
|
| 402 |
"""Format operational recommendations"""
|
|
|
|
|
|
|
|
|
|
| 403 |
response = ""
|
| 404 |
+
|
| 405 |
+
if not recommendations_results:
|
| 406 |
+
return "No recommendations available"
|
| 407 |
+
|
| 408 |
+
# Group by priority
|
| 409 |
+
high_priority = [r for r in recommendations_results if r.get("priority") == "High"]
|
| 410 |
+
medium_priority = [r for r in recommendations_results if r.get("priority") == "Medium"]
|
| 411 |
+
low_priority = [r for r in recommendations_results if r.get("priority") == "Low"]
|
| 412 |
+
|
| 413 |
+
if high_priority:
|
| 414 |
+
response += "### High Priority Recommendations\n\n"
|
| 415 |
+
for i, rec in enumerate(high_priority, 1):
|
| 416 |
+
response += f"**{i}. {rec.get('title', 'Recommendation')}**\n\n"
|
| 417 |
+
response += f"{rec.get('description', '')}\n\n"
|
| 418 |
+
if "expected_impact" in rec:
|
| 419 |
+
response += f"Expected Impact: {rec['expected_impact']}\n\n"
|
| 420 |
+
if "implementation" in rec:
|
| 421 |
+
response += f"Implementation: {rec['implementation']}\n\n"
|
| 422 |
+
response += "---\n\n"
|
| 423 |
+
|
| 424 |
+
if medium_priority:
|
| 425 |
+
response += "### Medium Priority Recommendations\n\n"
|
| 426 |
+
for i, rec in enumerate(medium_priority, 1):
|
| 427 |
+
response += f"**{i}. {rec.get('title', 'Recommendation')}**\n\n"
|
| 428 |
+
response += f"{rec.get('description', '')}\n\n"
|
| 429 |
+
if "expected_impact" in rec:
|
| 430 |
+
response += f"Expected Impact: {rec['expected_impact']}\n\n"
|
| 431 |
+
if "implementation" in rec:
|
| 432 |
+
response += f"Implementation: {rec['implementation']}\n\n"
|
| 433 |
+
response += "---\n\n"
|
| 434 |
+
|
| 435 |
+
if low_priority:
|
| 436 |
+
response += "### Low Priority Recommendations\n\n"
|
| 437 |
+
for i, rec in enumerate(low_priority, 1):
|
| 438 |
+
response += f"**{i}. {rec.get('title', 'Recommendation')}**\n\n"
|
| 439 |
+
response += f"{rec.get('description', '')}\n\n"
|
| 440 |
+
if "expected_impact" in rec:
|
| 441 |
+
response += f"Expected Impact: {rec['expected_impact']}\n\n"
|
| 442 |
+
if "implementation" in rec:
|
| 443 |
+
response += f"Implementation: {rec['implementation']}\n\n"
|
| 444 |
+
response += "---\n\n"
|
| 445 |
|
| 446 |
return response
|
| 447 |
|
| 448 |
@staticmethod
|
| 449 |
+
def _format_integration_opportunities(integration_results: Dict[str, Any]) -> str:
|
| 450 |
"""Format future integration opportunities"""
|
| 451 |
response = ""
|
| 452 |
|
| 453 |
+
if "summary" in integration_results:
|
| 454 |
+
response += f"**Integration Summary**: {integration_results['summary']}\n\n"
|
| 455 |
+
|
| 456 |
+
if "opportunities" in integration_results:
|
| 457 |
+
response += "### Integration Opportunities\n\n"
|
| 458 |
+
for i, opp in enumerate(integration_results["opportunities"], 1):
|
| 459 |
+
response += f"**{i}. {opp.get('title', 'Opportunity')}**\n\n"
|
| 460 |
+
response += f"{opp.get('description', '')}\n\n"
|
| 461 |
+
if "benefits" in opp:
|
| 462 |
+
response += "**Benefits:**\n"
|
| 463 |
+
for benefit in opp["benefits"]:
|
| 464 |
+
response += f"- {benefit}\n"
|
| 465 |
+
response += "\n"
|
| 466 |
+
if "challenges" in opp:
|
| 467 |
+
response += "**Challenges:**\n"
|
| 468 |
+
for challenge in opp["challenges"]:
|
| 469 |
+
response += f"- {challenge}\n"
|
| 470 |
+
response += "\n"
|
| 471 |
+
if "timeline" in opp:
|
| 472 |
+
response += f"**Timeline:** {opp['timeline']}\n\n"
|
| 473 |
+
response += "---\n\n"
|
| 474 |
+
|
| 475 |
+
if "roadmap" in integration_results:
|
| 476 |
+
response += "### Integration Roadmap\n\n"
|
| 477 |
+
response += "| Phase | Activities | Timeline |\n"
|
| 478 |
+
response += "|-------|------------|----------|\n"
|
| 479 |
+
for phase in integration_results["roadmap"]:
|
| 480 |
+
response += f"| {phase['name']} | {phase['activities']} | {phase['timeline']} |\n"
|
| 481 |
+
response += "\n"
|
| 482 |
|
| 483 |
return response if response else "No integration opportunities identified"
|