initial project setup with README and ignore
This commit is contained in:
173
run_simulation.py
Normal file
173
run_simulation.py
Normal file
@@ -0,0 +1,173 @@
|
||||
import json
|
||||
import logging
|
||||
import asyncio
|
||||
from app.services.core.assignment_service import AssignmentService
|
||||
from app.services.routing.route_optimizer import RouteOptimizer
|
||||
from app.core.arrow_utils import save_optimized_route_parquet
|
||||
|
||||
# Setup logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Load Environment Variables
|
||||
try:
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
print("✅ Loaded .env file")
|
||||
except ImportError:
|
||||
print("⚠️ python-dotenv not installed, skipping .env load")
|
||||
|
||||
async def run_simulation():
|
||||
print("🚀 Starting Logic Simulation (High Efficiency Mode + K-wMeans)...")
|
||||
|
||||
# 1. Load Orders (using route.json as source)
|
||||
try:
|
||||
with open('route.json', 'r') as f:
|
||||
route_data = json.load(f)
|
||||
except FileNotFoundError:
|
||||
print("❌ route.json not found.")
|
||||
return
|
||||
|
||||
raw_orders = route_data.get('details', [])
|
||||
# Strip assignment data to simulate fresh orders
|
||||
clean_orders = []
|
||||
for o in raw_orders:
|
||||
o_copy = o.copy()
|
||||
for key in ['userid', 'step', 'cumulativekms', 'eta']:
|
||||
o_copy.pop(key, None)
|
||||
clean_orders.append(o_copy)
|
||||
|
||||
print(f"📦 Loaded {len(clean_orders)} orders.")
|
||||
|
||||
# 2. Mock Riders
|
||||
# Using the 5 rider fleet as agreed
|
||||
rider_ids = [753, 883, 1114, 1271, 1116, 1096, 897, 950, 1272, 1133] # Full Active Riders List
|
||||
# Rider Starting Locations (Based on "Mostly Available Location")
|
||||
# Coordinates approximated for Coimbatore areas
|
||||
rider_locations = {
|
||||
1116: (11.0067, 76.9558), # VIVEK ANANDAN: RS PURAM
|
||||
1096: (11.0450, 76.9000), # NARAYANASAMY: VADAVALI
|
||||
897: (11.0430, 76.9380), # VARUN EDWARD: KAVUNDAMPALAYAM
|
||||
950: (11.0330, 76.9800), # JAYASABESH: GANAPATHY
|
||||
1114: (11.0450, 77.0000), # TAMILAZHAGAN: GANDHIMA NAGAR
|
||||
883: (11.0200, 77.0000), # RAJAN: PEELAMEDU
|
||||
1272: (10.9950, 77.0000), # MUTHURAJA: RAMANATHAPURAM
|
||||
753: (11.0000, 77.0300), # MANIKANDAN: SINGANALLUR
|
||||
1133: (11.0067, 76.9558), # THATCHINAMOORTHI: RS PURAM (Covering Kavundampalayam to Kovaipudur)
|
||||
1271: (11.0067, 76.9558) # Legacy ID for Thatchinamoorthi
|
||||
}
|
||||
|
||||
riders = []
|
||||
for i, rid in enumerate(rider_ids):
|
||||
lat, lon = rider_locations.get(rid, (11.0168, 76.9558)) # Default to Central if unknown
|
||||
riders.append({
|
||||
"userid": rid,
|
||||
"status": "idle",
|
||||
"onduty": 1,
|
||||
"latitude": str(lat),
|
||||
"longitude": str(lon)
|
||||
})
|
||||
|
||||
# 3. Run Assignment
|
||||
assignment_service = AssignmentService()
|
||||
try:
|
||||
assignments, unassigned_orders = assignment_service.assign_orders(clean_orders, riders)
|
||||
except Exception as e:
|
||||
print(f"❌ Error during assignment: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return
|
||||
|
||||
# 4. Generate Output (Mirroring API Logic)
|
||||
optimizer = RouteOptimizer()
|
||||
|
||||
output_details = []
|
||||
distribution = {}
|
||||
assigned_count = 0
|
||||
|
||||
# Prepare async tasks
|
||||
tasks = []
|
||||
task_rids = []
|
||||
|
||||
for rid, orders in assignments.items():
|
||||
if not orders: continue
|
||||
distribution[rid] = len(orders)
|
||||
assigned_count += len(orders)
|
||||
|
||||
# Optimize Route & Add Metrics (Cumulative KMS, Step, etc.)
|
||||
mock_rider = next((r for r in riders if r["userid"] == rid), None)
|
||||
start_coords = None
|
||||
if mock_rider:
|
||||
start_coords = (float(mock_rider['latitude']), float(mock_rider['longitude']))
|
||||
|
||||
tasks.append(optimizer.optimize_provider_payload(orders, start_coords=start_coords))
|
||||
task_rids.append(rid)
|
||||
|
||||
# Run tasks
|
||||
if tasks:
|
||||
results = await asyncio.gather(*tasks)
|
||||
|
||||
for rid, optimized_route in zip(task_rids, results):
|
||||
mock_rider = next((r for r in riders if r["userid"] == rid), {})
|
||||
r_name = mock_rider.get("username", "")
|
||||
r_contact = mock_rider.get("contactno", "")
|
||||
|
||||
total_kms = 0
|
||||
if optimized_route:
|
||||
try:
|
||||
total_kms = max([float(o.get("cumulativekms", 0)) for o in optimized_route])
|
||||
except:
|
||||
total_kms = sum([float(o.get("actualkms", o.get("kms", 0))) for o in optimized_route])
|
||||
|
||||
for o in optimized_route:
|
||||
o['userid'] = rid
|
||||
o['username'] = r_name
|
||||
o['rider'] = r_name
|
||||
o['ridercontactno'] = r_contact
|
||||
o['riderkms'] = str(round(total_kms, 2))
|
||||
output_details.append(o)
|
||||
|
||||
# 5. Zone Processing
|
||||
fuel_charge = 2.5
|
||||
base_pay = 30.0
|
||||
from app.services.routing.zone_service import ZoneService
|
||||
zone_service = ZoneService()
|
||||
zone_data = zone_service.group_by_zones(output_details, unassigned_orders, fuel_charge=fuel_charge, base_pay=base_pay)
|
||||
|
||||
# 6. Save output.json
|
||||
output_data = {
|
||||
"message": "Success",
|
||||
"status": True,
|
||||
"details": output_details,
|
||||
"zone_summary": zone_data["zone_analysis"],
|
||||
"zones": zone_data["detailed_zones"],
|
||||
"meta": {
|
||||
"total_orders": len(clean_orders),
|
||||
"total_riders": len(rider_ids),
|
||||
"assigned_orders": assigned_count,
|
||||
"unassigned_orders": len(unassigned_orders),
|
||||
"total_profit": round(sum(z["total_profit"] for z in zone_data["zone_analysis"]), 2),
|
||||
"unassigned_details": [
|
||||
{"id": o.get("orderid") or o.get("_id"), "reason": o.get("unassigned_reason")}
|
||||
for o in unassigned_orders
|
||||
],
|
||||
"distribution_summary": distribution
|
||||
}
|
||||
}
|
||||
|
||||
with open('output.json', 'w') as f:
|
||||
json.dump(output_data, f, indent=4)
|
||||
|
||||
# Apache Arrow / Parquet Export
|
||||
try:
|
||||
save_optimized_route_parquet(output_details, 'output.parquet')
|
||||
print("📊 Also saved results to output.parquet (Apache Arrow format)")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Could not save Parquet: {e}")
|
||||
|
||||
print("✅ Simulation Complete. Saved to output.json")
|
||||
print("📊 Distribution Summary:")
|
||||
print(json.dumps(distribution, indent=4))
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(run_simulation())
|
||||
Reference in New Issue
Block a user