File size: 5,502 Bytes
75c2779 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | """
Advanced Risk Engine - Explains crowd predictions with reasoning and recommendations
"""
from typing import Dict, List
RISK_CONFIG = {
"Low": {
"score": 15,
"color": "#10b981",
"bg": "#d1fae5",
"emoji": "π’",
"badge": "LOW RISK",
"advice": "Comfortable travel expected. Enjoy your journey!",
},
"Medium": {
"score": 50,
"color": "#f59e0b",
"bg": "#fef3c7",
"emoji": "π‘",
"badge": "MODERATE",
"advice": "Moderate crowd. Book window seat in advance if possible.",
},
"Extreme": {
"score": 90,
"color": "#ef4444",
"bg": "#fee2e2",
"emoji": "π΄",
"badge": "EXTREME",
"advice": "Very crowded! Consider alternate timing or route.",
},
}
HOUR_LABELS = {
5: "Early Morning", 6: "Early Morning",
7: "Morning Rush", 8: "Peak Morning Rush", 9: "Morning Rush",
10: "Mid Morning", 11: "Late Morning",
12: "Noon", 13: "Afternoon", 14: "Afternoon", 15: "Mid Afternoon", 16: "Late Afternoon",
17: "Evening Rush", 18: "Peak Evening Rush", 19: "Evening Rush",
20: "Late Evening", 21: "Night", 22: "Late Night",
}
WESTERN_STATIONS_ORDER = [
"Churchgate", "Marine Lines", "Charni Road", "Grant Road",
"Mumbai Central", "Mahalaxmi", "Lower Parel", "Dadar",
"Bandra", "Andheri", "Borivali", "Virar"
]
CENTRAL_STATIONS_ORDER = [
"CSMT", "Masjid", "Sandhurst Road", "Byculla",
"Dadar", "Kurla", "Ghatkopar", "Thane", "Kalyan"
]
HARBOUR_STATIONS_ORDER = [
"CSMT", "Masjid", "Dockyard Road", "Wadala Road",
"Kurla", "Vashi", "Nerul", "Panvel"
]
def get_risk_info(crowd_level: str) -> Dict:
return RISK_CONFIG.get(crowd_level, RISK_CONFIG["Low"])
def build_reasoning(
line: str, station: str, destination: str,
direction: str, hour: int, day_of_week: str,
crowd_level: str
) -> List[str]:
reasons = []
is_weekday = day_of_week not in ["Saturday", "Sunday"]
is_morning_peak = 7 <= hour <= 9
is_evening_peak = 17 <= hour <= 19
is_southbound = direction == "Southbound"
hour_label = HOUR_LABELS.get(hour, "")
# Time-based
if is_morning_peak:
reasons.append(f"β° {hour_label} ({hour}:00) β peak office hours create high demand")
elif is_evening_peak:
reasons.append(f"β° {hour_label} ({hour}:00) β peak return hours, trains are packed")
elif hour < 6:
reasons.append(f"β° Early morning ({hour}:00) β very few commuters at this hour")
elif hour > 21:
reasons.append(f"β° Late night ({hour}:00) β minimal traffic")
else:
reasons.append(f"β° {hour_label} ({hour}:00) β off-peak period")
# Day type
if is_weekday:
reasons.append(f"π
{day_of_week} is a working day β 20-30% more passengers than weekends")
else:
reasons.append(f"π
{day_of_week} is a weekend β lighter traffic overall")
# Directional logic
if is_morning_peak and is_southbound and is_weekday:
reasons.append("π Southbound during morning rush β commuters flooding into the city")
elif is_morning_peak and not is_southbound and is_weekday:
reasons.append("π Northbound during morning rush β outbound direction, relatively lighter")
elif is_evening_peak and not is_southbound and is_weekday:
reasons.append("π Northbound during evening rush β commuters heading home to suburbs")
elif is_evening_peak and is_southbound and is_weekday:
reasons.append("π Southbound during evening β reverse commute, lighter than northbound")
# Line-specific
if line == "Western":
reasons.append("π€οΈ Western Line β highest ridership line in Mumbai (approx. 4M+ daily)")
elif line == "Central":
reasons.append("π€οΈ Central Line β second busiest, serves eastern suburbs & Thane district")
elif line == "Harbour":
reasons.append("π€οΈ Harbour Line β connects Navi Mumbai, generally less crowded")
return reasons
def get_best_hours(
model, le_station, le_dest,
line: str, station: str, destination: str, direction: str, day: str,
predict_fn
) -> List[Dict]:
results = []
for h in range(5, 23):
pred = predict_fn(model, le_station, le_dest, line, station, destination, direction, h, day)
results.append({
"hour": h,
"label": f"{h:02d}:00",
"crowd_level": pred["crowd_level"],
"risk_score": RISK_CONFIG[pred["crowd_level"]]["score"],
"confidence": pred["confidence"]
})
return results
def get_travel_tip(crowd_level: str, direction: str, hour: int) -> str:
tips = {
"Low": [
"Perfect time to travel! You'll likely get a seat.",
"Great window! Trains are comfortable right now.",
"Off-peak bliss β smooth, uncrowded journey ahead.",
],
"Medium": [
"Manageable crowd β you may have to stand for a while.",
"Arrive 5 mins early to board comfortably.",
"It's busy but not terrible. Avoid the first bogie.",
],
"Extreme": [
"Packed trains! If flexible, shift by 30β60 minutes.",
"Consider the Ladies' Special or next train.",
"Carry water, maintain patience β it's Mumbai rush!",
]
}
import random
opts = tips.get(crowd_level, tips["Medium"])
return opts[hour % len(opts)]
|