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)]