initial project setup with README and ignore
This commit is contained in:
78
app/services/rider/rider_history_service.py
Normal file
78
app/services/rider/rider_history_service.py
Normal file
@@ -0,0 +1,78 @@
|
||||
|
||||
import os
|
||||
import pickle
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from typing import Dict, Any
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
HISTORY_FILE = "rider_history.pkl"
|
||||
|
||||
class RiderHistoryService:
|
||||
def __init__(self, history_file: str = HISTORY_FILE):
|
||||
self.history_file = history_file
|
||||
self.history = self._load_history()
|
||||
|
||||
def _load_history(self) -> Dict[int, Dict[str, float]]:
|
||||
"""Load history from pickle file."""
|
||||
if not os.path.exists(self.history_file):
|
||||
return {}
|
||||
|
||||
try:
|
||||
with open(self.history_file, 'rb') as f:
|
||||
return pickle.load(f)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to load rider history: {e}")
|
||||
return {}
|
||||
|
||||
def _save_history(self):
|
||||
"""Save history to pickle file."""
|
||||
try:
|
||||
with open(self.history_file, 'wb') as f:
|
||||
pickle.dump(self.history, f)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to save rider history: {e}")
|
||||
|
||||
def update_rider_stats(self, rider_id: int, distance_km: float, order_count: int):
|
||||
"""Update cumulative stats for a rider."""
|
||||
rider_id = int(rider_id)
|
||||
if rider_id not in self.history:
|
||||
self.history[rider_id] = {
|
||||
"total_km": 0.0,
|
||||
"total_orders": 0,
|
||||
"last_updated": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
self.history[rider_id]["total_km"] += distance_km
|
||||
self.history[rider_id]["total_orders"] += order_count
|
||||
self.history[rider_id]["last_updated"] = datetime.now().isoformat()
|
||||
|
||||
# Auto-save on update
|
||||
self._save_history()
|
||||
|
||||
def get_rider_score(self, rider_id: int) -> float:
|
||||
"""
|
||||
Get a score representing the rider's historical 'load' (KMs).
|
||||
Higher Score = More KMs driven recently.
|
||||
"""
|
||||
rider_id = int(rider_id)
|
||||
stats = self.history.get(rider_id, {})
|
||||
return stats.get("total_km", 0.0)
|
||||
|
||||
def get_preferred_assignment_type(self, rider_id: int, all_rider_scores: Dict[int, float]) -> str:
|
||||
"""
|
||||
Determine if rider should get 'Long' or 'Short' routes based on population average.
|
||||
"""
|
||||
score = self.get_rider_score(rider_id)
|
||||
if not all_rider_scores:
|
||||
return "ANY"
|
||||
|
||||
avg_score = sum(all_rider_scores.values()) / len(all_rider_scores)
|
||||
|
||||
# If rider has driven LESS than average, prefer LONG routes (Risky)
|
||||
if score < avg_score:
|
||||
return "LONG"
|
||||
# If rider has driven MORE than average, prefer SHORT routes (Economy)
|
||||
else:
|
||||
return "SHORT"
|
||||
Reference in New Issue
Block a user