File size: 6,628 Bytes
a8ba5ce c7ea7db a8ba5ce a9ae8ce a8ba5ce |
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 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
"""
Data models for Metro Train Scheduling System
Comprehensive models matching the KMRL (Kochi Metro Rail Limited) structure
"""
from pydantic import BaseModel, Field
from typing import List, Optional, Dict, Literal
from datetime import datetime, time
from enum import Enum
class TrainStatus(str, Enum):
"""Train operational status"""
REVENUE_SERVICE = "REVENUE_SERVICE"
STANDBY = "STANDBY"
MAINTENANCE = "MAINTENANCE"
CLEANING = "CLEANING"
OUT_OF_SERVICE = "OUT_OF_SERVICE"
class CertificateStatus(str, Enum):
"""Fitness certificate status"""
VALID = "VALID"
EXPIRING_SOON = "EXPIRING_SOON"
EXPIRED = "EXPIRED"
class MaintenanceType(str, Enum):
"""Types of maintenance operations"""
SCHEDULED_INSPECTION = "SCHEDULED_INSPECTION"
PREVENTIVE = "PREVENTIVE"
CORRECTIVE = "CORRECTIVE"
BREAKDOWN = "BREAKDOWN"
class Severity(str, Enum):
"""Alert severity levels"""
LOW = "LOW"
MEDIUM = "MEDIUM"
HIGH = "HIGH"
CRITICAL = "CRITICAL"
class FitnessCertificate(BaseModel):
"""Individual fitness certificate"""
valid_until: str # ISO format date
status: CertificateStatus
class FitnessCertificates(BaseModel):
"""All fitness certificates for a trainset"""
rolling_stock: FitnessCertificate
signalling: FitnessCertificate
telecom: FitnessCertificate
class JobCards(BaseModel):
"""Job cards and maintenance tasks"""
open: int
blocking: List[str] = Field(default_factory=list)
class Branding(BaseModel):
"""Advertising/branding information"""
advertiser: str
contract_hours_remaining: int
exposure_priority: Literal["NONE", "LOW", "MEDIUM", "HIGH", "CRITICAL"]
class ServiceBlock(BaseModel):
"""A service block represents a continuous operating period"""
block_id: str
departure_time: str # HH:MM format
origin: str
destination: str
trip_count: int # Number of round trips in this block
estimated_km: int
class Trainset(BaseModel):
"""Complete trainset information"""
trainset_id: str
status: TrainStatus
priority_rank: Optional[int] = None
assigned_duty: Optional[str] = None
# Service blocks for revenue service trains
service_blocks: List[ServiceBlock] = Field(default_factory=list)
# Maintenance information
maintenance_type: Optional[MaintenanceType] = None
ibl_bay: Optional[str] = None # Inspection/Berthing Location
estimated_completion: Optional[str] = None
# Cleaning information
cleaning_bay: Optional[str] = None
cleaning_type: Optional[str] = None
scheduled_service_start: Optional[str] = None
# Operational metrics
daily_km_allocation: int
cumulative_km: int
stabling_bay: Optional[str] = None
# Compliance and health
fitness_certificates: FitnessCertificates
job_cards: Optional[JobCards] = Field(default_factory=lambda: JobCards(open=0, blocking=[]))
# Branding
branding: Optional[Branding] = None
# Computed scores
readiness_score: float = Field(ge=0.0, le=1.0)
constraints_met: bool
# Alerts
alerts: List[str] = Field(default_factory=list)
standby_reason: Optional[str] = None
class FleetSummary(BaseModel):
"""Summary statistics for the entire fleet"""
total_trainsets: int
revenue_service: int
standby: int
maintenance: int
cleaning: int
availability_percent: float
class OptimizationMetrics(BaseModel):
"""Metrics about the optimization result"""
mileage_variance_coefficient: float
avg_readiness_score: float
branding_sla_compliance: float
shunting_movements_required: int
total_planned_km: int
fitness_expiry_violations: int
optimization_runtime_ms: int = 0
class Alert(BaseModel):
"""Alert or conflict in the schedule"""
trainset_id: str
severity: Severity
type: str
message: str
class DecisionRationale(BaseModel):
"""Explanation of optimization decisions"""
algorithm_version: str
objective_weights: Dict[str, float]
constraint_violations: int
optimization_runtime_ms: int
class DaySchedule(BaseModel):
"""Complete daily schedule for all trains"""
schedule_id: str
generated_at: str # ISO format with timezone
valid_from: str # ISO format
valid_until: str # ISO format
depot: str
trainsets: List[Trainset]
fleet_summary: FleetSummary
optimization_metrics: OptimizationMetrics
conflicts_and_alerts: List[Alert]
decision_rationale: DecisionRationale
class Station(BaseModel):
"""Metro station information"""
station_id: str
name: str
sequence: int # Position in the line (1-25)
distance_from_origin_km: float
avg_dwell_time_seconds: int = 30 # Average stopping time
class Route(BaseModel):
"""Single metro line route"""
route_id: str
name: str
stations: List[Station]
total_distance_km: float
avg_speed_kmh: float = 35 # Kochi Metro average operating speed: 35 km/h
turnaround_time_minutes: int = 10 # Time needed at terminals
class OperationalHours(BaseModel):
"""Service hours configuration"""
start_time: time = time(5, 0) # 5:00 AM
end_time: time = time(23, 0) # 11:00 PM
peak_hours: List[tuple] = Field(
default_factory=lambda: [
(time(7, 0), time(10, 0)), # Morning peak
(time(17, 0), time(20, 0)) # Evening peak
]
)
peak_frequency_minutes: int = 5 # Train every 5 minutes during peak
off_peak_frequency_minutes: int = 10 # Train every 10 minutes off-peak
class TrainHealthStatus(BaseModel):
"""Health status for optimization"""
trainset_id: str
is_fully_healthy: bool
available_hours: Optional[List[tuple]] = None # (start_hour, end_hour) if partial
unavailable_reason: Optional[str] = None
cumulative_mileage: int
days_since_maintenance: int
component_health: Dict[str, float] # Component: health_score (0-1)
class ScheduleRequest(BaseModel):
"""Request for schedule generation"""
date: str # YYYY-MM-DD
num_trains: int = Field(default=25, ge=15, le=40)
num_stations: int = Field(default=25, ge=10, le=50)
route_name: str = "Aluva-Pettah Line"
depot_name: str = "Muttom_Depot"
# Optional: override train health
train_health_overrides: Optional[List[TrainHealthStatus]] = None
# Optimization parameters
min_service_trains: int = 20
min_standby_trains: int = 2
max_daily_km_per_train: int = 300
balance_mileage: bool = True
prioritize_branding: bool = True
|