commit c742ef0e5395bc61fdfeb00c9b83d0ce6cc01f22 Author: Suriya Date: Mon Jun 22 17:40:08 2026 +0530 Initial commit diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..143bf4f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,58 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +*.egg-info/ +dist/ +build/ + +# Virtual environments +venv/ +env/ +ENV/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# Testing +.pytest_cache/ +.coverage +htmlcov/ + +# Documentation +*.md +!README.md + +# Environment +.env +.env.local + +# Logs +*.log + +# OS +.DS_Store +Thumbs.db + +# Git +.git/ +.gitignore + +# Docker +Dockerfile +docker-compose.yml +.dockerignore + +# Test files +test_*.py +*_test.py + +# Temporary files +*.tmp +*.bak + diff --git a/.env b/.env new file mode 100644 index 0000000..9c87aa7 --- /dev/null +++ b/.env @@ -0,0 +1,9 @@ +REDIS_PASSWORD=Package@324969# +GOOGLE_MAPS_API_KEY=AIzaSyBhkGfnq27sN0wV5y_S-M2KojpFTk_by-Q + +# nearledb (read-only source for empirical ETA — `deliveries` table only) +DB_HOST=66.116.207.225 +DB_PORT=6432 +DB_NAME=nearledb +DB_USER=admin +DB_PASSWORD=Package@123# \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3e3f603 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +# syntax=docker/dockerfile:1 +FROM python:3.11-slim + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + PIP_NO_CACHE_DIR=1 + +WORKDIR /app + +# Install dependencies first +COPY requirements.txt ./ +RUN pip install --upgrade pip \ + && pip install -r requirements.txt + +# Copy application code +COPY app ./app +COPY start.py ./start.py +COPY docker-entrypoint.sh ./docker-entrypoint.sh + +# Make entrypoint executable +RUN chmod +x docker-entrypoint.sh + +EXPOSE 8002 + +ENTRYPOINT ["./docker-entrypoint.sh"] diff --git a/Untitled (2) b/Untitled (2) new file mode 100644 index 0000000..34f401c --- /dev/null +++ b/Untitled (2) @@ -0,0 +1,2213 @@ +{ + "deliveries": [ + { + "orderheaderid": 140343, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109248", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "7", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Akash R", + "deliverycontactno": "9952272119", + "deliverylocationid": 0, + "deliveryaddress": "T.Stanes & Company Racecourse ", + "deliverysuburb": "", + "droplat": "10.9993822294134", + "droplon": "76.9812935889748", + "deliverylat": "10.9993822294134", + "deliverylong": "76.9812935889748", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 1, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140342, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109247", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "2", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Pooja", + "deliverycontactno": "9080859196", + "deliverylocationid": 0, + "deliveryaddress": "C1 castle park apartment, Ramanujam Nagar, Uppilipalayam C1- 3rd floor", + "deliverysuburb": "", + "droplat": "11.0193379075467", + "droplon": "77.0241522499801", + "deliverylat": "11.0193379075467", + "deliverylong": "77.0241522499801", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 2, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140341, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109246", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "7", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Kannammal", + "deliverycontactno": "8884366950", + "deliverylocationid": 0, + "deliveryaddress": "47 Ambika Layout, New Siddhapudur Opp to Kaleeswari Broiler", + "deliverysuburb": "", + "droplat": "11.0196258620096", + "droplon": "76.9729109577317", + "deliverylat": "11.0196258620096", + "deliverylong": "76.9729109577317", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 2, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 3, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140340, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109245", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "0", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Ajithkumar", + "deliverycontactno": "8825867517", + "deliverylocationid": 0, + "deliveryaddress": "Dream life education near psg hospital", + "deliverysuburb": "", + "droplat": "11.0164322", + "droplon": "77.0117072", + "deliverylat": "11.0164322", + "deliverylong": "77.0117072", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 4, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140339, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109244", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "6", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "SUDARSHAN", + "deliverycontactno": "9629274613", + "deliverylocationid": 0, + "deliveryaddress": "60, vaanagam road , venugopal layout , pappanaickenpalayam,coimbatore. Street last ", + "deliverysuburb": "", + "droplat": "11.0155", + "droplon": "76.9859", + "deliverylat": "11.0155", + "deliverylong": "76.9859", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 5, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140338, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109243", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Vasu dharani", + "deliverycontactno": "9042730736", + "deliverylocationid": 0, + "deliveryaddress": "Royal stitch, no.26 , Srinagar, hope college Royal stitch ", + "deliverysuburb": "", + "droplat": "11.0251802", + "droplon": "77.0198024", + "deliverylat": "11.0251802", + "deliverylong": "77.0198024", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 6, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140337, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109242", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Hema Priya Thangavel", + "deliverycontactno": "9176642609", + "deliverylocationid": 0, + "deliveryaddress": "6A, Thulak venkatasamy street, peelamedu , coimbatore 641004 Kurinji womens hostel branch 2 ", + "deliverysuburb": "", + "droplat": "11.025724104948", + "droplon": "77.0012132420476", + "deliverylat": "11.025724104948", + "deliverylong": "77.0012132420476", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 7, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140336, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109241", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "6", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Siri", + "deliverycontactno": "9573535434", + "deliverylocationid": 0, + "deliveryaddress": "C Block, GKNM hospital Gknm Hospital ", + "deliverysuburb": "", + "droplat": "11.0127622894822", + "droplon": "76.9808842310513", + "deliverylat": "11.0127622894822", + "deliverylong": "76.9808842310513", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 8, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140335, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109240", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Sudharsan", + "deliverycontactno": "9894958802", + "deliverylocationid": 0, + "deliveryaddress": "9-7, TNHB Housing Unit, Singanallur, Tamil Nadu 641005, India 18/21, RVL Colony West, Uppilipalayam Post, Coimbatore, Tamil Nadu 641015", + "deliverysuburb": "", + "droplat": "11.0015976", + "droplon": "77.0272937", + "deliverylat": "11.0015976", + "deliverylong": "77.0272937", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 9, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140334, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109239", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "5", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Anusha", + "deliverycontactno": "8925177754", + "deliverylocationid": 0, + "deliveryaddress": "3rd Floor, Haritha Centre, Avinashi Road, Opp to GKNM IOP, COimbatore Sony Centre Building", + "deliverysuburb": "", + "droplat": "11.0115588", + "droplon": "76.9846643", + "deliverylat": "11.0115588", + "deliverylong": "76.9846643", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 10, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140333, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109238", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "8", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "SARAVANAKUMAR N", + "deliverycontactno": "9994814524", + "deliverylocationid": 0, + "deliveryaddress": "THE COIMBATORE DISTRICT CENTRAL CO OPERATIVE BANK LTD, NO 80 BANK ROAD, OPPOSITE TO RAILWAY JUNCTION, COIMBATORE 641018 Opposite to railway junction ", + "deliverysuburb": "", + "droplat": "10.9958286717655", + "droplon": "76.9683176087512", + "deliverylat": "10.9958286717655", + "deliverylong": "76.9683176087512", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 11, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140332, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109237", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Kavitha", + "deliverycontactno": "9786404664", + "deliverylocationid": 0, + "deliveryaddress": "24 chellandiamman kovil street singanalur 25 Near chellandiamman temple", + "deliverysuburb": "", + "droplat": "10.998805", + "droplon": "77.0309321", + "deliverylat": "10.998805", + "deliverylong": "77.0309321", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 12, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140331, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109236", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Hello Sivi", + "deliverycontactno": "8008984800", + "deliverylocationid": 0, + "deliveryaddress": "Hello Sivi Software Labs,, Hindustan College Road, Nava India Nava India", + "deliverysuburb": "", + "droplat": "11.0132268", + "droplon": "76.9954829", + "deliverylat": "11.0132268", + "deliverylong": "76.9954829", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 13, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140330, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109235", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "5", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Jayabalan", + "deliverycontactno": "9942632926", + "deliverylocationid": 0, + "deliveryaddress": "383 Trichy road singanallur Coimbatore - 641005 Raja weigh bridge ", + "deliverysuburb": "", + "droplat": "11.0016806", + "droplon": "77.0367664", + "deliverylat": "11.0016806", + "deliverylong": "77.0367664", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 2, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 14, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140329, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109234", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Devapriyan", + "deliverycontactno": "9566569717", + "deliverylocationid": 0, + "deliveryaddress": "Udayampalayam Main Rd, Nava India Rd, Coimbatore, Tamil Nadu 641028 hanudev Techpark", + "deliverysuburb": "", + "droplat": "11.0190788982762", + "droplon": "76.9955501754631", + "deliverylat": "11.0190788982762", + "deliverylong": "76.9955501754631", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 15, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140328, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109233", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Sharumathi", + "deliverycontactno": "8220731236", + "deliverylocationid": 0, + "deliveryaddress": "Geojit financial services No. 496, A7, Grand CAG Central, Nava India, Avinashi road, CBE - 641004 behind Tata motors", + "deliverysuburb": "", + "droplat": "11.0174053", + "droplon": "76.991556", + "deliverylat": "11.0174053", + "deliverylong": "76.991556", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 16, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140327, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109232", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "2", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "CHITHRA R", + "deliverycontactno": "9791225952", + "deliverylocationid": 0, + "deliveryaddress": "Vistara Homes Flat No A1 First Floor, Varadharajapuram main road, G.V.Residency, Uppilipalayam. Coimbatore - 641015 Near Parson Apartment", + "deliverysuburb": "", + "droplat": "11.0097457", + "droplon": "77.0193997", + "deliverylat": "11.0097457", + "deliverylong": "77.0193997", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 17, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140326, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109231", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Lokesh Lakshmanan", + "deliverycontactno": "9741506425", + "deliverylocationid": 0, + "deliveryaddress": "The Focus Room 272, Mariamman Koil St, B Colony, Peelamedu Pudur, Masakalipalayam, Coimbatore, Tamil Nadu 641004 Inside road of Bharath petroleum ", + "deliverysuburb": "", + "droplat": "11.0205886775241", + "droplon": "76.9986305528885", + "deliverylat": "11.0205886775241", + "deliverylong": "76.9986305528885", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 18, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140325, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109230", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Rajesh", + "deliverycontactno": "9677386936", + "deliverylocationid": 0, + "deliveryaddress": " Avinashi Rd, Peelamedu, PKD Nagar, Coimbatore, Tamil Nadu 641004 Spaceone , third floor, petrocon engineers and consultants", + "deliverysuburb": "", + "droplat": "11.0252277", + "droplon": "77.0136989", + "deliverylat": "11.0252277", + "deliverylong": "77.0136989", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 19, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140324, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109229", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "2", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Dr Jeevananth S", + "deliverycontactno": "9095344692", + "deliverylocationid": 0, + "deliveryaddress": "A-33 , 5 th floor , RR krish apartment, GV residency RR krish apartment ", + "deliverysuburb": "", + "droplat": "11.0112030667755", + "droplon": "77.0190787864115", + "deliverylat": "11.0112030667755", + "deliverylong": "77.0190787864115", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 20, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140323, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109228", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "5", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Kuzhali tamizhiniyal", + "deliverycontactno": "9363035754", + "deliverylocationid": 0, + "deliveryaddress": "CMS, discover workspace,COSMAFAN Foundry Owners Association Hem Garden Road Off, Avinashi Rd, Peelamedu Tamil Nadu 641004 India opp road to sri ramakrishna dental college", + "deliverysuburb": "", + "droplat": "11.0201361298055", + "droplon": "76.98878683125", + "deliverylat": "11.0201361298055", + "deliverylong": "76.98878683125", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 2, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 21, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140322, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109227", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "2", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Sarath", + "deliverycontactno": "8940076989", + "deliverylocationid": 0, + "deliveryaddress": "Gen Y Cafe Call", + "deliverysuburb": "", + "droplat": "11.021752569061", + "droplon": "77.0254992711639", + "deliverylat": "11.021752569061", + "deliverylong": "77.0254992711639", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 22, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 140321, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024109226", + "orderdate": "2026-06-09T11:35:20+05:30", + "deliverydate": "2026-06-09 06:30:00", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-06-09 12:03:44", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-06-09 12:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Akkshara Baskaran", + "deliverycontactno": "9585514072", + "deliverylocationid": 0, + "deliveryaddress": "M/S Yatra travels #117 PKD Nagar 2nd Street Peelamedu Coimbatore 641004 Sakthi ladies hostel on the 2nd street pkd nagar ", + "deliverysuburb": "", + "droplat": "11.0272621741239", + "droplon": "77.0147930111887", + "deliverylat": "11.0272621741239", + "deliverylong": "77.0147930111887", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 23, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + } + ], + "absent_riders": [] +} \ No newline at end of file diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..f69fe75 --- /dev/null +++ b/app/__init__.py @@ -0,0 +1 @@ +# Delivery Route Optimization API diff --git a/app/__pycache__/__init__.cpython-312.pyc b/app/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..785dad0 Binary files /dev/null and b/app/__pycache__/__init__.cpython-312.pyc differ diff --git a/app/__pycache__/main.cpython-312.pyc b/app/__pycache__/main.cpython-312.pyc new file mode 100644 index 0000000..75c5542 Binary files /dev/null and b/app/__pycache__/main.cpython-312.pyc differ diff --git a/app/config/__init__.py b/app/config/__init__.py new file mode 100644 index 0000000..8ee06a4 --- /dev/null +++ b/app/config/__init__.py @@ -0,0 +1 @@ +"""Configuration package for mobile delivery optimization.""" diff --git a/app/config/__pycache__/__init__.cpython-312.pyc b/app/config/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..8627442 Binary files /dev/null and b/app/config/__pycache__/__init__.cpython-312.pyc differ diff --git a/app/config/__pycache__/dynamic_config.cpython-312.pyc b/app/config/__pycache__/dynamic_config.cpython-312.pyc new file mode 100644 index 0000000..4aa0b5a Binary files /dev/null and b/app/config/__pycache__/dynamic_config.cpython-312.pyc differ diff --git a/app/config/__pycache__/rider_preferences.cpython-312.pyc b/app/config/__pycache__/rider_preferences.cpython-312.pyc new file mode 100644 index 0000000..44caa11 Binary files /dev/null and b/app/config/__pycache__/rider_preferences.cpython-312.pyc differ diff --git a/app/config/dynamic_config.py b/app/config/dynamic_config.py new file mode 100644 index 0000000..08569aa --- /dev/null +++ b/app/config/dynamic_config.py @@ -0,0 +1,408 @@ +""" +Dynamic Configuration - rider-api + +Replaces all hardcoded hyperparameters with DB-backed values. +The ML hypertuner writes optimal values here; services read from here. + +Fallback: If DB is unavailable or no tuned values exist, defaults are used. +This means zero risk - the system works day 1 with no data. +""" + +import contextvars +import json +import logging +import os +import sqlite3 +from datetime import datetime +from typing import Any, Dict, Optional + +logger = logging.getLogger(__name__) + +# --- DB Path ------------------------------------------------------------------ +_DB_PATH = os.getenv("ML_DB_PATH", "ml_data/ml_store.db") + +# --------------------------------------------------------------------------- +# Per-request strategy override (async-safe via contextvars). +# Each FastAPI request/asyncio task gets its own copy — no cross-request leaks. +# Usage: +# set_request_strategy("fuel_saver") → override active for this request +# clear_request_strategy() → restore to DB value +# --------------------------------------------------------------------------- +_strategy_override: contextvars.ContextVar[Optional[str]] = contextvars.ContextVar( + "strategy_override", default=None +) + + +def set_request_strategy(strategy: Optional[str]) -> None: + """Override ml_strategy for the current async task only (thread-safe).""" + _strategy_override.set(strategy) + + +def clear_request_strategy() -> None: + """Remove the per-request strategy override for the current async task.""" + _strategy_override.set(None) + + +# --- Hard Defaults (What the system used before ML) --------------------------- +DEFAULTS: Dict[str, Any] = { + # System Strategy / Prompt + "ml_strategy": "balanced", + # AssignmentService + "max_pickup_distance_km": 10.0, + "max_kitchen_distance_km": 3.0, + "max_orders_per_rider": 12, + "ideal_load": 6, + "workload_balance_threshold": 0.7, + "workload_penalty_weight": 100.0, + "distance_penalty_weight": 2.0, + "preference_bonus": -15.0, + "home_zone_bonus_4km": -3.0, + "home_zone_bonus_2km": -5.0, + "emergency_load_penalty": 3.0, # km penalty per order in emergency assign + # RouteOptimizer + "search_time_limit_seconds": 5, + "avg_speed_kmh": 18.0, + "road_factor": 1.3, + # ClusteringService + "cluster_radius_km": 3.0, + # KalmanFilter + "kalman_process_noise": 1e-4, + "kalman_measurement_noise": 0.01, + # RealisticETACalculator + "eta_pickup_time_min": 3.0, + "eta_delivery_time_min": 4.0, + "eta_navigation_buffer_min": 1.5, + "eta_short_trip_factor": 0.8, # speed multiplier for dist < 2km + "eta_long_trip_factor": 1.1, # speed multiplier for dist > 8km + # EmpiricalETACalculator (learned ETAs from actual delivery times) + "eta_empirical_enabled": True, # False -> instantly revert to the formula + "eta_min_samples": 10, # min history samples a key needs before trust + # (backtest on live 14d data: 10 -> MAE 4.85 vs + # formula 5.73; 20 -> 5.64. 10 wins on held-out.) + "eta_history_days": 14, # rolling window pulled from nearledb + "eta_stat": "median", # "median" or "p75" (p75 = more conservative) + "eta_sync_interval_hours": 6, # autonomous background sync cadence + # Road-aware sequencing (Phase 2). OFF by default: enabling adds a Google + # Directions call (cost + latency) to the route hot path. Results are cached. + # Only the *visiting order* changes; step/ETA metrics stay aerial-based. + "routing_use_road_distance": False, # AGENT-MANAGED (see routing_auto_manage) + "routing_road_cache_ttl_seconds": 86400, # road geometry is stable; cache 24h + "routing_road_max_stops": 25, # Google distance-matrix practical cap + # Autonomous road-sequencing decision agent: measures road-vs-aerial travel + # time on real batches and flips routing_use_road_distance on its own. + "routing_auto_manage": True, # False -> humans own the flag + "routing_auto_enable_gain_pct": 3.0, # enable when mean gain >= this + "routing_auto_disable_gain_pct": 1.0, # disable when mean gain < this (hysteresis) + "routing_eval_sample_batches": 8, # batches measured per cycle (cost bound) + "routing_eval_min_batches": 3, # need >= this evaluated to decide + "routing_eval_interval_hours": 24, # decision cadence + "routing_eval_days": 14, # window sampled from the local mirror + # Learned rider->kitchen affinity (soft steering only; union with curated config). + "rider_affinity_enabled": True, # False -> pure curated config + "rider_affinity_min_deliveries": 10, # learned owner needs >= this many deliveries + "rider_affinity_refresh_hours": 6, # recompute cadence (piggybacks the agent) +} + + +class DynamicConfig: + """ + Thread-safe, DB-backed configuration store. + + Usage: + cfg = DynamicConfig() + max_dist = cfg.get("max_pickup_distance_km") + all_params = cfg.get_all() + """ + + _instance: Optional["DynamicConfig"] = None + + def __new__(cls) -> "DynamicConfig": + """Singleton - one config per process.""" + if cls._instance is None: + cls._instance = super().__new__(cls) + cls._instance._initialized = False + return cls._instance + + def __init__(self): + if self._initialized: + return + self._initialized = True + self._cache: Dict[str, Any] = {} + self._last_loaded: Optional[datetime] = None + self._ensure_db() + self._load() + + # -------------------------------------------------------------------------- + # Public API + # -------------------------------------------------------------------------- + + def get(self, key: str, default: Any = None) -> Any: + """Get a config value. Returns ML-tuned value if available, else default. + + For 'ml_strategy' specifically, a per-request ContextVar override takes + precedence so that hypertuning_params requests don't mutate the shared + singleton (thread-safe for concurrent FastAPI requests). + """ + self._maybe_reload() + # Per-request strategy override (async-safe, no cross-request leaks) + if key == "ml_strategy": + override = _strategy_override.get() + if override is not None: + return override + val = self._cache.get(key) + if val is not None: + return val + fallback = default if default is not None else DEFAULTS.get(key) + return fallback + + def get_all(self) -> Dict[str, Any]: + """Return all current config values (ML-tuned + defaults for missing keys).""" + self._maybe_reload() + result = dict(DEFAULTS) + result.update(self._cache) + return result + + def set(self, key: str, value: Any, source: str = "manual") -> None: + """Write a config value to DB (used by hypertuner).""" + try: + os.makedirs(os.path.dirname(_DB_PATH) or ".", exist_ok=True) + conn = sqlite3.connect(_DB_PATH) + conn.execute( + """ + INSERT INTO dynamic_config (key, value, source, updated_at) + VALUES (?, ?, ?, ?) + ON CONFLICT(key) DO UPDATE SET + value=excluded.value, + source=excluded.source, + updated_at=excluded.updated_at + """, + (key, json.dumps(value), source, datetime.utcnow().isoformat()), + ) + conn.commit() + conn.close() + self._cache[key] = value + logger.info(f"[DynamicConfig] Set {key}={value} (source={source})") + except Exception as e: + logger.error(f"[DynamicConfig] Failed to set {key}: {e}") + + def set_bulk(self, params: Dict[str, Any], source: str = "ml_hypertuner") -> None: + """Write multiple config values at once (called after each Optuna study).""" + for key, value in params.items(): + self.set(key, value, source=source) + logger.info(f"[DynamicConfig] Bulk update: {len(params)} params from {source}") + + def reset_to_defaults(self) -> None: + """Wipe all ML-tuned values, revert to hardcoded defaults.""" + try: + conn = sqlite3.connect(_DB_PATH) + conn.execute("DELETE FROM dynamic_config") + conn.commit() + conn.close() + self._cache.clear() + logger.warning("[DynamicConfig] Reset to factory defaults.") + except Exception as e: + logger.error(f"[DynamicConfig] Reset failed: {e}") + + # -------------------------------------------------------------------------- + # Internal + # -------------------------------------------------------------------------- + + def _ensure_db(self) -> None: + try: + os.makedirs(os.path.dirname(_DB_PATH) or ".", exist_ok=True) + conn = sqlite3.connect(_DB_PATH) + conn.execute(""" + CREATE TABLE IF NOT EXISTS dynamic_config ( + key TEXT PRIMARY KEY, + value TEXT NOT NULL, + source TEXT DEFAULT 'manual', + updated_at TEXT + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS kitchen_encoding ( + kitchen_name TEXT PRIMARY KEY, + label_id INTEGER NOT NULL, + frequency REAL DEFAULT 0.0, + avg_profit REAL DEFAULT 0.0, + order_count INTEGER DEFAULT 0, + updated_at TEXT + ) + """) + conn.commit() + conn.close() + except Exception as e: + logger.error(f"[DynamicConfig] DB init failed: {e}") + + def _load(self) -> None: + try: + conn = sqlite3.connect(_DB_PATH) + rows = conn.execute("SELECT key, value FROM dynamic_config").fetchall() + conn.close() + self._cache = {} + for key, raw in rows: + try: + self._cache[key] = json.loads(raw) + except Exception: + self._cache[key] = raw + self._last_loaded = datetime.utcnow() + if self._cache: + logger.info( + f"[DynamicConfig] Loaded {len(self._cache)} ML-tuned params from DB" + ) + except Exception as e: + logger.warning( + f"[DynamicConfig] Could not load from DB (using defaults): {e}" + ) + self._cache = {} + + def _maybe_reload(self, interval_seconds: int = 300) -> None: + """Reload from DB every 5 minutes - picks up new tuned params without restart.""" + if self._last_loaded is None: + self._load() + return + delta = (datetime.utcnow() - self._last_loaded).total_seconds() + if delta > interval_seconds: + self._load() + + +# --- Module-level convenience singleton --------------------------------------- +_cfg = DynamicConfig() + + +def get_config() -> DynamicConfig: + """Get the global DynamicConfig singleton.""" + return _cfg + + +__all__ = [ + "DynamicConfig", + "get_config", + "set_request_strategy", + "clear_request_strategy", + "get_kitchen_label_id", + "get_kitchen_frequency", + "update_kitchen_stats", + "get_kitchen_avg_profit_smoothed", +] + + +# --- Kitchen Encoding Persistence --------------------------------------------- +def get_kitchen_label_id(kitchen_name: str) -> int: + """Get or create persistent label ID for a kitchen.""" + try: + conn = sqlite3.connect(_DB_PATH) + row = conn.execute( + "SELECT label_id FROM kitchen_encoding WHERE kitchen_name = ?", + (kitchen_name,), + ).fetchone() + if row: + conn.close() + return row[0] + + max_id = conn.execute( + "SELECT COALESCE(MAX(label_id), -1) FROM kitchen_encoding" + ).fetchone()[0] + new_id = max_id + 1 + conn.close() + return new_id + except Exception as e: + logger.warning(f"[KitchenEncoding] Failed to get label_id: {e}") + return hash(kitchen_name.lower().strip()) % 10000 + + +def get_kitchen_frequency(kitchen_name: str) -> float: + """Get frequency ratio for a kitchen from DB.""" + try: + conn = sqlite3.connect(_DB_PATH) + row = conn.execute( + "SELECT frequency FROM kitchen_encoding WHERE kitchen_name = ?", + (kitchen_name,), + ).fetchone() + conn.close() + return row[0] if row else 0.0 + except Exception: + return 0.0 + + +def update_kitchen_stats(kitchen_name: str, profit: float): + """Update kitchen stats after order completion.""" + try: + conn = sqlite3.connect(_DB_PATH) + row = conn.execute( + "SELECT order_count, avg_profit FROM kitchen_encoding WHERE kitchen_name = ?", + (kitchen_name,), + ).fetchone() + + if row: + count, avg = row + new_count = count + 1 + new_avg = ((avg * count) + profit) / new_count + new_freq = new_count / ( + conn.execute( + "SELECT SUM(order_count) FROM kitchen_encoding" + ).fetchone()[0] + or 1 + ) + conn.execute( + "UPDATE kitchen_encoding SET order_count = ?, avg_profit = ?, frequency = ?, updated_at = ? WHERE kitchen_name = ?", + ( + new_count, + new_avg, + new_freq, + datetime.utcnow().isoformat(), + kitchen_name, + ), + ) + else: + conn.execute( + "INSERT INTO kitchen_encoding (kitchen_name, label_id, frequency, avg_profit, order_count, updated_at) VALUES (?, ?, ?, ?, ?, ?)", + ( + kitchen_name, + get_kitchen_label_id(kitchen_name), + 1.0, + profit, + 1, + datetime.utcnow().isoformat(), + ), + ) + conn.commit() + conn.close() + except Exception as e: + logger.warning(f"[KitchenEncoding] Failed to update stats: {e}") + + +def get_kitchen_avg_profit_smoothed( + kitchen_name: str, global_avg: float = 40.0, min_samples: int = 5 +) -> float: + """ + Get smoothed average profit for a kitchen using Bayesian smoothing. + Reduces noise for kitchens with few orders. + + Formula: smoothed = (kitchen_count * kitchen_avg + min_samples * global_avg) / (kitchen_count + min_samples) + + This means: + - Kitchen with many samples -> uses its own avg + - Kitchen with few samples -> pulls toward global avg + """ + try: + conn = sqlite3.connect(_DB_PATH) + row = conn.execute( + "SELECT order_count, avg_profit FROM kitchen_encoding WHERE kitchen_name = ?", + (kitchen_name,), + ).fetchone() + conn.close() + + if row and row[0] > 0: + count, avg = row + if count >= min_samples: + return avg + # Bayesian smoothing + smoothed = ((count * avg) + (min_samples * global_avg)) / ( + count + min_samples + ) + return smoothed + + return global_avg # Unknown kitchen defaults to global avg + except Exception: + return global_avg diff --git a/app/config/mobile_config.py b/app/config/mobile_config.py new file mode 100644 index 0000000..5381c15 --- /dev/null +++ b/app/config/mobile_config.py @@ -0,0 +1,33 @@ +"""Mobile-specific configuration for delivery route optimization.""" + +# Mobile optimization settings +MOBILE_CONFIG = { + "default_algorithm": "greedy", + "max_deliveries": 100, + "timeout_seconds": 5, + "response_compression": True, + "performance_monitoring": True, + "mobile_headers": True +} + +# Performance targets for mobile +PERFORMANCE_TARGETS = { + "greedy_algorithm": { + "max_response_time": 0.1, # 100ms + "max_deliveries": 50, + "description": "Ultra-fast for real-time mobile apps" + }, + "tsp_algorithm": { + "max_response_time": 3.0, # 3 seconds + "max_deliveries": 30, + "description": "Optimal but slower, good for planning" + } +} + +# Mobile app recommendations +MOBILE_RECOMMENDATIONS = { + "real_time_delivery": "greedy", + "route_planning": "tsp", + "large_batches": "greedy", + "cost_optimization": "tsp" +} diff --git a/app/config/rider_preferences.py b/app/config/rider_preferences.py new file mode 100644 index 0000000..0219ce0 --- /dev/null +++ b/app/config/rider_preferences.py @@ -0,0 +1,51 @@ +""" +Rider Preferred Kitchens Configuration +Mapping of Rider ID (int) to list of preferred Kitchen names (str). +Updated based on Deployment Plan. +""" + +RIDER_PREFERRED_KITCHENS = { + # 1. VIGNESH - RS PURAM, TOWNHALL, PODANUR, KUNIAMUTHUR + 1036: ["Bhuvaneshwari kitchen"], + + # 2. VARUN EDWARD - KAVUNDAMPALAYAM, THUDIYALUR + 897: ["Daily grubs(jayanthi kitchen)"], + + # 3. JAYASABESH - GANAPATHY, SARAVANAMPATTI + 950: ["Daily grubs nandhini"], + + # 4. TAMILAZHAGAN - GANDHIMA NAGAR, NEHRU NAGAR, SITRA + 1114: ["Daily grubs nandhini"], + + # 5. RAJAN - PEELAMEDU, P N PALAYAM + 883: ["Daily grubs nandhini", "Vidhya kitchen"], + + # 6. MANIKANDAN - SINGANALLUR + 753: ["Vidhya kitchen"], + + # 7. NAGALAKSHMI - SAIBABA COLONY, R S PURAM, GANDHIPURAM + 1062: ["Daily grubs(jayanthi kitchen)"], + + # 8. MURALI - RAMANATHAPURAM, PODANUR, RACE COURSE + 1111: ["Vidhya kitchen"], +} + +# --------------------------------------------------------------------------- +# Blocked / test rider IDs — SINGLE source of truth. +# Import this set wherever blocked-rider filtering is needed instead of +# hard-coding the list in multiple files. +# --------------------------------------------------------------------------- +BLOCKED_RIDERS: frozenset = frozenset({1242, 1266, 1245, 1232, 1240, 1007}) + +# Anchor Coordinates for Riders (Based on Area Name) +# Used as fallback if GPS is missing, or to bias assignment to their Home Zone. +RIDER_HOME_LOCATIONS = { + 1036: (11.0067, 76.9558), # VIGNESH: RS PURAM, TOWNHALL, PODANUR, KUNIAMUTHUR + 897: (11.0430, 76.9380), # VARUN EDWARD: KAVUNDAMPALAYAM, THUDIYALUR + 950: (11.0330, 76.9800), # JAYASABESH: GANAPATHY, SARAVANAMPATTI + 1114: (11.0450, 77.0000), # TAMILAZHAGAN: GANDHIMA NAGAR, NEHRU NAGAR, SITRA + 883: (11.0200, 77.0000), # RAJAN: PEELAMEDU, P N PALAYAM + 753: (11.0000, 77.0300), # MANIKANDAN: SINGANALLUR + 1062: (11.0250, 76.9450), # NAGALAKSHMI: SAIBABA COLONY, R S PURAM, GANDHIPURAM + 1111: (10.9950, 77.0000), # MURALI: RAMANATHAPURAM, PODANUR, RACE COURSE +} diff --git a/app/controllers/__init__.py b/app/controllers/__init__.py new file mode 100644 index 0000000..48a50e1 --- /dev/null +++ b/app/controllers/__init__.py @@ -0,0 +1,5 @@ +"""Controllers package.""" + +from .route_controller import RouteController + +__all__ = ["RouteController"] diff --git a/app/controllers/__pycache__/__init__.cpython-312.pyc b/app/controllers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..7722358 Binary files /dev/null and b/app/controllers/__pycache__/__init__.cpython-312.pyc differ diff --git a/app/controllers/__pycache__/route_controller.cpython-312.pyc b/app/controllers/__pycache__/route_controller.cpython-312.pyc new file mode 100644 index 0000000..2fab056 Binary files /dev/null and b/app/controllers/__pycache__/route_controller.cpython-312.pyc differ diff --git a/app/controllers/route_controller.py b/app/controllers/route_controller.py new file mode 100644 index 0000000..47cb541 --- /dev/null +++ b/app/controllers/route_controller.py @@ -0,0 +1,104 @@ +"""Controller for provider payload optimization and forwarding.""" + +import logging +import hashlib +import json +from typing import Dict, Any +import httpx +from fastapi import HTTPException + +from app.core.exceptions import ValidationError, APIException +from app.services.routing.route_optimizer import RouteOptimizer +from app.services import cache + +logger = logging.getLogger(__name__) + + +class RouteController: + """Controller for optimizing provider payloads and forwarding upstream.""" + + def __init__(self): + self.route_optimizer = RouteOptimizer() + + def _hash_key(self, prefix: str, payload: Dict[str, Any]) -> str: + """Create a stable cache key from a dict payload.""" + # ensure deterministic json by sorting keys + serialized = json.dumps(payload, sort_keys=True, separators=(",", ":")) + digest = hashlib.sha256(serialized.encode("utf-8")).hexdigest() + return f"routes:{prefix}:{digest}" + + async def optimize_and_forward_provider_payload(self, orders: list[dict], forward_url: str) -> dict: + """Optimize provider payload and return it (forwarding paused). + + - Input: list of provider orders (dicts) + - Output: {code, details, message, status} where details is the optimized array + """ + try: + if not isinstance(orders, list) or not orders: + raise ValidationError("Orders array is required", field="body") + + # Create a cache key from the orders payload + cache_key = self._hash_key("provider_payload", {"orders": orders}) + + # Check cache + cached_result = cache.get_json(cache_key) + if cached_result: + logger.info(f"Cache hit for key: {cache_key}") + return cached_result + + optimized = await self.route_optimizer.optimize_provider_payload(orders) + + # Debug sample of optimized payload (first 3 items, select keys) + try: + sample = [ + { + k: item.get(k) + for k in ("orderheaderid", "orderid", "deliverycustomerid", "step", "previouskms", "cumulativekms", "eta") + } + for item in optimized[:3] + ] + logger.debug(f"Optimized payload sample: {sample}") + trace = [ + { + "orderid": item.get("orderid"), + "step": item.get("step"), + "prev": item.get("previouskms"), + "cum": item.get("cumulativekms"), + } + for item in optimized + ] + logger.debug(f"Optimized order trace: {trace}") + except Exception: + logger.debug("Optimized payload sample logging failed") + + # Forwarding paused: return optimized payload directly + result = { + "code": 200, + "details": optimized, + "message": "Success", + "status": True, + } + + # Store in cache + try: + cache.set_json(cache_key, result) + except Exception as e: + logger.warning(f"Failed to cache optimization result: {e}") + + return result + except ValidationError: + raise + except httpx.HTTPStatusError as e: + status_code = e.response.status_code + body_text = e.response.text + logger.error(f"Forwarding failed: {status_code} - {body_text}") + # Surface upstream details to the client for faster debugging + raise APIException( + status_code=502, + message=f"Upstream service error (status {status_code}): {body_text}", + code="UPSTREAM_ERROR" + ) + except Exception as e: + logger.error(f"Error optimizing/forwarding provider payload: {e}", exc_info=True) + raise APIException(status_code=500, message="Internal server error", code="INTERNAL_ERROR") +# Batch routes removed - use single-route optimization for each pickup location \ No newline at end of file diff --git a/app/core/__init__.py b/app/core/__init__.py new file mode 100644 index 0000000..863f2cc --- /dev/null +++ b/app/core/__init__.py @@ -0,0 +1,2 @@ +"""Core application components.""" + diff --git a/app/core/__pycache__/__init__.cpython-312.pyc b/app/core/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..33240e4 Binary files /dev/null and b/app/core/__pycache__/__init__.cpython-312.pyc differ diff --git a/app/core/__pycache__/arrow_utils.cpython-312.pyc b/app/core/__pycache__/arrow_utils.cpython-312.pyc new file mode 100644 index 0000000..18e0c82 Binary files /dev/null and b/app/core/__pycache__/arrow_utils.cpython-312.pyc differ diff --git a/app/core/__pycache__/exception_handlers.cpython-312.pyc b/app/core/__pycache__/exception_handlers.cpython-312.pyc new file mode 100644 index 0000000..5734f6d Binary files /dev/null and b/app/core/__pycache__/exception_handlers.cpython-312.pyc differ diff --git a/app/core/__pycache__/exceptions.cpython-312.pyc b/app/core/__pycache__/exceptions.cpython-312.pyc new file mode 100644 index 0000000..9dbd416 Binary files /dev/null and b/app/core/__pycache__/exceptions.cpython-312.pyc differ diff --git a/app/core/__pycache__/log_context.cpython-312.pyc b/app/core/__pycache__/log_context.cpython-312.pyc new file mode 100644 index 0000000..9601f0d Binary files /dev/null and b/app/core/__pycache__/log_context.cpython-312.pyc differ diff --git a/app/core/arrow_utils.py b/app/core/arrow_utils.py new file mode 100644 index 0000000..738c081 --- /dev/null +++ b/app/core/arrow_utils.py @@ -0,0 +1,63 @@ +""" +High-performance utilities using Apache Arrow and NumPy for geographic data. +Provides vectorized operations for distances and coordinate processing. +""" + +import numpy as np +import pyarrow as pa +import pyarrow.parquet as pq +import logging +from typing import List, Dict, Any, Tuple + +logger = logging.getLogger(__name__) + +def calculate_haversine_matrix_vectorized(lats: np.ndarray, lons: np.ndarray) -> np.ndarray: + """ + Calculate an N x N distance matrix using the Haversine formula. + Fully vectorized using NumPy for O(N^2) speed improvement over Python loops. + """ + # Earth's radius in kilometers + R = 6371.0 + + # Convert degrees to radians + lats_rad = np.radians(lats) + lons_rad = np.radians(lons) + + # Create meshgrids for pairwise differences + # lats.reshape(-1, 1) creates a column vector + # lats.reshape(1, -1) creates a row vector + # Subtracting them creates an N x N matrix of differences + dlat = lats_rad.reshape(-1, 1) - lats_rad.reshape(1, -1) + dlon = lons_rad.reshape(-1, 1) - lons_rad.reshape(1, -1) + + # Haversine formula + a = np.sin(dlat / 2)**2 + np.cos(lats_rad.reshape(-1, 1)) * np.cos(lats_rad.reshape(1, -1)) * np.sin(dlon / 2)**2 + c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a)) + + return R * c + +def orders_to_arrow_table(orders: List[Dict[str, Any]]) -> pa.Table: + """ + Convert a list of order dictionaries to an Apache Arrow Table. + This enables zero-copy operations and efficient columnar storage. + """ + return pa.Table.from_pylist(orders) + +def save_optimized_route_parquet(orders: List[Dict[str, Any]], filename: str): + """ + Save optimized route data to a Parquet file for high-speed analysis. + Useful for logging and historical simulation replays. + """ + try: + table = orders_to_arrow_table(orders) + pq.write_table(table, filename) + logger.info(f" Saved route data to Parquet: {filename}") + except Exception as e: + logger.error(f" Failed to save Parquet: {e}") + +def load_route_parquet(filename: str) -> List[Dict[str, Any]]: + """ + Load route data from a Parquet file and return as a list of dicts. + """ + table = pq.read_table(filename) + return table.to_pylist() diff --git a/app/core/constants.py b/app/core/constants.py new file mode 100644 index 0000000..60c4a0c --- /dev/null +++ b/app/core/constants.py @@ -0,0 +1,26 @@ +"""API constants and configuration.""" + +# API Configuration +API_VERSION = "2.0.0" +API_TITLE = "Route Optimization API" +API_DESCRIPTION = "Professional API for delivery route optimization" + +# Route Optimization Limits +MAX_DELIVERIES = 50 +MIN_DELIVERIES = 1 + +# Coordinate Validation +MIN_LATITUDE = -90 +MAX_LATITUDE = 90 +MIN_LONGITUDE = -180 +MAX_LONGITUDE = 180 + +# Algorithm Types +ALGORITHM_GREEDY = "greedy" +ALGORITHM_TSP = "tsp" + +# Response Messages +MESSAGE_SUCCESS = "Route optimized successfully" +MESSAGE_VALIDATION_ERROR = "Request validation failed" +MESSAGE_INTERNAL_ERROR = "An unexpected error occurred" + diff --git a/app/core/exception_handlers.py b/app/core/exception_handlers.py new file mode 100644 index 0000000..31735df --- /dev/null +++ b/app/core/exception_handlers.py @@ -0,0 +1,112 @@ +"""Professional exception handlers for the API.""" + +import logging +from fastapi import Request, status +from fastapi.responses import JSONResponse +from fastapi.exceptions import RequestValidationError +from starlette.exceptions import HTTPException as StarletteHTTPException + +from app.core.exceptions import APIException +from app.models.errors import ErrorResponse, ErrorDetail + +logger = logging.getLogger(__name__) + + +async def api_exception_handler(request: Request, exc: APIException) -> JSONResponse: + """Handle custom API exceptions.""" + request_id = getattr(request.state, "request_id", None) + + error_response = ErrorResponse( + success=False, + error=ErrorDetail( + field=exc.field, + message=exc.message, + code=exc.code + ), + path=request.url.path, + request_id=request_id + ) + + logger.warning(f"API Exception: {exc.code} - {exc.message} (Request ID: {request_id})") + + return JSONResponse( + status_code=exc.status_code, + content=error_response.model_dump(exclude_none=True) + ) + + +async def http_exception_handler(request: Request, exc: StarletteHTTPException) -> JSONResponse: + """Handle HTTP exceptions.""" + request_id = getattr(request.state, "request_id", None) + + error_response = ErrorResponse( + success=False, + error=ErrorDetail( + message=exc.detail, + code="HTTP_ERROR" + ), + path=request.url.path, + request_id=request_id + ) + + logger.warning(f"HTTP Exception: {exc.status_code} - {exc.detail} (Request ID: {request_id})") + + return JSONResponse( + status_code=exc.status_code, + content=error_response.model_dump(exclude_none=True) + ) + + +async def validation_exception_handler(request: Request, exc: RequestValidationError) -> JSONResponse: + """Handle validation errors with detailed field information.""" + request_id = getattr(request.state, "request_id", None) + + errors = exc.errors() + if errors: + first_error = errors[0] + field = ".".join(str(loc) for loc in first_error.get("loc", [])) + message = first_error.get("msg", "Validation error") + else: + field = None + message = "Validation error" + + error_response = ErrorResponse( + success=False, + error=ErrorDetail( + field=field, + message=message, + code="VALIDATION_ERROR" + ), + path=request.url.path, + request_id=request_id + ) + + logger.warning(f"Validation Error: {message} (Field: {field}, Request ID: {request_id})") + + return JSONResponse( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + content=error_response.model_dump(exclude_none=True) + ) + + +async def general_exception_handler(request: Request, exc: Exception) -> JSONResponse: + """Handle unexpected exceptions.""" + request_id = getattr(request.state, "request_id", None) + + error_response = ErrorResponse( + success=False, + error=ErrorDetail( + message="An unexpected error occurred. Please try again later.", + code="INTERNAL_SERVER_ERROR" + ), + path=request.url.path, + request_id=request_id + ) + + logger.error(f"Unexpected Error: {str(exc)} (Request ID: {request_id})", exc_info=True) + + return JSONResponse( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + content=error_response.model_dump(exclude_none=True) + ) + diff --git a/app/core/exceptions.py b/app/core/exceptions.py new file mode 100644 index 0000000..a0a7624 --- /dev/null +++ b/app/core/exceptions.py @@ -0,0 +1,70 @@ +"""Custom exceptions for the API.""" + +from fastapi import HTTPException, status + + +class APIException(HTTPException): + """Base API exception with structured error format.""" + + def __init__( + self, + status_code: int, + message: str, + field: str = None, + code: str = None, + detail: str = None + ): + self.message = message + self.field = field + self.code = code or self._get_default_code(status_code) + super().__init__(status_code=status_code, detail=detail or message) + + def _get_default_code(self, status_code: int) -> str: + """Get default error code based on status code.""" + codes = { + 400: "BAD_REQUEST", + 401: "UNAUTHORIZED", + 403: "FORBIDDEN", + 404: "NOT_FOUND", + 409: "CONFLICT", + 422: "VALIDATION_ERROR", + 429: "RATE_LIMIT_EXCEEDED", + 500: "INTERNAL_SERVER_ERROR", + 503: "SERVICE_UNAVAILABLE" + } + return codes.get(status_code, "UNKNOWN_ERROR") + + +class ValidationError(APIException): + """Validation error exception.""" + + def __init__(self, message: str, field: str = None): + super().__init__( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + message=message, + field=field, + code="VALIDATION_ERROR" + ) + + +class NotFoundError(APIException): + """Resource not found exception.""" + + def __init__(self, message: str = "Resource not found"): + super().__init__( + status_code=status.HTTP_404_NOT_FOUND, + message=message, + code="NOT_FOUND" + ) + + +class RateLimitError(APIException): + """Rate limit exceeded exception.""" + + def __init__(self, message: str = "Rate limit exceeded"): + super().__init__( + status_code=status.HTTP_429_TOO_MANY_REQUESTS, + message=message, + code="RATE_LIMIT_EXCEEDED" + ) + diff --git a/app/core/log_context.py b/app/core/log_context.py new file mode 100644 index 0000000..8bc76d2 --- /dev/null +++ b/app/core/log_context.py @@ -0,0 +1,30 @@ +""" +Per-request logging context. + +Carries the request id (the same one `RequestIDMiddleware` puts on the +`X-Request-ID` header) into every log record via a ContextVar + logging.Filter, +so a whole request's log lines can be grepped by one id — essential when +watching the live API. +""" + +import contextvars +import logging + +# Default "-" so non-request logs (startup, background agents) still format cleanly. +_request_id: contextvars.ContextVar[str] = contextvars.ContextVar("request_id", default="-") + + +def set_request_id(request_id: str) -> None: + _request_id.set(request_id or "-") + + +def get_request_id() -> str: + return _request_id.get() + + +class RequestIdFilter(logging.Filter): + """Injects `request_id` onto every LogRecord so the format string can use it.""" + + def filter(self, record: logging.LogRecord) -> bool: + record.request_id = _request_id.get() + return True diff --git a/app/main.py b/app/main.py new file mode 100644 index 0000000..fa7013a --- /dev/null +++ b/app/main.py @@ -0,0 +1,192 @@ +"""FastAPI application — Daily Grubs Rider Dispatch API.""" + +import logging +import os +import sys +import time +from contextlib import asynccontextmanager + +# Load .env (DB_*, REDIS_*, GOOGLE_MAPS_API_KEY) into the environment early, +# before any service reads os.getenv at import time. +try: + from dotenv import load_dotenv + load_dotenv() +except Exception: + pass + +from fastapi import FastAPI, Request +from fastapi.exceptions import RequestValidationError +from fastapi.middleware.cors import CORSMiddleware +from fastapi.middleware.gzip import GZipMiddleware +from starlette.exceptions import HTTPException as StarletteHTTPException + +from app.core.exception_handlers import ( + api_exception_handler, + general_exception_handler, + http_exception_handler, + validation_exception_handler, +) +from app.core.exceptions import APIException +from app.middleware.request_id import RequestIDMiddleware +from app.routes import cache_router, health_router, ml_router, ml_web_router, optimization_router, batch_analytics_router, riders_router + +# --------------------------------------------------------------------------- +# Logging +# --------------------------------------------------------------------------- +from app.core.log_context import RequestIdFilter + +_log_level = getattr(logging, os.getenv("LOG_LEVEL", "INFO").upper(), logging.INFO) +_handler = logging.StreamHandler(sys.stdout) +_handler.addFilter(RequestIdFilter()) +logging.basicConfig( + level=_log_level, + format="%(asctime)s - %(name)s - %(levelname)s - [req:%(request_id)s] - [%(filename)s:%(lineno)d] - %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + handlers=[_handler], +) +logger = logging.getLogger(__name__) +for _lib in ("httpx", "uvicorn", "uvicorn.error", "uvicorn.access"): + logging.getLogger(_lib).setLevel(_log_level) + + +# --------------------------------------------------------------------------- +# Lifespan (startup / shutdown) +# --------------------------------------------------------------------------- + +@asynccontextmanager +async def lifespan(app: FastAPI): + logger.info("[START] Route Optimization API starting up...") + + # Warm up the delivery-history FAISS store in the background + try: + from app.services.vector.delivery_history_store import get_delivery_history_store + store = get_delivery_history_store() + logger.info( + f"[DeliveryHistory] FAISS store ready — {store.record_count()} historical records loaded." + ) + except Exception as e: + logger.warning(f"[DeliveryHistory] Store warm-up failed (non-fatal): {e}") + + # Warm up the customer-coord FAISS store + try: + from app.services.vector.faiss_customer_store import get_faiss_store + cs = get_faiss_store() + logger.info(f"[FAISSCoords] Customer coord store ready — {cs.record_count()} records.") + except Exception as e: + logger.warning(f"[FAISSCoords] Store warm-up failed (non-fatal): {e}") + + # Log how many historical assignment events we have for analytics + try: + from app.services.ml.ml_data_collector import get_collector + n = get_collector().count_records() + logger.info(f"[Analytics] {n} assignment events in the analytics DB.") + except Exception as e: + logger.warning(f"[Analytics] DB check failed (non-fatal): {e}") + + # Warm up the Thompson Sampling bandit (bootstraps from historical DB) + try: + from app.services.ml.strategy_bandit import get_bandit + bandit = get_bandit() + stats = bandit.get_stats() + logger.info( + f"[Bandit] RL strategy bandit ready — " + f"{stats['context_count']} contexts, " + f"{stats['total_updates']} historical updates loaded." + ) + except Exception as e: + logger.warning(f"[Bandit] Warm-up failed (non-fatal): {e}") + + # Start the autonomous empirical-ETA sync agent (daemon thread). + # It mirrors completed deliveries locally and rebuilds learned ETAs on a + # schedule, so the request path never touches Postgres. + try: + from app.services.routing.delivery_history_service import get_delivery_history_service + from app.config.dynamic_config import get_config + cfg = get_config() + get_delivery_history_service().ensure_background_sync( + interval_hours=int(cfg.get("eta_sync_interval_hours", 6)), + days=int(cfg.get("eta_history_days", 14)), + ) + logger.info("[ETA-Agent] autonomous empirical-ETA sync scheduled.") + except Exception as e: + logger.warning(f"[ETA-Agent] Sync agent start failed (non-fatal): {e}") + + # Start the autonomous road-sequencing decision agent. It measures road vs + # aerial sequencing on real batches and turns routing_use_road_distance on/off + # by itself — no manual flag flip needed. + try: + from app.services.routing.road_sequencing_agent import get_road_agent + from app.config.dynamic_config import get_config + get_road_agent().ensure_background_agent( + interval_hours=int(get_config().get("routing_eval_interval_hours", 24)), + ) + logger.info("[RoadAgent] autonomous road-sequencing decision agent scheduled.") + except Exception as e: + logger.warning(f"[RoadAgent] Decision agent start failed (non-fatal): {e}") + + logger.info("[OK] Application ready.") + yield + logger.info("[STOP] Route Optimization API shutting down.") + + +# --------------------------------------------------------------------------- +# App +# --------------------------------------------------------------------------- + +app = FastAPI( + title="Route Optimization API", + version="2.0.0", + docs_url="/docs", + redoc_url="/redoc", + openapi_url="/api/v1/openapi.json", + lifespan=lifespan, +) + +app.add_middleware(RequestIDMiddleware) +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"], + allow_headers=["*"], + expose_headers=["X-Request-ID", "X-Process-Time"], +) +app.add_middleware(GZipMiddleware, minimum_size=1000) + + +@app.middleware("http") +async def add_process_time_header(request: Request, call_next): + start = time.time() + response = await call_next(request) + response.headers["X-Process-Time"] = str(round(time.time() - start, 4)) + response.headers["X-API-Version"] = "2.0.0" + return response + + +app.add_exception_handler(APIException, api_exception_handler) +app.add_exception_handler(StarletteHTTPException, http_exception_handler) +app.add_exception_handler(RequestValidationError, validation_exception_handler) +app.add_exception_handler(Exception, general_exception_handler) + +app.include_router(optimization_router) +app.include_router(health_router) +app.include_router(cache_router) +app.include_router(ml_router) +app.include_router(ml_web_router) +app.include_router(batch_analytics_router) +app.include_router(riders_router) + + +@app.get("/", tags=["Root"]) +async def root(request: Request): + return { + "service": "Route Optimization API", + "version": "2.0.0", + "status": "operational", + "docs": "/docs", + } + + +if __name__ == "__main__": + import uvicorn + uvicorn.run("app.main:app", host="0.0.0.0", port=8002, reload=True) diff --git a/app/middleware/__init__.py b/app/middleware/__init__.py new file mode 100644 index 0000000..d9d9d2b --- /dev/null +++ b/app/middleware/__init__.py @@ -0,0 +1,2 @@ +"""Middleware components.""" + diff --git a/app/middleware/__pycache__/__init__.cpython-312.pyc b/app/middleware/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..b9b6e6d Binary files /dev/null and b/app/middleware/__pycache__/__init__.cpython-312.pyc differ diff --git a/app/middleware/__pycache__/request_id.cpython-312.pyc b/app/middleware/__pycache__/request_id.cpython-312.pyc new file mode 100644 index 0000000..313173a Binary files /dev/null and b/app/middleware/__pycache__/request_id.cpython-312.pyc differ diff --git a/app/middleware/request_id.py b/app/middleware/request_id.py new file mode 100644 index 0000000..a0cc137 --- /dev/null +++ b/app/middleware/request_id.py @@ -0,0 +1,30 @@ +"""Request ID middleware for request tracing.""" + +import uuid +from fastapi import Request +from starlette.middleware.base import BaseHTTPMiddleware +from starlette.responses import Response + +from app.core.log_context import set_request_id + + +class RequestIDMiddleware(BaseHTTPMiddleware): + """Middleware to add unique request ID to each request.""" + + async def dispatch(self, request: Request, call_next): + # Generate or retrieve request ID (short form keeps logs readable) + request_id = request.headers.get("X-Request-ID") or uuid.uuid4().hex[:8] + + # Add request ID to request state + logging context (so every log line + # for this request carries it — grep one id to follow the whole request). + request.state.request_id = request_id + set_request_id(request_id) + + # Process request + response = await call_next(request) + + # Add request ID to response headers + response.headers["X-Request-ID"] = request_id + + return response + diff --git a/app/models/__init__.py b/app/models/__init__.py new file mode 100644 index 0000000..6fd5bd1 --- /dev/null +++ b/app/models/__init__.py @@ -0,0 +1,21 @@ +"""Models package.""" + +from .schemas import ( + Location, + Delivery, + RouteOptimizationRequest, + RouteStep, + OptimizedRoute, + PickupLocation, + DeliveryLocation +) + +__all__ = [ + "Location", + "Delivery", + "RouteOptimizationRequest", + "RouteStep", + "OptimizedRoute", + "PickupLocation", + "DeliveryLocation" +] diff --git a/app/models/__pycache__/__init__.cpython-312.pyc b/app/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..6d2349c Binary files /dev/null and b/app/models/__pycache__/__init__.cpython-312.pyc differ diff --git a/app/models/__pycache__/errors.cpython-312.pyc b/app/models/__pycache__/errors.cpython-312.pyc new file mode 100644 index 0000000..2f954d8 Binary files /dev/null and b/app/models/__pycache__/errors.cpython-312.pyc differ diff --git a/app/models/__pycache__/schemas.cpython-312.pyc b/app/models/__pycache__/schemas.cpython-312.pyc new file mode 100644 index 0000000..5f7129f Binary files /dev/null and b/app/models/__pycache__/schemas.cpython-312.pyc differ diff --git a/app/models/errors.py b/app/models/errors.py new file mode 100644 index 0000000..93b006f --- /dev/null +++ b/app/models/errors.py @@ -0,0 +1,45 @@ +"""Professional error response models for API.""" + +from typing import Optional, Any, Dict +from pydantic import BaseModel, Field +from datetime import datetime + + +class ErrorDetail(BaseModel): + """Detailed error information.""" + field: Optional[str] = Field(None, description="Field name that caused the error") + message: str = Field(..., description="Error message") + code: Optional[str] = Field(None, description="Error code") + + +class ErrorResponse(BaseModel): + """Standardized error response model.""" + success: bool = Field(False, description="Request success status") + error: ErrorDetail = Field(..., description="Error details") + timestamp: str = Field(default_factory=lambda: datetime.utcnow().isoformat(), description="Error timestamp") + path: Optional[str] = Field(None, description="Request path") + request_id: Optional[str] = Field(None, description="Request ID for tracing") + + class Config: + json_schema_extra = { + "example": { + "success": False, + "error": { + "field": "pickup_location", + "message": "Pickup location is required", + "code": "VALIDATION_ERROR" + }, + "timestamp": "2024-01-15T10:30:00.000Z", + "path": "/api/v1/optimization/single-route", + "request_id": "req-123456" + } + } + + +class SuccessResponse(BaseModel): + """Standardized success response wrapper.""" + success: bool = Field(True, description="Request success status") + data: Any = Field(..., description="Response data") + timestamp: str = Field(default_factory=lambda: datetime.utcnow().isoformat(), description="Response timestamp") + request_id: Optional[str] = Field(None, description="Request ID for tracing") + diff --git a/app/models/schemas.py b/app/models/schemas.py new file mode 100644 index 0000000..e5c4448 --- /dev/null +++ b/app/models/schemas.py @@ -0,0 +1,167 @@ +"""Professional Pydantic models for request/response validation.""" + +from typing import List, Optional +from pydantic import BaseModel, Field, field_validator +from datetime import datetime + + +class Location(BaseModel): + """Location model with latitude and longitude.""" + lat: float = Field(..., description="Latitude") + lng: float = Field(..., description="Longitude") + + +class PickupLocation(BaseModel): + """Pickup location model with latitude and longitude.""" + pickuplat: float = Field( + ..., + description="Pickup latitude", + ge=-90, + le=90, + examples=[11.0050534] + ) + pickuplon: float = Field( + ..., + description="Pickup longitude", + ge=-180, + le=180, + examples=[76.9508991] + ) + + @field_validator("pickuplat", "pickuplon") + @classmethod + def validate_coordinates(cls, v): + """Validate coordinate values.""" + if v is None: + raise ValueError("Coordinate cannot be None") + return float(v) + + +class DeliveryLocation(BaseModel): + """Delivery location model with latitude and longitude.""" + deliverylat: float = Field( + ..., + description="Delivery latitude", + ge=-90, + le=90, + examples=[11.0309723] + ) + deliverylong: float = Field( + ..., + description="Delivery longitude", + ge=-180, + le=180, + examples=[77.0004574] + ) + + @field_validator("deliverylat", "deliverylong") + @classmethod + def validate_coordinates(cls, v): + """Validate coordinate values.""" + if v is None: + raise ValueError("Coordinate cannot be None") + return float(v) + + +class Delivery(BaseModel): + """Delivery order model.""" + deliveryid: str = Field(..., description="Unique delivery identifier") + deliverycustomerid: int = Field(..., description="Customer ID for this delivery") + location: DeliveryLocation = Field(..., description="Delivery location coordinates") + + +class RouteOptimizationRequest(BaseModel): + """ + Request model for route optimization. + + Optimizes delivery routes starting from a pickup location (warehouse/store) to multiple delivery locations. + Uses greedy nearest-neighbor algorithm for fast, efficient route calculation. + """ + pickup_location: PickupLocation = Field( + ..., + description="Pickup location (warehouse/store) coordinates - starting point for optimization" + ) + pickup_location_id: Optional[int] = Field( + None, + description="Optional pickup location ID for tracking purposes" + ) + deliveries: List[Delivery] = Field( + ..., + min_items=1, + max_items=50, + description="List of delivery locations to optimize (1-50 deliveries supported)" + ) + + class Config: + json_schema_extra = { + "example": { + "pickup_location": { + "pickuplat": 11.0050534, + "pickuplon": 76.9508991 + }, + "pickup_location_id": 1, + "deliveries": [ + { + "deliveryid": "90465", + "deliverycustomerid": 1, + "location": { + "deliverylat": 11.0309723, + "deliverylong": 77.0004574 + } + } + ] + } + } + + +class RouteStep(BaseModel): + """Single step in the optimized route.""" + step_number: int = Field(..., description="Step number in the route") + delivery_id: str = Field(..., description="Delivery ID for this step") + delivery_customer_id: int = Field(..., description="Customer ID for this delivery") + location: DeliveryLocation = Field(..., description="Delivery location coordinates") + distance_from_previous_km: float = Field(..., description="Distance from previous step in kilometers") + cumulative_distance_km: float = Field(..., description="Total distance traveled so far in kilometers") + + +class OptimizedRoute(BaseModel): + """ + Optimized route response with step-by-step delivery sequence. + + Contains the optimized route starting from pickup location, with each step showing: + - Delivery order (Step 1, Step 2, etc.) + - Distance from previous step + - Cumulative distance traveled + """ + route_id: str = Field(..., description="Unique route identifier (UUID)") + pickup_location_id: Optional[int] = Field(None, description="Pickup location ID") + pickup_location: PickupLocation = Field(..., description="Pickup location (warehouse/store) coordinates") + total_distance_km: float = Field( + ..., + ge=0, + description="Total route distance in kilometers", + examples=[12.45] + ) + total_deliveries: int = Field( + ..., + ge=1, + description="Total number of deliveries in the route", + examples=[5] + ) + optimization_algorithm: str = Field( + "greedy", + description="Algorithm used for optimization", + examples=["greedy"] + ) + steps: List[RouteStep] = Field( + ..., + description="Ordered list of route steps (Step 1 = nearest from pickup, Step 2 = nearest from Step 1, etc.)" + ) + created_at: str = Field( + default_factory=lambda: datetime.utcnow().isoformat(), + description="Route creation timestamp (ISO 8601)" + ) + + +# Batch optimization removed - no rider support needed +# Use single-route optimization for each pickup location \ No newline at end of file diff --git a/app/routes/__init__.py b/app/routes/__init__.py new file mode 100644 index 0000000..870e2ce --- /dev/null +++ b/app/routes/__init__.py @@ -0,0 +1,18 @@ +"""Routes package.""" + +from .optimization import router as optimization_router +from .health import router as health_router +from .cache import router as cache_router +from .ml_admin import router as ml_router, web_router as ml_web_router +from .batch_analytics import router as batch_analytics_router +from .riders import router as riders_router + +__all__ = [ + "optimization_router", + "health_router", + "cache_router", + "ml_router", + "ml_web_router", + "batch_analytics_router", + "riders_router", +] diff --git a/app/routes/__pycache__/__init__.cpython-312.pyc b/app/routes/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..d51954a Binary files /dev/null and b/app/routes/__pycache__/__init__.cpython-312.pyc differ diff --git a/app/routes/__pycache__/batch_analytics.cpython-312.pyc b/app/routes/__pycache__/batch_analytics.cpython-312.pyc new file mode 100644 index 0000000..72cb78f Binary files /dev/null and b/app/routes/__pycache__/batch_analytics.cpython-312.pyc differ diff --git a/app/routes/__pycache__/cache.cpython-312.pyc b/app/routes/__pycache__/cache.cpython-312.pyc new file mode 100644 index 0000000..e78ac61 Binary files /dev/null and b/app/routes/__pycache__/cache.cpython-312.pyc differ diff --git a/app/routes/__pycache__/health.cpython-312.pyc b/app/routes/__pycache__/health.cpython-312.pyc new file mode 100644 index 0000000..ff24e6a Binary files /dev/null and b/app/routes/__pycache__/health.cpython-312.pyc differ diff --git a/app/routes/__pycache__/ml_admin.cpython-312.pyc b/app/routes/__pycache__/ml_admin.cpython-312.pyc new file mode 100644 index 0000000..d83cd6f Binary files /dev/null and b/app/routes/__pycache__/ml_admin.cpython-312.pyc differ diff --git a/app/routes/__pycache__/optimization.cpython-312.pyc b/app/routes/__pycache__/optimization.cpython-312.pyc new file mode 100644 index 0000000..2128f8e Binary files /dev/null and b/app/routes/__pycache__/optimization.cpython-312.pyc differ diff --git a/app/routes/batch_analytics.py b/app/routes/batch_analytics.py new file mode 100644 index 0000000..1cb25c8 --- /dev/null +++ b/app/routes/batch_analytics.py @@ -0,0 +1,263 @@ +""" +Batch Efficiency Analytics Endpoint +===================================== +POST /api/v1/batch/efficiency + +Analyses a delivery batch for idle-rider substitution opportunities. +Supports named batch windows (morning / afternoon / evening) or custom +time ranges so you can run the same analysis for any shift. + +Request body: + { + "batch": "morning", // "morning" | "afternoon" | "evening" | "custom" + "date": "2026-05-28", // defaults to today + "tenant_id": 916, // defaults to 916 + "from_time": "06:00", // only for batch="custom" + "to_time": "09:00", // only for batch="custom" + "deliveries": [...], // supply inline instead of DB fetch + "rider_names": {"1036": "Vignesh S", ...}, + "config": { + "idle_threshold_minutes": 30, + "road_kmh": 13.0, + "max_transfer_orders": 4 + } + } + +Batch windows (assigntime range, inclusive start / exclusive end): + morning : 06:00 – 09:00 (breakfast + early lunch prep) + afternoon : 11:00 – 15:00 (lunch) + evening : 17:00 – 21:30 (dinner) + custom : caller provides from_time / to_time + +Header shorthand (all equivalent to body.batch): + X-Batch-Window: morning | afternoon | evening +""" + +import logging +import os +from datetime import date as _date +from typing import Any + +from fastapi import APIRouter, Body, Header, HTTPException, status + +from app.services.routing.batch_efficiency import analyse_batch + +logger = logging.getLogger(__name__) + +router = APIRouter( + prefix="/api/v1/batch", + tags=["Batch Analytics"], + responses={500: {"description": "Internal server error"}}, +) + +# --------------------------------------------------------------------------- +# Named batch windows {name: (from_time, to_time)} — 24-h "HH:MM" strings +# --------------------------------------------------------------------------- +BATCH_WINDOWS: dict[str, tuple[str, str]] = { + "morning": ("06:00", "09:00"), + "afternoon": ("11:00", "15:00"), + "evening": ("17:00", "21:30"), +} + +DEFAULT_BATCH = "morning" + + +# --------------------------------------------------------------------------- +# DB fetch +# --------------------------------------------------------------------------- + +def _fetch_from_db( + target_date: str, + tenant_id: int, + from_time: str, + to_time: str, +) -> tuple[list[dict], dict[int, str]]: + """ + Fetch deliveries assigned within [from_time, to_time) on target_date. + Times are 24-h "HH:MM" strings, e.g. "06:00", "09:00". + Returns (deliveries, rider_names) where rider_names maps userid → username. + """ + # Shared nearledb connector (single source of truth for DB_* creds). + from app.services.routing.delivery_history_service import connect_nearledb + + try: + conn = connect_nearledb() + except ImportError: + raise HTTPException( + status_code=status.HTTP_503_SERVICE_UNAVAILABLE, + detail="psycopg2 not installed — cannot fetch from DB.", + ) + except Exception as exc: + raise HTTPException( + status_code=status.HTTP_503_SERVICE_UNAVAILABLE, + detail=f"DB connection failed: {exc}", + ) + + try: + cur = conn.cursor() + cur.execute( + """ + SELECT + d.deliveryid, + d.userid, + d.pickupcustomer, + d.assigntime, + d.arrivaltime, + d.pickuptime, + d.deliverytime, + COALESCE(d.droplat, d.deliverylat) AS dlat, + COALESCE(d.droplon, d.deliverylong) AS dlon + FROM deliveries d + WHERE d.tenantid = %s + AND DATE(d.assigntime::timestamp) = %s + AND CAST(SPLIT_PART(d.assigntime, ' ', 2) AS TIME) >= %s + AND CAST(SPLIT_PART(d.assigntime, ' ', 2) AS TIME) < %s + AND COALESCE(d.droplat, d.deliverylat) IS NOT NULL + AND d.userid IS NOT NULL + ORDER BY d.userid, d.assigntime + """, + (tenant_id, target_date, from_time + ":00", to_time + ":00"), + ) + cols = [c.name for c in cur.description] + rows = cur.fetchall() + cur.close() + deliveries = [dict(zip(cols, r)) for r in rows] + + # Fetch rider names for the returned userids + rider_names_db: dict[int, str] = {} + try: + unique_uids = list({int(r["userid"]) for r in deliveries if r.get("userid") is not None}) + if unique_uids: + cur2 = conn.cursor() + cur2.execute( + "SELECT userid, username FROM users WHERE userid = ANY(%s)", + (unique_uids,) + ) + for uid, uname in cur2.fetchall(): + if uname: + rider_names_db[int(uid)] = str(uname) + cur2.close() + except Exception: + pass # names are non-critical; callers fall back to "Rider {uid}" + + return deliveries, rider_names_db + except Exception as exc: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"DB query failed: {exc}", + ) + finally: + conn.close() + + +# --------------------------------------------------------------------------- +# Endpoint +# --------------------------------------------------------------------------- + +@router.post( + "/efficiency", + summary="Batch efficiency analysis", + description=( + "Analyse a delivery batch for idle-rider substitution opportunities. " + "Pass `batch` as 'morning', 'afternoon', or 'evening' to select the " + "time window automatically, or use `batch='custom'` with `from_time`/`to_time`. " + "Supply `deliveries` inline to skip the DB fetch entirely." + ), +) +async def batch_efficiency( + body: Any = Body(default=None), + x_batch_window: str | None = Header(default=None), +): + if body is None: + body = {} + + # ---- Parse inputs ------------------------------------------------------- + deliveries: list[dict] | None = None + target_date: str | None = None + tenant_id: int = 916 + rider_names: dict[int, str] = {} + cfg: dict = {} + batch_name: str = DEFAULT_BATCH + from_time: str | None = None + to_time: str | None = None + + if isinstance(body, dict): + deliveries = body.get("deliveries") + target_date = body.get("date") + tenant_id = int(body.get("tenant_id", 916)) + batch_name = (body.get("batch") or x_batch_window or DEFAULT_BATCH).lower() + from_time = body.get("from_time") + to_time = body.get("to_time") + rider_names_raw = body.get("rider_names") or {} + rider_names = {int(k): v for k, v in rider_names_raw.items()} + cfg = body.get("config") or {} + elif isinstance(body, list): + deliveries = body + batch_name = (x_batch_window or DEFAULT_BATCH).lower() + + # ---- Resolve time window ------------------------------------------------ + if batch_name == "custom": + if not from_time or not to_time: + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail="batch='custom' requires from_time and to_time (e.g. '11:00', '15:00').", + ) + elif batch_name in BATCH_WINDOWS: + from_time, to_time = BATCH_WINDOWS[batch_name] + else: + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=( + f"Unknown batch '{batch_name}'. " + f"Valid values: {list(BATCH_WINDOWS.keys())} or 'custom'." + ), + ) + + # ---- Fetch from DB if no inline deliveries ------------------------------ + if not deliveries: + if not target_date: + target_date = str(_date.today()) + + logger.info( + f"[BatchEfficiency] Fetching batch={batch_name} " + f"date={target_date} window={from_time}-{to_time} tenant={tenant_id}" + ) + deliveries, db_rider_names = _fetch_from_db(target_date, tenant_id, from_time, to_time) + + if not deliveries: + return { + "batch": batch_name, + "window": {"from": from_time, "to": to_time}, + "date": target_date, + "fleet_summary": {}, + "rider_timelines": [], + "substitution_opportunities": [], + "top_recommendation": None, + "message": ( + f"No {batch_name}-batch orders found for {target_date} " + f"between {from_time} and {to_time}." + ), + } + + # Merge: DB-fetched names as base, request-provided names take precedence + rider_names = {**db_rider_names, **rider_names} + + logger.info( + f"[BatchEfficiency] Analysing {len(deliveries)} deliveries — " + f"batch={batch_name} date={target_date or 'inline'}" + ) + + # ---- Run analysis ------------------------------------------------------- + result = analyse_batch( + deliveries=deliveries, + rider_names=rider_names, + road_kmh=float(cfg.get("road_kmh", 13.0)), + idle_threshold_min=float(cfg.get("idle_threshold_minutes", 30.0)), + max_transfer=int(cfg.get("max_transfer_orders", 4)), + ) + + result["batch"] = batch_name + result["window"] = {"from": from_time, "to": to_time} + result["date"] = target_date or "inline" + result["input_delivery_count"] = len(deliveries) + return result diff --git a/app/routes/cache.py b/app/routes/cache.py new file mode 100644 index 0000000..2e202b0 --- /dev/null +++ b/app/routes/cache.py @@ -0,0 +1,79 @@ +"""Cache management API endpoints.""" + +import logging +from fastapi import APIRouter, HTTPException +from typing import Dict, Any + +from app.services import cache + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/api/v1/cache", tags=["Cache Management"]) + + +@router.get("/stats", response_model=Dict[str, Any]) +async def get_cache_stats(): + """ + Get cache statistics. + + Returns: + - hits: Number of cache hits + - misses: Number of cache misses + - sets: Number of cache writes + - total_keys: Current number of cached route keys + - enabled: Whether Redis cache is enabled + """ + try: + stats = cache.get_stats() + # Calculate hit rate + total_requests = stats.get("hits", 0) + stats.get("misses", 0) + if total_requests > 0: + stats["hit_rate"] = round(stats.get("hits", 0) / total_requests * 100, 2) + else: + stats["hit_rate"] = 0.0 + return stats + except Exception as e: + logger.error(f"Error getting cache stats: {e}") + raise HTTPException(status_code=500, detail="Internal server error") + + +@router.get("/keys") +async def list_cache_keys(pattern: str = "routes:*"): + """ + List cache keys matching pattern. + + - **pattern**: Redis key pattern (default: "routes:*") + """ + try: + keys = cache.get_keys(pattern) + return { + "pattern": pattern, + "count": len(keys), + "keys": keys[:100] # Limit to first 100 for response size + } + except Exception as e: + logger.error(f"Error listing cache keys: {e}") + raise HTTPException(status_code=500, detail="Internal server error") + + +@router.delete("/clear") +async def clear_cache(pattern: str = "routes:*"): + """ + Clear cache keys matching pattern. + + - **pattern**: Redis key pattern to delete (default: "routes:*") + + [WARN] **Warning**: This will delete cached route optimizations! + """ + try: + deleted_count = cache.delete(pattern) + logger.info(f"Cleared {deleted_count} cache keys matching pattern: {pattern}") + return { + "pattern": pattern, + "deleted_count": deleted_count, + "message": f"Cleared {deleted_count} cache keys" + } + except Exception as e: + logger.error(f"Error clearing cache: {e}") + raise HTTPException(status_code=500, detail="Internal server error") + diff --git a/app/routes/health.py b/app/routes/health.py new file mode 100644 index 0000000..2029735 --- /dev/null +++ b/app/routes/health.py @@ -0,0 +1,98 @@ +"""Professional health check endpoints.""" + +import time +import logging +import sys +from typing import Optional +from datetime import datetime +from fastapi import APIRouter, Request +from pydantic import BaseModel, Field + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/api/v1/health", tags=["Health"]) + +start_time = time.time() + + +class HealthResponse(BaseModel): + """Health check response model.""" + status: str = Field(..., description="Service status") + uptime_seconds: float = Field(..., description="Service uptime in seconds") + version: str = Field("2.0.0", description="API version") + timestamp: str = Field(..., description="Health check timestamp (ISO 8601)") + request_id: Optional[str] = Field(None, description="Request ID for tracing") + + +@router.get("/", response_model=HealthResponse) +async def health_check(request: Request): + """ + Health check endpoint. + + Returns the current health status of the API service including: + - Service status (healthy/unhealthy) + - Uptime in seconds + - API version + - Timestamp + """ + try: + uptime = time.time() - start_time + request_id = getattr(request.state, "request_id", None) + + return HealthResponse( + status="healthy", + uptime_seconds=round(uptime, 2), + version="2.0.0", + timestamp=datetime.utcnow().isoformat() + "Z", + request_id=request_id + ) + except Exception as e: + logger.error(f"Health check failed: {e}", exc_info=True) + request_id = getattr(request.state, "request_id", None) + + return HealthResponse( + status="unhealthy", + uptime_seconds=0.0, + version="2.0.0", + timestamp=datetime.utcnow().isoformat() + "Z", + request_id=request_id + ) + + +@router.get("/ready") +async def readiness_check(request: Request): + """ + Readiness check endpoint for load balancers. + + Returns 200 if the service is ready to accept requests. + """ + try: + # Check if critical services are available + # Add your service health checks here + + return { + "status": "ready", + "timestamp": datetime.utcnow().isoformat() + "Z", + "request_id": getattr(request.state, "request_id", None) + } + except Exception as e: + logger.error(f"Readiness check failed: {e}") + return { + "status": "not_ready", + "timestamp": datetime.utcnow().isoformat() + "Z", + "request_id": getattr(request.state, "request_id", None) + } + + +@router.get("/live") +async def liveness_check(request: Request): + """ + Liveness check endpoint for container orchestration. + + Returns 200 if the service is alive. + """ + return { + "status": "alive", + "timestamp": datetime.utcnow().isoformat() + "Z", + "request_id": getattr(request.state, "request_id", None) + } \ No newline at end of file diff --git a/app/routes/ml_admin.py b/app/routes/ml_admin.py new file mode 100644 index 0000000..28de651 --- /dev/null +++ b/app/routes/ml_admin.py @@ -0,0 +1,586 @@ +""" +Analytics & ML Admin API +========================= +Exposes historical assignment quality data, the empirical-ETA pipeline, and the +autonomous road-sequencing / rider-affinity agents. (The XGBoost/Optuna hypertuner, +ID3 risk tree, and profit predictor have all been retired — they never affected +assignment.) + +Endpoints: + GET /api/v1/ml/status – quality trend, analytics DB + history stats + GET /api/v1/ml/analytics – hourly stats, zone stats, histogram + GET /api/v1/ml/config – active config values + PATCH /api/v1/ml/config – manual config override + POST /api/v1/ml/reset – reset config to defaults + POST /api/v1/ml/strategy – change optimization strategy + POST /api/v1/ml/refresh-eta – sync nearledb + rebuild empirical ETA stats + GET /api/v1/ml/eta-accuracy – formula vs empirical ETA backtest + GET/POST /api/v1/ml/road-eval – autonomous road-sequencing decision + GET /api/v1/ml/rider-affinity – learned vs configured rider→kitchen affinity + GET /api/v1/ml/export – download assignment log as CSV + GET /api/v1/ml/history – delivery-history FAISS store stats +""" + +import json +import logging +import os + +from fastapi import APIRouter, Body, HTTPException +from fastapi.responses import PlainTextResponse, FileResponse + +logger = logging.getLogger(__name__) + +router = APIRouter( + prefix="/api/v1/ml", + tags=["Analytics & ML"], + responses={500: {"description": "Internal server error"}}, +) + +web_router = APIRouter(tags=["ML Monitor Web Dashboard"]) + + +# --------------------------------------------------------------------------- +# Dashboard (HTML) +# --------------------------------------------------------------------------- + +@web_router.get("/ml-ops", summary="Visual ML monitoring dashboard") +def ml_dashboard(): + path = os.path.join(os.getcwd(), "app/templates/ml_dashboard.html") + if not os.path.isfile(path): + raise HTTPException(status_code=404, detail=f"Dashboard template not found at {path}") + return FileResponse(path) + + +# --------------------------------------------------------------------------- +# GET /status +# --------------------------------------------------------------------------- + +@router.get("/status", summary="Assignment quality trend & store stats") +def ml_status(): + """ + Returns: + - How many assignment events are logged + - Recent quality score trend (last 50 calls) + - Delivery history FAISS store record count + - Active config values + """ + try: + from app.services.ml.ml_data_collector import get_collector + from app.services.vector.delivery_history_store import get_delivery_history_store + from app.config.dynamic_config import get_config + + collector = get_collector() + history = get_delivery_history_store() + cfg = get_config() + + return { + "status": "ok", + "db_records": collector.count_records(), + "quality_trend": collector.get_recent_quality_trend(last_n=50), + "delivery_history": { + "record_count": history.record_count(), + "status": "ready" if history.record_count() > 0 else "empty", + }, + "config": cfg.get_all(), + } + except Exception as e: + logger.error(f"[ML API] status: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +# --------------------------------------------------------------------------- +# GET /analytics +# --------------------------------------------------------------------------- + +@router.get("/analytics", summary="Hourly stats, zone stats, quality histogram") +def ml_analytics(): + """Operational analytics from historical assignment logs.""" + try: + from app.services.ml.ml_data_collector import get_collector + collector = get_collector() + return { + "status": "ok", + "hourly_stats": collector.get_hourly_stats(), + "zone_stats": collector.get_zone_stats(), + "quality_histogram": collector.get_quality_histogram(), + "strategy_comparison": collector.get_strategy_comparison(), + } + except Exception as e: + logger.error(f"[ML API] analytics: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +# --------------------------------------------------------------------------- +# GET /config +# --------------------------------------------------------------------------- + +@router.get("/config", summary="Current active configuration values") +def ml_config(): + from app.config.dynamic_config import get_config, DEFAULTS + try: + cfg = get_config() + all_values = cfg.get_all() + cached_keys = set(cfg._cache.keys()) + annotated = { + k: {"value": v, "source": "override" if k in cached_keys else "default"} + for k, v in all_values.items() + } + return { + "status": "ok", + "hyperparameters": annotated, + "total_params": len(annotated), + "override_count": sum(1 for x in annotated.values() if x["source"] == "override"), + } + except Exception as e: + logger.error(f"[ML API] config: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +@router.patch("/config", summary="Override specific config values") +def ml_config_patch(payload: dict = Body(...)): + """Manually set any config key, e.g. {\"road_factor\": 1.4}""" + from app.config.dynamic_config import get_config + try: + get_config().set_bulk(payload, source="ml_admin") + return {"status": "ok", "updated": list(payload.keys())} + except Exception as e: + logger.error(f"[ML API] config patch: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +# --------------------------------------------------------------------------- +# POST /reset +# --------------------------------------------------------------------------- + +@router.post("/reset", summary="Reset all config overrides to factory defaults") +def ml_reset(): + from app.config.dynamic_config import get_config + try: + get_config().reset_to_defaults() + return {"status": "ok", "message": "All config values reset to factory defaults."} + except Exception as e: + logger.error(f"[ML API] reset: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +# --------------------------------------------------------------------------- +# POST /strategy +# --------------------------------------------------------------------------- + +@router.post("/strategy", summary="Change the optimization strategy") +def ml_strategy(strategy: str = Body(default="balanced", embed=True)): + """ + Choices: balanced | fuel_saver | aggressive_speed | zone_strict + Affects how the quality score is computed in analytics only. + """ + valid = ["balanced", "fuel_saver", "aggressive_speed", "zone_strict"] + if strategy not in valid: + raise HTTPException(400, f"Invalid strategy. Choose from {valid}") + from app.config.dynamic_config import get_config + try: + get_config().set("ml_strategy", strategy) + return {"status": "ok", "strategy": strategy} + except Exception as e: + logger.error(f"[ML API] strategy: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +# --------------------------------------------------------------------------- +# POST /auto-tune +# --------------------------------------------------------------------------- + +@router.post("/auto-tune", summary="Run SQL-based strategy auto-tuner") +def ml_auto_tune(): + """ + Analyses the assignment log and picks the best-performing ml_strategy + based on average quality score across all recorded calls. + + Rules: + - A strategy needs ≥ 10 calls to be considered. + - At least 2 strategies must have enough data to compare. + - If a better strategy is found it is written to DynamicConfig + immediately and takes effect on the next /riderassign call. + - Also returns per-hour breakdown so you can see peak-hour patterns. + + Safe to call any time. Runs in < 100ms. + """ + from app.services.ml.ml_data_collector import get_collector + from app.config.dynamic_config import get_config, DEFAULTS + try: + collector = get_collector() + cfg = get_config() + comparison = collector.get_strategy_comparison() + hourly = collector.get_hourly_stats() + total_records = collector.count_records() + + if total_records == 0: + return { + "status": "no_data", + "message": "No assignment events logged yet. " + "Call /riderassign a few times first.", + "total_records": 0, + } + + qualified = [s for s in comparison if s["call_count"] >= 10] + current_strategy = cfg.get("ml_strategy", "balanced") + action = "no_change" + recommendation = None + + if len(qualified) >= 2: + best = max(qualified, key=lambda x: x["avg_quality"]) + recommendation = best["strategy"] + if best["strategy"] != current_strategy: + cfg.set("ml_strategy", best["strategy"], source="auto_tuner") + action = "updated" + logger.info( + f"[AutoTune API] Strategy: '{current_strategy}' → " + f"'{best['strategy']}' (quality={best['avg_quality']:.1f})" + ) + elif len(comparison) > 0: + action = "insufficient_data" + recommendation = comparison[0]["strategy"] # best so far even if < 10 calls + + # Per-hour best strategy (informational — not auto-applied) + # Shows which strategy logged the highest quality at each hour + hour_best: list = [] + if hourly: + for h in hourly: + # Find which strategy performed best in this hour block + # (simple: use the dominant strategy for that hour from comparison) + hour_best.append({ + "hour": h["hour"], + "avg_quality": h["avg_quality"], + "call_count": h["call_count"], + "sla_breaches": h["sla_breaches"], + }) + + return { + "status": "ok", + "action": action, + "current_strategy": cfg.get("ml_strategy", "balanced"), + "recommendation": recommendation, + "total_records": total_records, + "strategy_comparison": comparison, + "hourly_quality": hour_best, + "message": ( + f"Strategy updated to '{recommendation}'." + if action == "updated" + else "Current strategy is already optimal." + if action == "no_change" + else "More data needed (≥ 10 calls per strategy to compare)." + ), + } + except Exception as e: + logger.error(f"[ML API] auto-tune: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +# --------------------------------------------------------------------------- +# GET /bandit +# --------------------------------------------------------------------------- + +@router.get("/bandit", summary="Thompson Sampling bandit — posterior stats per context") +def ml_bandit(): + """ + Shows the current state of the RL strategy bandit. + + Each context (time_band|load_band) has 4 arms (strategies). + For each arm: + mean_reward — expected quality / 100 based on posterior mean + observations — number of observed calls (excluding prior) + alpha / beta — Beta distribution parameters + + The bandit uses Thompson Sampling to select strategies automatically + on every /riderassign call, balancing exploration vs exploitation. + """ + try: + from app.services.ml.strategy_bandit import get_bandit + return {"status": "ok", **get_bandit().get_stats()} + except Exception as e: + logger.error(f"[ML API] bandit: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +# --------------------------------------------------------------------------- +# GET /rider-efficiency +# --------------------------------------------------------------------------- + +@router.get("/rider-efficiency", summary="Per-rider efficiency scores from 30-day CSV history") +def ml_rider_efficiency(): + """ + Computes efficiency scores for each rider from the delivery_details.csv. + + Metrics: + delivery_count — total deliveries in the 30-day window + avg_km — average km per delivery + unique_zones — number of distinct 1.1 km delivery cells served + efficiency_score — normalised 0..1 composite (high = efficient) + + Used internally as tiebreaker during solo rider consolidation + and Phase-0 pattern pre-assignment host selection. + """ + try: + from app.services.vector.delivery_history_store import get_delivery_history_store + scores = get_delivery_history_store().get_rider_efficiency_scores() + ranked = sorted(scores.items(), key=lambda x: x[1]["efficiency_score"], reverse=True) + return { + "status": "ok", + "rider_count": len(scores), + "riders": [{"rider_id": rid, **data} for rid, data in ranked], + } + except Exception as e: + logger.error(f"[ML API] rider-efficiency: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +# --------------------------------------------------------------------------- +# GET /history +# --------------------------------------------------------------------------- + +@router.get("/history", summary="Delivery-history FAISS store stats + pattern table") +def ml_history(patterns: bool = False): + """ + Shows the delivery history store status. + + Add ?patterns=true to include the full pattern table + (all clear dominant-rider zones, sorted by pattern score). + """ + from app.services.vector.delivery_history_store import ( + get_delivery_history_store, _INDEX_PATH, _META_PATH, CSV_PATH + ) + try: + store = get_delivery_history_store() + meta = {} + if os.path.isfile(_META_PATH): + with open(_META_PATH, "r", encoding="utf-8") as f: + meta = json.load(f) + + resp = { + "status": "ok", + "record_count": store.record_count(), + "pattern_count": store.pattern_count(), + "index_ready": store.record_count() > 0, + "disk_index": os.path.isfile(_INDEX_PATH), + "csv_path": CSV_PATH, + "csv_exists": os.path.isfile(CSV_PATH), + "saved_meta": meta, + } + if patterns: + resp["patterns"] = store.get_pattern_stats() + return resp + except Exception as e: + logger.error(f"[ML API] history: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +# --------------------------------------------------------------------------- +# POST /inject-corrections +# --------------------------------------------------------------------------- + +@router.post("/inject-corrections", summary="Inject manually-corrected delivery CSV as high-weight priors") +def ml_inject_corrections( + corrections_path: str = Body(default="delivery_corrections.csv", embed=True), + weight: int = Body(default=5, embed=True), +): + """ + Loads a manually-corrected delivery CSV and injects it into the live + delivery-history pattern table as high-weight prior evidence. + + Each record in the corrections file is counted `weight` times (default 5), + so 5 correction votes easily override 1-2 noise votes from regular history. + + The correction CSV must have the same columns as delivery_details.csv: + pickupcustomer, pickuplat, pickuplon, deliverylat, deliverylong, + userid, ridername + + After injection the pattern table is rebuilt in-memory and saved to disk. + No server restart needed. + + Parameters: + corrections_path Path inside the container (default: delivery_corrections.csv) + weight How many times each correction record is counted (default: 5) + """ + from app.services.vector.delivery_history_store import get_delivery_history_store + try: + store = get_delivery_history_store() + result = store.inject_corrections(corrections_path, weight=weight) + return {"status": "ok", **result} + except FileNotFoundError as e: + raise HTTPException(status_code=404, detail=str(e)) + except Exception as e: + logger.error(f"[ML API] inject-corrections: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +# --------------------------------------------------------------------------- +# POST /reload-history +# --------------------------------------------------------------------------- + +@router.post("/reload-history", summary="Rebuild FAISS delivery-history index from CSV") +def ml_reload_history(): + """ + Forces a full rebuild of the delivery-history FAISS index from + delivery_details.csv, then saves the new index to disk. + + Call this whenever you update the CSV with a fresh 30-day export. + No server restart needed — the in-memory store is hot-swapped. + + Returns the number of records now loaded. + """ + from app.services.vector.delivery_history_store import get_delivery_history_store + try: + store = get_delivery_history_store() + n = store.reload_from_csv() + return { + "status": "ok", + "record_count": n, + "message": f"FAISS history index rebuilt from CSV — {n} records loaded and saved to disk.", + } + except Exception as e: + logger.error(f"[ML API] reload-history: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + + +# --------------------------------------------------------------------------- +# POST /refresh-eta +# --------------------------------------------------------------------------- + +@router.post("/refresh-eta", summary="Sync nearledb -> local mirror and rebuild empirical ETA stats") +def ml_refresh_eta( + days: int = Body(default=None, embed=True), + tenant_id: int = Body(default=916, embed=True), + full: bool = Body(default=False, embed=True), +): + """ + Manually trigger the empirical-ETA pipeline (the autonomous agent does this + on a schedule too): incremental READ-ONLY pull of new completed deliveries + from nearledb into the local mirror, then rebuild the learned medians. + + `days` defaults to `eta_history_days`. Set `full=true` to force a full + backfill of the window instead of an incremental sync. + """ + from app.services.routing.delivery_history_service import get_delivery_history_service + from app.config.dynamic_config import get_config + try: + window = int(days if days is not None else get_config().get("eta_history_days", 14)) + result = get_delivery_history_service().refresh_eta_stats( + days=window, tenant_id=tenant_id, full=full + ) + return {"status": "ok", "result": result} + except Exception as e: + logger.error(f"[ML API] refresh-eta: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +# --------------------------------------------------------------------------- +# GET /eta-accuracy +# --------------------------------------------------------------------------- + +@router.get("/eta-accuracy", summary="Backtest: formula ETA MAE vs empirical ETA MAE") +def ml_eta_accuracy(days: int = None, tenant_id: int = 916): + """ + Honest time-split backtest. Trains empirical medians on the older 80% of the + history window and reports mean-absolute-error (minutes) of the formula vs + the empirical model on the held-out recent 20%. + + Use this as the gate before trusting empirical ETAs: if `interpretation` is + not "empirical_better", leave `eta_empirical_enabled=false` and investigate. + """ + from app.services.routing.delivery_history_service import get_delivery_history_service + from app.config.dynamic_config import get_config + try: + cfg = get_config() + window = int(days if days is not None else cfg.get("eta_history_days", 14)) + result = get_delivery_history_service().backtest( + days=window, + tenant_id=tenant_id, + min_samples=int(cfg.get("eta_min_samples", 20)), + stat=str(cfg.get("eta_stat", "median")), + ) + return {"status": "ok", "backtest": result} + except Exception as e: + logger.error(f"[ML API] eta-accuracy: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +# --------------------------------------------------------------------------- +# GET/POST /road-eval (autonomous road-sequencing decision agent) +# --------------------------------------------------------------------------- + +@router.get("/road-eval", summary="Last autonomous road-sequencing decision") +def ml_road_eval_get(): + """ + Show the road-sequencing agent's most recent decision: whether road-aware + ordering beat straight-line ordering on real batches, the measured mean + travel-time gain, and whether it auto-enabled/disabled `routing_use_road_distance`. + """ + from app.services.routing.road_sequencing_agent import get_road_agent + from app.config.dynamic_config import get_config + try: + agent = get_road_agent() + return { + "status": "ok", + "road_distance_enabled": bool(get_config().get("routing_use_road_distance", False)), + "auto_manage": bool(get_config().get("routing_auto_manage", True)), + "last_decision": agent.last_decision or get_config().get("routing_road_eval", {}), + } + except Exception as e: + logger.error(f"[ML API] road-eval get: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +@router.post("/road-eval", summary="Run the road-sequencing decision now") +def ml_road_eval_run(): + """ + Trigger an immediate evaluation + autonomous decision (the agent also does + this on a schedule). Measures road vs aerial sequencing on sampled real + batches and may flip `routing_use_road_distance` based on the measured gain. + Also reports whether we beat the riders' actual delivered order. + """ + from app.services.routing.road_sequencing_agent import get_road_agent + try: + return {"status": "ok", "decision": get_road_agent().decide_and_apply()} + except Exception as e: + logger.error(f"[ML API] road-eval run: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +# --------------------------------------------------------------------------- +# GET /rider-affinity (learned vs configured rider→kitchen affinity) +# --------------------------------------------------------------------------- + +@router.get("/rider-affinity", summary="Learned vs configured rider→kitchen affinity") +def ml_rider_affinity(refresh: bool = False): + """ + Show the learned rider→kitchen affinity (from real delivery history) merged + with the curated config. `?refresh=true` recomputes from the local mirror + first. Learned data only augments SOFT steering — hard kitchen locks and + BLOCKED_RIDERS stay sourced from the curated config. + """ + from app.services.routing.rider_affinity_service import get_rider_affinity + try: + aff = get_rider_affinity() + if refresh: + aff.refresh() + return {"status": "ok", "affinity": aff.get_summary()} + except Exception as e: + logger.error(f"[ML API] rider-affinity: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +# --------------------------------------------------------------------------- +# GET /export +# --------------------------------------------------------------------------- + +@router.get("/export", summary="Download all assignment logs as CSV") +def ml_export(): + from app.services.ml.ml_data_collector import get_collector + try: + csv_data = get_collector().export_csv() + response = PlainTextResponse(content=csv_data, media_type="text/csv") + response.headers["Content-Disposition"] = 'attachment; filename="assignment_log.csv"' + return response + except Exception as e: + logger.error(f"[ML API] export: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) diff --git a/app/routes/optimization.py b/app/routes/optimization.py new file mode 100644 index 0000000..eac8850 --- /dev/null +++ b/app/routes/optimization.py @@ -0,0 +1,1373 @@ +"""Provider payload optimization endpoints.""" + +import asyncio as _asyncio +import logging +import os +import time +from concurrent.futures import ThreadPoolExecutor +from math import radians, cos, sin, asin, sqrt as _math_sqrt +from typing import Any +from fastapi import APIRouter, Body, Request, Depends, status, HTTPException, Query + +from app.controllers.route_controller import RouteController +from app.core.exceptions import APIException +from app.core.arrow_utils import save_optimized_route_parquet + +logger = logging.getLogger(__name__) + +# ── Thread pool for parallel per-rider TSP route optimization ──────────────── +# +# Problem: asyncio.gather on async coroutines that call OR-Tools internally +# does NOT give true CPU parallelism. Python's GIL means only one thread +# runs Python bytecode at a time, so "parallel" async TSP calls actually +# execute sequentially on a single core. +# +# Solution: run each rider's optimize_provider_payload in a ThreadPoolExecutor. +# OR-Tools is a C++ extension that RELEASES the GIL during solving, so threads +# genuinely run on separate CPU cores simultaneously. +# +# Result: 8 riders' routes are solved in parallel instead of serially. +# Typical gain: 8 × 200ms serial → ~200ms parallel (4-8× speedup). +# +# Pool size: capped at 12 workers (enough for max expected simultaneous riders; +# more workers than cores still helps because OR-Tools releases the GIL). +_route_executor = ThreadPoolExecutor( + max_workers=min(12, (os.cpu_count() or 4)), + thread_name_prefix="route-tsp", +) + + +def _sync_optimize_route(rider_orders: list) -> list: + """ + Thread-pool worker: run optimize_provider_payload inside an isolated event loop. + + Design decisions: + - Fresh RouteOptimizer per call: the class is cheap to construct (just + config reads) and creates no shared mutable state, so this is safe + and avoids any future thread-safety risk from shared instances. + - Fresh asyncio event loop per thread: event loops are NOT thread-safe; + each OS thread must own its own loop. asyncio.new_event_loop() + + run_until_complete is the documented way to call async code from a + synchronous thread context. + """ + from app.services.routing.route_optimizer import RouteOptimizer as _RO + _opt = _RO() + _loop = _asyncio.new_event_loop() + try: + return _loop.run_until_complete( + _opt.optimize_provider_payload(rider_orders, start_coords=None) + ) + except Exception: + logger.exception("[ThreadTSP] Route optimization failed in worker thread") + return [] + finally: + _loop.close() + +# ── Background thread pool for ML tasks (logging, retraining, auto-tuning) ─── +# Kept deliberately small (2 workers) — these jobs are lightweight SQLite +# writes and in-memory ID3 fits that finish in < 1 s each. They must never +# compete with the route-tsp pool for CPU during a live request. +_ml_executor = ThreadPoolExecutor( + max_workers=2, + thread_name_prefix="ml-bg", +) + + +def _haversine_km(lat1: float, lon1: float, lat2: float, lon2: float) -> float: + """Great-circle distance in km (inline, no external dep).""" + try: + la1, lo1, la2, lo2 = map(radians, [float(lat1), float(lon1), float(lat2), float(lon2)]) + dlat = la2 - la1 + dlon = lo2 - lo1 + a = sin(dlat / 2) ** 2 + cos(la1) * cos(la2) * sin(dlon / 2) ** 2 + return 2 * asin(min(1.0, _math_sqrt(a))) * 6371.0 + except Exception: + return float("inf") + + +def _auto_tune_strategy(collector) -> None: + """ + SQL-based strategy auto-tuner. + + Reads quality_score statistics from the assignment log grouped by + ml_strategy. If one strategy clearly outperforms the rest (minimum + 10 calls, ≥ 2 strategies compared) it is written to DynamicConfig so + all future requests benefit automatically. + + Safe to call at any time — DynamicConfig write is idempotent. + """ + try: + comparison = collector.get_strategy_comparison() + if not comparison or len(comparison) < 2: + return # not enough variety to compare + + # Only consider strategies with at least 10 real observations + qualified = [s for s in comparison if s["call_count"] >= 10] + if not qualified: + return + + best = max(qualified, key=lambda x: x["avg_quality"]) + from app.config.dynamic_config import get_config as _gc + cfg = _gc() + current = cfg.get("ml_strategy", "balanced") + if best["strategy"] != current: + cfg.set("ml_strategy", best["strategy"], source="auto_tuner") + logger.info( + f"[AutoTune] Strategy updated: '{current}' → '{best['strategy']}' " + f"(avg_quality={best['avg_quality']:.1f}, n={best['call_count']})" + ) + else: + logger.debug( + f"[AutoTune] Strategy '{current}' already optimal " + f"(avg_quality={best['avg_quality']:.1f})" + ) + except Exception as _ate: + logger.warning(f"[AutoTune] Failed (non-fatal): {_ate}") + + +def _bg_log_and_maybe_retrain( + num_orders: int, + num_riders: int, + hyperparams: dict, + assignments: dict, + unassigned_count: int, + elapsed_ms: float, + bandit_context: "tuple | None" = None, # (time_band, load_band) +) -> None: + """ + Background worker: log event → update RL bandit → auto-retrain ID3 + → auto-tune strategy. Runs in _ml_executor (never blocks the response). + + Thresholds: + every call → bandit posterior update (Thompson Sampling RL) + every 100 evts → greedy SQL auto-tuner (backup check, rarely fires now) + """ + try: + from app.services.ml.ml_data_collector import get_collector as _gc + collector = _gc() + + # ── 1. Log event, get back quality_score ────────────────────────── + quality_score = collector.log_assignment_event( + num_orders=num_orders, + num_riders=num_riders, + hyperparams=hyperparams, + assignments=assignments, + unassigned_count=unassigned_count, + elapsed_ms=elapsed_ms, + ) or 50.0 + + count = collector.count_records() + logger.debug(f"[ML BG] Logged event #{count}, quality={quality_score:.1f}") + + # ── 2. Thompson Sampling bandit update (RL feedback) ────────────── + if bandit_context: + try: + from app.services.ml.strategy_bandit import get_bandit as _gb + _t_band, _l_band = bandit_context + _strategy = hyperparams.get("ml_strategy", "balanced") + get_bandit_fn = _gb + get_bandit_fn().update(_t_band, _l_band, _strategy, quality_score) + logger.debug( + f"[Bandit] Updated ctx={_t_band}|{_l_band} " + f"arm={_strategy} reward={quality_score/100:.3f}" + ) + except Exception as _be: + logger.debug(f"[Bandit] Update failed (non-fatal): {_be}") + + # ── 3. Greedy SQL auto-tune every 100 events (backup) ──────────── + if count >= 20 and count % 100 == 0: + _auto_tune_strategy(collector) + + except Exception as _e: + logger.warning(f"[ML BG] Background task failed (non-fatal): {_e}") + + +router = APIRouter( + prefix="/api/v1/optimization", + tags=["Route Optimization"], + responses={ + 400: {"description": "Bad request - Invalid input parameters"}, + 422: {"description": "Validation error - Request validation failed"}, + 500: {"description": "Internal server error"}, + }, +) + + +def get_route_controller() -> RouteController: + """Dependency injection for route controller.""" + return RouteController() + + +# Legacy single-route endpoint removed; provider flow only. +@router.post( + "/createdeliveries", + status_code=status.HTTP_200_OK, + summary="Optimize provider payload (forwarding paused)", + description=""" + Accepts the provider's orders array, reorders it using greedy nearest-neighbor, adds only: + - step (1..N) + - previouskms (distance from previous stop in km) + - cumulativekms (total distance so far in km) + - actualkms (direct pickup-to-delivery distance) + + Forwarding is temporarily paused: returns the optimized array in the response. + """, + responses={ + 200: { + "description": "Upstream response", + "content": { + "application/json": { + "example": { + "code": 200, + "details": [], + "message": "Success", + "status": True, + } + } + }, + } + }, +) +async def provider_optimize_forward( + body: list[dict], controller: RouteController = Depends(get_route_controller) +): + """ + Accept provider JSON array, reorder by greedy nearest-neighbor, annotate each item with: + - step (1..N) + - previouskms (km from previous point) + - cumulativekms (km so far) + - actualkms (pickup to delivery distance) + Then forward the optimized array to the external API and return only its response. + """ + try: + url = "https://jupiter.nearle.app/live/api/v1/deliveries/createdeliveries" + result = await controller.optimize_and_forward_provider_payload(body, url) + + # Parquet snapshot — offloaded so it never blocks the response + def _snap(): + try: + os.makedirs("data/snapshots", exist_ok=True) + snapshot_path = f"data/snapshots/route_{int(time.time())}.parquet" + save_optimized_route_parquet(body, snapshot_path) + logger.info(f"Apache Arrow: Snapshot saved to {snapshot_path}") + except Exception as e: + logger.warning(f"Could not save Arrow snapshot: {e}") + _ml_executor.submit(_snap) + + return result + except APIException: + raise + except Exception as e: + logger.error( + f"Unexpected error in provider_optimize_forward: {e}", exc_info=True + ) + raise HTTPException(status_code=500, detail="Internal server error") + + +@router.get("/createdeliveries", summary="Usage info for provider optimize forward") +async def provider_optimize_forward_info(): + """Return usage info; this endpoint accepts POST only for processing.""" + return { + "message": "Use POST with a JSON array of orders to optimize and forward.", + "method": "POST", + "path": "/api/v1/optimization/provider-optimize-forward", + } + + +# --------------------------------------------------------------------------- +# STEP RECONCILIATION +# --------------------------------------------------------------------------- + +def _detect_step_anomaly(orders: list[dict]) -> tuple[bool, str]: + """ + Check whether a rider's order list has a clean sequential step sequence. + + Returns (anomaly_found, reason_string). + + Anomaly cases: + - duplicate step numbers + - gap in step numbers (e.g. 1,2,3,5,6 — missing 4) + - step numbers don't start at 1 for pending-only list + - an order has no "step" field at all + """ + steps = [] + for o in orders: + s = o.get("step") + if s is None: + return True, "missing_step" + try: + steps.append(int(s)) + except (ValueError, TypeError): + return True, "invalid_step" + + if not steps: + return False, "empty" + + steps_sorted = sorted(steps) + + # Duplicate check + if len(steps_sorted) != len(set(steps_sorted)): + return True, "duplicate" + + # Gap / non-sequential check + expected = list(range(steps_sorted[0], steps_sorted[0] + len(steps_sorted))) + if steps_sorted != expected: + return True, "gap" + + # Should start from 1 (not from some arbitrary offset) + if steps_sorted[0] != 1: + return True, "wrong_start" + + return False, "ok" + + +@router.post( + "/reconcile-steps", + status_code=status.HTTP_200_OK, + summary="Reconcile step numbers after manual rider reassignment", + description=""" + When the operations team manually moves an order from one rider to another, + step numbers become inconsistent: + - Donor rider gets a gap (steps 1,2,3,5,6 — step 4 was transferred) + - Recipient rider gets a new order with a conflicting or missing step + + This endpoint: + 1. Detects anomalies per rider (gap, duplicate, missing, wrong order) + 2. Separates each rider's already-delivered orders from pending ones + 3. Re-runs the route optimizer on the pending orders to get the best sequence + 4. Returns clean sequential steps starting from 1 for each rider + + Input: + { + "riders": [ + { + "rider_id": 883, + "orders": [ ...full order objects with current step values... ] + } + ] + } + + The "orders" array for each rider should include ALL current orders + (delivered + pending). The endpoint determines delivered status from + the "deliverytime" field (non-null/non-empty = delivered). + """, +) +async def reconcile_steps(body: Any = Body(default=None)): + if not body or not isinstance(body, dict): + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail='Body must be {"riders": [{"rider_id": X, "orders": [...]}]}', + ) + + riders_input: list = body.get("riders") or [] + if not riders_input: + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail="No riders provided.", + ) + + from app.services.routing.route_optimizer import RouteOptimizer + + results = [] + + for rider_block in riders_input: + rider_id = rider_block.get("rider_id") or rider_block.get("userid") + all_orders: list[dict] = rider_block.get("orders") or [] + + # Resolve rider name: explicit input > order username field > fallback + rider_name = ( + rider_block.get("rider_name") + or rider_block.get("username") + or next( + (o.get("username") or o.get("rider") for o in all_orders + if o.get("username") or o.get("rider")), + None, + ) + or f"Rider {rider_id}" + ) + + if not all_orders: + results.append({ + "rider_id": rider_id, + "rider_name": rider_name, + "anomaly_detected": False, + "anomaly_type": "empty", + "delivered_count": 0, + "pending_count": 0, + "resequenced": False, + "orders": [], + }) + continue + + # ── Split delivered vs pending ────────────────────────────────────── + # Delivered = deliverytime is non-null and non-empty string. + # Pending = everything else (in-transit or not yet started). + delivered: list[dict] = [] + pending: list[dict] = [] + for o in all_orders: + dt = o.get("deliverytime") + if dt and str(dt).strip() not in ("", "0", "null", "None"): + delivered.append(dict(o)) + else: + pending.append(dict(o)) + + # ── Detect anomaly on the FULL order list ─────────────────────────── + anomaly, reason = _detect_step_anomaly(all_orders) + + if not anomaly and not pending: + # Everything delivered, steps clean — nothing to do + results.append({ + "rider_id": rider_id, + "rider_name": rider_name, + "anomaly_detected": False, + "anomaly_type": "ok", + "delivered_count": len(delivered), + "pending_count": 0, + "resequenced": False, + "orders": all_orders, + }) + continue + + # ── Step-value helper (used by both fallback sort and delivered sort) ─ + def _step_val(o: dict) -> int: + try: + return int(o.get("step") or 0) + except (ValueError, TypeError): + return 0 + + # ── Coordinate normalizer ─────────────────────────────────────────── + # optimize_provider_payload reads only deliverylat / deliverylong. + # Orders from reconcile callers may carry coords under droplat/droplon + # or dlat/dlon. Normalise so the optimizer always gets valid coords. + def _norm_coords(o: dict) -> dict: + o = dict(o) + def _fv(v): + try: return float(v or 0) + except: return 0.0 + if _fv(o.get("deliverylat")) == 0: + o["deliverylat"] = o.get("droplat") or o.get("dlat") or o.get("deliverylat") or "" + if _fv(o.get("deliverylong")) == 0: + o["deliverylong"] = ( + o.get("droplon") or o.get("dlon") + or o.get("deliverylong") or "" + ) + return o + + # ── Re-optimise pending orders ────────────────────────────────────── + # Run the same route optimizer used at assignment time so step order + # matches the greedy + 2-opt algorithm (now with crossings eliminated). + # Fallback: sort by existing step value so at least the sequence is + # deterministic when the optimizer cannot run. + resequenced_pending: list[dict] = sorted(pending, key=_step_val) + + if pending: + try: + _opt = RouteOptimizer() + _optimized = await _opt.optimize_provider_payload( + [_norm_coords(o) for o in pending], + start_coords=None, + ) + if _optimized: + # Optimizer returns list in route order (index 0 = first stop). + # Use it; otherwise keep the sorted fallback. + resequenced_pending = _optimized + else: + logger.warning( + f"[Reconcile] Optimizer returned empty result for rider " + f"{rider_id} — keeping step-sorted fallback." + ) + except Exception as _oe: + logger.warning( + f"[Reconcile] Route re-optimize failed for rider {rider_id} " + f"(non-fatal, keeping step-sorted fallback): {_oe}" + ) + + # ── Renumber: delivered keep positions 1..N, pending continue after ─ + # Sort delivered by their existing step so the sequence is stable. + delivered_sorted = sorted(delivered, key=_step_val) + + # Reassign delivered steps cleanly (fills any gap in delivered portion) + for i, o in enumerate(delivered_sorted, start=1): + o["step"] = i + max_delivered_step = len(delivered_sorted) + + # Pending steps start immediately after the last delivered step. + # resequenced_pending is already in route order (optimizer output or + # step-sorted fallback), so enumerate order == correct delivery order. + for i, o in enumerate(resequenced_pending, start=max_delivered_step + 1): + o["step"] = i + + final_orders = delivered_sorted + resequenced_pending + + results.append({ + "rider_id": rider_id, + "rider_name": rider_name, + "anomaly_detected": anomaly, + "anomaly_type": reason, + "delivered_count": len(delivered), + "pending_count": len(pending), + "resequenced": True, + "orders": final_orders, + }) + + logger.info( + f"[Reconcile] Rider {rider_id}: anomaly={reason} " + f"delivered={len(delivered)} pending={len(pending)} " + f"resequenced={len(resequenced_pending)}" + ) + + return { + "status": True, + "reconciled_riders": len(results), + "riders": results, + } + + +@router.post( + "/riderassign", + status_code=status.HTTP_200_OK, + summary="Assign created orders to active riders", + description=""" + Assigns orders to riders based on kitchen preferences, proximity, and load. + + - If a payload of orders is provided, processes those. + - If payload is empty, fetches all 'created' orders from the external API. + - Fetches active riders and matches them. + """, + responses={ + 200: { + "description": "Assignment Result", + "content": { + "application/json": { + "example": { + "code": 200, + "details": {"1234": [{"orderid": "..."}]}, + "message": "Success", + "status": True, + } + } + }, + } + }, +) +async def assign_orders_to_riders( + request: Request, + body: Any = Body(default=None), + reshuffle: bool = Query(False, alias="reshuffle"), + hypertuning_params: str = None, +): + """ + Smart assignment of orders to riders. + + Accepts two payload formats: + - Legacy: flat JSON array of order objects + - New: {"deliveries": [...], "absent_riders": [{"userid": 123, "username": "..."}]} + + Riders listed in absent_riders are excluded from all assignment phases for + this call — even if they are the best pattern match. + """ + from app.services.rider.get_active_riders import ( + fetch_active_riders, + fetch_created_orders, + ) + from app.services.core.assignment_service import AssignmentService + from app.services.routing.route_optimizer import RouteOptimizer + from app.services.routing.empirical_eta_calculator import EmpiricalETACalculator + from datetime import datetime, timedelta + from dateutil.parser import parse as parse_date + import asyncio + + eta_calculator = EmpiricalETACalculator() + + try: + _t0 = time.time() # wall-clock start for elapsed_ms logging + + # ── Parse new payload format ───────────────────────────────────────── + # {"deliveries": [...], "absent_riders": [{"userid": X}, ...]} + # vs legacy flat list [...]. + absent_rider_ids: set = set() + if isinstance(body, dict): + _absent_list = body.get("absent_riders") or [] + for _ar in _absent_list: + try: + _arid = int(_ar.get("userid") or _ar.get("id") or 0) + if _arid: + absent_rider_ids.add(_arid) + except (ValueError, TypeError): + pass + body = body.get("deliveries") or [] + if absent_rider_ids: + logger.info( + f"[Absent] Excluding {len(absent_rider_ids)} absent riders " + f"from this batch: {sorted(absent_rider_ids)}" + ) + + # Accept both ?reshuffle and legacy typo variants in URL for backwards compat + q_params = request.query_params + do_reshuffle = reshuffle or any( + k in q_params for k in ["resuffle", "rehuffle"] + ) + + # 1. Fetch riders and (if body is empty) orders in parallel. + if body: + riders = await fetch_active_riders() + orders = body + logger.info(f"[PROCESS] Received {len(orders)} orders from payload.") + else: + logger.info( + "[PROCESS] No payload — fetching riders and orders in parallel." + ) + riders, orders = await asyncio.gather( + fetch_active_riders(), + fetch_created_orders(), + ) + if orders: + logger.info(f"[PROCESS] Fetched {len(orders)} created orders from external API.") + else: + logger.info("[PROCESS] No created orders returned from external API.") + + fuel_charge = 2.5 + base_pay = 0.0 + + # 2. Validate absent_rider_ids against the live roster + _live_ids: set = { + int(r.get("userid") or r.get("riderid") or r.get("id") or 0) + for r in riders + } - {0} + if absent_rider_ids: + _unknown_absent = absent_rider_ids - _live_ids + _confirmed_absent = absent_rider_ids & _live_ids + if _unknown_absent: + logger.warning( + f"[Absent] Rider ID(s) not in active roster (typo?): " + f"{sorted(_unknown_absent)} — these will have no effect." + ) + if _confirmed_absent: + logger.info( + f"[Absent] Confirmed absent (in roster, now excluded): " + f"{sorted(_confirmed_absent)}" + ) + else: + _unknown_absent = set() + _confirmed_absent = set() + + # 3. Log summary after all data is in hand + mode_str = "reshuffle" if do_reshuffle else "normal" + tuning_str = hypertuning_params if hypertuning_params else "null" + logger.info( + f"\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" + f"[API HIT] POST /api/v1/optimization/riderassign\n" + f"[CONFIG] Mode: {mode_str.upper()} | Hypertuning: {tuning_str} | Active Riders: {len(riders)}\n" + f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + ) + logger.info(f"[API] riderassign ▶ orders={len(orders)} riders={len(riders)} mode={mode_str}") + + if not orders: + return { + "code": 200, + "details": {}, + "message": "No orders found to assign.", + "status": True, + "meta": {"active_riders_count": len(riders)}, + } + + _faiss_corrected = 0 + _faiss_store = None + + # 2b. FAISS coordinate verification — correct noisy delivery coords + # using historically verified rider delivery positions. + try: + from app.services.vector.faiss_customer_store import get_faiss_store + _faiss_store = get_faiss_store() + _faiss_corrected = 0 + + for _order in orders: + # Resolve phone number across common field name variants + _phone = ( + _order.get("customerphonenumber") + or _order.get("customerphone") + or _order.get("phonenumber") + or _order.get("mobile") + or _order.get("phone") + or _order.get("customer_phone") + ) + _name = ( + _order.get("customername") + or _order.get("customer_name") + or _order.get("deliveryname") + or "" + ) + try: + _raw_lat = float( + _order.get("deliverylat") or _order.get("droplat") or 0 + ) + _raw_lon = float( + _order.get("deliverylong") or _order.get("droplon") or 0 + ) + except (ValueError, TypeError): + _raw_lat, _raw_lon = 0.0, 0.0 + + if not _phone or _raw_lat == 0.0 or _raw_lon == 0.0: + continue + + _v_lat, _v_lon, _corrected = _faiss_store.get_verified_coords( + _phone, _name, _raw_lat, _raw_lon + ) + + if _corrected: + # Replace delivery coords with verified historical coords + _order["deliverylat"] = _v_lat + _order["deliverylong"] = _v_lon + if "droplat" in _order: + _order["droplat"] = _v_lat + if "droplon" in _order: + _order["droplon"] = _v_lon + _order["_coord_source"] = "faiss_verified" + _faiss_corrected += 1 + else: + _order["_coord_source"] = "input" + + logger.info( + f"[FAISS] Verified {_faiss_corrected} out of {len(orders)} orders " + f"using historical coordinates (from {_faiss_store.record_count()} stored records)." + ) + except Exception as _fe: + logger.warning(f"[FAISS] Coord verification failed (non-fatal): {_fe}") + + # ── PHASE 0: FAISS DELIVERY HISTORY — pre-assign well-known routes ──── + # For each order look up the rider who covered that kitchen → delivery + # area most in the last 30-day CSV. Only pre-assigns when: + # (a) that rider wins ≥ 50 % of filtered historical neighbours + # (b) that rider is currently active + # (c) that rider is not blocked + # Remaining orders go to the VRP solver as normal. + history_assignments: dict = {} + history_pre_assigned_ids: set = set() + _history_hits = 0 + + _KITCHEN_KEYS_PH0 = [ + "pickupcustomer", "locationname", "storename", "store_name", + "restaurantname", "restaurant_name", "kitchenname", "kitchen_name", + "partnername", "partner_name", "tenantname", + ] + + try: + from app.services.vector.delivery_history_store import get_delivery_history_store + from app.config.rider_preferences import BLOCKED_RIDERS as _BLOCKED_H + + _hist_store = get_delivery_history_store() + + if _hist_store.record_count() > 0: + # Build set of active, non-blocked, non-absent rider IDs for validation + _active_rider_ids: set = set() + for _r in riders: + try: + _rid0 = int(_r.get("userid") or _r.get("riderid") or _r.get("id") or 0) + if _rid0 and _rid0 not in _BLOCKED_H and _rid0 not in absent_rider_ids: + _active_rider_ids.add(_rid0) + except (ValueError, TypeError): + pass + + for _order in orders: + # Extract kitchen name + _kitchen_h = "" + for _kk in _KITCHEN_KEYS_PH0: + _kv = _order.get(_kk) + if _kv and str(_kv).strip(): + _kitchen_h = str(_kv).strip() + break + + try: + _h_plat = float(_order.get("pickuplat") or 0) + _h_plon = float(_order.get("pickuplon") or _order.get("pickuplong") or 0) + _h_dlat = float(_order.get("deliverylat") or _order.get("droplat") or 0) + _h_dlon = float(_order.get("deliverylong") or _order.get("droplon") or 0) + except (TypeError, ValueError): + continue + + if not _h_dlat: + continue # no delivery coords, skip + + _hit = _hist_store.find_rider( + _kitchen_h, _h_plat, _h_plon, _h_dlat, _h_dlon + ) + if _hit and _hit["userid"] in _active_rider_ids: + _h_rid = _hit["userid"] + history_assignments.setdefault(_h_rid, []).append(_order) + history_pre_assigned_ids.add(id(_order)) + _history_hits += 1 + + logger.info( + f"[FAISS History] Pre-assigned {_history_hits}/{len(orders)} orders " + f"from delivery history ({_hist_store.record_count()} records). " + f"Riders: {list(history_assignments.keys())}" + ) + else: + logger.info("[FAISS History] Store empty — skipping history pre-assignment.") + except Exception as _he: + logger.warning(f"[FAISS History] Pre-assignment failed (non-fatal): {_he}") + + # Orders not covered by FAISS history go to the VRP / 2-phase solver. + vrp_orders = [o for o in orders if id(o) not in history_pre_assigned_ids] + + # 3. Run Assignment (AssignmentService) + # -- Per-request strategy override (thread-safe via contextvars) -- + # Old approach mutated _cfg._cache directly — a race condition when two + # concurrent requests set different strategies simultaneously. + # New approach: each async task gets its OWN copy of the ContextVar, + # so overrides never leak between concurrent requests. + from app.config.dynamic_config import get_config, set_request_strategy + from app.services.ml.behavior_analyzer import time_band as _tb, load_band as _lb + from datetime import datetime as _DT + + _cfg = get_config() + + # ── Bandit context (used both for selection + background update) ── + _bandit_t_band = _tb(_DT.now().isoformat()) + _bandit_l_band = _lb(len(vrp_orders) / max(1, len(riders))) + _bandit_context = (_bandit_t_band, _bandit_l_band) + + valid_strategies = ["balanced", "fuel_saver", "aggressive_speed", "zone_strict"] + if hypertuning_params and hypertuning_params in valid_strategies: + # Explicit caller override always wins + set_request_strategy(hypertuning_params) + logger.info(f"[HYPERTUNE] Per-request strategy override: {hypertuning_params}") + else: + # ── Thompson Sampling: let the bandit choose ────────────────── + # The bandit samples from Beta posteriors for this (time, load) + # context and picks the arm with highest sample. It naturally + # explores when uncertain and exploits known-good strategies as + # data accumulates. Replaces the one-size-fits-all greedy picker. + try: + from app.services.ml.strategy_bandit import get_bandit as _gb + _bandit_strategy = _gb().select(_bandit_t_band, _bandit_l_band) + set_request_strategy(_bandit_strategy) + logger.info( + f"[Bandit] Strategy='{_bandit_strategy}' " + f"ctx={_bandit_t_band}|{_bandit_l_band}" + ) + except Exception as _bse: + logger.debug(f"[Bandit] Selection failed (non-fatal): {_bse}") + + optimizer = RouteOptimizer() + + # ── PHASE 3a: TRUE VRP (primary solver) ────────────────────────────── + # Attempt to solve assignment + routing simultaneously with OR-Tools VRP. + # This is globally optimal — one model for all riders and all orders. + # Falls back to 2-phase if OR-Tools unavailable or solver finds no solution. + # ───────────────────────────────────────────────────────────────────── + vrp_assignments: dict = {} + unassigned_orders: list = [] + used_vrp = False + + if not do_reshuffle: # VRP not meaningful during reshuffle (intentional exploration) + try: + # Build minimal rider info for VRP + from app.services.routing.kalman_filter import smooth_rider_locations + _smooth_riders = smooth_rider_locations(list(riders)) + + from app.services.core.assignment_service import AssignmentService as _AS + _svc_tmp = _AS() + + # Import the single source-of-truth blocked-rider set. + from app.config.rider_preferences import BLOCKED_RIDERS as _BLOCKED_RIDERS + + rider_data_for_vrp = [] + for r in _smooth_riders: + rid_raw = r.get("userid") or r.get("riderid") or r.get("id") + try: + rid = int(rid_raw) + except (ValueError, TypeError): + continue + if rid in _BLOCKED_RIDERS or rid in absent_rider_ids: + continue + lat, lon = _svc_tmp.get_lat_lon(r) + if lat == 0 or lon == 0: + continue + rider_data_for_vrp.append({"id": rid, "lat": lat, "lon": lon}) + + if rider_data_for_vrp: + import math as _math + # Hard cap at 12 orders/rider regardless of what ML tunes. + # This gives ceil(35/12) = 3 riders for a typical 35-order load, + # which matches the real-world target for this fleet. + # Preference discounts (below) steer each of those 3 riders + # toward their own kitchen's orders — so cap=12 is safe. + _max_opr = int(_cfg.get("max_orders_per_rider", 12)) + _vrp_cap = min(_max_opr, 12) # never let ML push this above 12 + + logger.info( + f"[VRP] Capacity: {_vrp_cap}/rider | " + f"{len(vrp_orders)} orders (of {len(orders)} total, " + f"{_history_hits} pre-assigned by FAISS history) / " + f"{len(rider_data_for_vrp)} riders → " + f"expect ≈{_math.ceil(max(1, len(vrp_orders)) / _vrp_cap)} active riders" + ) + + vrp_result = optimizer.solve_vrp_multi_rider( + orders=vrp_orders, # excludes Phase-0 pre-assigned orders + rider_data=rider_data_for_vrp, + max_orders_per_rider=_vrp_cap, + soft_prefs=_svc_tmp.soft_preferences, + soft_home=_svc_tmp.home_locations, + ) + if vrp_result: + vrp_assignments = vrp_result + # Orders not in any VRP route AND not in Phase-0 → unassigned + _vrp_assigned_ids = { + id(o) for rider_ords in vrp_assignments.values() for o in rider_ords + } + unassigned_orders = [ + o for o in orders + if id(o) not in _vrp_assigned_ids + and id(o) not in history_pre_assigned_ids + ] + used_vrp = True + # Removed logging from here, moved to after both solvers run + except Exception as _vrp_err: + logger.warning(f"[VRP] Primary solver skipped: {_vrp_err}") + + # ── PHASE 3b: 2-PHASE FALLBACK (cluster → score → assign) ──────────── + if not used_vrp: + service = AssignmentService() + _available_riders = [ + r for r in riders + if int(r.get("userid") or r.get("riderid") or r.get("id") or 0) + not in absent_rider_ids + ] if absent_rider_ids else riders + vrp_assignments, _fb_unassigned = await service.assign_orders( + riders=_available_riders, + orders=vrp_orders, # excludes Phase-0 pre-assigned orders + fuel_charge=fuel_charge, + base_pay=base_pay, + reshuffle=do_reshuffle, + ) + # Unassigned = 2-phase leftovers (history orders are always assigned) + unassigned_orders = list(_fb_unassigned) + + # Merge Phase-0 FAISS history pre-assignments into VRP/fallback result + for _h_rid, _h_ords in history_assignments.items(): + if _h_rid in vrp_assignments: + # Prepend history orders (rider knows these routes best) + vrp_assignments[_h_rid] = list(_h_ords) + vrp_assignments[_h_rid] + else: + vrp_assignments[_h_rid] = list(_h_ords) + + assignments = vrp_assignments + + # ── SOLO RIDER CONSOLIDATION ───────────────────────────────────────── + # A rider deployed for a single order is almost always a net loss. + # Rule: if a rider has exactly 1 order and another rider is already + # running a route from the same (or nearby) kitchen, transfer the + # order there instead of deploying a solo trip. + # + # Priority for matching a host: + # 0 → same pickuplocationid (same kitchen counter, zero extra pickup) + # 1 → same kitchen name (logical same kitchen, different ID edge-case) + # 2 → pickup within 1.5 km (very close kitchen cluster) + # + # Among equal-priority hosts: pick the one whose delivery centroid is + # nearest to the solo order's drop point (minimises route extension). + # + # Pass 1: merge solos into multi-order riders (≥ 2 orders). + # Pass 2: merge remaining solos with each other (same kitchen only). + # + # Hard cap: never pile > 10 orders onto one host. + # Safety: if no suitable host found, keep the solo assignment as-is + # (unassigned is worse than a solo trip). + # ───────────────────────────────────────────────────────────────────── + _SOLO_MAX_PICKUP_KM = 1.5 + _SOLO_ORDER_CAP = 10 + _consolidation_moves = 0 + + def _ord_pickup_locid(o: dict) -> int: + try: return int(o.get("pickuplocationid") or 0) + except: return 0 + + def _ord_kitchen(o: dict) -> str: + for _k in ("pickupcustomer", "locationname", "tenantname"): + _v = o.get(_k, "") + if _v: return str(_v).strip().lower() + return "" + + def _ord_pickup_coords(o: dict): + try: + return (float(o.get("pickuplat") or 0), + float(o.get("pickuplon") or o.get("pickuplong") or 0)) + except: return (0.0, 0.0) + + def _delivery_centroid(ords: list): + lats = [float(o.get("deliverylat") or o.get("droplat") or 0) for o in ords] + lons = [float(o.get("deliverylong") or o.get("droplon") or 0) for o in ords] + lats = [x for x in lats if x]; lons = [x for x in lons if x] + if not lats: return (0.0, 0.0) + return (sum(lats) / len(lats), sum(lons) / len(lons)) + + # Rider efficiency scores (from 30-day CSV history) used as tiebreaker + _rider_efficiency: dict = {} + try: + from app.services.vector.delivery_history_store import get_delivery_history_store as _gds + _rider_efficiency = _gds().get_rider_efficiency_scores() + except Exception: + pass + + def _best_host(solo_order: dict, host_pool: dict, + min_host_orders: int) -> "tuple | None": + """Return (host_rider_id, score) or None if no match. + Score tuple: (priority, drop_dist, -efficiency) + lower priority = better kitchen match + lower drop_dist = less route extension + higher efficiency = prefer that rider as tiebreaker + """ + _s_locid = _ord_pickup_locid(solo_order) + _s_kname = _ord_kitchen(solo_order) + _s_plat, _s_plon = _ord_pickup_coords(solo_order) + try: + _s_dlat = float(solo_order.get("deliverylat") or solo_order.get("droplat") or 0) + _s_dlon = float(solo_order.get("deliverylong") or solo_order.get("droplon") or 0) + except: _s_dlat = _s_dlon = 0.0 + + _best_rid, _best_score = None, None + for _hrid, _hords in host_pool.items(): + if len(_hords) < min_host_orders or len(_hords) >= _SOLO_ORDER_CAP: + continue + _h0 = _hords[0] + _h_locid = _ord_pickup_locid(_h0) + _h_kname = _ord_kitchen(_h0) + _h_plat, _h_plon = _ord_pickup_coords(_h0) + _pickup_dist = ( + _haversine_km(_s_plat, _s_plon, _h_plat, _h_plon) + if _s_plat and _h_plat else 999.0 + ) + if _s_locid and _h_locid and _s_locid == _h_locid: _pri = 0 + elif _s_kname and _h_kname and _s_kname == _h_kname: _pri = 1 + elif _pickup_dist <= _SOLO_MAX_PICKUP_KM: _pri = 2 + else: continue + + _centroid = _delivery_centroid(_hords) + _drop_dist = ( + _haversine_km(_s_dlat, _s_dlon, _centroid[0], _centroid[1]) + if _s_dlat and _centroid[0] else 999.0 + ) + # Efficiency tiebreaker: higher score = better host (negate for min-sort) + _eff = _rider_efficiency.get(_hrid, {}).get("efficiency_score", 0.5) + _score = (_pri, round(_drop_dist, 2), round(1.0 - _eff, 4)) + if _best_score is None or _score < _best_score: + _best_score = _score; _best_rid = _hrid + return (_best_rid, _best_score) if _best_rid is not None else None + + # --- Pass 1: solo → multi-order host (≥ 2 existing orders) ---------- + _solo_rids = [rid for rid, ords in assignments.items() if len(ords) == 1] + _active_pool = {rid: ords for rid, ords in assignments.items() if len(ords) >= 2} + + for _srid in _solo_rids: + if not assignments.get(_srid): continue # already cleared + _solo_ord = assignments[_srid][0] + _match = _best_host(_solo_ord, _active_pool, min_host_orders=2) + if _match: + _hrid, _hscore = _match + _active_pool[_hrid].append(_solo_ord) + assignments[_hrid] = _active_pool[_hrid] + assignments[_srid] = [] + _consolidation_moves += 1 + logger.info( + f"[Consolidate] Rider {_srid} (1 order) → merged into rider " + f"{_hrid} (now {len(_active_pool[_hrid])} orders, " + f"kitchen-priority={_hscore[0]}, drop-dist={_hscore[1]:.1f}km)" + ) + + # --- Pass 2: remaining solos → each other (same kitchen only) -------- + _still_solo = [rid for rid in _solo_rids if len(assignments.get(rid, [])) == 1] + _solo_pool = {rid: assignments[rid] for rid in _still_solo} + + _merged_in_p2: set = set() + for _srid in _still_solo: + if _srid in _merged_in_p2: continue + _solo_ord = assignments[_srid][0] + # Only same-kitchen merges in pass 2 (pickup_locid or name match) + _candidates = { + rid: ords for rid, ords in _solo_pool.items() + if rid != _srid and rid not in _merged_in_p2 + } + _match = _best_host(_solo_ord, _candidates, min_host_orders=1) + if _match: + _hrid, _hscore = _match + if _hscore[0] <= 1: # only locid/name matches in pass 2 + assignments[_hrid].append(_solo_ord) + assignments[_srid] = [] + _merged_in_p2.add(_srid) + _consolidation_moves += 1 + logger.info( + f"[Consolidate-P2] Solo {_srid} merged into solo " + f"{_hrid} (now {len(assignments[_hrid])} orders, " + f"kitchen-priority={_hscore[0]})" + ) + + if _consolidation_moves: + logger.info( + f"[Consolidate] {_consolidation_moves} solo order(s) merged into " + f"existing routes — {len([r for r in _solo_rids if not assignments.get(r)])} " + f"rider(s) freed up." + ) + + # Log outcome for whichever solver was used + assigned_count = sum(len(v) for v in assignments.values()) + solver_name = "VRP Optimal" if used_vrp else "2-Phase Heuristic" + logger.info( + f"\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" + f"[SUMMARY] Solver Used: {solver_name}\n" + f"[OUTCOME] Assigned {assigned_count} out of {len(orders)} orders.\n" + f"[RIDERS] Utilized {len([v for v in assignments.values() if v])} out of {len(riders)} active riders.\n" + f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + ) + + # No explicit restore needed — contextvars are scoped to this async task. + # When the task ends the ContextVar value is automatically discarded. + + if do_reshuffle: + logger.info( + "[RESHUFFLE] Retry mode active - exploring alternative rider assignments." + ) + + # 4. Optimize Routes for Each Rider and Flatten Response + # (OR-Tools TSP + 2-opt per rider, now with time windows if pickupSlot present) + flat_orders_list = [] + + # Build an ordered list of (rider_id, orders) pairs so we can align + # task_contexts with results after the parallel gather. + task_items = [ + (rider_id, rider_orders) + for rider_id, rider_orders in assignments.items() + if rider_orders + ] + task_contexts = [rider_id for rider_id, _ in task_items] + + total_assigned = 0 + + if task_items: + # ── TRUE PARALLEL TSP via ThreadPoolExecutor ───────────────────── + # OR-Tools (C++ extension) releases the GIL during solving, so + # threads genuinely run on separate CPU cores at the same time. + # asyncio.get_running_loop().run_in_executor schedules each worker + # on the thread pool and yields control to the event loop while + # the threads compute, keeping FastAPI fully responsive. + loop = asyncio.get_running_loop() + results = await asyncio.gather(*[ + loop.run_in_executor( + _route_executor, + _sync_optimize_route, + rider_orders, + ) + for _, rider_orders in task_items + ]) + + # Create a lookup for rider details + rider_info_map = {} + for r in riders: + # Use string conversion for robust ID matching + r_id = str(r.get("userid") or r.get("_id", "")) + if r_id: + rider_info_map[r_id] = { + "name": r.get("username", ""), + "contactno": r.get("contactno", ""), + } + + # Process results matching them back to riders + for stored_rider_id, optimized_route in zip(task_contexts, results): + r_id_str = str(stored_rider_id) + r_info = rider_info_map.get(r_id_str, {}) + rider_name = r_info.get("name", "") + rider_contact = r_info.get("contactno", "") + + # Calculate total distance for this rider + total_rider_kms = 0 + if optimized_route: + # Usually the last order has the max cumulative kms if steps are 1..N + try: + total_rider_kms = max( + [float(o.get("cumulativekms", 0)) for o in optimized_route] + ) + except: + total_rider_kms = sum( + [ + float(o.get("actualkms", o.get("kms", 0))) + for o in optimized_route + ] + ) + + for order in optimized_route: + order["userid"] = stored_rider_id + order["username"] = rider_name + # Populate the specific fields requested by the user + order["rider"] = rider_name + order["ridercontactno"] = rider_contact + order["riderkms"] = str(round(total_rider_kms, 2)) + + # --- DYNAMIC ETA COMPUTATION ----------------------------- + # Try various cases and names for pickup slot + pickup_slot_str = ( + order.get("pickupSlot") + or order.get("pickupslot") + or order.get("pickup_slot") + or order.get("pickuptime") + ) + + if pickup_slot_str: + try: + # Robust date parsing (handles almost any format magically) + pickup_time = parse_date(str(pickup_slot_str)) + + # Use cumulative_eta (total time from kitchen → this stop) + # if the route optimizer produced it; fall back to + # a fresh per-leg calculation using cumulativekms. + if order.get("cumulative_eta"): + eta_mins = int(order["cumulative_eta"]) + else: + dist_km = float( + order.get("cumulativekms") + or order.get("actualkms", order.get("kms", 0)) + ) + step = int(order.get("step", 1)) + order_type = order.get("ordertype", "Economy") + from app.services.routing.realistic_eta_calculator import get_time_of_day_category + _dcoords = None + try: + _dlat = float(order.get("deliverylat") or order.get("droplat") or 0) + _dlon = float(order.get("deliverylong") or order.get("droplon") or 0) + if _dlat and _dlon: + _dcoords = (_dlat, _dlon) + except (TypeError, ValueError): + _dcoords = None + eta_mins = eta_calculator.calculate_eta( + distance_km=dist_km, + is_first_order=(step == 1), + order_type=order_type, + time_of_day=get_time_of_day_category(), + kitchen=order.get("pickupcustomer") or order.get("locationname"), + drop_coords=_dcoords, + rider_id=order.get("userid"), + ) + + expected_time = pickup_time + timedelta(minutes=eta_mins) + + # Format output as requested: "2026-03-24 08:25 AM" + order["expectedDeliveryTime"] = expected_time.strftime( + "%Y-%m-%d %I:%M %p" + ) + order["transitMinutes"] = eta_mins + order["calculationDistanceKm"] = round( + float(order.get("cumulativekms") or order.get("actualkms", 0)), 2 + ) + except Exception as e: + logger.warning( + f"Could not calculate ETA from pickupSlot '{pickup_slot_str}': {e}" + ) + # --------------------------------------------------------- + + flat_orders_list.append(order) + total_assigned += len(optimized_route) + + # The ID3 "risk" tree was retired (it never affected assignment). Key kept + # static so existing response consumers don't break. + risk_meta: dict = {"label": "n/a", "model_trained": False, "deprecated": True} + + # ── BACKGROUND ML LOGGING ──────────────────────────────────────────── + # Fire-and-forget: log this assignment event to SQLite, auto-retrain + # ID3 every 50 events, auto-tune strategy every 100 events. + # Uses _ml_executor so the API response is never delayed. + try: + _elapsed_ms = (time.time() - _t0) * 1000 + _hyp_snapshot = get_config().get_all() # frozen copy for this call + _ml_executor.submit( + _bg_log_and_maybe_retrain, + len(orders), + len(riders), + _hyp_snapshot, + {rid: list(ords) for rid, ords in assignments.items()}, + len(unassigned_orders), + round(_elapsed_ms, 1), + _bandit_context, # (time_band, load_band) for RL update + ) + except Exception as _mle: + logger.debug(f"[ML BG] Submit failed (non-fatal): {_mle}") + + # ── Compact exit trace (grep one request_id to see the whole request) ── + try: + from app.services.routing.delivery_history_service import get_delivery_history_service + _road_on = bool(get_config().get("routing_use_road_distance", False)) + _eta_src = ( + "empirical" + if (get_config().get("eta_empirical_enabled", True) + and get_delivery_history_service().has_data()) + else "formula" + ) + logger.info( + f"[API] riderassign ◀ solver={'vrp_optimal' if used_vrp else '2phase'} " + f"assigned={total_assigned}/{len(orders)} unassigned={len(unassigned_orders)} " + f"riders_used={len([v for v in assignments.values() if v])}/{len(riders)} " + f"road_seq={'on' if _road_on else 'off'} eta={_eta_src} " + f"elapsed={round(_elapsed_ms)}ms" + ) + except Exception: + pass + + # 5. Zone Processing + from app.services.routing.zone_service import ZoneService + + zone_service = ZoneService() + zone_data = zone_service.group_by_zones( + flat_orders_list, + unassigned_orders, + fuel_charge=fuel_charge, + base_pay=base_pay, + ) + + zones_structure = zone_data["detailed_zones"] + zone_analysis = zone_data["zone_analysis"] + + return { + "code": 200, + "zone_summary": zone_analysis, # High-level zone metrics + "zones": zones_structure, # Detailed data + "details": flat_orders_list, # Flat list + "message": "Success", + "status": True, + "meta": { + "total_orders": len(orders), + "utilized_riders": len([rid for rid, rl in assignments.items() if rl]), + "active_riders_pool": len(riders), + "assigned_orders": total_assigned, + "unassigned_orders": len(unassigned_orders), + "total_profit": round(sum(z["total_profit"] for z in zone_analysis), 2), + "fuel_charge_base": fuel_charge, + "unassigned_details": [ + { + "orderid": o.get("orderid") or o.get("_id"), + "reason": o.get( + "unassigned_reason", "Unknown capacity/proximity issue" + ), + } + for o in unassigned_orders + ], + "distribution_summary": { + rid: len(rl) for rid, rl in assignments.items() if rl + }, + "reshuffle_mode": do_reshuffle, + "solver_mode": "vrp_optimal" if used_vrp else "2phase_heuristic", + "hypertuning_params": hypertuning_params or "default", + "faiss_coord_corrections": _faiss_corrected, + "faiss_customer_records": _faiss_store.record_count() if _faiss_store else 0, + "faiss_history_preassigned": _history_hits, + "solo_consolidations": _consolidation_moves, + "absent_riders_excluded": sorted(_confirmed_absent), + "absent_riders_unknown": sorted(_unknown_absent), + "risk_assessment": risk_meta, + }, + } + + except Exception as e: + logger.error(f"Error in rider assignment: {e}", exc_info=True) + raise HTTPException( + status_code=500, detail="Internal server error during assignment" + ) + diff --git a/app/routes/riders.py b/app/routes/riders.py new file mode 100644 index 0000000..b751fc9 --- /dev/null +++ b/app/routes/riders.py @@ -0,0 +1,149 @@ +""" +Riders Admin API +================ +Endpoints for the operations team to manage rider substitutions. + + POST /api/v1/riders/substitution – register one or many substitutions + GET /api/v1/riders/substitution – list upcoming/active subs + DELETE /api/v1/riders/substitution/{sub_date}/{absent_rider_id} – cancel one +""" + +import logging +from datetime import date +from typing import List + +from fastapi import APIRouter, Body, HTTPException, Path +from pydantic import BaseModel, model_validator + +logger = logging.getLogger(__name__) + +router = APIRouter( + prefix="/api/v1/riders", + tags=["Riders & Substitutions"], + responses={500: {"description": "Internal server error"}}, +) + + +class SubstitutionEntry(BaseModel): + sub_date: str + absent_rider_id: int + sub_rider_id: int + + @model_validator(mode="after") + def validate_entry(self): + try: + date.fromisoformat(self.sub_date) + except ValueError: + raise ValueError(f"Invalid date format '{self.sub_date}'. Use YYYY-MM-DD.") + if self.absent_rider_id == self.sub_rider_id: + raise ValueError("absent_rider_id and sub_rider_id must be different.") + return self + + +@router.post("/substitution", summary="Register one or multiple rider substitutions") +def register_substitution(entries: List[SubstitutionEntry] = Body(...)): + """ + Register rider substitutions for the operations team. Accepts a list so + you can submit all absent riders for a day in one call. + + Example — single: + ```json + [{"sub_date": "2026-06-20", "absent_rider_id": 101, "sub_rider_id": 205}] + ``` + + Example — batch (3 riders absent same day): + ```json + [ + {"sub_date": "2026-06-20", "absent_rider_id": 101, "sub_rider_id": 205}, + {"sub_date": "2026-06-20", "absent_rider_id": 102, "sub_rider_id": 206}, + {"sub_date": "2026-06-21", "absent_rider_id": 103, "sub_rider_id": 207} + ] + ``` + + Each sub rider **must** appear in that day's getriderlogs response. + The assignment engine copies the absent rider's kitchen ownership, soft + preferences, and home location onto the sub rider automatically — reverts + the next day with no action needed. + + Posting the same (sub_date, absent_rider_id) again updates sub_rider_id. + """ + if not entries: + raise HTTPException(status_code=400, detail="Request body must be a non-empty list.") + + try: + from app.services.rider.substitution_service import get_substitution_service + svc = get_substitution_service() + results = [svc.register(e.sub_date, e.absent_rider_id, e.sub_rider_id) for e in entries] + return { + "status": "ok", + "registered": len(results), + "substitutions": results, + } + except Exception as e: + logger.error(f"[Riders API] register_substitution: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +@router.get("/substitution", summary="List upcoming and active rider substitutions") +def list_substitutions(from_date: str = None): + """ + Returns all substitution records on or after `from_date` (default: today). + Use `?from_date=2026-06-01` to look back further. + """ + if from_date is not None: + try: + date.fromisoformat(from_date) + except ValueError: + raise HTTPException( + status_code=400, + detail=f"Invalid date format '{from_date}'. Use YYYY-MM-DD.", + ) + try: + from app.services.rider.substitution_service import get_substitution_service + records = get_substitution_service().list_all(from_date) + return { + "status": "ok", + "count": len(records), + "substitutions": records, + } + except Exception as e: + logger.error(f"[Riders API] list_substitutions: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +@router.delete( + "/substitution/{sub_date}/{absent_rider_id}", + summary="Cancel a rider substitution", +) +def cancel_substitution( + sub_date: str = Path(..., example="2026-06-20"), + absent_rider_id: int = Path(..., example=101), +): + """ + Remove a substitution record. The sub rider will no longer inherit the + absent rider's profile on that date. + """ + try: + date.fromisoformat(sub_date) + except ValueError: + raise HTTPException( + status_code=400, + detail=f"Invalid date format '{sub_date}'. Use YYYY-MM-DD.", + ) + try: + from app.services.rider.substitution_service import get_substitution_service + removed = get_substitution_service().cancel(sub_date, absent_rider_id) + if not removed: + raise HTTPException( + status_code=404, + detail=f"No substitution found for absent_rider_id={absent_rider_id} on {sub_date}.", + ) + return { + "status": "ok", + "message": f"Substitution cancelled: rider {absent_rider_id} on {sub_date}.", + } + except HTTPException: + raise + except Exception as e: + logger.error(f"[Riders API] cancel_substitution: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) diff --git a/app/services/__init__.py b/app/services/__init__.py new file mode 100644 index 0000000..fc9d666 --- /dev/null +++ b/app/services/__init__.py @@ -0,0 +1,175 @@ +"""Services package.""" + +from __future__ import annotations + +import json +import os +import logging +from typing import Any, Optional, Dict + +try: + import redis # type: ignore +except Exception: # pragma: no cover + redis = None # type: ignore + +logger = logging.getLogger(__name__) + + +class RedisCache: + """Lightweight Redis cache wrapper with graceful in-memory fallback.""" + + def __init__(self, url_env: str = "REDIS_URL", default_ttl_seconds: Optional[int] = None) -> None: + import threading + self._lock = threading.Lock() + self._memory_cache: Dict[str, tuple[float, str]] = {} # key -> (expire_time, serialized_value) + + # Allow TTL to be configurable via env var (default 300s = 5 min, or 86400 = 24h) + ttl_env = os.getenv("REDIS_CACHE_TTL_SECONDS") + if default_ttl_seconds is None: + default_ttl_seconds = int(ttl_env) if ttl_env else 300 + + self.default_ttl_seconds = default_ttl_seconds + self._enabled = False + self._client = None + self._stats = {"hits": 0, "misses": 0, "sets": 0} + + url = os.getenv(url_env) + if not url or redis is None: + logger.warning("Redis not configured or client unavailable; falling back to local thread-safe in-memory cache") + return + try: + self._client = redis.Redis.from_url(url, decode_responses=True) + self._client.ping() + self._enabled = True + logger.info(f"Redis cache connected (TTL: {self.default_ttl_seconds}s)") + except Exception as exc: + logger.warning(f"Redis connection failed: {exc}; falling back to local thread-safe in-memory cache") + self._enabled = False + self._client = None + + @property + def enabled(self) -> bool: + return self._enabled and self._client is not None + + def get_json(self, key: str) -> Optional[Any]: + if self.enabled: + try: + raw = self._client.get(key) # type: ignore[union-attr] + if raw: + self._stats["hits"] += 1 + return json.loads(raw) + else: + self._stats["misses"] += 1 + return None + except Exception as exc: + logger.debug(f"Redis get_json error for key={key}: {exc}") + self._stats["misses"] += 1 + return None + else: + import time + with self._lock: + if key in self._memory_cache: + expire_time, raw = self._memory_cache[key] + if expire_time < 0 or expire_time > time.time(): + self._stats["hits"] += 1 + return json.loads(raw) + else: + del self._memory_cache[key] + self._stats["misses"] += 1 + return None + + def set_json(self, key: str, value: Any, ttl_seconds: Optional[int] = None) -> None: + payload = json.dumps(value, default=lambda o: getattr(o, "model_dump", lambda: o)()) + ttl = ttl_seconds if ttl_seconds is not None else self.default_ttl_seconds + + if self.enabled: + try: + if ttl > 0: + self._client.setex(key, ttl, payload) # type: ignore[union-attr] + else: + self._client.set(key, payload) # type: ignore[union-attr] + self._stats["sets"] += 1 + except Exception as exc: + logger.debug(f"Redis set_json error for key={key}: {exc}") + else: + import time + expire_time = (time.time() + ttl) if ttl > 0 else -1.0 + with self._lock: + # Evict oldest keys if cache grows too large to prevent leak + if len(self._memory_cache) >= 2000: + now = time.time() + expired_keys = [k for k, (exp, _) in self._memory_cache.items() if exp > 0 and exp < now] + for k in expired_keys: + del self._memory_cache[k] + if len(self._memory_cache) >= 2000: + first_key = next(iter(self._memory_cache)) + del self._memory_cache[first_key] + self._memory_cache[key] = (expire_time, payload) + self._stats["sets"] += 1 + + def delete(self, pattern: str) -> int: + """Delete keys matching pattern (e.g., 'routes:*'). Returns count deleted.""" + if self.enabled: + try: + keys = list(self._client.scan_iter(match=pattern)) # type: ignore[union-attr] + if keys: + return self._client.delete(*keys) # type: ignore[union-attr] + return 0 + except Exception as exc: + logger.error(f"Redis delete error for pattern={pattern}: {exc}") + return 0 + else: + import fnmatch + deleted = 0 + with self._lock: + keys_to_del = [k for k in self._memory_cache.keys() if fnmatch.fnmatchcase(k, pattern)] + for k in keys_to_del: + del self._memory_cache[k] + deleted += 1 + return deleted + + def get_stats(self) -> Dict[str, Any]: + """Get cache statistics.""" + stats = self._stats.copy() + if self.enabled: + try: + # Count cache keys + route_keys = list(self._client.scan_iter(match="routes:*")) # type: ignore[union-attr] + stats["total_keys"] = len(route_keys) + stats["enabled"] = True + stats["type"] = "Redis" + except Exception: + stats["total_keys"] = 0 + stats["enabled"] = True + stats["type"] = "Redis" + else: + import time + now = time.time() + with self._lock: + active_keys = [k for k, (exp, _) in self._memory_cache.items() if exp < 0 or exp > now] + stats["total_keys"] = len(active_keys) + stats["enabled"] = True + stats["type"] = "In-Memory Fallback" + return stats + + def get_keys(self, pattern: str = "routes:*") -> list[str]: + """Get list of cache keys matching pattern.""" + if self.enabled: + try: + return list(self._client.scan_iter(match=pattern)) # type: ignore[union-attr] + except Exception as exc: + logger.error(f"Redis get_keys error for pattern={pattern}: {exc}") + return [] + else: + import fnmatch + import time + now = time.time() + with self._lock: + return [ + k for k, (exp, _) in self._memory_cache.items() + if (exp < 0 or exp > now) and fnmatch.fnmatchcase(k, pattern) + ] + + +# Singleton cache instance for app +cache = RedisCache() diff --git a/app/services/__pycache__/__init__.cpython-312.pyc b/app/services/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..7a18b5a Binary files /dev/null and b/app/services/__pycache__/__init__.cpython-312.pyc differ diff --git a/app/services/__pycache__/assignment_service.cpython-312.pyc b/app/services/__pycache__/assignment_service.cpython-312.pyc new file mode 100644 index 0000000..6920d30 Binary files /dev/null and b/app/services/__pycache__/assignment_service.cpython-312.pyc differ diff --git a/app/services/__pycache__/clustering_service.cpython-312.pyc b/app/services/__pycache__/clustering_service.cpython-312.pyc new file mode 100644 index 0000000..29c6b35 Binary files /dev/null and b/app/services/__pycache__/clustering_service.cpython-312.pyc differ diff --git a/app/services/__pycache__/get_active_riders.cpython-312.pyc b/app/services/__pycache__/get_active_riders.cpython-312.pyc new file mode 100644 index 0000000..0174795 Binary files /dev/null and b/app/services/__pycache__/get_active_riders.cpython-312.pyc differ diff --git a/app/services/__pycache__/kalman_filter.cpython-312.pyc b/app/services/__pycache__/kalman_filter.cpython-312.pyc new file mode 100644 index 0000000..9d7316a Binary files /dev/null and b/app/services/__pycache__/kalman_filter.cpython-312.pyc differ diff --git a/app/services/__pycache__/ml_data_collector.cpython-312.pyc b/app/services/__pycache__/ml_data_collector.cpython-312.pyc new file mode 100644 index 0000000..e649a1d Binary files /dev/null and b/app/services/__pycache__/ml_data_collector.cpython-312.pyc differ diff --git a/app/services/__pycache__/ml_hypertuner.cpython-312.pyc b/app/services/__pycache__/ml_hypertuner.cpython-312.pyc new file mode 100644 index 0000000..36c5e35 Binary files /dev/null and b/app/services/__pycache__/ml_hypertuner.cpython-312.pyc differ diff --git a/app/services/__pycache__/realistic_eta_calculator.cpython-312.pyc b/app/services/__pycache__/realistic_eta_calculator.cpython-312.pyc new file mode 100644 index 0000000..ca9db86 Binary files /dev/null and b/app/services/__pycache__/realistic_eta_calculator.cpython-312.pyc differ diff --git a/app/services/__pycache__/rider_history_service.cpython-312.pyc b/app/services/__pycache__/rider_history_service.cpython-312.pyc new file mode 100644 index 0000000..23f6505 Binary files /dev/null and b/app/services/__pycache__/rider_history_service.cpython-312.pyc differ diff --git a/app/services/__pycache__/rider_state_manager.cpython-312.pyc b/app/services/__pycache__/rider_state_manager.cpython-312.pyc new file mode 100644 index 0000000..a97fe82 Binary files /dev/null and b/app/services/__pycache__/rider_state_manager.cpython-312.pyc differ diff --git a/app/services/__pycache__/route_optimizer.cpython-312.pyc b/app/services/__pycache__/route_optimizer.cpython-312.pyc new file mode 100644 index 0000000..be28805 Binary files /dev/null and b/app/services/__pycache__/route_optimizer.cpython-312.pyc differ diff --git a/app/services/__pycache__/zone_service.cpython-312.pyc b/app/services/__pycache__/zone_service.cpython-312.pyc new file mode 100644 index 0000000..f6bcf5e Binary files /dev/null and b/app/services/__pycache__/zone_service.cpython-312.pyc differ diff --git a/app/services/core/__pycache__/assignment_service.cpython-312.pyc b/app/services/core/__pycache__/assignment_service.cpython-312.pyc new file mode 100644 index 0000000..12a190e Binary files /dev/null and b/app/services/core/__pycache__/assignment_service.cpython-312.pyc differ diff --git a/app/services/core/assignment_service.py b/app/services/core/assignment_service.py new file mode 100644 index 0000000..d68f6ac --- /dev/null +++ b/app/services/core/assignment_service.py @@ -0,0 +1,1166 @@ +import logging +import random +import time +import math +from math import radians, cos, sin, asin, sqrt, ceil +from typing import List, Dict, Any, Optional, Set +from collections import defaultdict +from app.config.rider_preferences import RIDER_PREFERRED_KITCHENS, BLOCKED_RIDERS as _BLOCKED_RIDERS_SET +from app.services.routing.kalman_filter import ( + smooth_rider_locations, + smooth_order_coordinates, +) +from app.config.dynamic_config import ( + get_config, + get_kitchen_label_id as _get_kitchen_label_id, + get_kitchen_frequency as _get_kitchen_frequency, + update_kitchen_stats, +) +from app.services.ml.ml_data_collector import get_collector + +logger = logging.getLogger(__name__) + + +class DataEncoder: + """ + Data Encoding Utilities for ML-ready feature engineering. + Implements techniques from idea.txt for categorical, spatial, and temporal data. + """ + + EARTH_RADIUS_KM = 6371 + + @staticmethod + def haversine(lat1: float, lon1: float, lat2: float, lon2: float) -> float: + """Calculate great circle distance between two points.""" + try: + lon1, lat1, lon2, lat2 = map( + radians, [float(lon1), float(lat1), float(lon2), float(lat2)] + ) + dlon = lon2 - lon1 + dlat = lat2 - lat1 + a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2 + c = 2 * asin(min(1.0, sqrt(a))) + return c * DataEncoder.EARTH_RADIUS_KM + except: + return 0.0 + + @staticmethod + def cyclic_encode_hour(hour: int) -> tuple[float, float]: + """ + Cyclic time encoding - captures traffic patterns better than discrete buckets. + hour_sin = sin(2π * hour / 24) + hour_cos = cos(2π * hour / 24) + """ + hour_sin = math.sin(2 * math.pi * hour / 24) + hour_cos = math.cos(2 * math.pi * hour / 24) + return hour_sin, hour_cos + + @staticmethod + def cyclic_encode_day(day_of_week: int) -> tuple[float, float]: + """ + Cyclic day encoding for weekly patterns. + """ + day_sin = math.sin(2 * math.pi * day_of_week / 7) + day_cos = math.cos(2 * math.pi * day_of_week / 7) + return day_sin, day_cos + + @staticmethod + def geohash_encode(lat: float, lon: float, precision: int = 7) -> str: + """ + Geohash encoding for spatial data. + Converts lat/lon to grid cell string for locality capture. + precision=7 gives ~153m x 153m cells (good for delivery zones) + """ + try: + return _simple_geohash(lat, lon, precision) + except: + return "unknown" + + +def _simple_geohash(lat: float, lon: float, precision: int = 7) -> str: + """Standard geohash encoding — 5 bits per character, BASE32 output.""" + if lat == 0 or lon == 0: + return "unknown" + BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz" + lat_min, lat_max = -90.0, 90.0 + lon_min, lon_max = -180.0, 180.0 + hash_chars = [] + is_lon = True + for _ in range(precision): + char_bits = 0 + for _ in range(5): + if is_lon: + mid = (lon_min + lon_max) / 2 + if lon >= mid: + char_bits = (char_bits << 1) | 1 + lon_min = mid + else: + char_bits = char_bits << 1 + lon_max = mid + else: + mid = (lat_min + lat_max) / 2 + if lat >= mid: + char_bits = (char_bits << 1) | 1 + lat_min = mid + else: + char_bits = char_bits << 1 + lat_max = mid + is_lon = not is_lon + hash_chars.append(BASE32[char_bits]) + return "".join(hash_chars) + + +def _zone_key(lat: float, lon: float) -> str: + """O(1) ~5 km grid cell key for zone proximity matching.""" + if lat == 0 or lon == 0: + return "unknown" + return f"{int(lat / 0.044)},{int(lon / 0.044)}" + + +# Kitchen encoding now uses persistent DB storage from dynamic_config + + +def update_kitchen_encoding(kitchen_name: str, profit: float = None): + """Update kitchen stats in DB when orders are processed.""" + if kitchen_name and kitchen_name != "Unknown": + if profit is not None: + update_kitchen_stats(kitchen_name, profit) + + +def get_kitchen_label_id(kitchen_name: str) -> int: + """Get persistent label ID for a kitchen.""" + return _get_kitchen_label_id(kitchen_name) + + +def get_kitchen_frequency(kitchen_name: str) -> float: + """Get persistent frequency ratio for a kitchen.""" + return _get_kitchen_frequency(kitchen_name) + + +class AssignmentService: + def __init__(self): + # Curated config drives HARD kitchen ownership. Copy so substitution + # mutations are per-request and never bleed into the module-level dict. + self.rider_preferences = dict(RIDER_PREFERRED_KITCHENS) + # SOFT steering (preference bonus, distance bypass, home bonus) uses the + # learned-augmented view: curated config ∪ learned affinity. Falls back to + # pure config if the affinity service is unavailable. + try: + from app.services.routing.rider_affinity_service import get_rider_affinity + _aff = get_rider_affinity() + self.soft_preferences = _aff.get_preferred_kitchens() + self.home_locations = _aff.get_home_locations() + except Exception: + from app.config.rider_preferences import RIDER_HOME_LOCATIONS as _H + self.soft_preferences = dict(RIDER_PREFERRED_KITCHENS) + self.home_locations = dict(_H) + + # Apply today's substitutions: copy absent rider's profile onto sub rider. + # The sub rider appears in getriderlogs; the absent rider does not. + # Reverts automatically the next day because the lookup is date-keyed. + try: + from app.services.rider.substitution_service import get_substitution_service + _sub_map = get_substitution_service().get_today_map() # {absent_id: sub_id} + if _sub_map: + for _absent_id, _sub_id in _sub_map.items(): + # Hard ownership: sub rider inherits absent rider's kitchens + _absent_hard = self.rider_preferences.get(_absent_id, []) + if _absent_hard: + _sub_hard = list(self.rider_preferences.get(_sub_id, [])) + _hard_lower = {k.lower() for k in _sub_hard} + for _k in _absent_hard: + if _k.lower() not in _hard_lower: + _sub_hard.append(_k) + self.rider_preferences[_sub_id] = _sub_hard + # Soft preferences: merge absent rider's learned kitchens + _absent_soft = self.soft_preferences.get(_absent_id, []) + if _absent_soft: + _sub_soft = list(self.soft_preferences.get(_sub_id, [])) + _soft_lower = {k.lower() for k in _sub_soft} + for _k in _absent_soft: + if _k.lower() not in _soft_lower: + _sub_soft.append(_k) + self.soft_preferences[_sub_id] = _sub_soft + # Home location: use absent rider's home if sub has none + _absent_home = self.home_locations.get(_absent_id, (0.0, 0.0)) + if _absent_home and _absent_home != (0.0, 0.0): + _sub_home = self.home_locations.get(_sub_id, (0.0, 0.0)) + if not _sub_home or _sub_home == (0.0, 0.0): + self.home_locations[_sub_id] = _absent_home + logger.info( + f"[Substitution] {len(_sub_map)} active substitution(s) applied: " + + ", ".join(f"absent={a} → sub={s}" for a, s in _sub_map.items()) + ) + except Exception as _e: + logger.warning(f"[Substitution] Could not apply substitutions: {_e}") + + self.earth_radius_km = 6371 + self._cfg = get_config() + self._encoder = DataEncoder() + + # Cost parameters for composite cost function + self._fuel_rate = 2.5 # Per km + self._base_rider_cost = 0.0 + self._merchant_margin_avg = 5.0 # Default average margin + + # Profit encoding cache + self._kitchen_profit_cache: Dict[str, List[float]] = defaultdict(list) + self._profit_mean = 0.0 + self._profit_std = 1.0 + + def calculate_order_profit_features( + self, order: Dict[str, Any], distance_km: float + ) -> Dict[str, float]: + """ + Calculate engineered profit features for ML-ready data. + + Features: + - profit: order amount - rider cost + - profit_density: profit per kilometer (key signal!) + - cost_efficiency: rider cost per estimated time + - route_score: profit - composite cost (maximize this!) + - encoded_geohash: spatial encoding + - cyclic_time: hour_sin, hour_cos + """ + features = {} + + # Extract order values + try: + order_amount = float( + order.get("orderamount") or order.get("deliveryamount") or 0 + ) + except: + order_amount = 0.0 + + # Calculate rider cost: base + (distance * fuel_rate) + rider_cost = self._base_rider_cost + (distance_km * self._fuel_rate) + features["rider_cost"] = rider_cost + + # Profit = revenue - cost + profit = order_amount - rider_cost + features["profit"] = profit + + # Profit density = profit / distance (HIGH SIGNAL feature!) + # High density = profitable short deliveries + if distance_km > 0: + features["profit_density"] = profit / distance_km + else: + features["profit_density"] = 0.0 + + # Cost efficiency = cost / time estimate (assuming 15 min per order average) + estimated_time_min = max(15, distance_km * 4) # Rough estimate + features["cost_efficiency"] = ( + rider_cost / estimated_time_min if estimated_time_min > 0 else 0 + ) + + # Route score = profit - distance_cost (what we want to MAXIMIZE) + # This is the core optimization target + features["route_score"] = profit - ( + distance_km * 0.5 + ) # 0.5 = opportunity cost per km + + # Composite edge weight for optimizer (MINIMIZE this) + # weight = cost - profit_margin_bonus + features["composite_weight"] = rider_cost - (profit * 0.3) # 30% profit bonus + + return features + + def _load_config(self): + """Load ML-tuned hyperparams fresh on every assignment call.""" + cfg = self._cfg + self.MAX_PICKUP_DISTANCE_KM = cfg.get("max_pickup_distance_km") + self.MAX_KITCHEN_DISTANCE_KM = cfg.get("max_kitchen_distance_km") + + # Hard cap: ML hypertuner must never exceed 12 orders per rider. + # Food delivery reality — more than 12 stops means 90+ min routes, + # cold food, and rider exhaustion. The tuner found 20 optimal for + # some statistical metric but that is operationally unacceptable. + _raw_max = int(cfg.get("max_orders_per_rider")) + self.MAX_ORDERS_PER_RIDER = min(_raw_max, 12) + + # Ideal load must be ≥ half of max so fill-before-spill is meaningful. + # ideal_load=4 with max=12 means riders switch at 33% — too early. + # Floor at 6 so a rider reaches 50% before we open a new one. + _raw_ideal = int(cfg.get("ideal_load")) + self.IDEAL_LOAD = max(_raw_ideal, 6) + + # ── DYNAMIC NEW-RIDER PENALTY ───────────────────────────────────── + # WORKLOAD_PENALTY_WEIGHT must be loaded FIRST so that NEW_RIDER_PENALTY + # (which depends on it) can be computed correctly. + # + # Bug that was here: NEW_RIDER_PENALTY was calculated on the line ABOVE + # the line that sets WORKLOAD_PENALTY_WEIGHT, causing AttributeError on + # the first call and stale values on every subsequent call. + # + # Fix: NEW_RIDER_PENALTY = WORKLOAD_PENALTY_WEIGHT × 1.5 + # This guarantees non-preferred riders NEVER beat a preferred rider + # at ANY load level (max preferred score = 76.82, penalty = 115.2). + # Preferred riders fill to capacity before others are ever opened. + self.WORKLOAD_BALANCE_THRESHOLD = cfg.get("workload_balance_threshold") + self.WORKLOAD_PENALTY_WEIGHT = cfg.get("workload_penalty_weight") # ← set FIRST + self.NEW_RIDER_PENALTY = self.WORKLOAD_PENALTY_WEIGHT * 1.5 # ← then derived + self.DISTANCE_PENALTY_WEIGHT = cfg.get("distance_penalty_weight") + self.PREFERENCE_BONUS = cfg.get("preference_bonus") + self.HOME_ZONE_BONUS_4KM = cfg.get("home_zone_bonus_4km") + self.HOME_ZONE_BONUS_2KM = cfg.get("home_zone_bonus_2km") + self.EMERGENCY_LOAD_PENALTY = cfg.get("emergency_load_penalty") + + def haversine(self, lat1, lon1, lat2, lon2): + """Calculate the great circle distance between two points.""" + lon1, lat1, lon2, lat2 = map( + radians, [float(lon1), float(lat1), float(lon2), float(lat2)] + ) + dlon = lon2 - lon1 + dlat = lat2 - lat1 + a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2 + c = 2 * asin(min(1.0, sqrt(a))) # Clamp to 1.0 to avoid domain errors + return c * self.earth_radius_km + + def get_lat_lon(self, obj: Dict[str, Any], prefix: str = "") -> tuple[float, float]: + """Generic helper to extract lat/lon from diversely named keys.""" + # Try specific prefixes first + candidates = [ + (f"{prefix}lat", f"{prefix}lon"), + (f"{prefix}lat", f"{prefix}long"), + (f"{prefix}latitude", f"{prefix}longitude"), + ] + # Also try standard keys if prefix fails + candidates.extend( + [ + ("lat", "lon"), + ("latitude", "longitude"), + ("pickuplat", "pickuplon"), + ("pickuplat", "pickuplong"), + ("deliverylat", "deliverylong"), + ("droplat", "droplon"), + ] + ) + + for lat_key, lon_key in candidates: + if lat_key in obj and lon_key in obj and obj[lat_key] and obj[lon_key]: + try: + return float(obj[lat_key]), float(obj[lon_key]) + except: + pass + + # Special case: nested 'pickup_location' + if "pickup_location" in obj: + return self.get_lat_lon(obj["pickup_location"]) + + return 0.0, 0.0 + + def get_order_kitchen(self, order: Dict[str, Any]) -> str: + possible_keys = [ + "pickupcustomer", # confirmed primary field in production orders + "locationname", # confirmed backup field in production orders + "storename", "store_name", + "restaurantname", "restaurant_name", + "kitchenname", "kitchen_name", + "partnername", "partner_name", + "tenantname", + ] + for key in possible_keys: + if key in order and order[key]: + return str(order[key]).strip() + return "Unknown" + + def _select_coverage_riders( + self, + valid_riders: List[Dict], + clusters: List[Dict], + target_count: int, + rider_states: Dict, + ) -> Set[int]: + """ + Greedy set-cover: select the minimal set of riders that geographically + covers all kitchen cluster centroids within MAX_PICKUP_DISTANCE_KM. + + Step 1: greedily pick rider that covers the most uncovered clusters. + Step 2: pad up to target_count with remaining riders ordered by total + distance to all cluster centroids (closest = most useful). + + Returns a set of rider IDs that form the preferred/pre-selected pool. + """ + if not valid_riders or not clusters: + return {r["id"] for r in valid_riders[:target_count]} + + # Sort by ID so greedy selection is deterministic regardless of + # the order riders arrive in the API response. + valid_riders = sorted(valid_riders, key=lambda r: r["id"]) + + selected_ids: Set[int] = set() + uncovered = list(range(len(clusters))) + + # Step 1 — greedy max-coverage selection + while len(selected_ids) < target_count and uncovered: + best_rider = None + best_coverage = -1 + + for r in valid_riders: + if r["id"] in selected_ids: + continue + coverage = sum( + 1 + for ci in uncovered + if self.haversine( + r["lat"], r["lon"], + clusters[ci]["centroid"][0], clusters[ci]["centroid"][1], + ) <= self.MAX_PICKUP_DISTANCE_KM + ) + if coverage > best_coverage: + best_coverage = coverage + best_rider = r + + if not best_rider or best_coverage == 0: + break + + selected_ids.add(best_rider["id"]) + # Remove clusters now covered by this rider + uncovered = [ + ci for ci in uncovered + if self.haversine( + best_rider["lat"], best_rider["lon"], + clusters[ci]["centroid"][0], clusters[ci]["centroid"][1], + ) > self.MAX_PICKUP_DISTANCE_KM + ] + + # Step 2 — pad with closest-aggregate riders up to target_count + if len(selected_ids) < target_count: + def total_dist_to_clusters(r): + return sum( + self.haversine( + r["lat"], r["lon"], + c["centroid"][0], c["centroid"][1], + ) + for c in clusters + ) + + remaining = sorted( + [r for r in valid_riders if r["id"] not in selected_ids], + key=total_dist_to_clusters, + ) + for r in remaining: + selected_ids.add(r["id"]) + if len(selected_ids) >= target_count: + break + + return selected_ids + + async def assign_orders( + self, + orders: List[Dict[str, Any]], + riders: List[Dict[str, Any]], + reshuffle: bool = False, + fuel_charge: float = 2.5, + base_pay: float = 0.0, + ) -> tuple[Dict[int, List[Dict[str, Any]]], List[Dict[str, Any]]]: + """ + ENHANCED: Cluster-Based Load-Balanced Assignment with Minimal Rider Selection. + + Strategy: + 1. Cluster orders by kitchen proximity + 2. Pre-select the MINIMUM set of riders needed to handle all orders + (ceil(total_orders / max_orders_per_rider)) via greedy set-cover. + 3. FILL-BEFORE-SPILL: prefer already-started riders until ideal_load + before activating a fresh rider — reduces rider count for small batches. + 4. Assign clusters to best-fit riders (proximity + workload balance) + 5. Rebalance if needed + + If reshuffle=True, controlled randomness is injected into rider scoring + so that retrying the same input can explore alternative assignments. + """ + from app.services.rider.rider_history_service import RiderHistoryService + from app.services.rider.rider_state_manager import RiderStateManager + from app.services.routing.clustering_service import ClusteringService + + # -- Load ML-tuned hyperparameters (or defaults on first run) ------ + self._load_config() + # Use caller-supplied pricing so dynamic API rates flow into scoring + self._fuel_rate = fuel_charge + self._base_rider_cost = base_pay + _call_start = time.time() + + # 0. Prep + assignments: Dict[int, List[Dict[str, Any]]] = defaultdict(list) + unassigned_orders: List[Dict[str, Any]] = [] + rider_states = {} # Track live load + + # 0a. KALMAN FILTER - Smooth rider GPS locations before scoring + riders = smooth_rider_locations(list(riders)) + + # 0b. KALMAN FILTER - Smooth order delivery coordinates before clustering + orders = smooth_order_coordinates(list(orders)) + + # 1. Parse and Filter Riders + valid_riders = [] + BLOCKED_RIDERS = _BLOCKED_RIDERS_SET # frozenset — single source of truth, O(1) lookup + + # Load Existing State (Persistence) + state_mgr = RiderStateManager() + + for r in riders: + # Robust ID Extraction + rid_raw = r.get("userid") or r.get("riderid") or r.get("id") or r.get("_id") + try: + rid = int(rid_raw) + except (ValueError, TypeError): + continue + + if rid in BLOCKED_RIDERS: + continue + + # Robust Status Check + # Keep if: onduty (1, "1", True) OR status is active/idle/online + is_onduty = str(r.get("onduty")) in ["1", "True"] or r.get("onduty") is True + is_active = r.get("status") in ["active", "idle", "online"] + + if not (is_onduty or is_active): + continue + + # Location + lat, lon = self.get_lat_lon(r) + + # Fetch previous state to know if they are already busy + p_state = state_mgr.get_rider_state(rid) + + # If rider has valid GPS, use it. If not, fallback to Last Drop or Home. + if lat == 0 or lon == 0: + if p_state["last_drop_lat"]: + lat, lon = p_state["last_drop_lat"], p_state["last_drop_lon"] + else: + # Home Location Fallback (learned-augmented) + lat, lon = self.home_locations.get(rid, (0.0, 0.0)) + + valid_riders.append({"id": rid, "lat": lat, "lon": lon, "obj": r}) + + # Initialize rider state with existing workload + existing_load = ( + p_state.get("minutes_remaining", 0) / 15 + ) # Convert minutes to order estimate + + rider_states[rid] = { + "lat": lat, + "lon": lon, + "kitchens": set(), + "count": int(existing_load), # Start with existing workload + "workload_score": existing_load, # For prioritization + } + + if not valid_riders: + logger.warning( + "No riders passed on-duty filter. Retrying with all available riders as emergency rescue..." + ) + # If no on-duty riders, we take ANY rider provided by the API to ensure assignment + for r in riders: + rid = int(r.get("userid", 0)) + if rid in _BLOCKED_RIDERS_SET: + continue + + lat, lon = self.get_lat_lon(r) + if lat == 0 or lon == 0: + lat, lon = self.home_locations.get(rid, (0.0, 0.0)) + + if lat != 0: + valid_riders.append({"id": rid, "lat": lat, "lon": lon, "obj": r}) + rider_states[rid] = { + "lat": lat, + "lon": lon, + "kitchens": set(), + "count": 0, + "workload_score": 0, + } + + if not valid_riders: + logger.error("DANGER: Absolutely no riders available for assignment.") + # Mark all as unassigned + for o in orders: + o["unassigned_reason"] = ( + "No riders found (check partner online status)." + ) + unassigned_orders.append(o) + return assignments, unassigned_orders + + logger.info(f"Found {len(valid_riders)} active riders") + + # 2. CLUSTER ORDERS BY KITCHEN PROXIMITY + clustering_service = ClusteringService() + clusters = clustering_service.cluster_orders_by_kitchen( + orders, max_cluster_radius_km=self.MAX_KITCHEN_DISTANCE_KM + ) + + # 2b. ENRICH CLUSTERS WITH PROFIT FEATURES (Data Encoding: Target + Frequency) + for cluster in clusters: + cluster["kitchen_names"] = set() + for order in cluster["orders"]: + k_name = self.get_order_kitchen(order) + cluster["kitchen_names"].add(k_name) + update_kitchen_encoding(k_name) + + # Update kitchen profit cache for target encoding + for order in cluster["orders"]: + k_name = self.get_order_kitchen(order) + profit = ( + float(order.get("orderamount") or order.get("deliveryamount") or 50) + - 40 + ) + self._kitchen_profit_cache[k_name].append(profit) + + # Calculate profit statistics for normalization + all_profits = [ + p for profits in self._kitchen_profit_cache.values() for p in profits + ] + if all_profits: + self._profit_mean = sum(all_profits) / len(all_profits) + if len(all_profits) > 1: + variance = sum((p - self._profit_mean) ** 2 for p in all_profits) / len( + all_profits + ) + self._profit_std = variance**0.5 + + logger.info(f"Created {len(clusters)} order clusters with profit encoding") + + # 2c. MINIMAL RIDER PRE-SELECTION + # Calculate the theoretical minimum number of riders needed so we don't + # spray 40 orders across 9 riders when 4-5 would suffice. + min_riders_needed = max(1, ceil(len(orders) / self.MAX_ORDERS_PER_RIDER)) + # Cap at available riders + min_riders_needed = min(min_riders_needed, len(valid_riders)) + + # Fair-share target: maximum orders any single rider should ideally carry. + # Used as a per-batch cap so no rider consumes an entire large cluster + # while other riders sit idle (the 15-16 vs 3-4 imbalance pattern). + target_orders_per_rider = ceil(len(orders) / min_riders_needed) + + preferred_rider_ids = self._select_coverage_riders( + valid_riders, clusters, min_riders_needed, rider_states + ) + logger.info( + f"[MinRider] {len(orders)} orders → min {min_riders_needed} riders needed " + f"(capacity {self.MAX_ORDERS_PER_RIDER}/rider). " + f"Pre-selected coverage pool: {preferred_rider_ids}" + ) + + # 3. ASSIGN CLUSTERS TO RIDERS (Fill-Before-Spill, Load-Balanced) + for cluster_idx, cluster in enumerate(clusters): + centroid_lat, centroid_lon = cluster["centroid"] + cluster_orders = cluster["orders"] + cluster_size = len(cluster_orders) + + logger.info( + f"Assigning cluster {cluster_idx + 1}/{len(clusters)}: {cluster_size} orders at ({centroid_lat:.4f}, {centroid_lon:.4f})" + ) + + # Find best riders for this cluster + candidate_riders = [] + + # Calculate cluster-level profit features (Data Encoding: Engineered Features) + cluster_profit = 0.0 + cluster_profit_density = 0.0 + cluster_geohash = _zone_key(centroid_lat, centroid_lon) + + for order in cluster_orders: + k_name = self.get_order_kitchen(order) + # Target encoding: use average profit for this kitchen + kitchen_profits = self._kitchen_profit_cache.get(k_name, [0]) + avg_kitchen_profit = ( + sum(kitchen_profits) / len(kitchen_profits) + if kitchen_profits + else 0 + ) + + o_lat = float(order.get("pickuplat", 0)) + o_lon = float(order.get("pickuplon", 0)) + dist = ( + self.haversine(centroid_lat, centroid_lon, o_lat, o_lon) + if o_lat + else 2.0 + ) + + profit_features = self.calculate_order_profit_features(order, dist) + cluster_profit += profit_features["profit"] + cluster_profit_density += profit_features["profit_density"] + + avg_profit_density = ( + cluster_profit_density / cluster_size if cluster_size > 0 else 0 + ) + + # ── HARD KITCHEN OWNERSHIP (rider_preferences.py = source of truth) ── + # Step 1: find which rider IDs are configured for this cluster's kitchens + cluster_preferred_rids: set = set() + for k_name in cluster["kitchen_names"]: + k_lower = k_name.lower() + for cfg_rid, cfg_prefs in self.rider_preferences.items(): + for p in cfg_prefs: + if p.lower() in k_lower or k_lower in p.lower(): + cluster_preferred_rids.add(cfg_rid) + + # Step 2: among those, which are actually in the active fleet with capacity? + active_preferred_with_cap = { + r["id"] for r in valid_riders + if r["id"] in cluster_preferred_rids + and rider_states[r["id"]]["count"] < self.MAX_ORDERS_PER_RIDER + } + + # RULE: if at least one configured rider is available with capacity, + # only that rider (or those riders) can be assigned this cluster's orders. + # Non-configured riders are completely skipped. + # If NO configured rider is available (all full / off-duty), open to all. + kitchen_has_owner = bool(active_preferred_with_cap) + + if cluster_preferred_rids: + logger.info( + f" [Kitchen owner] cluster kitchens={list(cluster['kitchen_names'])} " + f"→ configured riders={cluster_preferred_rids} " + f"| active+capacity={active_preferred_with_cap} " + f"| hard_lock={'YES' if kitchen_has_owner else 'NO (overflow)'}" + ) + + for r in valid_riders: + rid = r["id"] + r_state = rider_states[rid] + + # ── HARD KITCHEN LOCK ──────────────────────────────────────── + # If this kitchen has an owner and this rider isn't the owner → skip + if kitchen_has_owner and rid not in active_preferred_with_cap: + continue + + # Calculate distance to cluster centroid + dist = self.haversine( + r_state["lat"], r_state["lon"], centroid_lat, centroid_lon + ) + + # Preference flag (SOFT: distance-limit bypass + preference bonus). + # Uses learned-augmented prefs so riders who actually serve a + # kitchen are steered there even if not in the curated config. + prefs = self.soft_preferences.get(rid, []) + has_preference = False + for k_name in cluster["kitchen_names"]: + if any( + p.lower() in k_name.lower() or k_name.lower() in p.lower() + for p in prefs + ): + has_preference = True + break + + # Dynamic Limit: 6km default, 10km for preferred kitchens + allowed_dist = self.MAX_PICKUP_DISTANCE_KM + if has_preference: + allowed_dist = max(allowed_dist, 10.0) + + # Skip if too far + if dist > allowed_dist: + continue + + # Calculate workload utilization (0.0 to 1.0) + utilization = r_state["count"] / self.MAX_ORDERS_PER_RIDER + + # ── FILL-BEFORE-SPILL workload scoring ────────────────────── + # Goal: fill a started rider to IDEAL_LOAD before routing orders + # to a fresh rider. This naturally minimises active rider count. + # + # • count == 0, not in pre-selected pool → NEW_RIDER_PENALTY + # (heavy cost to discourage opening a new rider unnecessarily) + # • count == 0, in pre-selected pool → neutral (no penalty) + # • 0 < count < IDEAL_LOAD → FILL_BONUS (negative = better score) + # bonus grows as the rider is closer to full + # • count >= IDEAL_LOAD → linear workload penalty (ML-tuned) + # ───────────────────────────────────────────────────────────── + # Use the dynamic NEW_RIDER_PENALTY computed in _load_config + # (= WORKLOAD_PENALTY_WEIGHT × 1.5, always above any possible + # workload score so non-preferred riders never open early). + NEW_RIDER_PENALTY = self.NEW_RIDER_PENALTY + FILL_BONUS_PER_SLOT = 8.0 # reward per empty slot below ideal_load + + is_preferred = rid in preferred_rider_ids + current_count = r_state["count"] + + if current_count == 0: + if is_preferred: + workload_penalty = 0.0 # Pre-selected, neutral cost + else: + workload_penalty = NEW_RIDER_PENALTY # Discourage extra riders + elif current_count < self.IDEAL_LOAD: + # Strong incentive to fill an already-started rider + slots_remaining = self.IDEAL_LOAD - current_count + workload_penalty = -(slots_remaining * FILL_BONUS_PER_SLOT) + else: + # Above ideal load — apply ML-tuned linear penalty + workload_penalty = utilization * self.WORKLOAD_PENALTY_WEIGHT + + distance_penalty = dist * self.DISTANCE_PENALTY_WEIGHT + + # Preference bonus (ML-tuned) + preference_bonus = self.PREFERENCE_BONUS if has_preference else 0 + + # Home zone bonus (ML-tuned). Uses learned-augmented home coords. + h_lat, h_lon = self.home_locations.get(rid, (0.0, 0.0)) + home_bonus = 0 + if h_lat != 0: + home_dist = self.haversine(h_lat, h_lon, centroid_lat, centroid_lon) + if home_dist <= 4.0: + home_bonus = self.HOME_ZONE_BONUS_4KM + if home_dist <= 2.0: + home_bonus = self.HOME_ZONE_BONUS_2KM + + # PROFIT-AWARE SCORING (Data Encoding: Composite Cost Function) + # Higher profit density clusters should get priority (lower score = better) + profit_bonus = avg_profit_density * 10 # Scale up profit density signal + + # Geohash zone proximity bonus + # The _simple_geohash produces a binary bit-string (only '0'/'1' chars). + # precision=25 → 13 lon bits + 12 lat bits (alternating). + # Global lon range (360°) / 2^13 = 0.044° ≈ 4.9 km per cell. + # Global lat range (180°) / 2^12 = 0.044° ≈ 4.9 km per cell. + # Full 25-char prefix comparison = exact same ~5km cell. + h_geohash = _zone_key(h_lat, h_lon) if h_lat != 0 else "" + geohash_match_bonus = 0 + if h_geohash and cluster_geohash not in ("", "unknown"): + if h_geohash == cluster_geohash: + geohash_match_bonus = -15 # Negative = better score (≈6km zone match) + + score = ( + workload_penalty + + distance_penalty + + preference_bonus + + home_bonus + - profit_bonus + + geohash_match_bonus # Profit-aware scoring + ) + + # RESHUFFLE: Add controlled noise so retries explore different riders + if reshuffle: + noise = random.uniform(-15.0, 15.0) + score += noise + + candidate_riders.append( + { + "id": rid, + "score": score, + "distance": dist, + "utilization": utilization, + "current_load": r_state["count"], + # Store per-candidate bonuses so the re-scorer inside the + # inner while-loop can reconstruct the full score correctly + # (Bug fix: old re-scorer dropped these, reverting to + # plain distance+workload after the first batch assignment). + "_preference_bonus": preference_bonus, + "_home_bonus": home_bonus, + "_profit_bonus": profit_bonus, + "_geohash_match_bonus": geohash_match_bonus, + } + ) + + if not candidate_riders: + logger.warning(f"No riders available for cluster {cluster_idx + 1}") + for o in cluster_orders: + o["unassigned_reason"] = ( + f"No riders within {self.MAX_PICKUP_DISTANCE_KM}km radius of kitchen." + ) + unassigned_orders.append(o) + continue + + # Sort by score (best first) + candidate_riders.sort(key=lambda x: x["score"]) + + # SMART DISTRIBUTION: Split cluster if needed + remaining_orders = cluster_orders[:] + + while remaining_orders and candidate_riders: + best_rider = candidate_riders[0] + rid = best_rider["id"] + r_state = rider_states[rid] + + # How many orders can this rider take? + available_capacity = self.MAX_ORDERS_PER_RIDER - r_state["count"] + + if available_capacity <= 0: + # Rider is full, remove from candidates + candidate_riders.pop(0) + continue + + # Decide batch size + # ── FAIR-SHARE CAP ──────────────────────────────────────────── + # Never give a rider more than (target_orders_per_rider - current) + # in a single iteration. This prevents one rider consuming an + # entire large cluster (e.g. 15 orders) while 3 others stay idle. + # max(1, ...) ensures the loop always makes forward progress even + # if the rider has slightly exceeded their target. + _fairshare_remaining = max(1, target_orders_per_rider - r_state["count"]) + + if best_rider["utilization"] < self.WORKLOAD_BALANCE_THRESHOLD: + # Rider has capacity — cap at fair share for balanced distribution + batch_size = min(available_capacity, len(remaining_orders), _fairshare_remaining) + else: + # Rider is getting busy, be conservative (IDEAL_LOAD from ML) + batch_size = min( + self.IDEAL_LOAD - r_state["count"], + len(remaining_orders), + available_capacity, + _fairshare_remaining, + ) + batch_size = max(1, batch_size) # At least 1 order + + # Assign batch + batch = remaining_orders[:batch_size] + remaining_orders = remaining_orders[batch_size:] + + assignments[rid].extend(batch) + + # Update rider state + r_state["count"] += len(batch) + r_state["lat"] = centroid_lat + r_state["lon"] = centroid_lon + r_state["kitchens"].update(cluster["kitchen_names"]) + r_state["workload_score"] = r_state["count"] / self.MAX_ORDERS_PER_RIDER + + logger.info( + f" -> Assigned {len(batch)} orders to Rider {rid} (load: {r_state['count']}/{self.MAX_ORDERS_PER_RIDER})" + ) + + # Re-sort candidates by updated scores (use ML-tuned weights, not hardcoded). + # Only the rider that just received orders needs a score update; all others + # keep their current scores (their workload didn't change). + for candidate in candidate_riders: + if candidate["id"] == rid: + new_count = rider_states[candidate["id"]]["count"] + new_util = new_count / self.MAX_ORDERS_PER_RIDER + candidate["utilization"] = new_util + candidate["current_load"] = new_count + + # Reapply fill-before-spill workload component + if new_count == 0: + _wp = 0.0 if candidate["id"] in preferred_rider_ids else self.NEW_RIDER_PENALTY + elif new_count < self.IDEAL_LOAD: + _wp = -((self.IDEAL_LOAD - new_count) * 8.0) + else: + _wp = new_util * self.WORKLOAD_PENALTY_WEIGHT + + # Bug fix: restore ALL scoring components, not just workload+distance. + # The previous code dropped preference_bonus, home_bonus, profit_bonus, + # and geohash_match_bonus, reverting to plain distance+workload + # for every cluster iteration after the first batch was assigned. + candidate["score"] = ( + _wp + + candidate["distance"] * self.DISTANCE_PENALTY_WEIGHT + + candidate["_preference_bonus"] + + candidate["_home_bonus"] + - candidate["_profit_bonus"] + + candidate["_geohash_match_bonus"] + ) + + candidate_riders.sort(key=lambda x: x["score"]) + + # If any orders left in the cluster after exhaustion of candidates + if remaining_orders: + # Instead of giving up, keep them in a pool for mandatory assignment + unassigned_orders.extend(remaining_orders) + + # 4. EMERGENCY MANDATORY ASSIGNMENT (Ensures 0 unassigned if riders exist) + if unassigned_orders and valid_riders: + logger.info( + f"[ALERT] Starting Emergency Mandatory Assignment for {len(unassigned_orders)} orders..." + ) + force_pool = unassigned_orders[:] + unassigned_orders.clear() + + for o in force_pool: + # Determine pickup location + o_lat, o_lon = self.get_lat_lon(o, prefix="pickup") + if o_lat == 0: + o["unassigned_reason"] = "Could not geolocate order (0,0)." + unassigned_orders.append(o) + continue + + # Find the 'least bad' rider (Closest + Balanced Load) + best_emergency_rider = None + best_emergency_score = float("inf") + + for r in valid_riders: + rid = r["id"] + r_state = rider_states[rid] + + dist = self.haversine(r_state["lat"], r_state["lon"], o_lat, o_lon) + # For emergency: Distance is important, but load prevents one rider taking EVERYTHING + # Score = distance + ML-tuned penalty per existing order + e_score = dist + (r_state["count"] * self.EMERGENCY_LOAD_PENALTY) + + if e_score < best_emergency_score: + best_emergency_score = e_score + best_emergency_rider = rid + + if best_emergency_rider: + assignments[best_emergency_rider].append(o) + rider_states[best_emergency_rider]["count"] += 1 + logger.info( + f" Force-Assigned order {o.get('orderid')} to Rider {best_emergency_rider} (Score: {best_emergency_score:.2f})" + ) + else: + unassigned_orders.append(o) + + # 5. FINAL REBALANCING (Optional) + # Check if any rider is overloaded while others are idle + self._rebalance_workload(assignments, rider_states, valid_riders) + + # 6. Commit State and History + self._post_process(assignments, rider_states, state_mgr) + + # 7. -- ML DATA COLLECTION ----------------------------------------- + try: + elapsed_ms = (time.time() - _call_start) * 1000 + get_collector().log_assignment_event( + num_orders=len(orders), + num_riders=len(riders), + hyperparams=self._cfg.get_all(), + assignments=assignments, + unassigned_count=len(unassigned_orders), + elapsed_ms=elapsed_ms, + ) + except Exception as _ml_err: + logger.debug(f"ML logging skipped: {_ml_err}") + + # Log final distribution (use r_orders to avoid shadowing the outer `orders` list) + logger.info("=" * 50) + logger.info("FINAL ASSIGNMENT DISTRIBUTION:") + for rid, r_orders in sorted(assignments.items()): + logger.info(f" Rider {rid}: {len(r_orders)} orders") + + if unassigned_orders: + logger.warning( + f" [ALERT] STILL UNASSIGNED: {len(unassigned_orders)} (Reason: No riders online or invalid coords)" + ) + else: + logger.info(" [OK] ALL ORDERS ASSIGNED SUCCESSFULLY") + logger.info("=" * 50) + + return assignments, unassigned_orders + + def _rebalance_workload( + self, assignments: Dict[int, List], rider_states: Dict, valid_riders: List + ): + """ + Rebalance if workload is heavily skewed. + Move orders from overloaded riders to idle ones if possible. + """ + if not assignments: + return + + # Calculate average load — divide by ACTIVE riders only (those with ≥1 order), + # not all valid riders. Using all riders artificially lowers avg_load and causes + # false-positive over/under-load detection. + total_orders = sum(len(rl) for rl in assignments.values()) + active_rider_count = sum(1 for r in valid_riders if rider_states[r["id"]]["count"] > 0) + avg_load = total_orders / active_rider_count if active_rider_count > 0 else 0 + + # Find overloaded and underutilized riders + overloaded = [] + underutilized = [] + + for r in valid_riders: + rid = r["id"] + load = rider_states[rid]["count"] + + if load > avg_load * 1.5 and load > self.IDEAL_LOAD: # 50% above average + overloaded.append(rid) + elif load < avg_load * 0.5: # 50% below average + underutilized.append(rid) + + if not overloaded or not underutilized: + return + + logger.info( + f"Rebalancing: {len(overloaded)} overloaded, {len(underutilized)} underutilized riders" + ) + + # Try to move orders from overloaded to underutilized + for over_rid in overloaded: + over_orders = assignments[over_rid] + over_state = rider_states[over_rid] + + # Try to offload some orders + for under_rid in underutilized: + under_state = rider_states[under_rid] + under_capacity = self.MAX_ORDERS_PER_RIDER - under_state["count"] + + if under_capacity <= 0: + continue + + # Find orders that are closer to underutilized rider + transferable = [] + for order in over_orders: + o_lat, o_lon = self.get_lat_lon(order, prefix="pickup") + if o_lat == 0: + continue + + dist_to_under = self.haversine( + under_state["lat"], under_state["lon"], o_lat, o_lon + ) + dist_to_over = self.haversine( + over_state["lat"], over_state["lon"], o_lat, o_lon + ) + + # Transfer if underutilized rider is closer or similar distance + if ( + dist_to_under <= self.MAX_PICKUP_DISTANCE_KM + and dist_to_under <= dist_to_over * 1.2 + ): + transferable.append(order) + + if transferable: + # Transfer up to capacity. + # over_state["count"] - IDEAL_LOAD is the surplus above ideal; + # guard with max(1, ...) so we always move at least one order + # and never get a zero/negative transfer_count. + surplus = max(1, over_state["count"] - self.IDEAL_LOAD) + transfer_count = min( + len(transferable), + under_capacity, + surplus, + ) + transfer_batch = transferable[:transfer_count] + + # Move orders + for order in transfer_batch: + over_orders.remove(order) + assignments[under_rid].append(order) + + # Update states + over_state["count"] -= len(transfer_batch) + under_state["count"] += len(transfer_batch) + + logger.info( + f" Rebalanced: {len(transfer_batch)} orders from Rider {over_rid} -> {under_rid}" + ) + + def _post_process(self, assignments, rider_states, state_mgr): + """Update History and Persistence.""" + from app.services.rider.rider_history_service import RiderHistoryService + + history_service = RiderHistoryService() + ts = time.time() + + for rid, rider_orders in assignments.items(): + if not rider_orders: + continue + + # Calculate actual cumulative distance for this rider instead of + # the old hardcoded 5.0 km placeholder. + total_km = 0.0 + for o in rider_orders: + try: + total_km += float(o.get("actualkms") or o.get("kms") or 0) + except (TypeError, ValueError): + pass + + history_service.update_rider_stats(rid, total_km, len(rider_orders)) + + st = rider_states[rid] + # ETA per order ≈ 15 min (used for workload decay in RiderStateManager) + state_mgr.states[rid] = { + "minutes_remaining": len(rider_orders) * 15, + "last_drop_lat": st["lat"], + "last_drop_lon": st["lon"], + "active_kitchens": st["kitchens"], + "last_updated_ts": ts, + } + + state_mgr._save_states() diff --git a/app/services/ml/__pycache__/behavior_analyzer.cpython-312.pyc b/app/services/ml/__pycache__/behavior_analyzer.cpython-312.pyc new file mode 100644 index 0000000..f6780d6 Binary files /dev/null and b/app/services/ml/__pycache__/behavior_analyzer.cpython-312.pyc differ diff --git a/app/services/ml/__pycache__/id3_classifier.cpython-312.pyc b/app/services/ml/__pycache__/id3_classifier.cpython-312.pyc new file mode 100644 index 0000000..f632f52 Binary files /dev/null and b/app/services/ml/__pycache__/id3_classifier.cpython-312.pyc differ diff --git a/app/services/ml/__pycache__/ml_data_collector.cpython-312.pyc b/app/services/ml/__pycache__/ml_data_collector.cpython-312.pyc new file mode 100644 index 0000000..63f726b Binary files /dev/null and b/app/services/ml/__pycache__/ml_data_collector.cpython-312.pyc differ diff --git a/app/services/ml/__pycache__/route_score_predictor.cpython-312.pyc b/app/services/ml/__pycache__/route_score_predictor.cpython-312.pyc new file mode 100644 index 0000000..877bb08 Binary files /dev/null and b/app/services/ml/__pycache__/route_score_predictor.cpython-312.pyc differ diff --git a/app/services/ml/__pycache__/strategy_bandit.cpython-312.pyc b/app/services/ml/__pycache__/strategy_bandit.cpython-312.pyc new file mode 100644 index 0000000..41ea63f Binary files /dev/null and b/app/services/ml/__pycache__/strategy_bandit.cpython-312.pyc differ diff --git a/app/services/ml/behavior_analyzer.py b/app/services/ml/behavior_analyzer.py new file mode 100644 index 0000000..0ade27b --- /dev/null +++ b/app/services/ml/behavior_analyzer.py @@ -0,0 +1,55 @@ +""" +Feature band encoders +====================== +Discrete bucketers for assignment-context features (distance, time-of-day, load, +order density). These are small pure helpers used by the Thompson-sampling +strategy bandit (`strategy_bandit.py`) and the /riderassign bandit context. + +NOTE: The ID3 SUCCESS/RISK decision tree that used to live here has been retired — +it only ever produced response metadata and never affected any assignment. Only +the generic feature-band encoders remain. +""" + +from datetime import datetime + + +def distance_band(km: float) -> str: + """Total route distance -> discrete band.""" + if km <= 5.0: return "SHORT" + if km <= 15.0: return "MID" + if km <= 30.0: return "LONG" + return "VERY_LONG" + + +def time_band(ts_str: str) -> str: + """ISO timestamp -> time-of-day band.""" + try: + hour = datetime.fromisoformat(ts_str).hour + if 6 <= hour < 10: return "MORNING_RUSH" + if 10 <= hour < 12: return "LATE_MORNING" + if 12 <= hour < 14: return "LUNCH_RUSH" + if 14 <= hour < 17: return "AFTERNOON" + if 17 <= hour < 20: return "EVENING_RUSH" + if 20 <= hour < 23: return "NIGHT" + return "LATE_NIGHT" + except Exception: + return "UNKNOWN" + + +def load_band(avg_load: float) -> str: + """Average orders-per-rider -> load band.""" + if avg_load <= 2.0: return "LIGHT" + if avg_load <= 5.0: return "MODERATE" + if avg_load <= 8.0: return "HEAVY" + return "OVERLOADED" + + +def order_density_band(num_orders: int, num_riders: int) -> str: + """Orders per available rider -> density band.""" + if num_riders == 0: + return "NO_RIDERS" + ratio = num_orders / num_riders + if ratio <= 2.0: return "SPARSE" + if ratio <= 5.0: return "NORMAL" + if ratio <= 9.0: return "DENSE" + return "OVERLOADED" diff --git a/app/services/ml/ml_data_collector.py b/app/services/ml/ml_data_collector.py new file mode 100644 index 0000000..f83646d --- /dev/null +++ b/app/services/ml/ml_data_collector.py @@ -0,0 +1,611 @@ +""" +ML Data Collector - Production Grade +====================================== +Logs every assignment call (inputs + outcomes) to SQLite. + +Key upgrades over the original +-------------------------------- +1. FROZEN historical scores - quality_score is written ONCE at log time. + get_training_data() returns scores as-is from the DB (no retroactive mutation). +2. Rich schema - zone_id, city_id, is_peak, weather_code, + sla_breached, avg_delivery_time_min for richer features. +3. SLA tracking - logs whether delivery SLA was breached. +4. Analytics API - get_hourly_stats(), get_strategy_comparison(), + get_quality_histogram(), get_zone_stats() for dashboard consumption. +5. Thread-safe writes - connection-per-write pattern for FastAPI workers. +6. Indexed columns - timestamp, ml_strategy, zone_id for fast queries. +""" + +import csv +import io +import logging +import os +import sqlite3 +import threading +from datetime import datetime, timedelta +from typing import Any, Dict, List, Optional + +logger = logging.getLogger(__name__) + +_DB_PATH = os.getenv("ML_DB_PATH", "ml_data/ml_store.db") +_WRITE_LOCK = threading.Lock() + + +def _std(values: List[float]) -> float: + if len(values) < 2: + return 0.0 + mean = sum(values) / len(values) + return (sum((v - mean) ** 2 for v in values) / len(values)) ** 0.5 + + +class MLDataCollector: + """ + Event logger for assignment service calls. + + Each log_assignment_event() call writes one row capturing: + - Operating context (time, orders, riders, zone, city) + - Active hyperparams (exact config snapshot for this call) + - Measured outcomes (quality score, SLA, latency, distances) + + quality_score is computed once and FROZEN - never retroactively changed. + """ + + def __init__(self): + self._db_path = _DB_PATH + self._ensure_db() + + # ------------------------------------------------------------------ + # Main logging API + # ------------------------------------------------------------------ + + def log_assignment_event( + self, + *, + num_orders: int, + num_riders: int, + hyperparams: Dict[str, Any], + assignments: Dict[int, List[Any]], + unassigned_count: int, + elapsed_ms: float, + zone_id: str = "default", + city_id: str = "default", + weather_code: str = "CLEAR", + sla_minutes: Optional[float] = None, + avg_delivery_time_min: Optional[float] = None, + ) -> None: + """ + Log one assignment event. + + Call this at the END of AssignmentService.assign_orders() once + outcomes are known. + """ + try: + now = datetime.utcnow() + hour = now.hour + day_of_week = now.weekday() + is_peak = int(hour in (7, 8, 9, 12, 13, 18, 19, 20)) + + rider_loads = [len(orders) for orders in assignments.values() if orders] + riders_used = len(rider_loads) + total_assigned = sum(rider_loads) + avg_load = total_assigned / riders_used if riders_used else 0.0 + load_std = _std(rider_loads) if rider_loads else 0.0 + + all_orders = [ + o for orders in assignments.values() if orders for o in orders + ] + total_distance_km = sum(self._get_km(o) for o in all_orders) + ml_strategy = hyperparams.get("ml_strategy", "balanced") + max_opr = hyperparams.get("max_orders_per_rider", 12) + + sla_breached = 0 + if sla_minutes and avg_delivery_time_min: + sla_breached = int(avg_delivery_time_min > sla_minutes) + + # Quality score - FROZEN at log time + quality_score = self._compute_quality_score( + num_orders=num_orders, + unassigned_count=unassigned_count, + load_std=load_std, + riders_used=riders_used, + num_riders=num_riders, + total_distance_km=total_distance_km, + max_orders_per_rider=max_opr, + ml_strategy=ml_strategy, + ) + + row = { + "timestamp": now.isoformat(), + "hour": hour, + "day_of_week": day_of_week, + "is_peak": is_peak, + "zone_id": zone_id, + "city_id": city_id, + "weather_code": weather_code, + "num_orders": num_orders, + "num_riders": num_riders, + "max_pickup_distance_km": hyperparams.get( + "max_pickup_distance_km", 10.0 + ), + "max_kitchen_distance_km": hyperparams.get( + "max_kitchen_distance_km", 3.0 + ), + "max_orders_per_rider": max_opr, + "ideal_load": hyperparams.get("ideal_load", 6), + "workload_balance_threshold": hyperparams.get( + "workload_balance_threshold", 0.7 + ), + "workload_penalty_weight": hyperparams.get( + "workload_penalty_weight", 100.0 + ), + "distance_penalty_weight": hyperparams.get( + "distance_penalty_weight", 2.0 + ), + "cluster_radius_km": hyperparams.get("cluster_radius_km", 3.0), + "search_time_limit_seconds": hyperparams.get( + "search_time_limit_seconds", 5 + ), + "road_factor": hyperparams.get("road_factor", 1.3), + "ml_strategy": ml_strategy, + "riders_used": riders_used, + "total_assigned": total_assigned, + "unassigned_count": unassigned_count, + "avg_load": round(avg_load, 3), + "load_std": round(load_std, 3), + "total_distance_km": round(total_distance_km, 2), + "elapsed_ms": round(elapsed_ms, 1), + "sla_breached": sla_breached, + "avg_delivery_time_min": round(avg_delivery_time_min or 0.0, 2), + "quality_score": round(quality_score, 2), + } + + with _WRITE_LOCK: + self._insert(row) + + logger.info( + f"[MLCollector] zone={zone_id} orders={num_orders} " + f"assigned={total_assigned} unassigned={unassigned_count} " + f"quality={quality_score:.1f} elapsed={elapsed_ms:.0f}ms" + ) + return round(quality_score, 2) + + except Exception as e: + logger.warning(f"[MLCollector] Logging failed (non-fatal): {e}") + return 50.0 # neutral fallback so bandit update still fires + + # ------------------------------------------------------------------ + # Data retrieval for training + # ------------------------------------------------------------------ + + def get_training_data( + self, + min_records: int = 30, + strategy_filter: Optional[str] = None, + since_hours: Optional[int] = None, + ) -> Optional[List[Dict[str, Any]]]: + """ + Return logged rows for model training. + quality_score is returned AS-IS (frozen at log time - no re-scoring). + """ + try: + conn = sqlite3.connect(self._db_path) + conn.row_factory = sqlite3.Row + + query = "SELECT * FROM assignment_ml_log" + params: list = [] + clauses: list = [] + + if strategy_filter: + clauses.append("ml_strategy = ?") + params.append(strategy_filter) + if since_hours: + cutoff = (datetime.utcnow() - timedelta(hours=since_hours)).isoformat() + clauses.append("timestamp >= ?") + params.append(cutoff) + + if clauses: + query += " WHERE " + " AND ".join(clauses) + query += " ORDER BY id ASC" + + rows = conn.execute(query, params).fetchall() + conn.close() + + if len(rows) < min_records: + logger.info( + f"[MLCollector] {len(rows)} records < {min_records} minimum." + ) + return None + + return [dict(r) for r in rows] + + except Exception as e: + logger.error(f"[MLCollector] get_training_data failed: {e}") + return None + + # ------------------------------------------------------------------ + # Analytics API + # ------------------------------------------------------------------ + + def get_recent_quality_trend(self, last_n: int = 50) -> Dict[str, Any]: + """Recent quality scores + series for sparkline charts.""" + try: + conn = sqlite3.connect(self._db_path) + rows = conn.execute( + "SELECT quality_score, timestamp, unassigned_count, elapsed_ms " + "FROM assignment_ml_log ORDER BY id DESC LIMIT ?", + (last_n,), + ).fetchall() + conn.close() + if not rows: + return {"avg_quality": 0.0, "sample_size": 0, "history": []} + scores = [r[0] for r in rows] + return { + "avg_quality": round(sum(scores) / len(scores), 2), + "min_quality": round(min(scores), 2), + "max_quality": round(max(scores), 2), + "sample_size": len(scores), + "history": list(reversed(scores)), + "timestamps": list(reversed([r[1] for r in rows])), + "unassigned_series": list(reversed([r[2] for r in rows])), + "latency_series": list(reversed([r[3] for r in rows])), + } + except Exception: + return {"avg_quality": 0.0, "sample_size": 0, "history": []} + + def get_hourly_stats(self, last_days: int = 7) -> List[Dict[str, Any]]: + """Quality, SLA, and call volume aggregated by hour-of-day.""" + try: + conn = sqlite3.connect(self._db_path) + cutoff = (datetime.utcnow() - timedelta(days=last_days)).isoformat() + rows = conn.execute( + """ + SELECT hour, + COUNT(*) AS call_count, + AVG(quality_score) AS avg_quality, + AVG(unassigned_count) AS avg_unassigned, + AVG(elapsed_ms) AS avg_latency_ms, + SUM(CASE WHEN sla_breached=1 THEN 1 ELSE 0 END) AS sla_breaches + FROM assignment_ml_log WHERE timestamp >= ? + GROUP BY hour ORDER BY hour + """, + (cutoff,), + ).fetchall() + conn.close() + return [ + { + "hour": r[0], + "call_count": r[1], + "avg_quality": round(r[2] or 0.0, 2), + "avg_unassigned": round(r[3] or 0.0, 2), + "avg_latency_ms": round(r[4] or 0.0, 1), + "sla_breaches": r[5], + } + for r in rows + ] + except Exception as e: + logger.error(f"[MLCollector] get_hourly_stats: {e}") + return [] + + def get_strategy_comparison(self) -> List[Dict[str, Any]]: + """Compare quality metrics across ml_strategy values.""" + try: + conn = sqlite3.connect(self._db_path) + rows = conn.execute( + """ + SELECT ml_strategy, + COUNT(*) AS call_count, + AVG(quality_score) AS avg_quality, + MIN(quality_score) AS min_quality, + MAX(quality_score) AS max_quality, + AVG(unassigned_count) AS avg_unassigned, + AVG(total_distance_km) AS avg_distance_km, + AVG(elapsed_ms) AS avg_latency_ms + FROM assignment_ml_log + GROUP BY ml_strategy ORDER BY avg_quality DESC + """ + ).fetchall() + conn.close() + return [ + { + "strategy": r[0], + "call_count": r[1], + "avg_quality": round(r[2] or 0.0, 2), + "min_quality": round(r[3] or 0.0, 2), + "max_quality": round(r[4] or 0.0, 2), + "avg_unassigned": round(r[5] or 0.0, 2), + "avg_distance_km": round(r[6] or 0.0, 2), + "avg_latency_ms": round(r[7] or 0.0, 1), + } + for r in rows + ] + except Exception as e: + logger.error(f"[MLCollector] get_strategy_comparison: {e}") + return [] + + def get_quality_histogram(self, bins: int = 10) -> List[Dict[str, Any]]: + """Quality score distribution for histogram chart.""" + try: + conn = sqlite3.connect(self._db_path) + rows = conn.execute( + "SELECT quality_score FROM assignment_ml_log" + ).fetchall() + conn.close() + scores = [r[0] for r in rows if r[0] is not None] + if not scores: + return [] + bin_width = 100.0 / bins + return [ + { + "range": f"{i * bin_width:.0f}-{(i + 1) * bin_width:.0f}", + "count": sum( + 1 for s in scores if i * bin_width <= s < (i + 1) * bin_width + ), + } + for i in range(bins) + ] + except Exception as e: + logger.error(f"[MLCollector] get_quality_histogram: {e}") + return [] + + def get_zone_stats(self) -> List[Dict[str, Any]]: + """Quality and SLA stats grouped by zone.""" + try: + conn = sqlite3.connect(self._db_path) + rows = conn.execute( + """ + SELECT zone_id, COUNT(*) AS call_count, + AVG(quality_score) AS avg_quality, + SUM(sla_breached) AS sla_breaches, + AVG(total_distance_km) AS avg_distance_km + FROM assignment_ml_log + GROUP BY zone_id ORDER BY avg_quality DESC + """ + ).fetchall() + conn.close() + return [ + { + "zone_id": r[0], + "call_count": r[1], + "avg_quality": round(r[2] or 0.0, 2), + "sla_breaches": r[3], + "avg_distance_km": round(r[4] or 0.0, 2), + } + for r in rows + ] + except Exception as e: + logger.error(f"[MLCollector] get_zone_stats: {e}") + return [] + + def count_records(self) -> int: + try: + conn = sqlite3.connect(self._db_path) + count = conn.execute("SELECT COUNT(*) FROM assignment_ml_log").fetchone()[0] + conn.close() + return count + except Exception: + return 0 + + def count_by_strategy(self) -> Dict[str, int]: + try: + conn = sqlite3.connect(self._db_path) + rows = conn.execute( + "SELECT ml_strategy, COUNT(*) FROM assignment_ml_log GROUP BY ml_strategy" + ).fetchall() + conn.close() + return {r[0]: r[1] for r in rows} + except Exception: + return {} + + def export_csv(self) -> str: + """Export all records as CSV string.""" + try: + conn = sqlite3.connect(self._db_path) + conn.row_factory = sqlite3.Row + rows = conn.execute( + "SELECT * FROM assignment_ml_log ORDER BY id ASC" + ).fetchall() + conn.close() + if not rows: + return "" + buf = io.StringIO() + writer = csv.DictWriter(buf, fieldnames=rows[0].keys()) + writer.writeheader() + writer.writerows([dict(r) for r in rows]) + return buf.getvalue() + except Exception as e: + logger.error(f"[MLCollector] export_csv failed: {e}") + return "" + + def purge_old_records(self, keep_days: int = 90) -> int: + """Delete records older than keep_days. Returns count deleted.""" + try: + cutoff = (datetime.utcnow() - timedelta(days=keep_days)).isoformat() + conn = sqlite3.connect(self._db_path) + cursor = conn.execute( + "DELETE FROM assignment_ml_log WHERE timestamp < ?", (cutoff,) + ) + deleted = cursor.rowcount + conn.commit() + conn.close() + logger.info( + f"[MLCollector] Purged {deleted} records older than {keep_days} days." + ) + return deleted + except Exception as e: + logger.error(f"[MLCollector] purge failed: {e}") + return 0 + + # ------------------------------------------------------------------ + # Quality Score Formula (frozen at log time - do not change behavior) + # ------------------------------------------------------------------ + + @staticmethod + def _compute_quality_score( + num_orders: int, + unassigned_count: int, + load_std: float, + riders_used: int, + num_riders: int, + total_distance_km: float, + max_orders_per_rider: int, + ml_strategy: str = "balanced", + ) -> float: + """ + Multi-dimensional quality score (0–100, higher = better). + + Components: + ┌──────────────────────┬────────────────────────────────────────────────┐ + │ assigned_ratio │ % of orders successfully assigned │ + │ distance_ratio │ inverse of total km (shorter routes = better) │ + │ balance_ratio │ load spread across riders (lower std = better) │ + │ rider_efficiency │ reward using minimal riders for the batch size │ + └──────────────────────┴────────────────────────────────────────────────┘ + + Strategy weights (w_assign, w_dist, w_balance, w_efficiency): + - balanced : (45, 20, 20, 15) + - aggressive_speed: (70, 15, 0, 15) — care about assignment + efficiency + - fuel_saver : (25, 60, 0, 15) — heavily penalise long routes + - zone_strict : (35, 25, 25, 15) — balanced with zone awareness + """ + import math + if num_orders == 0: + return 0.0 + + assigned = num_orders - unassigned_count + assigned_ratio = assigned / num_orders + + max_std = max(1.0, max_orders_per_rider / 2.0) + if riders_used <= 1: + balance_ratio = 0.5 # spread is undefined for a single rider; use neutral + else: + balance_ratio = max(0.0, 1.0 - (load_std / max_std)) + + max_dist = max(1.0, float(assigned * 8.0)) + distance_ratio = max(0.0, 1.0 - (total_distance_km / max_dist)) + + # Rider efficiency: 1.0 = used the theoretical minimum; drops as we + # use more riders than needed. + min_riders_needed = max(1, math.ceil(num_orders / max_orders_per_rider)) + rider_efficiency = min(1.0, min_riders_needed / max(1, riders_used)) + + weights = { + # assign dist balance efficiency + "aggressive_speed": (70.0, 15.0, 0.0, 15.0), + "fuel_saver": (25.0, 60.0, 0.0, 15.0), + "zone_strict": (35.0, 25.0, 25.0, 15.0), + "balanced": (45.0, 20.0, 20.0, 15.0), + } + w_comp, w_dist, w_bal, w_eff = weights.get(ml_strategy, (45.0, 20.0, 20.0, 15.0)) + + return min( + assigned_ratio * w_comp + + distance_ratio * w_dist + + balance_ratio * w_bal + + rider_efficiency * w_eff, + 100.0, + ) + + @staticmethod + def _get_km(order: Any) -> float: + try: + return float(order.get("kms") or order.get("calculationDistanceKm") or 0.0) + except Exception: + return 0.0 + + # ------------------------------------------------------------------ + # DB Bootstrap + # ------------------------------------------------------------------ + + def _ensure_db(self) -> None: + try: + os.makedirs(os.path.dirname(self._db_path) or ".", exist_ok=True) + conn = sqlite3.connect(self._db_path) + conn.execute(""" + CREATE TABLE IF NOT EXISTS assignment_ml_log ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + timestamp TEXT NOT NULL, + hour INTEGER, + day_of_week INTEGER, + is_peak INTEGER DEFAULT 0, + zone_id TEXT DEFAULT 'default', + city_id TEXT DEFAULT 'default', + weather_code TEXT DEFAULT 'CLEAR', + num_orders INTEGER, + num_riders INTEGER, + max_pickup_distance_km REAL, + max_kitchen_distance_km REAL, + max_orders_per_rider INTEGER, + ideal_load INTEGER, + workload_balance_threshold REAL, + workload_penalty_weight REAL, + distance_penalty_weight REAL, + cluster_radius_km REAL, + search_time_limit_seconds INTEGER, + road_factor REAL, + ml_strategy TEXT DEFAULT 'balanced', + riders_used INTEGER, + total_assigned INTEGER, + unassigned_count INTEGER, + avg_load REAL, + load_std REAL, + total_distance_km REAL DEFAULT 0.0, + elapsed_ms REAL, + sla_breached INTEGER DEFAULT 0, + avg_delivery_time_min REAL DEFAULT 0.0, + quality_score REAL + ) + """) + migrations = [ + "ALTER TABLE assignment_ml_log ADD COLUMN is_peak INTEGER DEFAULT 0", + "ALTER TABLE assignment_ml_log ADD COLUMN zone_id TEXT DEFAULT 'default'", + "ALTER TABLE assignment_ml_log ADD COLUMN city_id TEXT DEFAULT 'default'", + "ALTER TABLE assignment_ml_log ADD COLUMN weather_code TEXT DEFAULT 'CLEAR'", + "ALTER TABLE assignment_ml_log ADD COLUMN sla_breached INTEGER DEFAULT 0", + "ALTER TABLE assignment_ml_log ADD COLUMN avg_delivery_time_min REAL DEFAULT 0.0", + "ALTER TABLE assignment_ml_log ADD COLUMN ml_strategy TEXT DEFAULT 'balanced'", + "ALTER TABLE assignment_ml_log ADD COLUMN total_distance_km REAL DEFAULT 0.0", + ] + for ddl in migrations: + try: + conn.execute(ddl) + except Exception: + pass + for idx in [ + "CREATE INDEX IF NOT EXISTS idx_timestamp ON assignment_ml_log(timestamp)", + "CREATE INDEX IF NOT EXISTS idx_strategy ON assignment_ml_log(ml_strategy)", + "CREATE INDEX IF NOT EXISTS idx_zone ON assignment_ml_log(zone_id)", + ]: + conn.execute(idx) + conn.commit() + conn.close() + except Exception as e: + logger.error(f"[MLCollector] DB init failed: {e}") + + def _insert(self, row: Dict[str, Any]) -> None: + os.makedirs(os.path.dirname(self._db_path) or ".", exist_ok=True) + conn = sqlite3.connect(self._db_path) + cols = ", ".join(row.keys()) + placeholders = ", ".join(["?"] * len(row)) + conn.execute( + f"INSERT INTO assignment_ml_log ({cols}) VALUES ({placeholders})", + list(row.values()), + ) + conn.commit() + conn.close() + + +# --------------------------------------------------------------------------- +# Module-level singleton +# --------------------------------------------------------------------------- + +_collector: Optional[MLDataCollector] = None +_collector_lock = threading.Lock() + + +def get_collector() -> MLDataCollector: + global _collector + if _collector is None: + with _collector_lock: + if _collector is None: + _collector = MLDataCollector() + return _collector diff --git a/app/services/ml/strategy_bandit.py b/app/services/ml/strategy_bandit.py new file mode 100644 index 0000000..2c3cb51 --- /dev/null +++ b/app/services/ml/strategy_bandit.py @@ -0,0 +1,277 @@ +""" +Thompson Sampling Contextual Bandit — Strategy Selector +========================================================= +Replaces the greedy SQL auto-tuner with proper online RL. + +Problem +------- +The old greedy tuner picks the strategy with the highest *average* quality +across all history. It never explores alternatives once one strategy leads, +and it ignores context (the same strategy isn't best at all times of day +and all load levels). + +Solution +-------- +A contextual multi-armed bandit with Thompson Sampling: + + Context = (time_band, load_band) — up to 7 × 4 = 28 states + Arms = 4 strategies — balanced / fuel_saver / aggressive_speed / zone_strict + Reward = quality_score / 100 — 0..1 float, already logged by MLDataCollector + +How Thompson Sampling works +--------------------------- +Each (context, arm) pair has a Beta(α, β) posterior where: + α = sum of rewards seen so far (high quality calls push α up) + β = sum of "anti-rewards" (low quality calls push β up) + +To SELECT a strategy: + 1. For each arm, sample θ ~ Beta(α, β) + 2. Pick arm with highest θ + → Naturally balances exploration (uncertain arms get sampled often) + with exploitation (well-known good arms dominate when confident) + +To UPDATE after an assignment: + reward = quality_score / 100 + α += reward + β += (1 - reward) + +Bootstrap +--------- +On first startup the entire historical SQLite DB is replayed to warm up +posteriors so the bandit starts informed, not blank. +If saved state already exists it is loaded from disk instead. + +Persistence +----------- +ml_data/strategy_bandit.json — saved every 10 updates. +""" + +import json +import logging +import os +import threading +from typing import Dict, List, Optional, Tuple + +import numpy as np + +logger = logging.getLogger(__name__) + +_SAVE_PATH = os.getenv("BANDIT_PATH", "ml_data/strategy_bandit.json") +_DB_PATH = os.getenv("ML_DB_PATH", "ml_data/ml_store.db") + +ARMS = ["balanced", "fuel_saver", "aggressive_speed", "zone_strict"] + + +class ContextualBandit: + """ + Thompson Sampling bandit for ml_strategy selection. + + Context key : "{time_band}|{load_band}" + Arms : ARMS list (4 strategies) + Prior : Beta(1, 1) — uniform, no initial preference + """ + + def __init__(self): + self._lock = threading.Lock() + # _posteriors[ctx_key][arm] = [alpha, beta] + self._posteriors: Dict[str, Dict[str, List[float]]] = {} + self._update_count = 0 + self._total_pulls = 0 + self._load() + self._bootstrap_from_db() + + # ── Public API ─────────────────────────────────────────────────────────── + + def select(self, time_band: str, load_band: str) -> str: + """ + Sample from Beta posteriors and return the strategy with the highest + sample. Explores uncertain arms naturally; exploits known-good arms + as confidence grows. + """ + ctx = self._ctx(time_band, load_band) + with self._lock: + samples = { + arm: float(np.random.beta(*self._ab(ctx, arm))) + for arm in ARMS + } + self._total_pulls += 1 + chosen = max(samples, key=samples.__getitem__) + logger.debug( + f"[Bandit] ctx={ctx} " + f"samples={{{', '.join(f'{k}:{v:.3f}' for k, v in samples.items())}}} " + f"→ {chosen}" + ) + return chosen + + def update(self, time_band: str, load_band: str, + strategy: str, quality_score: float) -> None: + """Update the Beta posterior for (context, arm) after observing quality.""" + if strategy not in ARMS: + return + ctx = self._ctx(time_band, load_band) + reward = min(1.0, max(0.0, float(quality_score) / 100.0)) + with self._lock: + ab = self._ab(ctx, strategy) + ab[0] += reward # alpha ← quality adds to success mass + ab[1] += (1.0 - reward) # beta ← (1-quality) adds to failure mass + self._update_count += 1 + should_save = self._update_count % 10 == 0 + if should_save: + self._save() + + def best_arm(self, time_band: str, load_band: str) -> Tuple[str, float]: + """ + Return the arm with the highest posterior mean (pure exploitation, no + sampling noise). Used for logging and dashboard, not for live selection. + """ + ctx = self._ctx(time_band, load_band) + with self._lock: + means = { + arm: self._ab(ctx, arm)[0] / sum(self._ab(ctx, arm)) + for arm in ARMS + } + best = max(means, key=means.__getitem__) + return best, round(means[best], 4) + + def get_stats(self) -> Dict: + """Return per-context arm statistics for the ML admin dashboard.""" + with self._lock: + stats: Dict[str, Dict] = {} + for ctx, arms in sorted(self._posteriors.items()): + stats[ctx] = {} + for arm in ARMS: + if arm not in arms: + stats[ctx][arm] = {"mean_reward": 0.5, "observations": 0, + "alpha": 1.0, "beta": 1.0} + continue + alpha, beta = arms[arm] + n = alpha + beta - 2.0 # subtract the Beta(1,1) prior mass + mean = alpha / (alpha + beta) + stats[ctx][arm] = { + "mean_reward": round(mean, 4), + "observations": round(max(0, n), 1), + "alpha": round(alpha, 2), + "beta": round(beta, 2), + } + return { + "total_pulls": self._total_pulls, + "total_updates": self._update_count, + "context_count": len(self._posteriors), + "arms": ARMS, + "contexts": stats, + } + + # ── Persistence ────────────────────────────────────────────────────────── + + def _save(self) -> None: + try: + with self._lock: + snapshot = { + "posteriors": { + ctx: {arm: list(ab) for arm, ab in arms.items()} + for ctx, arms in self._posteriors.items() + }, + "update_count": self._update_count, + "total_pulls": self._total_pulls, + } + os.makedirs(os.path.dirname(_SAVE_PATH) or ".", exist_ok=True) + with open(_SAVE_PATH, "w", encoding="utf-8") as f: + json.dump(snapshot, f, indent=2) + except Exception as e: + logger.warning(f"[Bandit] Save failed: {e}") + + def _load(self) -> None: + try: + if not os.path.exists(_SAVE_PATH): + logger.info("[Bandit] No saved state — will bootstrap from DB.") + return + with open(_SAVE_PATH, "r", encoding="utf-8") as f: + data = json.load(f) + self._posteriors = data.get("posteriors", {}) + self._update_count = data.get("update_count", 0) + self._total_pulls = data.get("total_pulls", 0) + logger.info( + f"[Bandit] Loaded from disk — " + f"{len(self._posteriors)} contexts, {self._update_count} updates" + ) + except Exception as e: + logger.warning(f"[Bandit] Load failed (starting fresh): {e}") + + # ── Bootstrap ──────────────────────────────────────────────────────────── + + def _bootstrap_from_db(self) -> None: + """ + Warm-up posteriors by replaying every historical assignment event. + Skipped if the saved JSON already reflects current DB data. + """ + if self._update_count > 0: + logger.info( + f"[Bandit] Already warmed ({self._update_count} updates) — " + "skipping DB bootstrap." + ) + return + try: + import sqlite3 + from app.services.ml.behavior_analyzer import ( + time_band as _tb, + load_band as _lb, + ) + conn = sqlite3.connect(_DB_PATH) + rows = conn.execute( + "SELECT timestamp, avg_load, ml_strategy, quality_score " + "FROM assignment_ml_log " + "WHERE ml_strategy IS NOT NULL AND quality_score IS NOT NULL " + "ORDER BY id ASC" + ).fetchall() + conn.close() + + if not rows: + logger.info("[Bandit] No historical data — starting with uniform priors.") + return + + for ts, avg_load, strategy, quality in rows: + t_band = _tb(str(ts)) if ts else "UNKNOWN" + l_band = _lb(float(avg_load or 0)) + self.update(t_band, l_band, strategy, float(quality or 50)) + + # Reset counter so we don't confuse bootstrap updates with live ones + with self._lock: + self._update_count = len(rows) + + logger.info( + f"[Bandit] Bootstrapped from {len(rows)} historical events — " + f"{len(self._posteriors)} contexts, {len(ARMS)} arms." + ) + self._save() + except Exception as e: + logger.warning(f"[Bandit] Bootstrap failed (non-fatal): {e}") + + # ── Helpers ────────────────────────────────────────────────────────────── + + @staticmethod + def _ctx(time_band: str, load_band: str) -> str: + return f"{time_band}|{load_band}" + + def _ab(self, ctx: str, arm: str) -> List[float]: + """Get or create Beta(1, 1) uniform prior for (ctx, arm). NOT thread-safe alone.""" + if ctx not in self._posteriors: + self._posteriors[ctx] = {} + if arm not in self._posteriors[ctx]: + self._posteriors[ctx][arm] = [1.0, 1.0] + return self._posteriors[ctx][arm] + + +# ── Singleton ──────────────────────────────────────────────────────────────── + +_bandit_instance: Optional[ContextualBandit] = None +_bandit_lock = threading.Lock() + + +def get_bandit() -> ContextualBandit: + """Return the process-level singleton ContextualBandit.""" + global _bandit_instance + if _bandit_instance is None: + with _bandit_lock: + if _bandit_instance is None: + _bandit_instance = ContextualBandit() + return _bandit_instance diff --git a/app/services/rider/get_active_riders.py b/app/services/rider/get_active_riders.py new file mode 100644 index 0000000..35f8216 --- /dev/null +++ b/app/services/rider/get_active_riders.py @@ -0,0 +1,78 @@ + +import httpx +import logging +from datetime import datetime +from typing import List, Dict, Any + +logger = logging.getLogger(__name__) + +async def fetch_active_riders() -> List[Dict[str, Any]]: + """ + Fetch active rider logs from the external API for the current date. + Returns a list of rider log dictionaries. + """ + try: + today_str = datetime.now().strftime("%Y-%m-%d") + url = "https://jupiter.nearle.app/live/api/v2/partners/getriderlogs/" + params = { + "applocationid": 1, + "partnerid": 44, + "fromdate": today_str, + "todate": today_str, + "keyword": "" + } + + async with httpx.AsyncClient(timeout=30.0) as client: + response = await client.get(url, params=params) + response.raise_for_status() + data = response.json() + + if data and data.get("code") == 200 and data.get("details"): + # Filter riders who are in our preferences list and are 'active' or 'idle' (assuming we want online riders) + # The user's example showed "onduty": 1. We might want to filter by that. + # For now, returning all logs, filtering can happen in assignment logic or here. + # Let's return the raw list as requested, filtering logic will be applied during assignment. + return data.get("details", []) + + logger.warning(f"Fetch active riders returned no details: {data}") + return [] + + except Exception as e: + logger.error(f"Error fetching active riders: {e}", exc_info=True) + return [] + +async def fetch_created_orders() -> List[Dict[str, Any]]: + """ + Fetch all orders in 'created' state for the current date. + """ + try: + today_str = datetime.now().strftime("%Y-%m-%d") + url = "https://jupiter.nearle.app/live/api/v1/orders/tenant/getorders/" + # Removed pagesize as per user request to fetch all + params = { + "applocationid": 0, + "tenantid": 0, + "locationid": 0, + "status": "created", + "fromdate": today_str, + "todate": today_str, + "keyword": "", + "pageno": 1 + # "pagesize" intentionally omitted to fetch all + } + + async with httpx.AsyncClient(timeout=60.0) as client: + response = await client.get(url, params=params) + response.raise_for_status() + data = response.json() + + if data and data.get("code") == 200 and data.get("details"): + return data.get("details", []) + + logger.warning(f"Fetch created orders returned no details: {data}") + return [] + + except Exception as e: + logger.error(f"Error fetching created orders: {e}", exc_info=True) + return [] + diff --git a/app/services/rider/rider_history_service.py b/app/services/rider/rider_history_service.py new file mode 100644 index 0000000..b2290bd --- /dev/null +++ b/app/services/rider/rider_history_service.py @@ -0,0 +1,68 @@ + +import os +import pickle +import logging +from datetime import datetime +from typing import Dict, Any + +logger = logging.getLogger(__name__) + +# Absolute path so this pickle is written to the same location regardless of +# which directory uvicorn is launched from. +_PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname( + os.path.abspath(__file__) +)))) +HISTORY_FILE = os.path.join(_PROJECT_ROOT, "data", "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.""" + os.makedirs(os.path.dirname(self.history_file), exist_ok=True) + 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) + diff --git a/app/services/rider/rider_state_manager.py b/app/services/rider/rider_state_manager.py new file mode 100644 index 0000000..3728902 --- /dev/null +++ b/app/services/rider/rider_state_manager.py @@ -0,0 +1,120 @@ +import os +import pickle +import logging +import threading +import time +from datetime import datetime +from typing import Dict, Any, List, Set + +logger = logging.getLogger(__name__) + +# Use an absolute path anchored to the project root (two levels up from this file) +# so the pickle is always written to the same place regardless of the working +# directory at startup time. +_PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname( + os.path.abspath(__file__) +)))) +STATE_FILE = os.path.join(_PROJECT_ROOT, "data", "rider_active_state.pkl") +_FILE_LOCK = threading.Lock() + + +class RiderStateManager: + """ + Manages the 'Short-Term' Active State of Riders for session persistence. + Tracks: + - Minutes Committed (Remaining Workload) + - Active Kitchens (Unique Pickups in current queue) + - Last Planned Drop Location (for Daisy Chaining) + - Timestamp of last update (for Time Decay) + """ + def __init__(self, state_file: str = STATE_FILE): + self.state_file = state_file + self.states = self._load_states() + + def _load_states(self) -> Dict[str, Any]: + """Load states from pickle.""" + os.makedirs(os.path.dirname(self.state_file), exist_ok=True) + if not os.path.exists(self.state_file): + return {} + try: + with _FILE_LOCK: + with open(self.state_file, 'rb') as f: + return pickle.load(f) + except Exception as e: + logger.error(f"Failed to load rider active states: {e}") + return {} + + def _save_states(self): + """Save states to pickle.""" + try: + with _FILE_LOCK: + with open(self.state_file, 'wb') as f: + pickle.dump(self.states, f) + except Exception as e: + logger.error(f"Failed to save rider active states: {e}") + + def get_rider_state(self, rider_id: int) -> Dict[str, Any]: + """ + Get the current active state of a rider with TIME DECAY applied. + If the server restarts after 30 mins, the 'minutes_committed' should reduce by 30. + """ + rider_id = int(rider_id) + raw_state = self.states.get(rider_id) + + if not raw_state: + return { + 'minutes_remaining': 0.0, + 'last_drop_lat': None, + 'last_drop_lon': None, + 'active_kitchens': set(), + 'last_updated_ts': time.time() + } + + # Apply Time Decay + last_ts = raw_state.get('last_updated_ts', time.time()) + current_ts = time.time() + elapsed_mins = (current_ts - last_ts) / 60.0 + + remaining = max(0.0, raw_state.get('minutes_remaining', 0.0) - elapsed_mins) + + # If queue is empty, kitchens are cleared + kitchens = raw_state.get('active_kitchens', set()) + if remaining <= 5.0: # Buffer: if almost done, free up kitchens + kitchens = set() + + return { + 'minutes_remaining': remaining, + 'last_drop_lat': raw_state.get('last_drop_lat'), + 'last_drop_lon': raw_state.get('last_drop_lon'), + 'active_kitchens': kitchens, + 'last_updated_ts': current_ts + } + + def update_rider_state(self, rider_id: int, added_minutes: float, new_kitchens: Set[str], last_lat: float, last_lon: float): + """ + Update the state after a new assignment. + """ + rider_id = int(rider_id) + + # Get current state (decayed) + current = self.get_rider_state(rider_id) + + # Accumulate + updated_minutes = current['minutes_remaining'] + added_minutes + updated_kitchens = current['active_kitchens'].union(new_kitchens) + + self.states[rider_id] = { + 'minutes_remaining': updated_minutes, + 'last_drop_lat': last_lat, + 'last_drop_lon': last_lon, + 'active_kitchens': updated_kitchens, + 'last_updated_ts': time.time() + } + + self._save_states() + + def clear_state(self, rider_id: int): + rider_id = int(rider_id) + if rider_id in self.states: + del self.states[rider_id] + self._save_states() diff --git a/app/services/rider/substitution_service.py b/app/services/rider/substitution_service.py new file mode 100644 index 0000000..c4cfdd1 --- /dev/null +++ b/app/services/rider/substitution_service.py @@ -0,0 +1,163 @@ +""" +Rider Substitution Service +========================== +Stores ops-team substitution records: when rider X is absent, rider Y +(the sub) covers X's kitchens and zone for that day. + +On each dispatch call, AssignmentService loads today's map and merges the +absent rider's kitchen + zone affinity into the sub rider's profile for +that request only. No server restart needed. Automatically reverts the +next day because the lookup is date-keyed. + +Storage: SQLite at data/substitutions.db +""" + +import logging +import os +import sqlite3 +import threading +from datetime import datetime, timezone +from typing import Dict, List, Optional +from zoneinfo import ZoneInfo + +logger = logging.getLogger(__name__) + +# All date comparisons use IST so the substitution fires on the correct +# calendar day regardless of what timezone the server (Docker/UTC) runs in. +_IST = ZoneInfo("Asia/Kolkata") + + +def _today_ist() -> str: + """Current date in IST as YYYY-MM-DD string.""" + return datetime.now(_IST).date().isoformat() + +_PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname( + os.path.abspath(__file__) +)))) +_DB_PATH = os.path.join(_PROJECT_ROOT, "data", "substitutions.db") + +_DDL = """ +CREATE TABLE IF NOT EXISTS rider_substitutions ( + sub_date TEXT NOT NULL, + absent_rider_id INTEGER NOT NULL, + sub_rider_id INTEGER NOT NULL, + created_at TEXT NOT NULL, + PRIMARY KEY (sub_date, absent_rider_id) +); +""" + + +class SubstitutionService: + def __init__(self, db_path: str = _DB_PATH): + self._db_path = db_path + self._lock = threading.Lock() + # In-memory cache for today's substitution map. + # Keyed by IST date string so it auto-invalidates at midnight IST. + self._cache: Dict[int, int] = {} + self._cache_date: str = "" + self._init_db() + + def _init_db(self): + os.makedirs(os.path.dirname(self._db_path), exist_ok=True) + with sqlite3.connect(self._db_path) as conn: + conn.execute(_DDL) + conn.commit() + + def _conn(self) -> sqlite3.Connection: + conn = sqlite3.connect(self._db_path) + conn.row_factory = sqlite3.Row + return conn + + def _invalidate_cache(self): + """Clear the in-memory cache so the next get_today_map() re-reads from DB.""" + self._cache_date = "" + + def register(self, sub_date: str, absent_rider_id: int, sub_rider_id: int) -> Dict: + """Register or update a substitution for a given date.""" + created_at = datetime.now(timezone.utc).isoformat() + with self._lock: + with self._conn() as conn: + conn.execute( + """ + INSERT INTO rider_substitutions + (sub_date, absent_rider_id, sub_rider_id, created_at) + VALUES (?, ?, ?, ?) + ON CONFLICT(sub_date, absent_rider_id) + DO UPDATE SET sub_rider_id = excluded.sub_rider_id, + created_at = excluded.created_at + """, + (sub_date, int(absent_rider_id), int(sub_rider_id), created_at), + ) + conn.commit() + self._invalidate_cache() + logger.info( + f"[Substitution] Registered: {sub_date} — absent={absent_rider_id} sub={sub_rider_id}" + ) + return { + "sub_date": sub_date, + "absent_rider_id": absent_rider_id, + "sub_rider_id": sub_rider_id, + "created_at": created_at, + } + + def cancel(self, sub_date: str, absent_rider_id: int) -> bool: + """Remove a substitution record. Returns True if a row was deleted.""" + with self._lock: + with self._conn() as conn: + cur = conn.execute( + "DELETE FROM rider_substitutions WHERE sub_date=? AND absent_rider_id=?", + (sub_date, int(absent_rider_id)), + ) + conn.commit() + self._invalidate_cache() + return cur.rowcount > 0 + + def get_today_map(self) -> Dict[int, int]: + """ + Return {absent_rider_id: sub_rider_id} for today (IST). + + Result is cached in memory — one SQLite read per IST day (or after any + register/cancel call). Every dispatch call after the first is a plain + dict lookup with no DB I/O. + """ + today = _today_ist() + with self._lock: + if self._cache_date == today: + return dict(self._cache) + # Cache miss: query DB once, store result + with self._conn() as conn: + rows = conn.execute( + "SELECT absent_rider_id, sub_rider_id FROM rider_substitutions WHERE sub_date=?", + (today,), + ).fetchall() + self._cache = {int(r["absent_rider_id"]): int(r["sub_rider_id"]) for r in rows} + self._cache_date = today + if self._cache: + logger.info(f"[Substitution] Cache loaded for {today}: {self._cache}") + return dict(self._cache) + + def list_all(self, from_date: Optional[str] = None) -> List[Dict]: + """Return all substitutions on or after from_date (default: today), ordered by date.""" + cutoff = from_date or _today_ist() + with self._conn() as conn: + rows = conn.execute( + """SELECT sub_date, absent_rider_id, sub_rider_id, created_at + FROM rider_substitutions + WHERE sub_date >= ? + ORDER BY sub_date, absent_rider_id""", + (cutoff,), + ).fetchall() + return [dict(r) for r in rows] + + +_service: Optional[SubstitutionService] = None +_service_lock = threading.Lock() + + +def get_substitution_service() -> SubstitutionService: + global _service + if _service is None: + with _service_lock: + if _service is None: + _service = SubstitutionService() + return _service diff --git a/app/services/routing/__pycache__/batch_efficiency.cpython-312.pyc b/app/services/routing/__pycache__/batch_efficiency.cpython-312.pyc new file mode 100644 index 0000000..93f10cc Binary files /dev/null and b/app/services/routing/__pycache__/batch_efficiency.cpython-312.pyc differ diff --git a/app/services/routing/__pycache__/clustering_service.cpython-312.pyc b/app/services/routing/__pycache__/clustering_service.cpython-312.pyc new file mode 100644 index 0000000..0760122 Binary files /dev/null and b/app/services/routing/__pycache__/clustering_service.cpython-312.pyc differ diff --git a/app/services/routing/__pycache__/delivery_history_service.cpython-312.pyc b/app/services/routing/__pycache__/delivery_history_service.cpython-312.pyc new file mode 100644 index 0000000..4952567 Binary files /dev/null and b/app/services/routing/__pycache__/delivery_history_service.cpython-312.pyc differ diff --git a/app/services/routing/__pycache__/empirical_eta_calculator.cpython-312.pyc b/app/services/routing/__pycache__/empirical_eta_calculator.cpython-312.pyc new file mode 100644 index 0000000..94db40d Binary files /dev/null and b/app/services/routing/__pycache__/empirical_eta_calculator.cpython-312.pyc differ diff --git a/app/services/routing/__pycache__/kalman_filter.cpython-312.pyc b/app/services/routing/__pycache__/kalman_filter.cpython-312.pyc new file mode 100644 index 0000000..eedf848 Binary files /dev/null and b/app/services/routing/__pycache__/kalman_filter.cpython-312.pyc differ diff --git a/app/services/routing/__pycache__/realistic_eta_calculator.cpython-312.pyc b/app/services/routing/__pycache__/realistic_eta_calculator.cpython-312.pyc new file mode 100644 index 0000000..29d666e Binary files /dev/null and b/app/services/routing/__pycache__/realistic_eta_calculator.cpython-312.pyc differ diff --git a/app/services/routing/__pycache__/rider_affinity_service.cpython-312.pyc b/app/services/routing/__pycache__/rider_affinity_service.cpython-312.pyc new file mode 100644 index 0000000..d50f8cb Binary files /dev/null and b/app/services/routing/__pycache__/rider_affinity_service.cpython-312.pyc differ diff --git a/app/services/routing/__pycache__/road_sequencing_agent.cpython-312.pyc b/app/services/routing/__pycache__/road_sequencing_agent.cpython-312.pyc new file mode 100644 index 0000000..7061d74 Binary files /dev/null and b/app/services/routing/__pycache__/road_sequencing_agent.cpython-312.pyc differ diff --git a/app/services/routing/__pycache__/route_optimizer.cpython-312.pyc b/app/services/routing/__pycache__/route_optimizer.cpython-312.pyc new file mode 100644 index 0000000..e0a1a4a Binary files /dev/null and b/app/services/routing/__pycache__/route_optimizer.cpython-312.pyc differ diff --git a/app/services/routing/__pycache__/zone_service.cpython-312.pyc b/app/services/routing/__pycache__/zone_service.cpython-312.pyc new file mode 100644 index 0000000..6d63667 Binary files /dev/null and b/app/services/routing/__pycache__/zone_service.cpython-312.pyc differ diff --git a/app/services/routing/batch_efficiency.py b/app/services/routing/batch_efficiency.py new file mode 100644 index 0000000..df876fc --- /dev/null +++ b/app/services/routing/batch_efficiency.py @@ -0,0 +1,860 @@ +""" +Batch Efficiency Analyser +========================= +Pure-function service that analyses a delivery batch and returns: + + - fleet_summary : aggregate metrics + load-balance scores + - rider_timelines : per-rider start/finish/pace/utilisation + - substitution_opportunities : ranked, scored transfer plans + - top_recommendation : best action with confidence, root-cause & risk factors + +No DB access here. The route handler owns fetching; this layer is +fully testable with any list of dicts. + +Expected delivery dict keys (all optional except userid): + userid : int rider id + pickupcustomer : str e.g. "Daily Grubs Bhuvaneshwari" + assigntime : str "YYYY-MM-DD HH:MM:SS" + pickuptime : str "YYYY-MM-DD HH:MM:SS" or None + deliverytime : str "YYYY-MM-DD HH:MM:SS" or None + dlat / droplat : float delivery lat (either key accepted) + dlon / droplon : float delivery lon (either key accepted) + deliveryid : int order id (for transfer manifests) +""" + +from __future__ import annotations + +import math +import statistics +from collections import defaultdict +from datetime import datetime, timedelta +from typing import Any + +# --------------------------------------------------------------------------- +# Defaults +# --------------------------------------------------------------------------- + +DEFAULT_KITCHEN_COORDS: dict[str, tuple[float, float]] = { + "vidhya": (11.01633, 77.01478), + "jayanthi": (11.03887, 76.93008), + "nandhini": (11.04324, 77.00068), + "bhuvaneshwari": (11.00352, 76.95455), + "selvarani": (10.99274, 77.00535), +} + +DEFAULT_KITCHEN_FRAGMENTS: list[str] = [ + "bhuvaneshwari", "jayanthi", "nandhini", "vidhya", "selvarani" +] + +DEFAULT_ROAD_KMH: float = 13.0 +DEFAULT_IDLE_THRESHOLD_MIN: float = 30.0 +DEFAULT_MAX_TRANSFER: int = 4 + + +# --------------------------------------------------------------------------- +# Internal helpers +# --------------------------------------------------------------------------- + +def _hav(la1: float, lo1: float, la2: float, lo2: float) -> float: + R = 6371.0 + la1, lo1, la2, lo2 = map(math.radians, [la1, lo1, la2, lo2]) + a = (math.sin((la2 - la1) / 2) ** 2 + + math.cos(la1) * math.cos(la2) * math.sin((lo2 - lo1) / 2) ** 2) + return R * 2 * math.asin(math.sqrt(max(0.0, min(1.0, a)))) + + +def _travel_min(km: float, kmh: float = DEFAULT_ROAD_KMH) -> float: + return km / kmh * 60.0 + + +def _parse_ts(s: Any) -> datetime | None: + if not s: + return None + s = str(s).strip() + for fmt in ("%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M"): + try: + return datetime.strptime(s, fmt) + except ValueError: + continue + return None + + +def _fmt(dt: datetime | None) -> str | None: + return dt.strftime("%H:%M:%S") if dt else None + + +def _get_coord(order: dict) -> tuple[float, float] | None: + lat = order.get("dlat") or order.get("droplat") or order.get("deliverylat") + lon = order.get("dlon") or order.get("droplon") or order.get("deliverylong") + try: + return float(lat), float(lon) + except (TypeError, ValueError): + return None + + +def _detect_kitchen( + pickupcustomer: str | None, + fragments: list[str], +) -> str | None: + kl = (pickupcustomer or "").lower() + for frag in fragments: + if frag in kl: + return frag + return None + + +def _stdev(values: list[float]) -> float: + """Population stdev; returns 0 for fewer than 2 values.""" + if len(values) < 2: + return 0.0 + try: + return statistics.stdev(values) + except Exception: + return 0.0 + + +def _score_candidate( + o: dict, + arrive_at_kitchen: datetime, + k_coord: tuple[float, float], + road_kmh: float, +) -> float: + """ + Score a candidate order for transfer to the idle rider. + Higher = better candidate. + + Two components: + time_gain : minutes saved vs the original delivery time. + Positive means idle rider genuinely arrives earlier. + geo_penalty: haversine distance from kitchen to the order drop point. + Penalises far orders that inflate the idle rider's extra km. + + Orders with negative time_gain (idle rider would be slower) still get a + score, allowing the caller to filter them out with a feasibility check. + """ + d_ts = _parse_ts(o.get("deliverytime")) + coord = _get_coord(o) + if not d_ts or not coord: + return -9999.0 + dist_km = _hav(k_coord[0], k_coord[1], coord[0], coord[1]) + est_deliver = arrive_at_kitchen + timedelta(minutes=_travel_min(dist_km, road_kmh)) + time_gain_min = (d_ts - est_deliver).total_seconds() / 60.0 + # Weight: time gain matters more than geography (70/30 split). + # Penalise 2 min per km of extra distance so nearby clusters float up. + return time_gain_min * 0.7 - dist_km * 2.0 * 0.3 + + +# --------------------------------------------------------------------------- +# Public API +# --------------------------------------------------------------------------- + +def analyse_batch( + deliveries: list[dict], + rider_names: dict[int, str] | None = None, + kitchen_coords: dict[str, tuple[float, float]] | None = None, + kitchen_fragments: list[str] | None = None, + road_kmh: float = DEFAULT_ROAD_KMH, + idle_threshold_min: float = DEFAULT_IDLE_THRESHOLD_MIN, + max_transfer: int = DEFAULT_MAX_TRANSFER, +) -> dict: + """ + Analyse a delivery batch and return substitution opportunities. + + Parameters + ---------- + deliveries : list of order dicts (see module docstring) + rider_names : optional {userid: name} override + kitchen_coords : optional kitchen pickup coordinates override + kitchen_fragments : optional kitchen detection strings override + road_kmh : estimated loaded-rider road speed + idle_threshold_min: minimum idle window to flag as opportunity + max_transfer : maximum orders to suggest transferring to one rider + """ + if kitchen_coords is None: + kitchen_coords = DEFAULT_KITCHEN_COORDS + if kitchen_fragments is None: + kitchen_fragments = DEFAULT_KITCHEN_FRAGMENTS + if rider_names is None: + rider_names = {} + + # ------------------------------------------------------------------ + # 1. Group deliveries by rider + # ------------------------------------------------------------------ + by_rider: dict[int, list[dict]] = defaultdict(list) + for o in deliveries: + uid = o.get("userid") + if uid is not None: + by_rider[int(uid)].append(o) + + if not by_rider: + return { + "fleet_summary": {}, + "rider_timelines": [], + "substitution_opportunities": [], + "top_recommendation": None, + "error": "No deliveries with valid userid found.", + } + + # ------------------------------------------------------------------ + # 2. Per-rider timeline + # ------------------------------------------------------------------ + timelines: list[dict] = [] + + for uid, orders in by_rider.items(): + # Detect primary kitchen by majority vote + kitchen_votes: dict[str, int] = defaultdict(int) + for o in orders: + k = _detect_kitchen(o.get("pickupcustomer"), kitchen_fragments) + if k: + kitchen_votes[k] += 1 + primary_kitchen = ( + max(kitchen_votes, key=kitchen_votes.get) if kitchen_votes else None + ) + kitchen_confidence = ( + round(kitchen_votes[primary_kitchen] / len(orders), 2) + if primary_kitchen else 0.0 + ) + + # Timestamps + finish_ts = None + start_ts = None + last_coord: tuple[float, float] | None = None + completed_orders = 0 + + for o in orders: + a = _parse_ts(o.get("assigntime")) + d = _parse_ts(o.get("deliverytime")) + if a and (start_ts is None or a < start_ts): + start_ts = a + if d: + completed_orders += 1 + if finish_ts is None or d > finish_ts: + finish_ts = d + coord = _get_coord(o) + if coord: + last_coord = coord + + # Active duration and pace + active_minutes: float | None = None + pace_orders_per_hour: float | None = None + if start_ts and finish_ts and finish_ts > start_ts: + active_minutes = round((finish_ts - start_ts).total_seconds() / 60, 1) + pace_orders_per_hour = round(completed_orders / (active_minutes / 60), 1) if active_minutes else None + + timelines.append({ + "userid": uid, + "name": rider_names.get(uid, f"Rider {uid}"), + "kitchen": primary_kitchen, + "kitchen_confidence": kitchen_confidence, + "order_count": len(orders), + "completed_orders": completed_orders, + "pending_orders": len(orders) - completed_orders, + "started_at": _fmt(start_ts), + "finished_at": _fmt(finish_ts), + "active_minutes": active_minutes, + "pace_orders_per_hour": pace_orders_per_hour, + "_finish_dt": finish_ts, + "_start_dt": start_ts, + "last_position": ( + {"lat": round(last_coord[0], 6), "lon": round(last_coord[1], 6)} + if last_coord else None + ), + "_last_coord": last_coord, + }) + + # Sort by finish time + timelines.sort(key=lambda t: t["_finish_dt"] or datetime.min) + + # ------------------------------------------------------------------ + # 3. Fleet summary + # ------------------------------------------------------------------ + valid_start = [t["_start_dt"] for t in timelines if t["_start_dt"]] + valid_finish = [t["_finish_dt"] for t in timelines if t["_finish_dt"]] + + fleet_start = min(valid_start) if valid_start else None + fleet_done = max(valid_finish) if valid_finish else None + + # Load balance: stdev of order counts and finish-time spread + order_counts = [t["order_count"] for t in timelines] + finish_offsets_min = ( + [(f - fleet_start).total_seconds() / 60 for f in valid_finish] + if fleet_start and valid_finish else [] + ) + finish_spread_min = ( + round((max(valid_finish) - min(valid_finish)).total_seconds() / 60) + if len(valid_finish) >= 2 else 0 + ) + load_balance_stdev = round(_stdev([float(c) for c in order_counts]), 2) + finish_time_stdev = round(_stdev(finish_offsets_min), 1) + + # Utilisation: how much of the batch window each rider was actively delivering + batch_duration_min = ( + round((fleet_done - fleet_start).total_seconds() / 60) + if fleet_start and fleet_done else None + ) + avg_active_minutes = ( + round( + sum(t["active_minutes"] for t in timelines if t["active_minutes"]) + / max(1, sum(1 for t in timelines if t["active_minutes"])), + 1, + ) + if any(t["active_minutes"] for t in timelines) else None + ) + avg_utilisation_pct = ( + round(avg_active_minutes / batch_duration_min * 100, 1) + if avg_active_minutes and batch_duration_min else None + ) + + fleet_summary = { + "total_orders": len(deliveries), + "total_riders": len(by_rider), + "fleet_start": _fmt(fleet_start), + "fleet_done": _fmt(fleet_done), + "total_duration_minutes": batch_duration_min, + "orders_per_rider_avg": round(len(deliveries) / len(by_rider), 1), + "load_balance_stdev": load_balance_stdev, + "finish_time_spread_minutes": finish_spread_min, + "finish_time_stdev_minutes": finish_time_stdev, + "avg_utilisation_pct": avg_utilisation_pct, + "avg_active_minutes": avg_active_minutes, + } + + if not fleet_done: + return { + "fleet_summary": fleet_summary, + "rider_timelines": _clean_timelines(timelines, fleet_done), + "substitution_opportunities": [], + "top_recommendation": None, + "error": "No completed deliveries found.", + } + + # Mark each rider's idle status and free window + for t in timelines: + fd = t["_finish_dt"] + if fd: + idle_min = (fleet_done - fd).total_seconds() / 60.0 + t["idle_minutes"] = round(idle_min) + t["free_window_minutes"] = round(idle_min) # time available for substitution + t["status"] = "idle" if idle_min >= idle_threshold_min else "active" + else: + t["idle_minutes"] = 0 + t["free_window_minutes"] = 0 + t["status"] = "unknown" + + # ------------------------------------------------------------------ + # 4. Substitution opportunities + # ------------------------------------------------------------------ + opportunities: list[dict] = [] + + idle_riders = [t for t in timelines if t["status"] == "idle" and t["_last_coord"]] + + for idle in idle_riders: + idle_uid = idle["userid"] + idle_finish = idle["_finish_dt"] + idle_coord = idle["_last_coord"] + free_window_min = idle["free_window_minutes"] + + if idle["kitchen"] is None: + continue # can't determine origin kitchen + + for target_kitchen, k_coord in kitchen_coords.items(): + if target_kitchen == idle["kitchen"]: + continue # skip own kitchen + + # Travel from idle rider's last drop to the target kitchen + travel_km = _hav(idle_coord[0], idle_coord[1], k_coord[0], k_coord[1]) + travel_min = _travel_min(travel_km, road_kmh) + + # Skip if idle rider can't even reach the kitchen before fleet is done + if travel_min >= free_window_min: + continue + + arrive_at_kitchen = idle_finish + timedelta(minutes=travel_min) + + # ---------------------------------------------------------- + # Candidate selection: score every order from this kitchen + # that was delivered after the idle rider could arrive. + # Score = time_gain (70%) + geo proximity (30%). + # This prefers orders where idle rider is genuinely faster + # AND that are close to the kitchen (less detour). + # ---------------------------------------------------------- + candidate_orders: list[tuple[int, dict, float]] = [] # (rid, order, score) + for rid, r_orders in by_rider.items(): + if rid == idle_uid: + continue + r_kitchen = next( + (t["kitchen"] for t in timelines if t["userid"] == rid), None + ) + if r_kitchen != target_kitchen: + continue + for o in r_orders: + d_ts = _parse_ts(o.get("deliverytime")) + if not d_ts or d_ts <= arrive_at_kitchen: + continue + score = _score_candidate(o, arrive_at_kitchen, k_coord, road_kmh) + candidate_orders.append((rid, o, score)) + + if not candidate_orders: + continue + + # Sort best candidates first (highest score = most time gained, closest) + candidate_orders.sort(key=lambda x: x[2], reverse=True) + take_pool = candidate_orders[:max_transfer] + + # Greedy nearest-neighbour route from the kitchen through selected orders + unvisited = list(range(len(take_pool))) + curr_nn = k_coord + greedy_take: list[tuple[int, dict]] = [] + while unvisited: + ni = min( + unvisited, + key=lambda i: ( + _hav(curr_nn[0], curr_nn[1], *c) + if (c := _get_coord(take_pool[i][1])) else 999.0 + ), + ) + unvisited.remove(ni) + greedy_take.append((take_pool[ni][0], take_pool[ni][1])) + coord = _get_coord(take_pool[ni][1]) + if coord: + curr_nn = coord + + # Simulate idle rider executing the greedy route + curr_pos = k_coord + est_time = arrive_at_kitchen + transfer_manifests: list[dict] = [] + total_delivery_leg_min = 0.0 + + for orig_rid, o in greedy_take: + coord = _get_coord(o) + if not coord: + continue + d_km = _hav(curr_pos[0], curr_pos[1], coord[0], coord[1]) + d_min = _travel_min(d_km, road_kmh) + total_delivery_leg_min += d_min + est_deliver = est_time + timedelta(minutes=d_min) + orig_deliver = _parse_ts(o.get("deliverytime")) + + improvement = ( + round((orig_deliver - est_deliver).total_seconds() / 60) + if orig_deliver and est_deliver else None + ) + is_feasible = improvement is not None and improvement > 0 + + transfer_manifests.append({ + "deliveryid": o.get("deliveryid"), + "from_rider_id": orig_rid, + "from_rider_name": rider_names.get(orig_rid, f"Rider {orig_rid}"), + "original_delivery_time": _fmt(orig_deliver), + "estimated_delivery_time": _fmt(est_deliver), + "improvement_minutes": improvement, + "is_feasible": is_feasible, + "location": {"lat": round(coord[0], 6), "lon": round(coord[1], 6)}, + }) + curr_pos = coord + est_time = est_deliver + + # Only keep orders where idle rider is actually faster + feasible_manifests = [m for m in transfer_manifests if m["is_feasible"]] + if not feasible_manifests: + continue + + idle_new_finish = est_time + + # Check idle rider can complete within their free window + total_obligation_min = travel_min + total_delivery_leg_min + if total_obligation_min > free_window_min: + # Idle rider would finish after fleet, extending rather than helping + continue + + # New fleet done after the transfer + taken_order_objs = {id(o) for (_, o) in greedy_take} + + new_finish_by_rider: dict[int, datetime | None] = {} + for rid, r_orders in by_rider.items(): + if rid == idle_uid: + new_finish_by_rider[rid] = idle_new_finish + continue + remaining = [o for o in r_orders if id(o) not in taken_order_objs] + finishes = [_parse_ts(o.get("deliverytime")) for o in remaining] + valid = [f for f in finishes if f] + new_finish_by_rider[rid] = max(valid) if valid else None + + new_fleet_done = max( + (v for v in new_finish_by_rider.values() if v), + default=fleet_done, + ) + fleet_improvement = round( + (fleet_done - new_fleet_done).total_seconds() / 60 + ) + + # Most relieved rider + orig_last_by_rider = { + rid: max( + (f for f in [_parse_ts(o.get("deliverytime")) for o in r_o] if f), + default=None, + ) + for rid, r_o in by_rider.items() + } + most_impacted_rid = max( + (rid for rid in {r for r, _ in greedy_take}), + key=lambda r: (orig_last_by_rider.get(r) or datetime.min), + default=None, + ) + orig_overloaded_finish = orig_last_by_rider.get(most_impacted_rid) + new_overloaded_finish = new_finish_by_rider.get(most_impacted_rid) + time_saved = ( + round((orig_overloaded_finish - new_overloaded_finish).total_seconds() / 60) + if orig_overloaded_finish and new_overloaded_finish else 0 + ) + + # Total extra km for idle rider (idle→kitchen + all delivery legs) + total_extra_km = travel_km + sum( + _hav( + (k_coord if i == 0 else (_get_coord(greedy_take[i-1][1]) or k_coord))[0], + (k_coord if i == 0 else (_get_coord(greedy_take[i-1][1]) or k_coord))[1], + *(_get_coord(o) or k_coord), + ) + for i, (_, o) in enumerate(greedy_take) + if _get_coord(o) + ) + + # ---------------------------------------------------------- + # Confidence score (0-100) + # Measures how comfortable this transfer is given real constraints. + # + # Component 1 – Slack ratio: how much free time the idle rider + # has beyond the time they'll spend doing the transfer. + # (free_window - total_obligation) / free_window → 0..1 + # + # Component 2 – Feasibility ratio: what fraction of the + # transferred orders actually deliver earlier than original. + # feasible_count / total_transferred → 0..1 + # + # Component 3 – Fleet gain ratio: minutes saved as a fraction + # of total batch duration. Capped at 20 min improvement for + # full score so small batches don't produce inflated scores. + # ---------------------------------------------------------- + slack_ratio = max(0.0, (free_window_min - total_obligation_min) / free_window_min) + feasibility_ratio = len(feasible_manifests) / max(1, len(transfer_manifests)) + fleet_gain_ratio = min(1.0, fleet_improvement / 20.0) if fleet_improvement > 0 else 0.0 + + confidence_score = round( + (slack_ratio * 0.4 + feasibility_ratio * 0.35 + fleet_gain_ratio * 0.25) * 100 + ) + + efficiency_ratio = ( + round(fleet_improvement / max(0.1, total_extra_km), 2) + if total_extra_km > 0 else 0.0 + ) + if efficiency_ratio >= 5: + efficiency_rating = "high" + elif efficiency_ratio >= 2: + efficiency_rating = "medium" + else: + efficiency_rating = "low" + + opportunities.append({ + "idle_rider": { + "userid": idle_uid, + "name": idle["name"], + "primary_kitchen": idle["kitchen"], + "order_count": idle["order_count"], + "finished_at": _fmt(idle_finish), + "idle_minutes": idle["idle_minutes"], + "free_window_minutes": free_window_min, + "last_position": idle["last_position"], + }, + "target_kitchen": target_kitchen, + "travel_to_kitchen_km": round(travel_km, 1), + "travel_to_kitchen_minutes": round(travel_min), + "arrive_at_kitchen": _fmt(arrive_at_kitchen), + "orders_to_transfer": transfer_manifests, + "total_orders_transferred": len(feasible_manifests), + "feasible_orders_count": len(feasible_manifests), + "most_relieved_rider": { + "userid": most_impacted_rid, + "name": rider_names.get(most_impacted_rid, f"Rider {most_impacted_rid}"), + "original_finish": _fmt(orig_overloaded_finish), + "new_finish": _fmt(new_overloaded_finish), + "time_saved_minutes": time_saved, + }, + "extra_km_for_idle_rider": round(total_extra_km, 1), + "total_obligation_minutes": round(total_obligation_min), + "idle_rider_new_finish": _fmt(idle_new_finish), + "original_fleet_done": _fmt(fleet_done), + "new_fleet_done": _fmt(new_fleet_done), + "fleet_improvement_minutes": fleet_improvement, + "confidence_score": confidence_score, + "efficiency_ratio": efficiency_ratio, + "efficiency_rating": efficiency_rating, + }) + + # Keep only net-positive opportunities + opportunities = [o for o in opportunities if o["fleet_improvement_minutes"] > 0] + + # Sort: confidence first (overall quality), then fleet improvement, then rider time saved + opportunities.sort( + key=lambda x: ( + -x["confidence_score"], + -x["fleet_improvement_minutes"], + -x["most_relieved_rider"]["time_saved_minutes"], + ) + ) + + # ------------------------------------------------------------------ + # 5. Top recommendation + # ------------------------------------------------------------------ + top_recommendation = _build_recommendation( + opportunities, idle_threshold_min, fleet_done, timelines, fleet_summary + ) + + return { + "fleet_summary": fleet_summary, + "rider_timelines": _clean_timelines(timelines, fleet_done), + "substitution_opportunities": opportunities, + "top_recommendation": top_recommendation, + } + + +# --------------------------------------------------------------------------- +# Helpers for clean output +# --------------------------------------------------------------------------- + +def _clean_timelines( + timelines: list[dict], + fleet_done: datetime | None, +) -> list[dict]: + out = [] + for t in timelines: + out.append({ + "userid": t["userid"], + "name": t["name"], + "kitchen": t["kitchen"], + "kitchen_confidence": t.get("kitchen_confidence", 0.0), + "order_count": t["order_count"], + "completed_orders": t.get("completed_orders", t["order_count"]), + "pending_orders": t.get("pending_orders", 0), + "started_at": t["started_at"], + "finished_at": t["finished_at"], + "active_minutes": t.get("active_minutes"), + "pace_orders_per_hour": t.get("pace_orders_per_hour"), + "idle_minutes": t.get("idle_minutes", 0), + "free_window_minutes": t.get("free_window_minutes", 0), + "status": t.get("status", "unknown"), + "last_position": t.get("last_position"), + }) + return out + + +def _build_recommendation( + opportunities: list[dict], + idle_threshold: float, + fleet_done: datetime | None, + timelines: list[dict], + fleet_summary: dict, +) -> dict | None: + if not opportunities: + # Diagnose WHY there are no opportunities even if some riders were idle + idle_count = sum(1 for t in timelines if t.get("status") == "idle") + if idle_count == 0: + reason = "All riders finished within the idle threshold window — batch was well balanced." + else: + reason = ( + f"{idle_count} rider(s) finished early but no feasible substitution found: " + "either travel time exceeds the idle window, or all candidate orders " + "would be delivered later by the idle rider than the original." + ) + return { + "action": "none", + "reason": reason, + "fleet_balance_assessment": _balance_assessment(fleet_summary), + } + + best = opportunities[0] + idle = best["idle_rider"] + target = best["target_kitchen"] + relieved = best["most_relieved_rider"] + primary_kitchen = idle["primary_kitchen"] or "unknown" + confidence = best["confidence_score"] + + # Root cause: why was this rider idle? + root_cause = _diagnose_root_cause(idle, timelines, fleet_summary) + + # Risk factors + risk_factors = _identify_risks(best, idle_threshold) + + description = ( + f"{idle['name']} ({primary_kitchen}) finished all {idle['order_count']} orders " + f"at {idle['finished_at']} — {idle['idle_minutes']} min before the fleet finished. " + f"Assigning {best['feasible_orders_count']} {target} orders: " + f"travel {best['travel_to_kitchen_km']} km ({best['travel_to_kitchen_minutes']} min), " + f"arrive at {target} kitchen at {best['arrive_at_kitchen']}. " + f"Relieves {relieved['name']} by {relieved['time_saved_minutes']} min " + f"({relieved['original_finish']} → {relieved['new_finish']}). " + f"Fleet finishes {best['fleet_improvement_minutes']} min earlier " + f"({best['original_fleet_done']} → {best['new_fleet_done']}). " + f"Confidence: {confidence}/100." + ) + + # Dynamic thresholds derived from the actual batch data + idle_rider_loads = [t["order_count"] for t in timelines if t.get("kitchen") == primary_kitchen] + target_rider_loads = [t["order_count"] for t in timelines if t.get("kitchen") == target] + activate_idle_threshold = max(6, idle.get("order_count", 6) + 2) + activate_target_threshold = max(8, round(sum(target_rider_loads) / max(1, len(target_rider_loads)) * 1.1)) + + activate_rule = { + "condition": "AND", + "rules": [ + { + "field": f"{primary_kitchen}_order_count", + "operator": "<=", + "value": activate_idle_threshold, + "reason": ( + f"{idle['name']} had {idle['order_count']} orders today and was idle " + f"{idle['idle_minutes']} min. Dual-kitchen kicks in when their load " + f"stays at or below {activate_idle_threshold}." + ), + }, + { + "field": f"{target}_order_count", + "operator": ">=", + "value": activate_target_threshold, + "reason": ( + f"{target.capitalize()} had enough orders today to justify the detour " + f"({sum(target_rider_loads)} total across {len(target_rider_loads)} rider(s)). " + f"Activate when {target} load is ≥ {activate_target_threshold}." + ), + }, + ], + } + + return { + "action": "dual_kitchen_assignment", + "idle_rider_id": idle["userid"], + "idle_rider_name": idle["name"], + "primary_kitchen": primary_kitchen, + "second_kitchen": target, + "second_kitchen_dispatch_after": best["arrive_at_kitchen"], + "description": description, + "fleet_improvement_minutes": best["fleet_improvement_minutes"], + "confidence_score": confidence, + "efficiency_rating": best["efficiency_rating"], + "root_cause": root_cause, + "risk_factors": risk_factors, + "activate_when": activate_rule, + "fleet_balance_assessment": _balance_assessment(fleet_summary), + "api_hint": { + "endpoint": "/api/v1/optimize", + "note": ( + f"In the next batch, pre-assign the last " + f"{best['feasible_orders_count']} {target} orders to " + f"rider {idle['userid']} ({idle['name']}) with a " + f"dispatch-after time of {best['arrive_at_kitchen']}." + ), + }, + } + + +def _diagnose_root_cause( + idle: dict, + timelines: list[dict], + fleet_summary: dict, +) -> str: + """ + Explain WHY this rider finished early by comparing their load + against the fleet average and their kitchen's order volume. + """ + avg_orders = fleet_summary.get("orders_per_rider_avg", 0) + rider_orders = idle["order_count"] + kitchen = idle["primary_kitchen"] or "their kitchen" + name = idle["name"] + + if avg_orders > 0 and rider_orders < avg_orders * 0.7: + shortfall = round(avg_orders - rider_orders, 1) + return ( + f"{name} received {rider_orders} orders vs fleet average of {avg_orders:.1f} " + f"(−{shortfall:.1f}). {kitchen.capitalize()} kitchen generated fewer orders " + f"than the fleet needed to keep this rider fully utilised. " + f"This is a systematic under-loading of the {kitchen} kitchen in this batch." + ) + elif rider_orders <= 4: + return ( + f"{name} had only {rider_orders} orders — a very light load regardless of fleet average. " + f"Likely a short-demand window at {kitchen} kitchen. " + f"Dual-kitchen assignment is especially effective when primary kitchen load is ≤ 4 orders." + ) + else: + spread = fleet_summary.get("finish_time_spread_minutes", 0) + return ( + f"{name} is simply faster than peers — finished {idle['idle_minutes']} min ahead " + f"despite a normal load of {rider_orders} orders. " + f"Fleet finish-time spread is {spread} min, indicating uneven workload distribution." + ) + + +def _identify_risks(best: dict, idle_threshold: float) -> list[str]: + """ + Enumerate operational risks for the recommended substitution. + """ + risks: list[str] = [] + travel_min = best["travel_to_kitchen_minutes"] + obligation = best["total_obligation_minutes"] + free_window = best["idle_rider"]["free_window_minutes"] + confidence = best["confidence_score"] + extra_km = best["extra_km_for_idle_rider"] + + slack_min = free_window - obligation + if slack_min < 10: + risks.append( + f"Tight schedule: only {slack_min} min of slack between idle rider's " + f"estimated finish and fleet completion. Any delay (traffic, kitchen wait) " + f"would eliminate the benefit." + ) + if travel_min > 15: + risks.append( + f"Long commute to target kitchen ({travel_min} min). " + f"Kitchen departure time must be precise — a late start erodes time savings." + ) + if extra_km > 8: + risks.append( + f"Extra {extra_km} km for the idle rider adds fuel cost and rider fatigue. " + f"Verify this is worthwhile if fleet improvement is marginal." + ) + if confidence < 50: + risks.append( + f"Low confidence ({confidence}/100): limited slack or few feasible transfers. " + f"Consider this as a contingency plan rather than a guaranteed improvement." + ) + if best.get("feasible_orders_count", 0) < best.get("total_orders_transferred", 1): + risks.append( + "Not all proposed transfers save time — some orders are included to fill " + "the idle rider's route but don't improve individual delivery times." + ) + if not risks: + risks.append("No significant risks identified. Transfer looks operationally sound.") + + return risks + + +def _balance_assessment(fleet_summary: dict) -> str: + """Short human-readable verdict on batch balance quality.""" + spread = fleet_summary.get("finish_time_spread_minutes", 0) + stdev = fleet_summary.get("load_balance_stdev", 0) + util = fleet_summary.get("avg_utilisation_pct") + + if spread <= 10 and stdev <= 1: + verdict = "Excellent — riders finished close together with balanced loads." + elif spread <= 20 and stdev <= 2: + verdict = "Good — minor imbalance, acceptable for this fleet size." + elif spread <= 35: + verdict = f"Moderate imbalance — {spread} min spread between earliest and latest finish." + else: + verdict = ( + f"High imbalance — {spread} min spread. Some riders sat idle while others overran. " + f"Pre-planning dual-kitchen assignments is strongly recommended." + ) + + if util is not None: + verdict += f" Average rider utilisation: {util}% of batch window." + return verdict diff --git a/app/services/routing/clustering_service.py b/app/services/routing/clustering_service.py new file mode 100644 index 0000000..709ae38 --- /dev/null +++ b/app/services/routing/clustering_service.py @@ -0,0 +1,300 @@ +""" +Geographic Clustering Service for Order Assignment +Uses K-means clustering to group orders by kitchen location. +Enhanced with Geohash encoding for spatial learning (idea.txt data encoding). +""" + +import logging +import numpy as np +from typing import List, Dict, Any, Tuple +from collections import defaultdict +from math import radians, cos, sin, asin, sqrt + +logger = logging.getLogger(__name__) + + +class GeohashEncoder: + """ + Geohash Encoding for spatial data. + Converts lat/lon coordinates to grid cell strings for locality capture. + + Precision levels: + - 4 chars: ~156km x 156km (regional) + - 5 chars: ~39km x 19km (city-level) + - 6 chars: ~4.9km x 4.9km (neighborhood) + - 7 chars: ~1.2km x 609m (local zone) + """ + + BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz" + + @classmethod + def encode(cls, lat: float, lon: float, precision: int = 6) -> str: + """ + Encode lat/lon to geohash string. + + Args: + lat: Latitude (-90 to 90) + lon: Longitude (-180 to 180) + precision: Number of characters (4-12) + + Returns: + Geohash string + """ + if lat == 0 and lon == 0: + return "unknown" + + lat_min, lat_max = -90.0, 90.0 + lon_min, lon_max = -180.0, 180.0 + + hash_chars = [] + is_lon = True + + for _ in range(precision): + char_bits = 0 + for _ in range(5): + if is_lon: + mid = (lon_min + lon_max) / 2 + if lon >= mid: + char_bits = (char_bits << 1) | 1 + lon_min = mid + else: + char_bits = char_bits << 1 + lon_max = mid + else: + mid = (lat_min + lat_max) / 2 + if lat >= mid: + char_bits = (char_bits << 1) | 1 + lat_min = mid + else: + char_bits = char_bits << 1 + lat_max = mid + is_lon = not is_lon + hash_chars.append(cls.BASE32[char_bits]) + + return "".join(hash_chars) + + @classmethod + def get_zone_from_geohash(cls, geohash: str) -> Dict[str, Any]: + """ + Extract zone metadata from geohash for ML features. + + Returns: + Dict with zone info: zone_id, precision, cell_size, etc. + """ + if not geohash or geohash == "unknown": + return {"zone_id": "unknown", "precision": 0} + + precision = len(geohash) + + # Approximate cell sizes (in km) + lat_error = 180.0 / (2 ** (precision * 5 // 2)) / 2 + lon_error = 360.0 / (2 ** (precision * 5 // 2 + 1)) / 2 + + # Cell size approximation + cell_width_km = lat_error * 111 # 1 degree lat ≈ 111km + cell_height_km = ( + lon_error * 111 * cos(11 * 3.14159 / 180) + ) # Adjust for Coimbatore lat + + return { + "zone_id": geohash, + "precision": precision, + "cell_width_km": round(cell_width_km, 3), + "cell_height_km": round(cell_height_km, 3), + "prefix_4": geohash[:4] if len(geohash) >= 4 else geohash, + "prefix_5": geohash[:5] if len(geohash) >= 5 else geohash, + "prefix_6": geohash[:6] if len(geohash) >= 6 else geohash, + } + + +class ClusteringService: + """Clusters orders geographically to enable balanced rider assignment.""" + + def __init__(self): + self.earth_radius_km = 6371 + self.geohash_encoder = GeohashEncoder() + + def haversine(self, lat1: float, lon1: float, lat2: float, lon2: float) -> float: + """Calculate distance between two points in km.""" + lon1, lat1, lon2, lat2 = map( + radians, [float(lon1), float(lat1), float(lon2), float(lat2)] + ) + dlon = lon2 - lon1 + dlat = lat2 - lat1 + a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2 + c = 2 * asin(min(1.0, sqrt(a))) + return c * self.earth_radius_km + + def get_kitchen_location(self, order: Dict[str, Any]) -> Tuple[float, float]: + """Extract kitchen coordinates from order.""" + try: + lat = float(order.get("pickuplat", 0)) + lon = float(order.get("pickuplon") or order.get("pickuplong", 0)) + if lat != 0 and lon != 0: + return lat, lon + except (ValueError, TypeError): + pass + return 0.0, 0.0 + + def _encode_location_features(self, lat: float, lon: float) -> Dict[str, Any]: + """ + Encode location with multiple spatial features (Data Encoding: Geohash + Distance). + + Returns: + Dict with geohash, zone info, distance features + """ + features = {} + + # Primary geohash encoding (6 chars = ~5km zone for Coimbatore) + geohash_6 = self.geohash_encoder.encode(lat, lon, 6) + features["geohash_6"] = geohash_6 + + # Fine-grained geohash (7 chars = ~1.2km zone) + geohash_7 = self.geohash_encoder.encode(lat, lon, 7) + features["geohash_7"] = geohash_7 + + # Coarse geohash for regional grouping (4 chars = ~156km) + geohash_4 = self.geohash_encoder.encode(lat, lon, 4) + features["geohash_4"] = geohash_4 + + # Zone metadata + features["zone_info"] = self.geohash_encoder.get_zone_from_geohash(geohash_6) + + return features + + def cluster_orders_by_kitchen( + self, orders: List[Dict[str, Any]], max_cluster_radius_km: float = 3.0 + ) -> List[Dict[str, Any]]: + """ + Cluster orders by kitchen proximity. + + Returns list of clusters, each containing: + - centroid: (lat, lon) of cluster center + - orders: list of orders in this cluster + - kitchen_names: set of kitchen names in cluster + - total_orders: count + - geohash_6: geohash encoding of centroid (NEW) + - zone_info: zone metadata (NEW) + - spatial_features: all location encodings (NEW) + """ + if not orders: + return [] + + # Group by kitchen location + kitchen_groups = defaultdict(list) + kitchen_coords = {} + + for order in orders: + k_name = self._get_kitchen_name(order) + k_lat, k_lon = self.get_kitchen_location(order) + + if k_lat == 0: + # Fallback: use delivery location if pickup missing + k_lat = float(order.get("deliverylat", 0)) + k_lon = float(order.get("deliverylong", 0)) + + if k_lat != 0: + kitchen_groups[k_name].append(order) + kitchen_coords[k_name] = (k_lat, k_lon) + + # Now cluster kitchens that are close together + clusters = [] + processed_kitchens = set() + + for k_name, k_orders in kitchen_groups.items(): + if k_name in processed_kitchens: + continue + + # Start a new cluster with this kitchen + cluster_kitchens = [k_name] + cluster_orders = k_orders[:] + processed_kitchens.add(k_name) + + k_lat, k_lon = kitchen_coords[k_name] + + # ── CHAIN-MERGE FIX ────────────────────────────────────────── + # Original bug: only checked against the SEED kitchen. + # Example: A→B = 2km, B→C = 2km, A→C = 4km (max_radius = 3km). + # Old code: C is NOT merged (A→C > 3km). + # New code: iteratively re-check remaining kitchens against the + # CURRENT centroid after each merge, so chains like A→B→C + # are correctly collapsed into one cluster. + # ───────────────────────────────────────────────────────────── + changed = True + while changed: + changed = False + # Recompute centroid of current cluster + c_lats = [kitchen_coords[n][0] for n in cluster_kitchens if n in kitchen_coords] + c_lons = [kitchen_coords[n][1] for n in cluster_kitchens if n in kitchen_coords] + c_lat = sum(c_lats) / len(c_lats) if c_lats else k_lat + c_lon = sum(c_lons) / len(c_lons) if c_lons else k_lon + + for other_name, other_coords in kitchen_coords.items(): + if other_name in processed_kitchens: + continue + other_lat, other_lon = other_coords + dist = self.haversine(c_lat, c_lon, other_lat, other_lon) + if dist <= max_cluster_radius_km: + cluster_kitchens.append(other_name) + cluster_orders.extend(kitchen_groups[other_name]) + processed_kitchens.add(other_name) + changed = True # centroid shifted — re-scan remaining + + # Calculate cluster centroid + lats = [] + lons = [] + for order in cluster_orders: + lat, lon = self.get_kitchen_location(order) + if lat != 0: + lats.append(lat) + lons.append(lon) + + if lats: + centroid_lat = sum(lats) / len(lats) + centroid_lon = sum(lons) / len(lons) + else: + centroid_lat, centroid_lon = k_lat, k_lon + + # ENHANCED: Add geohash encoding features + spatial_features = self._encode_location_features( + centroid_lat, centroid_lon + ) + + clusters.append( + { + "centroid": (centroid_lat, centroid_lon), + "orders": cluster_orders, + "kitchen_names": set(cluster_kitchens), + "total_orders": len(cluster_orders), + # NEW: Geohash encoding features + "geohash_6": spatial_features["geohash_6"], + "geohash_7": spatial_features["geohash_7"], + "geohash_4": spatial_features["geohash_4"], + "zone_info": spatial_features["zone_info"], + "spatial_features": spatial_features, + } + ) + + # Sort clusters by order count (largest first) + clusters.sort(key=lambda x: x["total_orders"], reverse=True) + + logger.info( + f"Created {len(clusters)} clusters from {len(kitchen_groups)} kitchens with geohash encoding" + ) + return clusters + + def _get_kitchen_name(self, order: Dict[str, Any]) -> str: + """Extract kitchen name from order.""" + possible_keys = [ + "pickupcustomer", # confirmed primary field in production orders + "locationname", # confirmed backup field in production orders + "storename", "store_name", + "restaurantname", "restaurant_name", + "kitchenname", "kitchen_name", + "partnername", "partner_name", + "tenantname", + ] + for key in possible_keys: + if key in order and order[key]: + return str(order[key]).strip() + return "Unknown" diff --git a/app/services/routing/delivery_history_service.py b/app/services/routing/delivery_history_service.py new file mode 100644 index 0000000..cc67927 --- /dev/null +++ b/app/services/routing/delivery_history_service.py @@ -0,0 +1,864 @@ +""" +Delivery History Service — Empirical ETA from ground truth +========================================================== + +WHY THIS EXISTS +--------------- +Until now every ETA in the system was a *formula guess* +(`RealisticETACalculator`: distance / configured_speed + fixed buffers) that was +never checked against what actually happened in the field. Senior feedback was +that manual riders deliver faster than our estimates — i.e. the guess is wrong. + +This service closes the loop. The external `nearledb` Postgres already records, +for every completed delivery, when the rider picked up (`pickuptime`) and when +the order was delivered (`deliverytime`). From those we reconstruct **actual +per-leg travel times** and learn empirical medians, so ETAs reflect reality +instead of a hand-tuned formula. + +GROUND-TRUTH RECONSTRUCTION (per-leg, matches the optimizer) +----------------------------------------------------------- +The optimizer feeds *aerial* (straight-line) leg distance to `calculate_eta` +(see route_optimizer.py — `step_dist` comes from `aerial_matrix`, no road +factor). To learn a model that plugs in behind the same call, we reconstruct +observations the same way: + + * Group a rider's completed deliveries by day, ordered by `deliverytime`. + * For each pair of consecutive deliveries: + leg_min = deliverytime[i] - deliverytime[i-1] (real door-to-door time) + leg_km = aerial haversine(drop[i-1], drop[i]) (same metric as optimizer) + * The first delivery of a group is the kitchen→first-drop leg: + leg_min = deliverytime[0] - pickuptime[0] (distance unknown w/o + kitchen coords, so it only feeds the non-distance keys). + +Only `droplat/droplon`, `pickuptime`, `deliverytime`, `pickupcustomer`, `userid` +are needed — all confirmed-present columns (same set batch_analytics reads). + +AGGREGATION + LOOKUP (hierarchical, cold-start safe) +---------------------------------------------------- +Each observation feeds several keys at decreasing specificity. At prediction +time we walk the same hierarchy and use the first key with enough samples, +falling back to the formula when history is too thin: + + kzd kitchen | drop_zone | traffic | dist_bucket (most specific) + kz kitchen | drop_zone | traffic + zd drop_zone | traffic | dist_bucket + z drop_zone | traffic + dt dist_bucket | traffic + t traffic (least specific) + → RealisticETACalculator formula (no data) + +`rkz` (rider | kitchen | zone | traffic) is also stored for Phase-2 learned +rider affinity; it is not used by the default lookup yet. +""" + +import logging +import math +import os +import sqlite3 +import threading +import statistics +import time +from datetime import datetime, timedelta +from collections import defaultdict +from typing import Any, Dict, List, Optional, Tuple + +from app.services.routing.zone_service import ZoneService + +logger = logging.getLogger(__name__) + +_DB_PATH = os.getenv("ML_DB_PATH", "ml_data/ml_store.db") +_WRITE_LOCK = threading.Lock() + +# Aerial leg-distance buckets (km) — must match the metric the optimizer feeds +# to calculate_eta (pure haversine, no road factor). +_DIST_BUCKETS: List[Tuple[float, float]] = [ + (0.0, 1.0), (1.0, 2.0), (2.0, 3.0), (3.0, 5.0), (5.0, 8.0), (8.0, 12.0), (12.0, 1e9) +] + +# Sanity filters for reconstructed legs. +_MAX_LEG_MIN = 60.0 # gaps longer than this are batch boundaries / idle, not a leg +_MAX_LEG_KM = 40.0 # implausible single hop + + +# --------------------------------------------------------------------------- +# Pure helpers +# --------------------------------------------------------------------------- + +def dist_bucket(km: Optional[float]) -> Optional[str]: + """Aerial leg distance -> discrete bucket label, or None if unknown.""" + if km is None: + return None + for lo, hi in _DIST_BUCKETS: + if km <= hi: + return f"{lo:g}-{hi:g}" if hi < 1e9 else f"{lo:g}+" + return f"{_DIST_BUCKETS[-1][0]:g}+" + + +def hour_to_traffic(hour: int) -> str: + """Time-of-day -> traffic category, mirroring get_time_of_day_category().""" + if (8 <= hour < 10) or (12 <= hour < 14) or (17 <= hour < 20): + return "peak" + if hour < 7 or hour >= 22: + return "light" + return "normal" + + +def normalize_kitchen(name: Any) -> str: + """Normalize a kitchen / pickup-customer name to a stable key token.""" + if not name: + return "?" + return " ".join(str(name).strip().lower().split()) + + +def _haversine_km(lat1: float, lon1: float, lat2: float, lon2: float) -> float: + """Great-circle (aerial) distance in km.""" + try: + rlat1, rlon1, rlat2, rlon2 = map(math.radians, (lat1, lon1, lat2, lon2)) + dlat = rlat2 - rlat1 + dlon = rlon2 - rlon1 + a = math.sin(dlat / 2) ** 2 + math.cos(rlat1) * math.cos(rlat2) * math.sin(dlon / 2) ** 2 + return 6371.0 * 2 * math.asin(min(1.0, math.sqrt(a))) + except Exception: + return 0.0 + + +def _parse_dt(val: Any) -> Optional[datetime]: + if val in (None, "", 0): + return None + if isinstance(val, datetime): + return val + s = str(val).strip() + for fmt in ("%Y-%m-%d %H:%M:%S", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S.%f", + "%Y-%m-%dT%H:%M:%SZ", "%Y-%m-%d %H:%M"): + try: + return datetime.strptime(s.split("+")[0].strip(), fmt) + except Exception: + continue + try: + from dateutil.parser import parse as _du + return _du(s) + except Exception: + return None + + +# --------------------------------------------------------------------------- +# Shared Postgres connector (single source of truth for nearledb creds) +# --------------------------------------------------------------------------- + +def connect_nearledb(connect_timeout: int = 10): + """ + Open a connection to the external nearledb Postgres. + + Credentials come from DB_* env vars (same defaults batch_analytics used). + Raises on failure — callers convert to their own error type. + """ + import psycopg2 # imported lazily so the app boots without it + + conn = psycopg2.connect( + host=os.getenv("DB_HOST", "66.116.207.225"), + port=int(os.getenv("DB_PORT", "6432")), + dbname=os.getenv("DB_NAME", "nearledb"), + user=os.getenv("DB_USER", "admin"), + password=os.getenv("DB_PASSWORD", "Package@123#"), + connect_timeout=connect_timeout, + ) + # Best-effort read-only session. (Port 6432 is pgbouncer, which rejects the + # `options` startup param, so we set it post-connect; our code only issues + # SELECTs regardless — we never write to or alter the source DB.) + try: + conn.set_session(readonly=True) + except Exception: + pass + return conn + + +# --------------------------------------------------------------------------- +# Key construction (build-side and lookup-side share this so they stay in sync) +# --------------------------------------------------------------------------- + +def _keys_for_observation(kitchen: str, zone: str, traffic: str, + bucket: Optional[str], rider_id: Any) -> List[str]: + """All aggregation keys an observation contributes to.""" + keys = [ + f"kz|{kitchen}|{zone}|{traffic}", + f"z|{zone}|{traffic}", + f"t|{traffic}", + f"rkz|{rider_id}|{kitchen}|{zone}|{traffic}", + ] + if bucket is not None: + keys += [ + f"kzd|{kitchen}|{zone}|{traffic}|{bucket}", + f"zd|{zone}|{traffic}|{bucket}", + f"dt|{bucket}|{traffic}", + ] + return keys + + +def _lookup_keys(kitchen: Optional[str], zone: str, traffic: str, + bucket: Optional[str]) -> List[str]: + """Ordered candidate keys, most specific first, for prediction-time lookup.""" + ordered: List[str] = [] + if kitchen and bucket is not None: + ordered.append(f"kzd|{kitchen}|{zone}|{traffic}|{bucket}") + if kitchen: + ordered.append(f"kz|{kitchen}|{zone}|{traffic}") + if bucket is not None: + ordered.append(f"zd|{zone}|{traffic}|{bucket}") + ordered.append(f"z|{zone}|{traffic}") + if bucket is not None: + ordered.append(f"dt|{bucket}|{traffic}") + ordered.append(f"t|{traffic}") + return ordered + + +# --------------------------------------------------------------------------- +# Service +# --------------------------------------------------------------------------- + +class DeliveryHistoryService: + """Ingests completed deliveries, learns empirical leg-time medians, serves lookups.""" + + def __init__(self): + self._db_path = _DB_PATH + self._zone = ZoneService() + # cache: full_key -> (count, median_min, p75_min) + self._cache: Dict[str, Tuple[int, float, float]] = {} + self._last_refreshed: Optional[datetime] = None + self._last_summary: Dict[str, Any] = {} + self._refresh_lock = threading.Lock() + self._refresh_attempt_at: Optional[datetime] = None + self._scheduler_started = False + self._ensure_db() + self._load_cache() + + # -- schema ------------------------------------------------------------- + + def _ensure_db(self) -> None: + try: + os.makedirs(os.path.dirname(self._db_path) or ".", exist_ok=True) + conn = sqlite3.connect(self._db_path) + conn.execute(""" + CREATE TABLE IF NOT EXISTS delivery_history ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + delivery_ts TEXT, + rider_id TEXT, + kitchen TEXT, + drop_zone TEXT, + traffic TEXT, + dist_bucket TEXT, + leg_km REAL, + leg_min REAL, + is_first INTEGER DEFAULT 0 + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS eta_stats ( + key TEXT PRIMARY KEY, + key_type TEXT, + sample_count INTEGER, + median_min REAL, + p75_min REAL, + updated_at TEXT + ) + """) + conn.execute("CREATE INDEX IF NOT EXISTS idx_eta_stats_type ON eta_stats(key_type)") + # Local mirror of the nearledb `deliveries` rows we care about. + # The request path NEVER touches Postgres — only this table. + # Deduped by deliveryid so incremental syncs are idempotent. + conn.execute(""" + CREATE TABLE IF NOT EXISTS delivery_raw ( + deliveryid TEXT PRIMARY KEY, + userid TEXT, + pickupcustomer TEXT, + pickuptime TEXT, + deliverytime TEXT, + dlat REAL, + dlon REAL, + plat REAL, + plon REAL + ) + """) + # Migration for stores created before pickup coords were added. + for _ddl in ( + "ALTER TABLE delivery_raw ADD COLUMN plat REAL", + "ALTER TABLE delivery_raw ADD COLUMN plon REAL", + ): + try: + conn.execute(_ddl) + except Exception: + pass + conn.execute("CREATE INDEX IF NOT EXISTS idx_raw_dtime ON delivery_raw(deliverytime)") + # Single-row sync watermark / bookkeeping. + conn.execute(""" + CREATE TABLE IF NOT EXISTS eta_sync_state ( + id INTEGER PRIMARY KEY CHECK (id = 1), + last_delivery_ts TEXT, + last_synced_at TEXT, + total_rows INTEGER DEFAULT 0 + ) + """) + conn.execute("INSERT OR IGNORE INTO eta_sync_state (id, total_rows) VALUES (1, 0)") + conn.commit() + conn.close() + except Exception as e: + logger.error(f"[DeliveryHistory] DB init failed: {e}") + + # -- ingestion ---------------------------------------------------------- + + def fetch_completed_deliveries( + self, days: int, tenant_id: int = 916, since: Optional[str] = None + ) -> List[Dict[str, Any]]: + """ + READ-ONLY pull from nearledb `deliveries`. + + * `since` set -> incremental: only rows newer than the watermark. + * `since` None -> initial backfill of the last `days`. + + Only the `deliveries` table is read; the session is read-only (no writes, + no schema changes — enforced at the connection level). + """ + conn = connect_nearledb() + try: + cur = conn.cursor() + if since: + where_time = "d.deliverytime::timestamp > %s" + time_param = since + else: + where_time = "d.deliverytime::timestamp >= %s" + time_param = (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%d %H:%M:%S") + cur.execute( + f""" + SELECT + d.deliveryid, + d.userid, + d.pickupcustomer, + d.pickuptime, + d.deliverytime, + COALESCE(d.droplat, d.deliverylat) AS dlat, + COALESCE(d.droplon, d.deliverylong) AS dlon, + d.pickuplat AS plat, + d.pickuplon AS plon + FROM deliveries d + WHERE d.tenantid = %s + AND d.deliverytime IS NOT NULL + AND d.pickuptime IS NOT NULL + AND {where_time} + AND COALESCE(d.droplat, d.deliverylat) IS NOT NULL + AND d.userid IS NOT NULL + ORDER BY d.deliverytime + """, + (tenant_id, time_param), + ) + cols = [c.name for c in cur.description] + rows = [dict(zip(cols, r)) for r in cur.fetchall()] + cur.close() + return rows + finally: + conn.close() + + # -- watermark / local raw store --------------------------------------- + + def _get_watermark(self) -> Optional[str]: + try: + conn = sqlite3.connect(self._db_path) + row = conn.execute( + "SELECT last_delivery_ts FROM eta_sync_state WHERE id = 1" + ).fetchone() + conn.close() + return row[0] if row and row[0] else None + except Exception: + return None + + def sync_from_db(self, days: int = 14, tenant_id: int = 916, + full: bool = False) -> Dict[str, Any]: + """ + Pull NEW completed deliveries from nearledb into the local mirror. + + Idempotent (INSERT OR IGNORE on deliveryid). On the first run (empty + watermark) or `full=True`, backfills the last `days`; afterwards only + rows newer than the watermark are fetched — minimal DB load. + """ + watermark = None if full else self._get_watermark() + rows = self.fetch_completed_deliveries(days, tenant_id, since=watermark) + + inserted = 0 + max_ts = watermark + conn = sqlite3.connect(self._db_path) + try: + if full: + # A full sync truly rebuilds the local mirror (also backfills any + # newly-added columns that INSERT OR IGNORE would otherwise skip). + conn.execute("DELETE FROM delivery_raw") + conn.execute("UPDATE eta_sync_state SET last_delivery_ts = NULL WHERE id = 1") + max_ts = None + for r in rows: + dt = str(r.get("deliverytime") or "") + try: + cur = conn.execute( + "INSERT OR IGNORE INTO delivery_raw " + "(deliveryid, userid, pickupcustomer, pickuptime, deliverytime, dlat, dlon, plat, plon) " + "VALUES (?,?,?,?,?,?,?,?,?)", + (str(r.get("deliveryid")), str(r.get("userid")), + r.get("pickupcustomer"), str(r.get("pickuptime") or ""), + dt, r.get("dlat"), r.get("dlon"), r.get("plat"), r.get("plon")), + ) + inserted += cur.rowcount + except Exception: + continue + if dt and (max_ts is None or dt > max_ts): + max_ts = dt + total = conn.execute("SELECT COUNT(*) FROM delivery_raw").fetchone()[0] + conn.execute( + "UPDATE eta_sync_state SET last_delivery_ts = ?, last_synced_at = ?, total_rows = ? WHERE id = 1", + (max_ts, datetime.utcnow().isoformat(), total), + ) + conn.commit() + finally: + conn.close() + return {"fetched": len(rows), "inserted": inserted, "local_total": total, + "watermark": max_ts, "mode": "full" if full else "incremental"} + + def _prune_raw(self, days: int) -> int: + """Drop local rows older than the rolling window to bound the store.""" + cutoff = (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%d %H:%M:%S") + try: + conn = sqlite3.connect(self._db_path) + cur = conn.execute("DELETE FROM delivery_raw WHERE deliverytime < ?", (cutoff,)) + deleted = cur.rowcount + conn.commit() + conn.close() + return deleted + except Exception: + return 0 + + def _load_raw_rows(self, days: int) -> List[Dict[str, Any]]: + """Read the local mirror within the rolling window (no DB hit).""" + cutoff = (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%d %H:%M:%S") + conn = sqlite3.connect(self._db_path) + rows = conn.execute( + "SELECT deliveryid, userid, pickupcustomer, pickuptime, deliverytime, dlat, dlon, plat, plon " + "FROM delivery_raw WHERE deliverytime >= ? ORDER BY deliverytime", + (cutoff,), + ).fetchall() + conn.close() + cols = ["deliveryid", "userid", "pickupcustomer", "pickuptime", "deliverytime", "dlat", "dlon", "plat", "plon"] + return [dict(zip(cols, r)) for r in rows] + + def sample_batches(self, days: int = 14, min_drops: int = 4, max_drops: int = 15, + limit: int = 10) -> List[Dict[str, Any]]: + """ + Real recent delivery batches from the local mirror for the road-sequencing + decision agent. Grouped by (rider, day, kitchen); origin = that kitchen's + pickup coords (centroid fallback). Most-recent batches first. + Returns [{origin, drops, rider, day, kitchen}]. + """ + rows = self._load_raw_rows(days) + groups: Dict[Tuple[str, str, str], List[Dict[str, Any]]] = defaultdict(list) + for r in rows: + dt = _parse_dt(r.get("deliverytime")) + if dt is None: + continue + try: + if not (float(r["dlat"]) and float(r["dlon"])): + continue + except (TypeError, ValueError): + continue + key = (str(r.get("userid")), dt.strftime("%Y-%m-%d"), + normalize_kitchen(r.get("pickupcustomer"))) + groups[key].append(r) + + batches: List[Dict[str, Any]] = [] + for key in sorted(groups, key=lambda k: k[1], reverse=True): + items = groups[key] + if not (min_drops <= len(items) <= max_drops): + continue + drops = [(float(i["dlat"]), float(i["dlon"])) for i in items] + origin = None + for i in items: + try: + pla, plo = float(i["plat"]), float(i["plon"]) + if pla and plo: + origin = (pla, plo) + break + except (TypeError, ValueError): + continue + if origin is None: + origin = (sum(d[0] for d in drops) / len(drops), + sum(d[1] for d in drops) / len(drops)) + batches.append({"origin": origin, "drops": drops, + "rider": key[0], "day": key[1], "kitchen": key[2]}) + if len(batches) >= limit: + break + return batches + + def _build_observations(self, rows: List[Dict[str, Any]]) -> List[Dict[str, Any]]: + """Reconstruct per-leg observations from ordered delivery rows.""" + # Group by (rider, calendar day of delivery) + groups: Dict[Tuple[str, str], List[Dict[str, Any]]] = defaultdict(list) + for r in rows: + dt = _parse_dt(r.get("deliverytime")) + pt = _parse_dt(r.get("pickuptime")) + if dt is None or pt is None: + continue + try: + dlat = float(r.get("dlat")) + dlon = float(r.get("dlon")) + except (TypeError, ValueError): + continue + if dlat == 0 or dlon == 0: + continue + groups[(str(r.get("userid")), dt.strftime("%Y-%m-%d"))].append({ + "dt": dt, "pt": pt, "lat": dlat, "lon": dlon, + "kitchen": normalize_kitchen(r.get("pickupcustomer")), + "rider": str(r.get("userid")), + }) + + obs: List[Dict[str, Any]] = [] + for _key, items in groups.items(): + items.sort(key=lambda x: x["dt"]) + prev = None + for i, it in enumerate(items): + zone = self._zone.determine_zone(it["lat"], it["lon"]) + traffic = hour_to_traffic(it["dt"].hour) + if i == 0: + # kitchen -> first drop; distance unknown without kitchen coords + leg_min = (it["dt"] - it["pt"]).total_seconds() / 60.0 + leg_km = None + is_first = 1 + else: + leg_min = (it["dt"] - prev["dt"]).total_seconds() / 60.0 + leg_km = _haversine_km(prev["lat"], prev["lon"], it["lat"], it["lon"]) + is_first = 0 + prev = it + # filter implausible legs + if leg_min <= 0 or leg_min > _MAX_LEG_MIN: + continue + if leg_km is not None and (leg_km <= 0 or leg_km > _MAX_LEG_KM): + continue + obs.append({ + "delivery_ts": it["dt"].strftime("%Y-%m-%d %H:%M:%S"), + "rider_id": it["rider"], + "kitchen": it["kitchen"], + "drop_zone": zone, + "traffic": traffic, + "dist_bucket": dist_bucket(leg_km), + "leg_km": leg_km, + "leg_min": round(leg_min, 2), + "is_first": is_first, + }) + return obs + + @staticmethod + def _aggregate(observations: List[Dict[str, Any]]) -> Dict[str, Tuple[int, float, float]]: + """Group observations by every key and compute (count, median, p75).""" + buckets: Dict[str, List[float]] = defaultdict(list) + for o in observations: + for k in _keys_for_observation( + o["kitchen"], o["drop_zone"], o["traffic"], o["dist_bucket"], o["rider_id"] + ): + buckets[k].append(o["leg_min"]) + stats: Dict[str, Tuple[int, float, float]] = {} + for k, vals in buckets.items(): + vals.sort() + n = len(vals) + median = statistics.median(vals) + p75 = vals[min(n - 1, int(math.ceil(0.75 * n)) - 1)] if n else median + stats[k] = (n, round(median, 2), round(p75, 2)) + return stats + + def rebuild_aggregates(self, days: int = 14) -> Dict[str, Any]: + """ + Rebuild empirical medians from the LOCAL mirror only (no DB hit). + Reconstructs per-leg observations, aggregates, persists, reloads cache. + """ + rows = self._load_raw_rows(days) + observations = self._build_observations(rows) + stats = self._aggregate(observations) + + now = datetime.utcnow().isoformat() + try: + conn = sqlite3.connect(self._db_path) + conn.execute("DELETE FROM delivery_history") + conn.execute("DELETE FROM eta_stats") + conn.executemany( + "INSERT INTO delivery_history " + "(delivery_ts, rider_id, kitchen, drop_zone, traffic, dist_bucket, leg_km, leg_min, is_first) " + "VALUES (?,?,?,?,?,?,?,?,?)", + [(o["delivery_ts"], o["rider_id"], o["kitchen"], o["drop_zone"], + o["traffic"], o["dist_bucket"], o["leg_km"], o["leg_min"], o["is_first"]) + for o in observations], + ) + conn.executemany( + "INSERT INTO eta_stats (key, key_type, sample_count, median_min, p75_min, updated_at) " + "VALUES (?,?,?,?,?,?)", + [(k, k.split("|", 1)[0], n, med, p75, now) for k, (n, med, p75) in stats.items()], + ) + conn.commit() + conn.close() + except Exception as e: + logger.error(f"[DeliveryHistory] persist failed: {e}", exc_info=True) + return {"status": "persist_failed", "error": str(e)} + + self._load_cache() + self._last_refreshed = datetime.utcnow() + n_by_type: Dict[str, int] = defaultdict(int) + for k in stats: + n_by_type[k.split("|", 1)[0]] += 1 + summary = { + "status": "ok", + "local_rows": len(rows), + "observations": len(observations), + "stat_keys": len(stats), + "keys_by_type": dict(n_by_type), + "history_days": days, + "rebuilt_at": self._last_refreshed.isoformat(), + } + logger.info( + f"[DeliveryHistory] aggregates rebuilt: local_rows={len(rows)} " + f"obs={len(observations)} keys={len(stats)} ({dict(n_by_type)})" + ) + return summary + + def refresh_eta_stats(self, days: int = 14, tenant_id: int = 916, + full: bool = False) -> Dict[str, Any]: + """ + Full pipeline: incremental DB sync -> prune local store -> rebuild + aggregates locally. This is what the scheduler and the admin endpoint + call. The DB is touched only by the sync step (new rows only). + """ + with _WRITE_LOCK: + try: + sync = self.sync_from_db(days=days, tenant_id=tenant_id, full=full) + except Exception as e: + logger.error(f"[DeliveryHistory] sync failed: {e}", exc_info=True) + # Still try to serve whatever is already local. + rebuilt = self.rebuild_aggregates(days) + self._last_summary = {"status": "sync_failed", "error": str(e), "rebuild": rebuilt} + return self._last_summary + + self._prune_raw(days) + rebuilt = self.rebuild_aggregates(days) + self._last_summary = {"status": "ok", "sync": sync, "rebuild": rebuilt} + return self._last_summary + + # -- cache + lookup ----------------------------------------------------- + + def _load_cache(self) -> None: + try: + conn = sqlite3.connect(self._db_path) + rows = conn.execute( + "SELECT key, sample_count, median_min, p75_min FROM eta_stats" + ).fetchall() + conn.close() + self._cache = {k: (int(n), float(med), float(p75)) for k, n, med, p75 in rows} + if self._cache: + logger.info(f"[DeliveryHistory] loaded {len(self._cache)} eta_stats keys into cache") + except Exception as e: + logger.warning(f"[DeliveryHistory] cache load failed: {e}") + self._cache = {} + + def has_data(self) -> bool: + return bool(self._cache) + + def maybe_background_refresh(self, days: int = 14, tenant_id: int = 916, + cooldown_s: int = 600) -> bool: + """ + If the cache is empty, kick off a one-shot background refresh (at most + once per cooldown). Keeps the prediction hot path non-blocking — the + current call falls back to the formula; later calls use empirical data. + Returns True if a refresh thread was started. + """ + if self._cache: + return False + with self._refresh_lock: + if self._cache: + return False + now = datetime.utcnow() + if (self._refresh_attempt_at is not None + and (now - self._refresh_attempt_at).total_seconds() < cooldown_s): + return False + self._refresh_attempt_at = now + + def _run(): + try: + self.refresh_eta_stats(days, tenant_id) + except Exception as e: + logger.warning(f"[DeliveryHistory] background refresh failed: {e}") + + threading.Thread(target=_run, daemon=True, name="eta-refresh").start() + return True + + def local_count(self) -> int: + try: + conn = sqlite3.connect(self._db_path) + n = conn.execute("SELECT COUNT(*) FROM delivery_raw").fetchone()[0] + conn.close() + return int(n) + except Exception: + return 0 + + def ensure_background_sync(self, interval_hours: int = 6, days: int = 14, + tenant_id: int = 916) -> bool: + """ + Start the autonomous sync agent (once per process). It refreshes + immediately on startup (full backfill if the local store is empty, + otherwise incremental), then re-syncs every `interval_hours`. + + Runs in a daemon thread so it never blocks the app; all request-path + ETA lookups read the local SQLite mirror, never Postgres. + """ + with self._refresh_lock: + if self._scheduler_started: + return False + self._scheduler_started = True + + def _loop(): + logger.info( + f"[ETA-Agent] autonomous sync started — interval={interval_hours}h, window={days}d" + ) + first = True + while True: + try: + full = first and self.local_count() == 0 + result = self.refresh_eta_stats(days=days, tenant_id=tenant_id, full=full) + logger.info(f"[ETA-Agent] sync cycle done: {result.get('status')}") + except Exception as e: + logger.warning(f"[ETA-Agent] sync cycle failed (will retry): {e}") + # Recompute learned rider affinity from the freshly-synced mirror. + try: + from app.services.routing.rider_affinity_service import get_rider_affinity + get_rider_affinity().refresh(days=days) + except Exception as e: + logger.debug(f"[ETA-Agent] affinity refresh skipped: {e}") + first = False + time.sleep(max(1, int(interval_hours)) * 3600) + + threading.Thread(target=_loop, daemon=True, name="eta-sync-agent").start() + return True + + def lookup( + self, + distance_km: float, + traffic_cat: str, + kitchen: Optional[str] = None, + drop_coords: Optional[Tuple[float, float]] = None, + min_samples: int = 20, + stat: str = "median", + ) -> Optional[Dict[str, Any]]: + """ + Return the empirical leg time (minutes) for a context, or None if no key + has >= min_samples. Walks the specificity hierarchy. + """ + if not self._cache: + return None + zone = "Unknown" + if drop_coords and drop_coords[0] and drop_coords[1]: + zone = self._zone.determine_zone(float(drop_coords[0]), float(drop_coords[1])) + bucket = dist_bucket(distance_km) if distance_km and distance_km > 0 else None + k_norm = normalize_kitchen(kitchen) if kitchen else None + + for full_key in _lookup_keys(k_norm, zone, traffic_cat, bucket): + hit = self._cache.get(full_key) + if hit and hit[0] >= min_samples: + count, median, p75 = hit + value = p75 if stat == "p75" else median + return { + "value_min": value, + "sample_count": count, + "source_key": full_key, + "key_type": full_key.split("|", 1)[0], + } + return None + + # -- diagnostics / backtest -------------------------------------------- + + def get_summary(self) -> Dict[str, Any]: + return { + "has_data": self.has_data(), + "cache_keys": len(self._cache), + "last_summary": self._last_summary, + } + + def backtest(self, days: int = 14, tenant_id: int = 916, + min_samples: int = 20, stat: str = "median") -> Dict[str, Any]: + """ + Honest time-split backtest: build empirical stats on the older 80% of + observations, then compare formula vs empirical MAE on the most recent + 20% (held out). Proves whether empirical beats the formula before trust. + """ + from app.services.routing.realistic_eta_calculator import RealisticETACalculator + formula = RealisticETACalculator() + + # Backtest runs entirely on the local mirror — no DB hit. + rows = self._load_raw_rows(days) + obs = self._build_observations(rows) + obs = [o for o in obs if o["is_first"] == 0] # need leg_km for both predictors + if len(obs) < 50: + return {"status": "insufficient_data", "observations": len(obs)} + + obs.sort(key=lambda o: o["delivery_ts"]) + split = int(len(obs) * 0.8) + train, test = obs[:split], obs[split:] + train_stats = self._aggregate(train) + + def _empirical(o) -> Optional[float]: + for full_key in _lookup_keys(o["kitchen"], o["drop_zone"], o["traffic"], o["dist_bucket"]): + hit = train_stats.get(full_key) + if hit and hit[0] >= min_samples: + return hit[2] if stat == "p75" else hit[1] + return None + + f_err, e_err, e_err_fallback, covered = [], [], [], 0 + for o in test: + actual = o["leg_min"] + f_pred = formula.calculate_eta( + distance_km=o["leg_km"], is_first_order=False, + order_type="Economy", time_of_day=o["traffic"], + ) + f_err.append(abs(f_pred - actual)) + emp = _empirical(o) + if emp is not None: + covered += 1 + e_err.append(abs(emp - actual)) + e_err_fallback.append(abs(emp - actual)) + else: + e_err_fallback.append(abs(f_pred - actual)) # fallback to formula + + def _mae(xs): + return round(sum(xs) / len(xs), 2) if xs else None + + return { + "status": "ok", + "history_days": days, + "observations": len(obs), + "test_size": len(test), + "empirical_coverage_pct": round(100.0 * covered / len(test), 1), + "formula_mae_min": _mae(f_err), + "empirical_mae_min_covered": _mae(e_err), + "empirical_mae_min_with_fallback": _mae(e_err_fallback), + "min_samples": min_samples, + "stat": stat, + "interpretation": ( + "empirical_better" + if (_mae(e_err_fallback) is not None and _mae(f_err) is not None + and _mae(e_err_fallback) < _mae(f_err)) + else "no_improvement" + ), + } + + +# --------------------------------------------------------------------------- +# Singleton +# --------------------------------------------------------------------------- + +_service: Optional[DeliveryHistoryService] = None +_service_lock = threading.Lock() + + +def get_delivery_history_service() -> DeliveryHistoryService: + """Get (and lazily build) the DeliveryHistoryService singleton.""" + global _service + with _service_lock: + if _service is None: + _service = DeliveryHistoryService() + return _service diff --git a/app/services/routing/empirical_eta_calculator.py b/app/services/routing/empirical_eta_calculator.py new file mode 100644 index 0000000..3cf0665 --- /dev/null +++ b/app/services/routing/empirical_eta_calculator.py @@ -0,0 +1,143 @@ +""" +Empirical ETA Calculator +======================== + +Drop-in replacement for `RealisticETACalculator` that prefers ETAs *learned +from actual delivery times* (see delivery_history_service.py) and falls back to +the original formula whenever history is too thin. + +Design goals +------------ +* **Interface-compatible**: `calculate_eta(...)` keeps the same positional args + and `int`-minutes return as the formula calculator, so existing call sites + work unchanged. Extra args (`kitchen`, `drop_coords`, `rider_id`) are optional + and let callers that *have* that context (the optimizer does) get sharper, + zone-aware estimates. +* **Safe by default**: if empirical data is missing for a context, or the + feature is disabled via `eta_empirical_enabled`, it returns exactly what the + formula would — zero behavior change until real data exists. +* **Non-blocking**: never calls Postgres on the hot path. If the stats cache is + empty it kicks off a one-shot background refresh and serves the formula + meanwhile. + +Empirical values are real door-to-door leg times (gap between consecutive +deliveries), so they already include travel + drop service time. We only add the +kitchen pickup buffer for the first leg, mirroring the formula's semantics. +""" + +import logging +from typing import Any, List, Optional, Tuple + +from app.services.routing.realistic_eta_calculator import ( + RealisticETACalculator, + get_time_of_day_category, +) + +logger = logging.getLogger(__name__) + + +class EmpiricalETACalculator: + """ETA calculator backed by empirical history, with formula fallback.""" + + def __init__(self): + # Composed formula calculator — the fallback and the source of buffers. + self.formula = RealisticETACalculator() + + # ------------------------------------------------------------------ + # Main entry point (signature is a superset of RealisticETACalculator) + # ------------------------------------------------------------------ + + def calculate_eta( + self, + distance_km: float, + is_first_order: bool = False, + order_type: str = "Economy", + time_of_day: str = "peak", + kitchen: Optional[str] = None, + drop_coords: Optional[Tuple[float, float]] = None, + rider_id: Optional[Any] = None, + ) -> int: + """Return ETA in minutes — empirical if available, else the formula.""" + if distance_km is not None and distance_km <= 0 and not is_first_order: + return 0 + + from app.config.dynamic_config import get_config + cfg = get_config() + + if not bool(cfg.get("eta_empirical_enabled", True)): + return self._formula_eta(distance_km, is_first_order, order_type, time_of_day) + + try: + from app.services.routing.delivery_history_service import ( + get_delivery_history_service, + ) + svc = get_delivery_history_service() + + if not svc.has_data(): + # Populate in the background; serve the formula for now. + svc.maybe_background_refresh( + days=int(cfg.get("eta_history_days", 14)), + ) + return self._formula_eta(distance_km, is_first_order, order_type, time_of_day) + + hit = svc.lookup( + distance_km=float(distance_km or 0.0), + traffic_cat=time_of_day, + kitchen=kitchen, + drop_coords=drop_coords, + min_samples=int(cfg.get("eta_min_samples", 20)), + stat=str(cfg.get("eta_stat", "median")), + ) + except Exception as e: + logger.debug(f"[EmpiricalETA] lookup failed, using formula: {e}") + hit = None + + if not hit: + return self._formula_eta(distance_km, is_first_order, order_type, time_of_day) + + value = float(hit["value_min"]) + # First leg includes time spent picking up at the kitchen; the empirical + # leg gap starts at pickup completion, so add the same buffer the formula uses. + if is_first_order: + value += float(cfg.get("eta_pickup_time_min", 3.0)) + return int(value) + 1 # round up for safety, matching the formula + + def _formula_eta(self, distance_km, is_first_order, order_type, time_of_day) -> int: + return self.formula.calculate_eta( + distance_km=distance_km, + is_first_order=is_first_order, + order_type=order_type, + time_of_day=time_of_day, + ) + + # ------------------------------------------------------------------ + # Batch helper (kept compatible with RealisticETACalculator) + # ------------------------------------------------------------------ + + def calculate_batch_eta(self, orders: List[dict]) -> List[dict]: + """Calculate ETAs for a batch in sequence (formula-parity batch path).""" + traffic = get_time_of_day_category() + for order in orders: + distance_km = float(order.get("previouskms", 0) or 0) + step = order.get("step", 1) + order_type = order.get("ordertype", "Economy") + drop = None + try: + dlat = float(order.get("deliverylat") or order.get("droplat") or 0) + dlon = float(order.get("deliverylong") or order.get("droplon") or 0) + if dlat and dlon: + drop = (dlat, dlon) + except (TypeError, ValueError): + drop = None + eta = self.calculate_eta( + distance_km=distance_km, + is_first_order=(step == 1), + order_type=order_type, + time_of_day=traffic, + kitchen=order.get("pickupcustomer") or order.get("locationname"), + drop_coords=drop, + rider_id=order.get("userid"), + ) + order["eta"] = str(eta) + order["eta_empirical"] = True + return orders diff --git a/app/services/routing/kalman_filter.py b/app/services/routing/kalman_filter.py new file mode 100644 index 0000000..608ac6f --- /dev/null +++ b/app/services/routing/kalman_filter.py @@ -0,0 +1,327 @@ +""" +GPS Kalman Filter \u2014 rider-api + +A 1D Kalman filter applied independently to latitude and longitude +to smooth noisy GPS coordinates from riders and delivery points. + +Why Kalman for GPS? +- GPS readings contain measurement noise (\u00b15\u201315m typical, \u00b150m poor signal) +- Rider location pings can "jump" due to bad signal or device error +- Kalman filter gives an optimal estimate by balancing: + (1) Previous predicted position (process model) + (2) New GPS measurement (observation model) + +Design: +- Separate filter instance per rider (stateful \u2014 preserves history) +- `CoordinateKalmanFilter` \u2014 single lat/lon smoother +- `GPSKalmanFilter` \u2014 wraps two CoordinateKalmanFilters (lat + lon) +- `RiderKalmanRegistry` \u2014 manages per-rider filter instances +- `smooth_coordinates()` \u2014 stateless single-shot smoother for delivery coords + +Usage: + # Stateless (one-shot, no history \u2014 for delivery coords): + smooth_lat, smooth_lon = smooth_coordinates(raw_lat, raw_lon) + + # Stateful (per-rider, preserves motion history): + registry = RiderKalmanRegistry() + lat, lon = registry.update(rider_id=1116, lat=11.0067, lon=76.9558) +""" + +import logging +import time +from typing import Dict, Optional, Tuple + +logger = logging.getLogger(__name__) + + +# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 +# CORE 1D KALMAN FILTER +# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 + +class CoordinateKalmanFilter: + """ + 1-dimensional Kalman filter for a single GPS coordinate (lat or lon). + + State model: position only (constant position with random walk). + + Equations: + Prediction: x\u0302\u2096\u207b = x\u0302\u2096\u208b\u2081 (no movement assumed between pings) + P\u0302\u2096\u207b = P\u2096\u208b\u2081 + Q (uncertainty grows over time) + + Update: K\u2096 = P\u0302\u2096\u207b / (P\u0302\u2096\u207b + R) (Kalman gain) + x\u0302\u2096 = x\u0302\u2096\u207b + K\u2096\u00b7(z\u2096 - x\u0302\u2096\u207b) (weighted fusion) + P\u2096 = (1 - K\u2096)\u00b7P\u0302\u2096\u207b (update uncertainty) + + Parameters: + process_noise (Q): How much position can change between measurements. + Higher = filter trusts new measurements more (less smoothing). + measurement_noise (R): GPS measurement uncertainty. + Higher = filter trusts history more (more smoothing). + """ + + def __init__( + self, + process_noise: float = 1e-4, + measurement_noise: float = 0.01, + initial_uncertainty: float = 1.0, + ): + self.Q = process_noise + self.R = measurement_noise + self._x: Optional[float] = None + self._P: float = initial_uncertainty + + @property + def initialized(self) -> bool: + return self._x is not None + + def update(self, measurement: float) -> float: + """Process one new measurement and return the filtered estimate.""" + if not self.initialized: + self._x = measurement + return self._x + + # Predict + x_prior = self._x + P_prior = self._P + self.Q + + # Update + K = P_prior / (P_prior + self.R) + self._x = x_prior + K * (measurement - x_prior) + self._P = (1.0 - K) * P_prior + + return self._x + + def reset(self): + self._x = None + self._P = 1.0 + + +# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 +# 2D GPS KALMAN FILTER (lat + lon) +# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 + +class GPSKalmanFilter: + """ + Two-dimensional GPS smoother using independent 1D Kalman filters + for latitude and longitude. + """ + + def __init__( + self, + process_noise: float = 1e-4, + measurement_noise: float = 0.01, + ): + self.lat_filter = CoordinateKalmanFilter(process_noise, measurement_noise) + self.lon_filter = CoordinateKalmanFilter(process_noise, measurement_noise) + self.last_updated: float = time.time() + self.update_count: int = 0 + + def update(self, lat: float, lon: float) -> Tuple[float, float]: + """Feed a new GPS reading and get the smoothed (lat, lon).""" + if not self._is_valid_coord(lat, lon): + if self.lat_filter.initialized: + return self.lat_filter._x, self.lon_filter._x + return lat, lon + + smooth_lat = self.lat_filter.update(lat) + smooth_lon = self.lon_filter.update(lon) + self.last_updated = time.time() + self.update_count += 1 + + return smooth_lat, smooth_lon + + def get_estimate(self) -> Optional[Tuple[float, float]]: + if self.lat_filter.initialized: + return self.lat_filter._x, self.lon_filter._x + return None + + def reset(self): + self.lat_filter.reset() + self.lon_filter.reset() + self.update_count = 0 + + @staticmethod + def _is_valid_coord(lat: float, lon: float) -> bool: + try: + lat, lon = float(lat), float(lon) + return ( + -90.0 <= lat <= 90.0 + and -180.0 <= lon <= 180.0 + and not (lat == 0.0 and lon == 0.0) + ) + except (TypeError, ValueError): + return False + + +# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 +# PER-RIDER FILTER REGISTRY +# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 + +class RiderKalmanRegistry: + """ + Maintains per-rider Kalman filter instances across calls. + Stale filters (> 30 min silence) are automatically reset. + """ + + def __init__( + self, + process_noise: float = 1e-4, + measurement_noise: float = 0.01, + stale_seconds: float = 1800.0, + ): + self._filters: Dict[str, GPSKalmanFilter] = {} + self._process_noise = process_noise + self._measurement_noise = measurement_noise + self._stale_seconds = stale_seconds + + def _get_or_create(self, rider_id) -> GPSKalmanFilter: + key = str(rider_id) + now = time.time() + if key in self._filters: + f = self._filters[key] + if now - f.last_updated > self._stale_seconds: + f.reset() + return f + self._filters[key] = GPSKalmanFilter( + process_noise=self._process_noise, + measurement_noise=self._measurement_noise, + ) + return self._filters[key] + + def update(self, rider_id, lat: float, lon: float) -> Tuple[float, float]: + return self._get_or_create(rider_id).update(lat, lon) + + def get_estimate(self, rider_id) -> Optional[Tuple[float, float]]: + key = str(rider_id) + if key in self._filters: + return self._filters[key].get_estimate() + return None + + def reset_rider(self, rider_id): + key = str(rider_id) + if key in self._filters: + self._filters[key].reset() + + def clear_all(self): + self._filters.clear() + + +# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 +# GLOBAL REGISTRY (process-level singleton) +# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 + +_global_registry = RiderKalmanRegistry() + + +def get_registry() -> RiderKalmanRegistry: + """Get the process-level rider Kalman filter registry.""" + return _global_registry + + +# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 +# STATELESS COORDINATE SMOOTHER +# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 + +def smooth_coordinates( + lat: float, + lon: float, + *, + prior_lat: Optional[float] = None, + prior_lon: Optional[float] = None, + process_noise: float = 1e-4, + measurement_noise: float = 0.01, +) -> Tuple[float, float]: + """ + Stateless single-shot GPS smoother. + If a prior is provided, blends the new reading towards it. + """ + f = GPSKalmanFilter(process_noise=process_noise, measurement_noise=measurement_noise) + if prior_lat is not None and prior_lon is not None: + try: + _flat = float(prior_lat) + _flon = float(prior_lon) + if GPSKalmanFilter._is_valid_coord(_flat, _flon): + f.update(_flat, _flon) + except (TypeError, ValueError): + pass + return f.update(lat, lon) + + +# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 +# BATCH SMOOTHERS +# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 + +def smooth_rider_locations(riders: list) -> list: + """ + Apply Kalman smoothing to a list of rider dicts in-place using + the global per-rider registry (history preserved across calls). + + Reads/writes: latitude, longitude (and currentlat/currentlong if present). + Adds: _kalman_smoothed = True on each processed rider. + """ + registry = get_registry() + for rider in riders: + try: + rider_id = ( + rider.get("userid") or rider.get("riderid") or + rider.get("id") or "unknown" + ) + raw_lat = float(rider.get("latitude") or rider.get("currentlat") or 0) + raw_lon = float(rider.get("longitude") or rider.get("currentlong") or 0) + if raw_lat == 0.0 and raw_lon == 0.0: + continue + smooth_lat, smooth_lon = registry.update(rider_id, raw_lat, raw_lon) + # Cast back to string for Go compatibility + s_lat, s_lon = str(round(smooth_lat, 8)), str(round(smooth_lon, 8)) + rider["latitude"] = s_lat + rider["longitude"] = s_lon + if "currentlat" in rider: + rider["currentlat"] = s_lat + if "currentlong" in rider: + rider["currentlong"] = s_lon + rider["_kalman_smoothed"] = True + except Exception as e: + logger.debug(f"Kalman rider smoothing skipped: {e}") + return riders + + +def smooth_order_coordinates(orders: list) -> list: + """ + Validate and lightly normalise delivery coordinates in a list of order dicts. + + DESIGN NOTE — why we do NOT use Kalman filtering here: + ───────────────────────────────────────────────────── + Kalman filtering is a *temporal* smoother: it blends successive measurements + from the same sensor over time. Delivery coordinates are a single static + point (one measurement). Feeding the kitchen location as a "prior" would + pull the customer's address toward the kitchen — exactly wrong. + + Per-customer GPS accuracy is handled upstream by the FAISS coordinate store + (verified historical rider-confirmed delivery points). This function only + normalises the coordinate fields to floats so downstream code never sees + raw strings or None values. + + Modifies orders in-place. Returns the same list. + """ + for order in orders: + try: + dlat_raw = order.get("deliverylat") or order.get("droplat") + dlon_raw = order.get("deliverylong") or order.get("droplon") + if dlat_raw is None or dlon_raw is None: + continue + dlat = float(dlat_raw) + dlon = float(dlon_raw) + if not GPSKalmanFilter._is_valid_coord(dlat, dlon): + continue + # Normalise to string (Go service expects string coordinates) + s_lat = str(round(dlat, 8)) + s_lon = str(round(dlon, 8)) + order["deliverylat"] = s_lat + order["deliverylong"] = s_lon + if "droplat" in order: + order["droplat"] = s_lat + if "droplon" in order: + order["droplon"] = s_lon + except Exception as e: + logger.debug(f"Coordinate normalisation skipped: {e}") + return orders diff --git a/app/services/routing/realistic_eta_calculator.py b/app/services/routing/realistic_eta_calculator.py new file mode 100644 index 0000000..06eac03 --- /dev/null +++ b/app/services/routing/realistic_eta_calculator.py @@ -0,0 +1,127 @@ +""" +Realistic ETA Calculator for Delivery Operations + +Accounts for: +- City traffic conditions +- Stop time at pickup/delivery +- Navigation time +- Parking/finding address time +- Different speeds for different order types +""" + +import logging +from typing import Dict, Any + +logger = logging.getLogger(__name__) + + +class RealisticETACalculator: + """ + Calculates realistic ETAs accounting for real-world delivery conditions. + """ + + def __init__(self): + from app.config.dynamic_config import get_config + cfg = get_config() + + # BASE SPEED (km/h) - Driven by the DB configuration + base_speed = cfg.get("avg_speed_kmh", 18.0) + + # REALISTIC SPEEDS based on time of day + self.CITY_SPEED_HEAVY_TRAFFIC = base_speed * 0.7 # Usually ~12 km/h + self.CITY_SPEED_MODERATE = base_speed # Usually ~18 km/h + self.CITY_SPEED_LIGHT = base_speed * 1.2 # Usually ~21.6 km/h + + # TIME BUFFERS (minutes) + self.PICKUP_TIME = cfg.get("eta_pickup_time_min", 3.0) + self.DELIVERY_TIME = cfg.get("eta_delivery_time_min", 4.0) + self.NAVIGATION_BUFFER = cfg.get("eta_navigation_buffer_min", 1.5) + + # DISTANCE-BASED SPEED SELECTION + # Short distances (<2km) are slower due to more stops/starts + # Long distances (>8km) might have highway portions + self.SHORT_TRIP_FACTOR = cfg.get("eta_short_trip_factor", 0.8) + self.LONG_TRIP_FACTOR = cfg.get("eta_long_trip_factor", 1.1) + + def calculate_eta(self, + distance_km: float, + is_first_order: bool = False, + order_type: str = "Economy", + time_of_day: str = "peak") -> int: + """ + Calculate realistic ETA in minutes. + + Args: + distance_km: Distance to travel in kilometers + is_first_order: If True, includes pickup time + order_type: "Economy", "Premium", or "Risky" + time_of_day: "peak", "normal", or "light" traffic + + Returns: + ETA in minutes (rounded up for safety) + """ + + if distance_km <= 0: + return 0 + + # 1. SELECT SPEED BASED ON CONDITIONS + if time_of_day == "peak": + base_speed = self.CITY_SPEED_HEAVY_TRAFFIC + elif time_of_day == "light": + base_speed = self.CITY_SPEED_LIGHT + else: + base_speed = self.CITY_SPEED_MODERATE + + # 2. ADJUST SPEED BASED ON DISTANCE + # Short trips are slower (more intersections, traffic lights) + if distance_km < 2.0: + effective_speed = base_speed * self.SHORT_TRIP_FACTOR + elif distance_km > 8.0: + effective_speed = base_speed * self.LONG_TRIP_FACTOR + else: + effective_speed = base_speed + + # 3. CALCULATE TRAVEL TIME + travel_time = (distance_km / effective_speed) * 60 # Convert to minutes + + # 4. ADD BUFFERS + total_time = travel_time + + # Pickup time (only for first order in sequence) + if is_first_order: + total_time += self.PICKUP_TIME + + # Delivery time (always) + total_time += self.DELIVERY_TIME + + # Navigation buffer (proportional to distance) + if distance_km > 3.0: + total_time += self.NAVIGATION_BUFFER + + # 5. SAFETY MARGIN (Round up to next minute) + # Riders prefer to arrive early than late + eta_minutes = int(total_time) + 1 + + return eta_minutes + + +def get_time_of_day_category() -> str: + """ + Determine current traffic conditions based on time. + + Returns: + "peak", "normal", or "light" + """ + from datetime import datetime + + + current_hour = datetime.now().hour + + # Peak hours: 8-10 AM, 12-2 PM, 5-8 PM + if (8 <= current_hour < 10) or (12 <= current_hour < 14) or (17 <= current_hour < 20): + return "peak" + # Light traffic: Late night/early morning + elif current_hour < 7 or current_hour >= 22: + return "light" + else: + return "normal" diff --git a/app/services/routing/rider_affinity_service.py b/app/services/routing/rider_affinity_service.py new file mode 100644 index 0000000..3d18860 --- /dev/null +++ b/app/services/routing/rider_affinity_service.py @@ -0,0 +1,171 @@ +""" +Rider Affinity Service (learned, agentic) +========================================= + +Learns each rider's real kitchen affinity and operating area from the local +delivery mirror (`delivery_raw`) and exposes them MERGED with the curated config +in `app/config/rider_preferences.py`: + + * get_preferred_kitchens() = curated RIDER_PREFERRED_KITCHENS ∪ learned + (rider served a kitchen >= `rider_affinity_min_deliveries` times). Union only — + never drops a curated owner. + * get_home_locations() = curated RIDER_HOME_LOCATIONS, with a learned drop + centroid filled in ONLY for riders missing from the config. + +These feed SOFT steering (preference discount / home bonus / distance bypass) in +the optimizer + assignment service. HARD kitchen locks and BLOCKED_RIDERS remain +sourced from the curated config — learned data can only broaden preference, never +change who is *eligible* for a kitchen. Recomputed by the autonomous agent loop. +""" + +import logging +import threading +from collections import defaultdict +from datetime import datetime +from typing import Any, Dict, List, Optional, Tuple + +from app.config.rider_preferences import RIDER_PREFERRED_KITCHENS, RIDER_HOME_LOCATIONS + +logger = logging.getLogger(__name__) + + +def _to_int_rid(v: Any) -> Optional[int]: + try: + return int(v) + except (TypeError, ValueError): + return None + + +class RiderAffinityService: + def __init__(self): + self._learned_pref: Dict[int, List[str]] = {} + self._learned_home: Dict[int, Tuple[float, float]] = {} + self._last_refreshed: Optional[datetime] = None + self._lock = threading.Lock() + + # ------------------------------------------------------------------ + + def refresh(self, days: Optional[int] = None) -> Dict[str, Any]: + """Recompute learned affinity from the local delivery mirror (no DB hit).""" + from app.config.dynamic_config import get_config + from app.services.routing.delivery_history_service import ( + get_delivery_history_service, normalize_kitchen, + ) + cfg = get_config() + window = int(days if days is not None else cfg.get("eta_history_days", 14)) + min_n = int(cfg.get("rider_affinity_min_deliveries", 10)) + + rows = get_delivery_history_service()._load_raw_rows(window) + counts: Dict[int, Dict[str, int]] = defaultdict(lambda: defaultdict(int)) + coords: Dict[int, List[Tuple[float, float]]] = defaultdict(list) + for r in rows: + rid = _to_int_rid(r.get("userid")) + if rid is None: + continue + kitchen = normalize_kitchen(r.get("pickupcustomer")) + if kitchen and kitchen != "?": + counts[rid][kitchen] += 1 + try: + la, lo = float(r.get("dlat")), float(r.get("dlon")) + if la and lo: + coords[rid].append((la, lo)) + except (TypeError, ValueError): + continue + + learned_pref = { + rid: [k for k, n in kc.items() if n >= min_n] + for rid, kc in counts.items() + } + learned_pref = {rid: ks for rid, ks in learned_pref.items() if ks} + learned_home = { + rid: (round(sum(p[0] for p in pts) / len(pts), 6), + round(sum(p[1] for p in pts) / len(pts), 6)) + for rid, pts in coords.items() if pts + } + + with self._lock: + self._learned_pref = learned_pref + self._learned_home = learned_home + self._last_refreshed = datetime.utcnow() + + summary = { + "status": "ok", + "riders_with_learned_kitchens": len(learned_pref), + "riders_with_learned_home": len(learned_home), + "min_deliveries": min_n, + "window_days": window, + "refreshed_at": self._last_refreshed.isoformat(), + } + logger.info( + f"[Affinity] learned kitchens for {len(learned_pref)} riders, " + f"home for {len(learned_home)} (min_deliveries={min_n})" + ) + return summary + + def _ensure_loaded(self) -> None: + if self._last_refreshed is None: + try: + self.refresh() + except Exception as e: + logger.debug(f"[Affinity] lazy refresh failed: {e}") + + # ------------------------------------------------------------------ + + def get_preferred_kitchens(self) -> Dict[int, List[str]]: + """Curated config ∪ learned (union — never drops a curated owner).""" + from app.config.dynamic_config import get_config + if not bool(get_config().get("rider_affinity_enabled", True)): + return {rid: list(v) for rid, v in RIDER_PREFERRED_KITCHENS.items()} + self._ensure_loaded() + merged: Dict[int, List[str]] = {rid: list(v) for rid, v in RIDER_PREFERRED_KITCHENS.items()} + with self._lock: + learned = {rid: list(v) for rid, v in self._learned_pref.items()} + for rid, kitchens in learned.items(): + base = merged.setdefault(rid, []) + base_lower = {b.lower() for b in base} + for k in kitchens: + if k.lower() not in base_lower: + base.append(k) + return merged + + def get_home_locations(self) -> Dict[int, Tuple[float, float]]: + """Curated home primary; learned drop centroid only for riders absent from config.""" + from app.config.dynamic_config import get_config + if not bool(get_config().get("rider_affinity_enabled", True)): + return dict(RIDER_HOME_LOCATIONS) + self._ensure_loaded() + merged: Dict[int, Tuple[float, float]] = dict(RIDER_HOME_LOCATIONS) + with self._lock: + learned = dict(self._learned_home) + for rid, home in learned.items(): + if rid not in merged or merged.get(rid) in (None, (0.0, 0.0)): + merged[rid] = home + return merged + + def get_summary(self) -> Dict[str, Any]: + """Learned-vs-config diff for the admin endpoint.""" + self._ensure_loaded() + with self._lock: + learned_pref = {rid: list(v) for rid, v in self._learned_pref.items()} + learned_home = dict(self._learned_home) + config_riders = set(RIDER_PREFERRED_KITCHENS) + new_pref_riders = sorted(set(learned_pref) - config_riders) + return { + "last_refreshed": self._last_refreshed.isoformat() if self._last_refreshed else None, + "config_preferred_riders": sorted(config_riders), + "learned_preferred": {str(k): v for k, v in sorted(learned_pref.items())}, + "riders_newly_learned_not_in_config": new_pref_riders, + "learned_home_count": len(learned_home), + } + + +_affinity: Optional[RiderAffinityService] = None +_affinity_lock = threading.Lock() + + +def get_rider_affinity() -> RiderAffinityService: + global _affinity + with _affinity_lock: + if _affinity is None: + _affinity = RiderAffinityService() + return _affinity diff --git a/app/services/routing/road_sequencing_agent.py b/app/services/routing/road_sequencing_agent.py new file mode 100644 index 0000000..a6ff717 --- /dev/null +++ b/app/services/routing/road_sequencing_agent.py @@ -0,0 +1,233 @@ +""" +Road-Sequencing Decision Agent +============================== + +Autonomous controller for the `routing_use_road_distance` feature. Instead of a +human flipping a config flag, this agent periodically *measures* whether road-aware +sequencing (road travel-time matrix + OR-Tools open-TSP) actually beats the default +straight-line ordering on REAL recent batches, and turns the feature on or off by +itself — re-checking every cycle so it self-corrects if the gain ever disappears. + +Decision (with hysteresis, so it doesn't flap): + mean travel-time gain >= routing_auto_enable_gain_pct -> enable + mean travel-time gain < routing_auto_disable_gain_pct -> disable + in between -> leave as-is + +Every decision is stored (auditable) in DynamicConfig under `routing_road_eval` +and exposed via GET /api/v1/ml/road-eval. Cost is bounded: it evaluates only +`routing_eval_sample_batches` batches once per `routing_eval_interval_hours`. +""" + +import asyncio +import json +import logging +import threading +import time +from datetime import datetime +from typing import Any, Dict, List, Optional + +import numpy as np + +logger = logging.getLogger(__name__) + + +def _total(order_idx: List[int], matrix: List[List[float]]) -> float: + """Total open-route cost: origin(0) -> drops in `order_idx` (1-based into matrix).""" + seq = [0] + [i + 1 for i in order_idx] + return sum(matrix[seq[k]][seq[k + 1]] for k in range(len(seq) - 1)) + + +class RoadSequencingAgent: + """Measures road-vs-aerial sequencing on real batches and auto-toggles the flag.""" + + def __init__(self): + self._opt = None # lazy RouteOptimizer + self._scheduler_started = False + self._lock = threading.Lock() + self.last_decision: Dict[str, Any] = {} + + def _optimizer(self): + if self._opt is None: + from app.services.routing.route_optimizer import RouteOptimizer + self._opt = RouteOptimizer() + return self._opt + + async def evaluate(self, sample_batches: int = 8, days: int = 14) -> Dict[str, Any]: + """ + Compare aerial-order vs road-order travel time on sampled real batches. + Returns mean gain % and per-batch detail. No flag changes here. + """ + from app.services.routing.delivery_history_service import get_delivery_history_service + from app.core.arrow_utils import calculate_haversine_matrix_vectorized + + opt = self._optimizer() + if not opt.use_google_maps: + return {"evaluated": 0, "reason": "no_google_key", "mean_gain_pct": 0.0} + + batches = get_delivery_history_service().sample_batches( + days=days, limit=sample_batches + ) + if not batches: + return {"evaluated": 0, "reason": "no_local_batches", "mean_gain_pct": 0.0} + + per_batch: List[Dict[str, Any]] = [] + for b in batches: + origin, drops = b["origin"], b["drops"] + locs = [origin] + drops + matrix = await opt._road_duration_matrix(locs) + if matrix is None: + continue + # aerial order (current production behaviour) + lats = np.array([p[0] for p in locs]) + lons = np.array([p[1] for p in locs]) + aerial = calculate_haversine_matrix_vectorized(lats, lons) + aer = [i - 1 for i in opt._two_opt_improve(opt._solve_greedy(locs, aerial), aerial) if i != 0] + # road order (OR-Tools open-TSP on the road travel-time matrix) + road = [i - 1 for i in opt._solve_tsp_ortools(locs, matrix) if i != 0] + + # Human's ACTUAL route: drops are already in delivered order + # (_load_raw_rows is ORDER BY deliverytime), so identity = what the + # rider really drove. This is the "do we beat the humans?" baseline. + human = list(range(len(drops))) + + t_aer = _total(aer, matrix) + t_road = _total(road, matrix) + t_human = _total(human, matrix) + gain = (100.0 * (t_aer - t_road) / t_aer) if t_aer > 0 else 0.0 + gain_vs_human = (100.0 * (t_human - t_road) / t_human) if t_human > 0 else 0.0 + per_batch.append({ + "rider": b["rider"], "day": b["day"], "drops": len(drops), + "aerial_min": round(t_aer, 1), "road_min": round(t_road, 1), + "human_min": round(t_human, 1), + "gain_pct": round(gain, 1), + "gain_vs_human_pct": round(gain_vs_human, 1), + "beat_human": t_road <= t_human + 1e-9, + }) + + if not per_batch: + return {"evaluated": 0, "reason": "matrix_unavailable", "mean_gain_pct": 0.0} + + n = len(per_batch) + mean_gain = sum(x["gain_pct"] for x in per_batch) / n + mean_vs_human = sum(x["gain_vs_human_pct"] for x in per_batch) / n + beats = sum(1 for x in per_batch if x["beat_human"]) + return { + "evaluated": n, + "mean_gain_pct": round(mean_gain, 2), + "median_gain_pct": round(sorted(x["gain_pct"] for x in per_batch)[n // 2], 2), + "human_beat_rate_pct": round(100.0 * beats / n, 1), + "human_beat_count": f"{beats}/{n}", + "mean_gain_vs_human_pct": round(mean_vs_human, 2), + "per_batch": per_batch, + } + + def decide_and_apply(self) -> Dict[str, Any]: + """Run an evaluation and autonomously enable/disable road sequencing.""" + from app.config.dynamic_config import get_config + cfg = get_config() + + sample = int(cfg.get("routing_eval_sample_batches", 8)) + days = int(cfg.get("routing_eval_days", 14)) + enable_thr = float(cfg.get("routing_auto_enable_gain_pct", 3.0)) + disable_thr = float(cfg.get("routing_auto_disable_gain_pct", 1.0)) + min_batches = int(cfg.get("routing_eval_min_batches", 3)) + auto_manage = bool(cfg.get("routing_auto_manage", True)) + + try: + result = asyncio.run(self.evaluate(sample_batches=sample, days=days)) + except RuntimeError: + # An event loop is already running in this thread — use a fresh one. + loop = asyncio.new_event_loop() + try: + result = loop.run_until_complete(self.evaluate(sample_batches=sample, days=days)) + finally: + loop.close() + + current = bool(cfg.get("routing_use_road_distance", False)) + evaluated = result.get("evaluated", 0) + gain = result.get("mean_gain_pct", 0.0) + action = "kept" + new_state = current + + if not auto_manage: + action = "auto_manage_off" + elif evaluated < min_batches: + action = "insufficient_data" + else: + if gain >= enable_thr and not current: + new_state = True + cfg.set("routing_use_road_distance", True, source="road_agent") + action = "enabled" + elif gain < disable_thr and current: + new_state = False + cfg.set("routing_use_road_distance", False, source="road_agent") + action = "disabled" + + decision = { + "decided_at": datetime.utcnow().isoformat(), + "action": action, + "flag_before": current, + "flag_after": new_state, + "mean_gain_pct": gain, + "enable_threshold_pct": enable_thr, + "disable_threshold_pct": disable_thr, + "evaluation": result, + } + self.last_decision = decision + try: + # Persist a compact copy for audit (without the full per-batch list). + compact = {k: v for k, v in decision.items() if k != "evaluation"} + compact["evaluated"] = evaluated + compact["human_beat_rate_pct"] = result.get("human_beat_rate_pct") + compact["mean_gain_vs_human_pct"] = result.get("mean_gain_vs_human_pct") + cfg.set("routing_road_eval", compact, source="road_agent") + except Exception: + pass + + logger.info( + f"[RoadAgent] action={action} gain_vs_aerial={gain}% evaluated={evaluated} " + f"flag {current}->{new_state}" + ) + if evaluated: + logger.info( + f"[RoadAgent] beat humans on {result.get('human_beat_count', '?')} batches " + f"(avg {result.get('mean_gain_vs_human_pct', 0)}% faster than actual delivered order)" + ) + return decision + + def ensure_background_agent(self, interval_hours: int = 24, + warmup_seconds: int = 120) -> bool: + """Start the autonomous decision loop once (daemon thread).""" + with self._lock: + if self._scheduler_started: + return False + self._scheduler_started = True + + def _loop(): + # Let the ETA sync agent populate the local mirror first. + time.sleep(max(0, warmup_seconds)) + logger.info(f"[RoadAgent] autonomous road-sequencing decision loop started " + f"(interval={interval_hours}h)") + while True: + try: + self.decide_and_apply() + except Exception as e: + logger.warning(f"[RoadAgent] decision cycle failed (will retry): {e}") + from app.config.dynamic_config import get_config + hrs = int(get_config().get("routing_eval_interval_hours", interval_hours)) + time.sleep(max(1, hrs) * 3600) + + threading.Thread(target=_loop, daemon=True, name="road-seq-agent").start() + return True + + +_agent: Optional[RoadSequencingAgent] = None +_agent_lock = threading.Lock() + + +def get_road_agent() -> RoadSequencingAgent: + global _agent + with _agent_lock: + if _agent is None: + _agent = RoadSequencingAgent() + return _agent diff --git a/app/services/routing/route_optimizer.py b/app/services/routing/route_optimizer.py new file mode 100644 index 0000000..fdc6580 --- /dev/null +++ b/app/services/routing/route_optimizer.py @@ -0,0 +1,1614 @@ +"""Production-grade route optimization using Google OR-Tools. + +ALGORITHM: TSP / VRP with Google OR-Tools +- Industry-standard solver (same as used by major logistics companies) +- Constraint-based optimization +- Handles time windows (future proofing) +- Guaranteed optimal or near-optimal solution + +FEATURES: +- Automatic outlier detection and coordinate correction +- Hybrid distance calculation (Google Maps + Haversine fallback) +- Robust error handling for invalid inputs +- Composite cost function (idea.txt: distance + profit - margin) +""" + +import math +import os +import hashlib +import logging +import asyncio +from typing import Dict, Any, List as _List, Optional, Tuple, Union +from datetime import datetime, timedelta +import httpx +from app.services.routing.kalman_filter import smooth_order_coordinates +import numpy as np +from app.core.arrow_utils import calculate_haversine_matrix_vectorized +from app.config.dynamic_config import get_config + +try: + from ortools.constraint_solver import routing_enums_pb2 + from ortools.constraint_solver import pywrapcp + + ORTOOLS_AVAILABLE = True +except ImportError: + ORTOOLS_AVAILABLE = False + logging.warning("Google OR-Tools not found. Falling back to simple greedy solver.") + +logger = logging.getLogger(__name__) + + +class CompositeCostCalculator: + """ + Composite Cost Function for Profit-Aware Route Optimization. + + Based on idea.txt data encoding techniques: + - Total Cost = Distance Cost + Rider Cost - Merchant Profit + - Edge Cost = (distance * fuel_rate) + rider_cost - merchant_margin + - route_score = profit - composite_cost (what we want to MAXIMIZE) + + This transforms the problem from: + "Find shortest route" -> "Find most profitable route" + """ + + def __init__(self): + # Cost parameters (can be ML-tuned via DynamicConfig) + self.fuel_rate_per_km = 2.5 + self.base_rider_cost = 0.0 + self.opportunity_cost_per_km = 0.5 # Cost of rider's time per km + self.profit_weight = 0.3 # How much profit influences routing (0-1) + self.traffic_multiplier_peak = 1.5 # Peak hour traffic penalty + self.traffic_multiplier_normal = 1.2 # Normal traffic multiplier + + # Defaults for orders without profit data + self.default_order_amount = 80.0 + self.default_merchant_margin = 5.0 + + def calculate_composite_cost( + self, + distance_km: float, + order_amount: float = None, + merchant_margin: float = None, + traffic_factor: float = 1.0, + time_of_day: str = "NORMAL", + ) -> Dict[str, float]: + """ + Calculate composite cost for a route edge. + + Args: + distance_km: Distance for this leg + order_amount: Revenue from this order (if known) + merchant_margin: Merchant's margin for this order (if known) + traffic_factor: Traffic multiplier (1.0 = normal) + time_of_day: Traffic time category ("PEAK", "NORMAL", "OFF_PEAK") + + Returns: + Dict with: + - distance_cost: Raw distance cost + - rider_cost: Total rider cost for this leg + - gross_profit: Revenue - rider cost + - net_cost: Cost after profit adjustment (MINIMIZE THIS) + - route_score: Profitability score (MAXIMIZE THIS) + """ + # Distance cost = fuel + opportunity cost + distance_cost = distance_km * self.fuel_rate_per_km + + # Rider cost = base + distance cost + rider_cost = self.base_rider_cost + distance_cost + + # Apply traffic penalty + if time_of_day == "PEAK": + rider_cost *= self.traffic_multiplier_peak + elif time_of_day == "NORMAL": + rider_cost *= self.traffic_multiplier_normal + + # Apply custom traffic factor + rider_cost *= traffic_factor + + # Profit calculation (target encoding: use order data if available) + if order_amount is None: + order_amount = self.default_order_amount + if merchant_margin is None: + merchant_margin = self.default_merchant_margin + + gross_profit = order_amount - rider_cost + + # Net cost = rider cost - profit contribution + # This means high-profit orders have LOWER cost (more desirable) + profit_adjustment = gross_profit * self.profit_weight + net_cost = rider_cost - profit_adjustment + + # Route score = profit - opportunity cost (for route planning) + route_score = gross_profit - (distance_km * self.opportunity_cost_per_km) + + # Ensure net_cost is never negative (minimum cost for any delivery) + net_cost = max(net_cost, 5.0) # Minimum 5 km equivalent cost + + return { + "distance_cost": round(distance_cost, 2), + "rider_cost": round(rider_cost, 2), + "gross_profit": round(gross_profit, 2), + "net_cost": round(net_cost, 2), + "route_score": round(route_score, 2), + } + + def calculate_cost_matrix( + self, + dist_matrix: np.ndarray, + orders: _List[Dict[str, Any]] = None, + traffic_condition: str = "NORMAL", + ) -> Tuple[np.ndarray, Dict[str, Any]]: + """ + Calculate composite cost matrix for all node pairs. + + Args: + dist_matrix: Distance matrix (N x N) + orders: List of orders (for profit data) + traffic_condition: Traffic condition ("PEAK", "NORMAL", "OFF_PEAK") + + Returns: + Tuple of (cost_matrix, summary_stats) + """ + n = len(dist_matrix) + cost_matrix = np.zeros((n, n)) + + # Extract order data for profit encoding + order_amounts = [] + merchant_margins = [] + + if orders: + for o in orders: + try: + amount = float( + o.get("orderamount") + or o.get("deliveryamount") + or self.default_order_amount + ) + margin = float( + o.get("merchant_margin") or self.default_merchant_margin + ) + except: + amount = self.default_order_amount + margin = self.default_merchant_margin + order_amounts.append(amount) + merchant_margins.append(margin) + else: + order_amounts = [self.default_order_amount] * n + merchant_margins = [self.default_merchant_margin] * n + + # Calculate costs for each pair + total_cost = 0.0 + total_profit = 0.0 + high_cost_count = 0 + + for i in range(n): + for j in range(n): + if i == j: + cost_matrix[i][j] = 0 + continue + + dist = dist_matrix[i][j] + + # Use order j's profit data (destination) + order_amount = ( + order_amounts[j - 1] if j > 0 else self.default_order_amount + ) + merchant_margin = ( + merchant_margins[j - 1] if j > 0 else self.default_merchant_margin + ) + + cost_data = self.calculate_composite_cost( + distance_km=dist, + order_amount=order_amount, + merchant_margin=merchant_margin, + time_of_day=traffic_condition, + ) + + cost_matrix[i][j] = cost_data["net_cost"] + total_cost += cost_data["net_cost"] + total_profit += cost_data["gross_profit"] + + if cost_data["net_cost"] > 50: + high_cost_count += 1 + + summary = { + "total_cost": round(total_cost, 2), + "total_profit": round(total_profit, 2), + "avg_cost": round(total_cost / (n * n) if n > 0 else 0, 2), + "avg_profit": round(total_profit / (n * n) if n > 0 else 0, 2), + "high_cost_legs": high_cost_count, + "traffic_condition": traffic_condition, + } + + return cost_matrix, summary + + +class RouteOptimizer: + """Route optimization using Google OR-Tools (Async).""" + + def __init__(self): + self.earth_radius = 6371 # Earth radius in km + _cfg = get_config() + + # Initialize ETA Calculator - empirical (learned from actual delivery + # times) with automatic fallback to the realistic formula. + from app.services.routing.realistic_eta_calculator import ( + get_time_of_day_category, + ) + from app.services.routing.empirical_eta_calculator import EmpiricalETACalculator + + self.eta_calculator = EmpiricalETACalculator() + self.get_traffic_condition = get_time_of_day_category + + # Speed settings (ML-tuned via DynamicConfig) + self.avg_speed_kmh = float(_cfg.get("avg_speed_kmh")) + + # Road factor (haversine -> road distance multiplier, ML-tuned) + self.road_factor = float(_cfg.get("road_factor")) + + # Google Maps API settings + self.google_maps_api_key = os.getenv("GOOGLE_MAPS_API_KEY", "") + self.use_google_maps = bool(self.google_maps_api_key) + + # Solver time limit (ML-tuned) + self.search_time_limit_seconds = int(_cfg.get("search_time_limit_seconds")) + + self.cost_calculator = CompositeCostCalculator() + + def haversine_distance( + self, lat1: float, lon1: float, lat2: float, lon2: float + ) -> float: + """Calculate great circle distance between two points on Earth (in km).""" + try: + lat1, lon1, lat2, lon2 = map( + math.radians, [float(lat1), float(lon1), float(lat2), float(lon2)] + ) + dlat = lat2 - lat1 + dlon = lon2 - lon1 + a = ( + math.sin(dlat / 2) ** 2 + + math.cos(lat1) * math.cos(lat2) * math.sin(dlon / 2) ** 2 + ) + c = 2 * math.asin(math.sqrt(a)) + return self.earth_radius * c + except Exception: + return 0.0 + + async def _get_google_maps_distances_batch( + self, origin_lat: float, origin_lon: float, destinations: _List[tuple] + ) -> Dict[tuple, float]: + """Get road distances for multiple destinations from Google Maps API. (Async, Parallel)""" + if not self.use_google_maps or not destinations: + return {} + + results = {} + batch_size = 25 + chunks = [ + destinations[i : i + batch_size] + for i in range(0, len(destinations), batch_size) + ] + + async def process_batch(batch): + batch_result = {} + try: + dest_str = "|".join([f"{lat},{lon}" for lat, lon in batch]) + url = "https://maps.googleapis.com/maps/api/distancematrix/json" + params = { + "origins": f"{origin_lat},{origin_lon}", + "destinations": dest_str, + "key": self.google_maps_api_key, + "units": "metric", + } + async with httpx.AsyncClient(timeout=10.0) as client: + response = await client.get(url, params=params) + response.raise_for_status() + data = response.json() + + if data.get("status") == "OK": + rows = data.get("rows", []) + if rows: + elements = rows[0].get("elements", []) + for idx, element in enumerate(elements): + if idx < len(batch): + dest_coord = batch[idx] + if element.get("status") == "OK": + dist = element.get("distance", {}).get("value") + dur = element.get("duration", {}).get("value") + if dist is not None: + batch_result[dest_coord] = { + "distance": dist / 1000.0, + "duration": dur / 60.0 if dur else None, + } + except Exception as e: + logger.warning(f"Google Maps batch call failed: {e}") + return batch_result + + batch_results_list = await asyncio.gather( + *[process_batch(chunk) for chunk in chunks] + ) + for res in batch_results_list: + results.update(res) + return results + + # ------------------------------------------------------------------ + # GOOGLE DIRECTIONS - WAYPOINT OPTIMISATION + # ------------------------------------------------------------------ + + async def _optimize_waypoints_google( + self, + origin_lat: float, + origin_lon: float, + waypoints: _List[Tuple[float, float]], + ) -> Tuple[Optional[_List[int]], Optional[_List[float]]]: + """ + Ask Google Directions API to find the optimal visiting order for a set + of delivery points starting from a kitchen/pickup location. + + Uses `optimize:true` in the waypoints parameter - Google solves the TSP + internally using actual road geometry (turn restrictions, one-way + streets, real distances) rather than Haversine approximation. + + Returns + ------- + (waypoint_order, leg_km) + waypoint_order 0-based indices into `waypoints` in optimal order. + e.g. [2, 0, 1] means visit wp[2] -> wp[0] -> wp[1]. + leg_km Actual road distance (km) for each leg in order: + leg_km[0] = kitchen -> wp[order[0]], + leg_km[1] = wp[order[0]] -> wp[order[1]], etc. + Both are None on any failure - caller falls back to OR-Tools. + + Notes + ----- + - Supports up to 25 intermediate waypoints (Google's standard limit). + - destination = origin (closed-loop TSP); the return leg is discarded. + - One API call per rider per assignment - cheap at delivery scale. + """ + if not self.use_google_maps or not waypoints or len(waypoints) < 2: + return None, None + if len(waypoints) > 25: + return None, None # fall back to OR-Tools for unusually large routes + + try: + wp_str = "optimize:true|" + "|".join( + f"{lat},{lon}" for lat, lon in waypoints + ) + params = { + "origin": f"{origin_lat},{origin_lon}", + "destination": f"{origin_lat},{origin_lon}", # closed loop + "waypoints": wp_str, + "key": self.google_maps_api_key, + } + async with httpx.AsyncClient(timeout=8.0) as client: + resp = await client.get( + "https://maps.googleapis.com/maps/api/directions/json", + params=params, + ) + resp.raise_for_status() + data = resp.json() + + status_code = data.get("status") + if status_code != "OK": + logger.debug( + f"[GoogleWaypoints] status={status_code} " + f"error='{data.get('error_message', '')}'" + ) + return None, None + + routes = data.get("routes", []) + if not routes: + return None, None + + route = routes[0] + wp_order = route.get("waypoint_order") + legs = route.get("legs", []) + + if wp_order is None or len(wp_order) != len(waypoints): + return None, None + + # Extract leg distances (metres -> km), skip the return-to-origin leg + leg_km: _List[float] = [] + for leg in legs[: len(waypoints)]: # first N legs only + dist_m = leg.get("distance", {}).get("value") + leg_km.append(dist_m / 1000.0 if dist_m is not None else 0.0) + + logger.debug( + f"[GoogleWaypoints] Optimised {len(waypoints)} stops -> order={wp_order}" + ) + return wp_order, leg_km + + except Exception as _e: + logger.debug(f"[GoogleWaypoints] Failed (non-fatal): {_e}") + return None, None + + # ------------------------------------------------------------------ + # ROAD-AWARE VISITING ORDER (Phase 2 - opt-in, cached) + # ------------------------------------------------------------------ + + async def _road_duration_matrix( + self, coords: _List[Tuple[float, float]] + ) -> Optional[_List[_List[float]]]: + """ + Full NxN road travel-TIME matrix (minutes) via Google Distance Matrix. + + Chunks destinations to respect Google's ~100-elements-per-request limit. + Returns None on any failure so the caller falls back to aerial ordering. + """ + if not self.use_google_maps: + return None + n = len(coords) + origins = "|".join(f"{la},{lo}" for la, lo in coords) + matrix = [[0.0] * n for _ in range(n)] + dest_chunk = max(1, 100 // max(1, n)) + try: + async with httpx.AsyncClient(timeout=15.0) as client: + for j0 in range(0, n, dest_chunk): + js = list(range(j0, min(j0 + dest_chunk, n))) + dests = "|".join(f"{coords[j][0]},{coords[j][1]}" for j in js) + resp = await client.get( + "https://maps.googleapis.com/maps/api/distancematrix/json", + params={"origins": origins, "destinations": dests, + "key": self.google_maps_api_key, "units": "metric"}, + ) + resp.raise_for_status() + data = resp.json() + if data.get("status") != "OK": + logger.debug(f"[RoadSeq] DistanceMatrix status={data.get('status')}") + return None + for i, row in enumerate(data.get("rows", [])): + for k, el in enumerate(row.get("elements", [])): + if el.get("status") == "OK": + dur = el.get("duration", {}).get("value") + if dur is not None: + matrix[i][js[k]] = dur / 60.0 + return matrix + except Exception as e: + logger.debug(f"[RoadSeq] matrix build failed: {e}") + return None + + async def _road_optimal_order( + self, + start_lat: float, + start_lon: float, + points: _List[Tuple[float, float]], + ) -> Optional[_List[int]]: + """ + Road-aware visiting order for `points`, starting from (start_lat, start_lon). + + Builds a real road travel-TIME matrix (Google Distance Matrix) and solves + an OPEN TSP with OR-Tools (return-to-depot edge = 0), so the sequence + respects real road geometry/one-ways instead of straight-line distance. + Validated on live batches to cut real travel time ~5-13% vs aerial; note + Google's Directions optimize:true is NOT used - it optimises a closed loop + and measured *worse* than aerial for our open delivery routes. + + Returns 0-based indices into `points` in optimal order, or None to signal + the caller to fall back to the existing aerial greedy + 2-opt. + + Safe + cheap on the live path: + * disabled unless `routing_use_road_distance` AND a Google key is set + * only for 3..`routing_road_max_stops` stops (fewer is trivial; more + exceeds Google's waypoint-optimize cap) + * result cached in Redis (default 24h) keyed by the rounded coords in + input order, so the returned indices always map back correctly + """ + cfg = get_config() + if not cfg.get("routing_use_road_distance", False): + return None + if not self.use_google_maps: + return None + n = len(points) + if n < 3 or n > int(cfg.get("routing_road_max_stops", 25)): + return None + + def _r(v) -> float: + return round(float(v), 4) # ~11 m - enough to dedupe near-identical batches + + pts_key = "|".join(f"{_r(la)},{_r(lo)}" for la, lo in points) + cache_key = "roadseq:" + hashlib.sha256( + f"{_r(start_lat)},{_r(start_lon)}#{pts_key}".encode("utf-8") + ).hexdigest() + + try: + from app.services import cache as _cache + cached = _cache.get_json(cache_key) + if isinstance(cached, list) and len(cached) == n: + logger.debug(f"[RoadSeq] cache hit ({n} stops)") + return cached + except Exception: + pass + + locs = [(start_lat, start_lon)] + list(points) + matrix = await self._road_duration_matrix(locs) + if matrix is None: + return None + # matrix contains minutes, not km — use scale=100 (centiseconds) so + # OR-Tools gets valid integer arc costs without the km→m * 1000 factor. + route = self._solve_tsp_ortools(locs, matrix, matrix_scale=100) + order = [i - 1 for i in route if i != 0] + if len(order) != n: + return None + + try: + from app.services import cache as _cache + _cache.set_json( + cache_key, order, + ttl_seconds=int(cfg.get("routing_road_cache_ttl_seconds", 86400)), + ) + except Exception: + pass + logger.info(f"[RoadSeq] road-optimal order for {n} stops -> {order}") + return order + + # ------------------------------------------------------------------ + # 2-OPT LOCAL SEARCH + # ------------------------------------------------------------------ + + def _two_opt_improve( + self, + route: _List[int], + dist_matrix, # numpy array or nested list + ) -> _List[int]: + """ + 2-opt local search: repeatedly reverses route segments to find a shorter path. + + Algorithm: + For each pair (i, j) where i < j, check whether reversing the + sub-route between positions i and j reduces total distance. + If yes, apply the reversal and restart scanning. + + Property: + * Guaranteed to terminate (finitely many distinct routes). + * Produces a *locally* 2-optimal solution - no 2-edge swap can + improve it further. + * Typical gain on delivery-scale instances: 815% shorter routes. + * Works on OPEN routes (depot stays at position 0, free return). + + Complexity: O(n) per improvement pass, O(n) worst case total. + Acceptable for n <= 50 orders per rider. + """ + if len(route) <= 3: + return route + + def d(a: int, b: int) -> float: + return float(dist_matrix[a][b]) + + best = list(route) + n = len(best) + improved = True + + while improved: + improved = False + for i in range(1, n - 1): + for j in range(i + 1, n): + # Cost of the TWO edges that would change in this swap: + # Current : best[i-1] -> best[i] and best[j] -> best[j+1] + # Reversed: best[i-1] -> best[j] and best[i] -> best[j+1] + # (open TSP: no edge from last node back to depot) + c_before = d(best[i - 1], best[i]) + c_after = d(best[i - 1], best[j]) + if j + 1 < n: + c_before += d(best[j], best[j + 1]) + c_after += d(best[i], best[j + 1]) + + # For asymmetric matrices (e.g., road duration), reversing the + # sub-route changes the cost of internal edges. We must add + # the exact difference. For symmetric matrices, this is 0. + internal_diff = 0.0 + for k in range(i, j): + internal_diff += d(best[k + 1], best[k]) - d(best[k], best[k + 1]) + + if c_after + internal_diff < c_before - 1e-10: + best[i : j + 1] = best[i : j + 1][::-1] + improved = True + + return best + + # ------------------------------------------------------------------ + # TSP SOLVER (with optional time windows + 2-opt post-processing) + # ------------------------------------------------------------------ + + def _solve_tsp_ortools( + self, + locations: _List[Tuple[float, float]], + dist_matrix: _List[_List[float]], + time_windows: Optional[_List[Tuple[int, int]]] = None, + matrix_scale: int = 1000, + ) -> _List[int]: + """ + Solve Open TSP using Google OR-Tools + GLS + 2-opt refinement. + + Args: + locations : list of (lat, lon) - index 0 is the depot (kitchen). + dist_matrix : NxN cost matrix. Default unit is km (scale=1000 → metres). + Pass matrix_scale=100 when the matrix contains minutes. + time_windows: Optional list of (earliest_min, latest_min) per node. + * Node 0 (depot): typically (0, horizon). + * Delivery node i: (0, max_delivery_deadline). + If None, no time-window constraints are applied. + matrix_scale: Integer multiplier applied to matrix values before + passing to OR-Tools (which requires integer arc costs). + + Returns: + Route as a list of node indices starting with 0 (depot). + """ + if not ORTOOLS_AVAILABLE: + route = self._solve_greedy(locations, dist_matrix) + return self._two_opt_improve(route, dist_matrix) + + if not locations or len(locations) <= 1: + return [0] + + n_nodes = len(locations) + manager = pywrapcp.RoutingIndexManager(n_nodes, 1, 0) + routing = pywrapcp.RoutingModel(manager) + + # -- DISTANCE CALLBACK -------------------------------------------- + # Open TSP: return-to-depot edge always costs 0 so the solver + # optimises the *path* from kitchen to last drop-off, not a closed loop. + def distance_callback(from_index, to_index): + from_node = manager.IndexToNode(from_index) + to_node = manager.IndexToNode(to_index) + if to_node == 0: + return 0 + return int(dist_matrix[from_node][to_node] * matrix_scale) + + transit_cb_idx = routing.RegisterTransitCallback(distance_callback) + routing.SetArcCostEvaluatorOfAllVehicles(transit_cb_idx) + + # -- TIME-WINDOW DIMENSION (optional) ---------------------------- + if time_windows and len(time_windows) == n_nodes: + speed_km_per_min = max(0.1, self.avg_speed_kmh / 60.0) + + def time_callback(from_index, to_index): + fn = manager.IndexToNode(from_index) + tn = manager.IndexToNode(to_index) + if tn == 0: + return 0 + travel_min = int(dist_matrix[fn][tn] / speed_km_per_min) + return travel_min + 4 # +4 min avg door time per stop + + time_cb_idx = routing.RegisterTransitCallback(time_callback) + max_horizon = 180 # 3-hour window + + routing.AddDimension( + time_cb_idx, + 30, # max waiting time at any node (30 min) + max_horizon, + False, # don't force start cumul to zero + "Time", + ) + time_dim = routing.GetDimensionOrDie("Time") + + for node_idx, (earliest, latest) in enumerate(time_windows): + if node_idx == 0: + continue # depot has no hard window + idx = manager.NodeToIndex(node_idx) + time_dim.CumulVar(idx).SetRange(int(earliest), int(latest)) + + # Minimise time at end of route (encourages ASAP delivery) + time_dim.SetGlobalSpanCostCoefficient(10) + + # -- SEARCH PARAMETERS -------------------------------------------- + search_params = pywrapcp.DefaultRoutingSearchParameters() + search_params.first_solution_strategy = ( + routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC + ) + search_params.local_search_metaheuristic = ( + routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH + ) + # TSP time limit hard-capped at 2 seconds per kitchen. + # The ML hypertuner may push search_time_limit_seconds up to 8-10s + # chasing marginally better routes, but at delivery scale (< 15 stops) + # OR-Tools finds a near-optimal solution in < 200ms. Waiting 8-10s + # per kitchen x 3 kitchens x 4 riders = 96s of unnecessary waiting. + # The VRP already has its own 3s cap. This cap applies to per-rider + # TSP and the per-kitchen beatmap solves. + search_params.time_limit.seconds = min(self.search_time_limit_seconds, 2) + + solution = routing.SolveWithParameters(search_params) + + if solution: + index = routing.Start(0) + route = [] + while not routing.IsEnd(index): + route.append(manager.IndexToNode(index)) + index = solution.Value(routing.NextVar(index)) + # -- 2-OPT POST-PROCESSING --------------------------------- + route = self._two_opt_improve(route, dist_matrix) + return route + else: + route = self._solve_greedy(locations, dist_matrix) + return self._two_opt_improve(route, dist_matrix) + + # ------------------------------------------------------------------ + # TRUE MULTI-RIDER VRP (Capacitated Pickup-and-Delivery Problem) + # ------------------------------------------------------------------ + + def solve_vrp_multi_rider( + self, + orders: _List[Dict[str, Any]], + rider_data: _List[Dict[str, Any]], # [{"id": rid, "lat": lat, "lon": lon}, ...] + max_orders_per_rider: int = 12, + soft_prefs: Optional[Dict] = None, + soft_home: Optional[Dict] = None, + ) -> Optional[Dict[int, _List[Dict[str, Any]]]]: + """ + Capacitated VRP - assigns all orders to riders simultaneously in a + single OR-Tools model, with strong load-balancing pressure. + + KEY FIXES over the previous PDPTW implementation: + ------------------------------------------------- + 1. CAPACITY MODEL (critical fix): + Old model used +1 at pickup and -1 at delivery (PDPTW). + Net demand per order = 0 -> solver could put ALL orders on 1 rider + by interleaving pickup/delivery pairs (capacity never exceeds 1). + New model: demand = 1 per delivery node only. + Capacity dimension tracks TOTAL orders assigned per rider (monotonic). + This correctly enforces max_orders_per_rider as a total limit. + + 2. MINIMUM VEHICLES + NATURAL BALANCE: + SetFixedCostOfAllVehicles(500_000) penalises each extra vehicle by + 500 km equivalent - far more than any real route saves. Solver uses + ceil(orders/capacity) riders; distance cost balances loads naturally. + + 3. DETERMINISM: + Riders sorted by ID so vehicle-0 always maps to the lowest-ID rider, + regardless of API response ordering. + SAVINGS first-solution strategy is deterministic for identical inputs. + + Node layout (total = 1 + N + M): + +-----------------------------------------------------+ + | 0 : global end-depot (free return) | + | 1 .. N : rider GPS start positions | + | N+1..N+M : order delivery nodes (demand = 1 each) | + +-----------------------------------------------------+ + + Returns {rider_id: [ordered list of order dicts]} or None on failure. + Falls back silently to None - caller must use 2-phase fallback. + """ + if not ORTOOLS_AVAILABLE: + return None + if not orders or not rider_data: + return None + + try: + M = len(orders) + N = len(rider_data) + + # -- SORT RIDERS FOR DETERMINISM ------------------------------ + # API response order can differ between calls. Sorting by rider ID + # ensures vehicle-v always maps to the same rider on every call + # with identical input data. + rider_data = sorted(rider_data, key=lambda r: r["id"]) + + def _f(v): + try: return float(v) + except: return 0.0 + + # -- BUILD NODE COORDINATE LIST ------------------------------- + # We use DELIVERY coordinates for VRP node locations. + # Riders are scored and routed by where they actually *deliver*, + # so the solver groups geographically close deliveries together. + # Kitchen sequencing (visit Kitchen A -> deliver, Kitchen B -> deliver) + # is handled downstream by beatmap_route / TSP. + # Kitchen *affinity* is handled by the preference-discount matrix below: + # preferred riders get a cost reduction on orders from their kitchen, + # which steers the solver to assign them those orders even if a + # non-preferred rider is marginally closer by delivery location. + end_depot = (0.0, 0.0) # dummy; cost to return here = 0 + rider_locs = [(r["lat"], r["lon"]) for r in rider_data] + + order_locs = [] + for o in orders: + dlat = _f(o.get("deliverylat") or o.get("droplat")) + dlon = _f(o.get("deliverylong") or o.get("droplon")) + if dlat == 0: # fallback to pickup coords if delivery missing + dlat = _f(o.get("pickuplat")) + dlon = _f(o.get("pickuplon") or o.get("pickuplong")) + order_locs.append((dlat, dlon)) + + all_locs = [end_depot] + rider_locs + order_locs + total_nodes = len(all_locs) # = 1 + N + M + + # -- DISTANCE MATRIX ------------------------------------------ + lats = np.array([loc[0] for loc in all_locs]) + lons = np.array([loc[1] for loc in all_locs]) + dist_m = ( + calculate_haversine_matrix_vectorized(lats, lons) * self.road_factor + ) + + # -- PREFERENCE DISCOUNT MATRIX ------------------------------- + # Build a per-rider discount (in metres) for orders from preferred + # kitchens. A negative arc-cost delta is achieved by reducing that + # rider's cost to reach preferred-kitchen delivery nodes. + # + # Discount = 3 000 m ~ 3 km equivalent, so a preferred rider + # up to ~3 km farther than a non-preferred rider still wins the bid. + # Home-zone bonus adds another 2 000 m for riders within 4 km of + # the kitchen's home area. + from app.config.rider_preferences import ( + RIDER_PREFERRED_KITCHENS, + RIDER_HOME_LOCATIONS, + ) + # SOFT steering uses learned-augmented affinity (config learned); + # the HARD kitchen constraint below stays on curated config only. + try: + if soft_prefs is not None and soft_home is not None: + _soft_prefs = soft_prefs + _soft_home = soft_home + else: + from app.services.routing.rider_affinity_service import get_rider_affinity + _aff = get_rider_affinity() + _soft_prefs = _aff.get_preferred_kitchens() + _soft_home = _aff.get_home_locations() + except Exception: + _soft_prefs = soft_prefs if soft_prefs is not None else RIDER_PREFERRED_KITCHENS + _soft_home = soft_home if soft_home is not None else RIDER_HOME_LOCATIONS + + PREF_DISCOUNT_M = 3_000 # 3 km equivalent discount for preferred kitchen + HOME_4KM_BONUS_M = 2_000 # extra 2 km for rider within home zone (4 km) + HOME_2KM_BONUS_M = 4_000 # extra 4 km for rider very close to home zone + + def _haversine_m(la1, lo1, la2, lo2): + import math + la1,lo1,la2,lo2 = map(math.radians,[float(la1),float(lo1),float(la2),float(lo2)]) + a = math.sin((la2-la1)/2)**2 + math.cos(la1)*math.cos(la2)*math.sin((lo2-lo1)/2)**2 + return 6_371_000 * 2 * math.asin(min(1.0, math.sqrt(a))) + + # Precompute kitchen name for each order node. + # Field priority (confirmed from real order payload): + # pickupcustomer -> "Daily grubs(jayanthi kitchen)" primary + # locationname -> "Daily grubs(jayanthi kitchen)" same value, backup + # Legacy / alternate API versions also checked below. + _KITCHEN_KEYS = [ + "pickupcustomer", # confirmed in production order JSON + "locationname", # confirmed in production order JSON + "storename", "store_name", + "restaurantname", "restaurant_name", + "kitchenname", "kitchen_name", + "partnername", "partner_name", + "tenantname", # "Daily grubs" (without branch suffix) + "brandname", "brand_name", + "providername", "provider_name", + "shopname", "shop_name", + ] + order_kitchens = [] + for o in orders: + kitchen = "" + for _k in _KITCHEN_KEYS: + _v = o.get(_k) + if _v and str(_v).strip(): + kitchen = str(_v).strip().lower() + break + order_kitchens.append(kitchen) + + # Log unique kitchen names found so user can verify they match prefs + unique_kitchens = sorted(set(k for k in order_kitchens if k)) + logger.info( + f"[VRP] Kitchen names in orders ({len(unique_kitchens)} unique): {unique_kitchens}" + ) + + # Build discount array: discount_m[v][order_i] + # Node index for order_i in all_locs = 1 + N + order_i + discount_m = [[0] * M for _ in range(N)] + for v, rd in enumerate(rider_data): + rid = rd["id"] + prefs = [p.lower() for p in _soft_prefs.get(rid, [])] + h_lat, h_lon = _soft_home.get(rid, (0.0, 0.0)) + + for i, kitchen in enumerate(order_kitchens): + if not kitchen or not prefs: + continue + # Bidirectional substring match (mirrors AssignmentService logic) + if any(p in kitchen or kitchen in p for p in prefs): + disc = PREF_DISCOUNT_M + # Tiebreak when two riders prefer the same kitchen: + # give extra discount to the rider whose home zone + # is closest to the delivery location. + if h_lat != 0: + dlat, dlon = order_locs[i] # delivery coords + if dlat != 0: + home_dist_m = _haversine_m(h_lat, h_lon, dlat, dlon) + if home_dist_m <= 2_000: + disc += HOME_2KM_BONUS_M + elif home_dist_m <= 4_000: + disc += HOME_4KM_BONUS_M + discount_m[v][i] = disc + + # -- OR-TOOLS MODEL ------------------------------------------- + starts = list(range(1, N + 1)) # each rider starts at its own node + ends = [0] * N # all end at dummy depot (free) + + manager = pywrapcp.RoutingIndexManager(total_nodes, N, starts, ends) + routing = pywrapcp.RoutingModel(manager) + + # Per-vehicle distance callbacks - each rider gets a preference discount + # on delivery nodes belonging to their preferred kitchens. + # OR-Tools requires one registered callback per vehicle when costs differ. + def make_pref_cb(v_idx, disc_row): + def cb(fi, ti): + fn = manager.IndexToNode(fi) + tn = manager.IndexToNode(ti) + if tn == 0: + return 0 + base = int(dist_m[fn][tn] * 1000) + # Apply discount if destination is a delivery node + order_i = tn - (1 + N) + if 0 <= order_i < M: + base = max(0, base - disc_row[order_i]) + return base + return cb + + for v in range(N): + cb_fn = make_pref_cb(v, discount_m[v]) + cb_idx = routing.RegisterTransitCallback(cb_fn) + routing.SetArcCostEvaluatorOfVehicle(cb_idx, v) + + # -- HARD KITCHEN CONSTRAINT ---------------------------------- + # rider_preferences.py is the source of truth. + # If a kitchen has at least one configured rider in the active + # fleet, ONLY those riders are allowed to visit those order nodes. + # Non-preferred riders are physically excluded by the solver. + # + # Fallback: if every preferred rider for a kitchen is absent from + # the active fleet, the order is left unconstrained (any rider). + # This prevents unsolvable models when a preferred rider is off-duty. + + # Build inverse map: kitchen_name_lower -> [vehicle_index, ...] + kitchen_to_vehicles: dict = {} + for v, rd in enumerate(rider_data): + rid = rd["id"] + for pref_k in RIDER_PREFERRED_KITCHENS.get(rid, []): + kitchen_to_vehicles.setdefault(pref_k.lower(), []).append(v) + + _hard_applied = 0 + for i, kitchen in enumerate(order_kitchens): + if not kitchen: + continue + allowed_v: set = set() + for cfg_k, vehicles in kitchen_to_vehicles.items(): + if cfg_k in kitchen or kitchen in cfg_k: + allowed_v.update(vehicles) + if allowed_v: + # OR-Tools hard constraint: solver cannot assign this order + node_idx = manager.NodeToIndex(1 + N + i) + try: + routing.SetAllowedVehiclesForIndex(list(allowed_v), node_idx) + except TypeError: + # Fallback for OR-Tools wrapper bug with absl::Span + routing.VehicleVar(node_idx).SetValues([int(x) for x in allowed_v]) + _hard_applied += 1 + + logger.info( + f"[VRP] Hard constraints: {_hard_applied}/{M} orders locked to " + f"their configured riders. " + f"({M - _hard_applied} orders unconstrained / no pref configured)" + ) + + has_prefs = any(any(d > 0 for d in row) for row in discount_m) + riders_with_prefs = sum(1 for row in discount_m if any(d > 0 for d in row)) + logger.info( + f"[VRP] Preference discounts applied: {has_prefs} | " + f"riders with prefs: {riders_with_prefs}/{N}" + ) + if not has_prefs: + active_ids = sorted(rd["id"] for rd in rider_data) + missing_ids = [rid for rid in active_ids if rid not in RIDER_PREFERRED_KITCHENS] + if missing_ids: + # IDs are not registered at all + logger.warning( + f"[VRP] ! NO preference discounts - rider IDs not in config!\n" + f" Active IDs not configured : {missing_ids}\n" + f" -> Add them to RIDER_PREFERRED_KITCHENS in " + f"app/config/rider_preferences.py" + ) + else: + # IDs are fine but kitchen NAME in orders doesn't match configured prefs + config_kitchens = sorted(set( + k.lower() + for prefs in RIDER_PREFERRED_KITCHENS.values() + for k in prefs + )) + logger.warning( + f"[VRP] ! NO preference discounts - kitchen NAMES don't match!\n" + f" Order kitchen names : {unique_kitchens}\n" + f" Configured prefs : {config_kitchens}\n" + f" -> These must overlap (substring match). " + f"Edit RIDER_PREFERRED_KITCHENS in rider_preferences.py " + f"to use the exact names shown in 'Order kitchen names' above." + ) + + # -- CAPACITY DIMENSION --------------------------------------- + # demand[delivery_node] = 1 (each order = 1 unit). + # Monotonically increases as rider picks up more orders. + # At max_orders_per_rider the rider is full - solver must use another. + demands = [0] * total_nodes + for i in range(M): + demands[1 + N + i] = 1 # delivery node i + + def demand_cb(fi): + return demands[manager.IndexToNode(fi)] + + dem_idx = routing.RegisterUnaryTransitCallback(demand_cb) + routing.AddDimensionWithVehicleCapacity( + dem_idx, + 0, # no slack + [max_orders_per_rider] * N, # hard cap per rider + True, # start cumul at 0 + "Capacity", + ) + + # -- LOAD BALANCING via Capacity span ------------------------- + # SetGlobalSpanCostCoefficient on the CAPACITY dimension adds + # (max_load - min_load) * coeff to the objective, pushing GLS + # to redistribute orders from heavy riders to light riders. + # + # Why it is SAFE here (unlike on the distance dimension): + # Fixed vehicle cost = 500,000 m + # Max span possible = max_orders_per_rider = 12 orders + # Max span saving = 12 x 3,000 = 36,000 m + # 36,000 << 500,000 -> adding an empty rider ALWAYS costs + # +464,000 m net -> solver will NEVER activate an extra rider + # just to reduce span. Balance happens only among the + # ceil(orders/cap) riders already chosen by the fixed cost. + # + # Effect: GLS will accept moving an order to a lighter rider + # even if that rider is up to ~3 km farther, as long as doing + # so reduces the max-min imbalance by at least 1 order. + cap_dim = routing.GetDimensionOrDie("Capacity") + cap_dim.SetGlobalSpanCostCoefficient(3_000) + + # -- MINIMUM VEHICLES (force fewest riders) ------------------- + # Each vehicle activated adds 500 km to the objective. + # 500 km >> any realistic multi-stop route (~ 60 km max), + # so the solver always uses ceil(orders / capacity) riders. + routing.SetFixedCostOfAllVehicles(500_000) + + # -- SEARCH PARAMETERS ---------------------------------------- + sp = pywrapcp.DefaultRoutingSearchParameters() + # PATH_CHEAPEST_ARC: works correctly for multi-depot VRP where + # each vehicle starts at a different location (rider position). + # SAVINGS (Clarke-Wright) requires a single shared depot and + # returns None for multi-depot inputs - do NOT use SAVINGS here. + sp.first_solution_strategy = ( + routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC + ) + sp.local_search_metaheuristic = ( + routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH + ) + # VRP time budget: cap at 3 seconds so the API response is never + # blocked longer than that. The x 3 multiplier caused 15-second + # responses with the default 5-second search_time_limit. + # PATH_CHEAPEST_ARC typically finds a good solution in < 1 second + # for our typical sizes (<= 15 riders, <= 60 orders); GLS then + # improves it within the remaining budget. + sp.time_limit.seconds = min(self.search_time_limit_seconds, 3) + + solution = routing.SolveWithParameters(sp) + + if not solution: + logger.warning("[VRP] No solution found - falling back to 2-phase assignment") + return None + + # -- EXTRACT & RETURN ASSIGNMENTS ----------------------------- + rider_assignments: Dict[int, _List[Dict[str, Any]]] = {} + for v in range(N): + rider_id = rider_data[v]["id"] + rider_route_orders: _List[Dict[str, Any]] = [] + + idx = routing.Start(v) + while not routing.IsEnd(idx): + node = manager.IndexToNode(idx) + idx = solution.Value(routing.NextVar(idx)) + + # Delivery nodes are indices N+1 to N+M + if node >= 1 + N: + order_i = node - (1 + N) + if 0 <= order_i < M: + rider_route_orders.append(orders[order_i]) + + if rider_route_orders: + rider_assignments[rider_id] = rider_route_orders + + assigned = sum(len(v) for v in rider_assignments.values()) + load_counts = sorted([len(v) for v in rider_assignments.values()], reverse=True) + logger.info( + f"[VRP] Solution: {assigned}/{M} orders -> " + f"{len(rider_assignments)}/{N} riders | " + f"distribution: {load_counts}" + ) + return rider_assignments + + except Exception as exc: + logger.error(f"[VRP] Solver error: {exc}", exc_info=True) + return None + + def _solve_greedy(self, locations, dist_matrix): + """Simple Greedy Nearest Neighbor fallback.""" + unvisited = set(range(1, len(locations))) + curr = 0 + route = [0] + while unvisited: + nearest = min(unvisited, key=lambda x: dist_matrix[curr][x]) + route.append(nearest) + unvisited.remove(nearest) + curr = nearest + return route + + def _cleanup_coords( + self, lat: Any, lon: Any, ref_lat: float, ref_lon: float + ) -> Tuple[float, float]: + """ + Heuristic to fix bad coordinates. + 1. Fixes lat==lon typo. + 2. Fixes missing negative signs if needed (not needed for India). + 3. Projects outlier > 500km to reference (centroid). + """ + try: + lat = float(lat) + lon = float(lon) + except: + return 0.0, 0.0 + + if lat == 0 or lon == 0: + return lat, lon + + # 1. Check strict equality (typo) + if abs(lat - lon) < 0.0001: + if ref_lon != 0: + # If reference is available, assume lat is correct and fix lon + # (Common error: copy lat to lon field) + return lat, ref_lon + + # 2. Check general outlier (e.g. 500km away) + if ref_lat != 0 and ref_lon != 0: + dist = self.haversine_distance(lat, lon, ref_lat, ref_lon) + if dist > 500: + # Returning reference prevents map explosion + return ref_lat, ref_lon + + return lat, lon + + async def optimize_provider_payload( + self, orders: _List[Dict[str, Any]], start_coords: Optional[tuple] = None + ) -> _List[Dict[str, Any]]: + """Optimize delivery route and add step metrics (OR-Tools).""" + if not orders: + return [] + + # Deep copy + orders = [dict(order) for order in orders] + + # 0. KALMAN FILTER - Smooth noisy delivery GPS coordinates + orders = smooth_order_coordinates(orders) + + # Helpers + def _to_float(v: Any) -> float: + try: + return float(v) + except: + return 0.0 + + def _normalize_dt(val: Any) -> str: + if val in (None, "", 0): + return "" + s = str(val).strip() + for fmt in ("%Y-%m-%dT%H:%M:%SZ", "%Y-%m-%d %H:%M:%S"): + try: + return datetime.strptime(s, fmt).strftime("%Y-%m-%d %H:%M:%S") + except: + pass + return s + + # 1. PREPARE COORDINATES & CENTROID + valid_lats = [] + valid_lons = [] + + for o in orders: + lat = _to_float(o.get("deliverylat")) + lon = _to_float(o.get("deliverylong")) + if lat != 0 and lon != 0: + valid_lats.append(lat) + valid_lons.append(lon) + + centroid_lat = sum(valid_lats) / len(valid_lats) if valid_lats else 0.0 + centroid_lon = sum(valid_lons) / len(valid_lons) if valid_lons else 0.0 + + # 2. DETERMINE START LOCATION (With Fix) + start_lat, start_lon = 0.0, 0.0 + + # Try explicit start_coords first + if start_coords and len(start_coords) == 2: + try: + start_lat, start_lon = float(start_coords[0]), float(start_coords[1]) + except: + pass + + # Fallback to pickup location in orders + if start_lat == 0: + for o in orders: + plat = _to_float(o.get("pickuplat")) + plon = _to_float(o.get("pickuplon") or o.get("pickuplong")) + if plat != 0: + start_lat, start_lon = plat, plon + break + + # Fallback to centroid + if start_lat == 0: + start_lat, start_lon = centroid_lat, centroid_lon + + # FIX BAD START COORDINATES + start_lat, start_lon = self._cleanup_coords( + start_lat, start_lon, centroid_lat, centroid_lon + ) + + # 3. BUILD LOCATIONS LIST FOR SOLVER + # Index 0 is Start (Depot), 1..N are orders + locations = [(start_lat, start_lon)] + points_map = [] # solver_idx-1 -> original order index + order_to_delivery_loc = {} # original order index -> (lat, lon) + + for idx, order in enumerate(orders): + lat = _to_float(order.get("deliverylat")) + lon = _to_float(order.get("deliverylong")) + + # Project coordinates and ensure they are strings for Go compatibility + lat, lon = self._cleanup_coords(lat, lon, centroid_lat, centroid_lon) + order_str_lat, order_str_lon = str(lat), str(lon) + + order["deliverylat"] = order_str_lat + order["deliverylong"] = order_str_lon + if "droplat" in order: + order["droplat"] = order_str_lat + if "droplon" in order: + order["droplon"] = order_str_lon + + locations.append((lat, lon)) + points_map.append(idx) + order_to_delivery_loc[idx] = (lat, lon) + + # 4. COMPUTE DISTANCE MATRICES + lats = np.array([loc[0] for loc in locations]) + lons = np.array([loc[1] for loc in locations]) + # aerial_matrix - pure straight-line km; used for step ORDERING. + # Road-distance ordering causes non-intuitive sequences: a delivery + # that is physically 200 m away can appear "far" because the road + # route loops around. Riders handle U-turns themselves - we just + # tell them the nearest unvisited point by crow-flies distance. + # dist_matrix - aerial x road_factor; used for ETA/cost analytics only. + aerial_matrix = calculate_haversine_matrix_vectorized(lats, lons) + dist_matrix = aerial_matrix * self.road_factor + + traffic = self.get_traffic_condition() + + # 5b. MULTI-KITCHEN BEATMAP DETECTION + # If a rider's orders come from more than one kitchen, use kitchen-aware + # sequencing: visit Kitchen A -> deliver A's orders -> Kitchen B -> deliver B's. + # Only count real kitchens (exclude the no-pickup-coords bucket). + kitchen_groups = self._group_by_kitchen(orders, _to_float) + real_kitchen_count = sum(1 for k in kitchen_groups if k[0] != "?") + if real_kitchen_count > 1: + logger.info( + f"Beatmap routing: {len(orders)} orders across {len(kitchen_groups)} kitchens" + ) + return await self._beatmap_route( + orders, kitchen_groups, order_to_delivery_loc, + start_lat, start_lon, _to_float, _normalize_dt + ) + + # 6. EXTRACT TIME WINDOWS (one per node, index 0 = depot/kitchen) + # -- Why here and not in the solver? ------------------------------- + # pickupSlot / pickuptime is an ORDER-level field that the TSP solver + # doesn't know about by itself. We convert them to minutes-from-now + # so OR-Tools can enforce delivery deadlines without external API calls. + # ------------------------------------------------------------------ + time_windows: Optional[_List[Tuple[int, int]]] = None + try: + from dateutil.parser import parse as _parse_dt + _now = datetime.now() + tw = [(0, 180)] # depot (kitchen): always open within 3-hour horizon + has_any_window = False + for order in orders: + slot = ( + order.get("pickupSlot") or order.get("pickupslot") + or order.get("pickuptime") or order.get("pickup_slot") + ) + if slot: + try: + t = _parse_dt(str(slot)) + # Earliest: rider shouldn't deliver before kitchen is ready + # Latest: food should be delivered within 45 min of ready + ready_min = max(0, int((t - _now).total_seconds() / 60)) + tw.append((0, ready_min + 45)) + has_any_window = True + except Exception: + tw.append((0, 180)) + else: + tw.append((0, 180)) + if has_any_window: + time_windows = tw + logger.debug(f"Time windows active for {sum(1 for w in tw if w[1] < 180)} orders") + except Exception as _twe: + logger.debug(f"Time window extraction skipped: {_twe}") + + # 6b. STEP ORDERING + # Prefer a road-aware visiting order (Google optimize:true) when enabled; + # it respects one-ways/turn restrictions that straight-line ordering can't. + # Fall back to aerial greedy nearest-neighbour + 2-opt (the default): greedy + # picks the closest unvisited stop, 2-opt removes crossing segments. Step + # metrics + ETA below stay aerial-based regardless, so the empirical ETA + # model (keyed on aerial buckets) remains valid. + optimized_order_indices = None + road_order = await self._road_optimal_order( + start_lat, start_lon, [locations[i] for i in range(1, len(locations))] + ) + if road_order is not None: + # road_order indexes into deliveries (0-based); solver index = wp + 1 + optimized_order_indices = [wp + 1 for wp in road_order] + else: + route_indices = self._solve_greedy(locations, aerial_matrix) + route_indices = self._two_opt_improve(route_indices, aerial_matrix) + optimized_order_indices = [i for i in route_indices if i != 0] + + # 7. BUILD RESULT + result = [] + cumulative_dist = 0.0 + cumulative_eta_min = 0 # total minutes from kitchen -> current delivery + prev_idx = 0 # starts at depot (kitchen / start location) + + for step_num, solver_idx in enumerate(optimized_order_indices, start=1): + order_idx = points_map[solver_idx - 1] + order = dict(orders[order_idx]) + + # Clean routing fields (will be recalculated) + for k in ("step", "previouskms", "cumulativekms", "eta", "actualkms", "ordertype"): + order.pop(k, None) + + # Normalize dates + for field in ["orderdate", "deliverytime", "created"]: + if field in order: + order[field] = _normalize_dt(order.get(field)) + + # Leg distance - aerial km (matches the ordering metric) + step_dist = float(aerial_matrix[prev_idx][solver_idx]) + cumulative_dist += step_dist + + # Step metadata + order["step"] = int(step_num) + order["previouskms"] = int(round(step_dist)) # Bug fix: was hardcoded 0 for step 1 + order["cumulativekms"] = int(round(cumulative_dist)) + + # actualkms = direct pickup-to-door distance (for billing) + plat, plon = start_lat, start_lon + if plat == 0: + plat, plon = ( + _to_float(order.get("pickuplat")), + _to_float(order.get("pickuplon") or order.get("pickuplong")), + ) + dlat, dlon = locations[solver_idx] + true_dist = self.haversine_distance(plat, plon, dlat, dlon) * 1.3 + + provided_kms = order.get("kms") + if provided_kms not in (None, "", 0, "0"): + try: + true_dist = float(provided_kms) + except: + pass + + order["actualkms"] = str(round(true_dist, 2)) + order["kms"] = str(provided_kms) if provided_kms else str(int(round(true_dist))) + + if "rider_charge" in order: + order["rider_charge"] = round(float(order["rider_charge"]), 2) + if "profit" in order: + order["profit"] = round(float(order["profit"]), 2) + + order["ordertype"] = ( + "Economy" if true_dist <= 5 + else "Premium" if true_dist <= 12 + else "Risky" + ) + + leg_eta = self.eta_calculator.calculate_eta( + distance_km=step_dist, + is_first_order=(step_num == 1), + order_type=order["ordertype"], + time_of_day=traffic, + kitchen=order.get("pickupcustomer") or order.get("locationname"), + drop_coords=(dlat, dlon), + rider_id=order.get("userid"), + ) + # -- CUMULATIVE ETA -------------------------------------------- + # `eta` = leg time from previous stop (legacy field, kept) + # `cumulative_eta` = total time from kitchen -> THIS delivery + # Customers should use cumulative_eta for "when does my food arrive" + # ------------------------------------------------------------- + cumulative_eta_min += leg_eta + order["eta"] = str(leg_eta) + order["cumulative_eta"] = str(cumulative_eta_min) + + result.append(order) + prev_idx = solver_idx + + return result + + # ------------------------------------------------------------------ + # Multi-kitchen beatmap helpers + # ------------------------------------------------------------------ + + def _group_by_kitchen(self, orders: _List[Dict], _to_float) -> Dict[tuple, _List[int]]: + """ + Group order indices by their kitchen (pickup) location. + Returns {(rounded_lat, rounded_lon): [order_idx, ...]} + Keys rounded to ~100 m so nearby pickup points merge into one kitchen. + """ + from collections import defaultdict + groups: Dict[tuple, _List[int]] = defaultdict(list) + for idx, order in enumerate(orders): + plat = _to_float(order.get("pickuplat")) + plon = _to_float(order.get("pickuplon") or order.get("pickuplong")) + if plat == 0 or plon == 0: + # No pickup coords - append to a special "no-kitchen" bucket + groups[("?", "?")].append(idx) + else: + key = (round(plat, 3), round(plon, 3)) + groups[key].append(idx) + return dict(groups) + + async def _beatmap_route( + self, + orders: _List[Dict], + kitchen_groups: Dict[tuple, _List[int]], + order_to_delivery_loc: Dict[int, tuple], + start_lat: float, + start_lon: float, + _to_float, + _normalize_dt, + ) -> _List[Dict]: + """ + Multi-kitchen beatmap: for each kitchen (nearest first) sequence the + deliveries by aerial nearest-neighbour, then concatenate. + + Sequencing: greedy nearest unvisited stop by straight-line km. + Riders handle U-turns; we just point them to the closest next drop. + + Flow: Kitchen A -> A1 -> A2 -> Kitchen B -> B1 -> B2 -> + Steps are numbered continuously across all kitchens. + """ + result: _List[Dict] = [] + global_step = 1 + cumulative_dist = 0.0 + cumulative_eta_min = 0 # total minutes from start -> current delivery + traffic = self.get_traffic_condition() + + # Separate kitchens with real coords from the no-kitchen bucket + real_kitchens = {k: v for k, v in kitchen_groups.items() if k[0] != "?"} + no_kitchen_indices = kitchen_groups.get(("?", "?"), []) + + # Visit kitchens: nearest to start first, then nearest to last delivery + remaining = list(real_kitchens.items()) + current_pos = (start_lat, start_lon) + + while remaining: + # Find nearest unvisited kitchen from current position + best_i = min( + range(len(remaining)), + key=lambda i: self.haversine_distance( + current_pos[0], current_pos[1], + remaining[i][0][0], remaining[i][0][1] + ), + ) + k_key, k_order_indices = remaining.pop(best_i) + k_lat, k_lon = float(k_key[0]), float(k_key[1]) + + # Build mini location list: kitchen at index 0, deliveries at 1..N + k_locs = [(k_lat, k_lon)] + k_idx_to_order = [] # k_solver_idx-1 -> original order idx + for order_idx in k_order_indices: + dlat, dlon = order_to_delivery_loc.get(order_idx, (0.0, 0.0)) + k_locs.append((dlat, dlon)) + k_idx_to_order.append(order_idx) + + # Pure aerial distance matrix for this kitchen group + k_lats = np.array([loc[0] for loc in k_locs]) + k_lons = np.array([loc[1] for loc in k_locs]) + k_aerial = calculate_haversine_matrix_vectorized(k_lats, k_lons) + + # Road-aware order for this kitchen's drops (opt-in, cached); + # else aerial greedy nearest-neighbour + 2-opt to remove crossings. + k_road = await self._road_optimal_order( + k_lat, k_lon, [k_locs[i] for i in range(1, len(k_locs))] + ) + if k_road is not None: + k_delivery_seq = [wp + 1 for wp in k_road] + else: + k_route = self._solve_greedy(k_locs, k_aerial) + k_route = self._two_opt_improve(k_route, k_aerial) + k_delivery_seq = [i for i in k_route if i != 0] + + k_prev_idx = 0 # start from kitchen + for k_solver_idx in k_delivery_seq: + order_idx = k_idx_to_order[k_solver_idx - 1] + order = dict(orders[order_idx]) + + # Clean routing fields + for fld in ("step", "previouskms", "cumulativekms", "eta", "actualkms", "ordertype"): + order.pop(fld, None) + for field in ["orderdate", "deliverytime", "created"]: + if field in order: + order[field] = _normalize_dt(order.get(field)) + + # Aerial leg distance (consistent with ordering metric) + step_dist = float(k_aerial[k_prev_idx][k_solver_idx]) + cumulative_dist += step_dist + + dlat, dlon = k_locs[k_solver_idx] + true_dist = self.haversine_distance(k_lat, k_lon, dlat, dlon) * 1.3 + provided_kms = order.get("kms") + if provided_kms not in (None, "", 0, "0"): + try: + true_dist = float(provided_kms) + except Exception: + pass + + order["step"] = global_step + order["previouskms"] = int(round(step_dist)) + order["cumulativekms"] = int(round(cumulative_dist)) + order["actualkms"] = str(round(true_dist, 2)) + order["kms"] = str(provided_kms) if provided_kms else str(int(round(true_dist))) + + if "rider_charge" in order: + order["rider_charge"] = round(float(order["rider_charge"]), 2) + if "profit" in order: + order["profit"] = round(float(order["profit"]), 2) + + order["ordertype"] = ( + "Economy" if true_dist <= 5 + else "Premium" if true_dist <= 12 + else "Risky" + ) + leg_eta = self.eta_calculator.calculate_eta( + distance_km=step_dist, + is_first_order=(global_step == 1), + order_type=order["ordertype"], + time_of_day=traffic, + kitchen=order.get("pickupcustomer") or order.get("locationname"), + drop_coords=(dlat, dlon), + rider_id=order.get("userid"), + ) + cumulative_eta_min += leg_eta + order["eta"] = str(leg_eta) + order["cumulative_eta"] = str(cumulative_eta_min) + + result.append(order) + k_prev_idx = k_solver_idx + global_step += 1 + + # Next kitchen search starts from the last delivery of this kitchen + if k_delivery_seq: + current_pos = k_locs[k_delivery_seq[-1]] + + # Append orders with no pickup coords at the end + for order_idx in no_kitchen_indices: + order = dict(orders[order_idx]) + for fld in ("step", "previouskms", "cumulativekms", "eta", "actualkms", "ordertype", "cumulative_eta"): + order.pop(fld, None) + order["step"] = global_step + order["previouskms"] = 0 + order["cumulativekms"] = int(round(cumulative_dist)) + order["actualkms"] = "0" + # Bug fix: kms was missing for no-kitchen orders; set it consistently + # with the normal path so downstream consumers always find the field. + provided_kms = order.get("kms") + order["kms"] = str(provided_kms) if provided_kms not in (None, "", 0, "0") else "0" + order["ordertype"] = "Economy" + order["eta"] = "15" + cumulative_eta_min += 15 + order["cumulative_eta"] = str(cumulative_eta_min) + result.append(order) + global_step += 1 + + return result + + diff --git a/app/services/routing/zone_service.py b/app/services/routing/zone_service.py new file mode 100644 index 0000000..83d5421 --- /dev/null +++ b/app/services/routing/zone_service.py @@ -0,0 +1,201 @@ + +import logging +from typing import List, Dict, Any + +logger = logging.getLogger(__name__) + +class ZoneService: + """ + Service to classify orders and riders into geographic zones. + Defaulting to Coimbatore logic as per user context. + """ + + # Approximate Center of Coimbatore (Gandhipuram/Bus Stand area) + CENTER_LAT = 11.0168 + CENTER_LON = 76.9558 + + def __init__(self): + pass + + def determine_zone(self, lat: float, lon: float) -> str: + """ + Determine the zone (North, South, East, West, etc.) based on coordinates. + """ + if lat == 0 or lon == 0: + return "Unknown" + + lat_diff = lat - self.CENTER_LAT + lon_diff = lon - self.CENTER_LON + + # Simple Quadrant Logic + # North: +Lat + # South: -Lat + # East: +Lon + # West: -Lon + + # Define a small central buffer (0.01 degrees ~ 1.1km) + buffer = 0.010 + + is_north = lat_diff > buffer + is_south = lat_diff < -buffer + is_east = lon_diff > buffer + is_west = lon_diff < -buffer + + zone_parts = [] + + if is_north: zone_parts.append("North") + elif is_south: zone_parts.append("South") + + if is_east: zone_parts.append("East") + elif is_west: zone_parts.append("West") + + if not zone_parts: + return "Central" + + return " ".join(zone_parts) + + def group_by_zones(self, flat_orders: List[Dict[str, Any]], unassigned_orders: List[Dict[str, Any]] = None, fuel_charge: float = 2.5, base_pay: float = 0.0) -> Dict[str, Any]: + """ + Group a flat list of optimized orders into Zones -> Riders -> Orders. + Calculates profit per order and per zone. + """ + zones_map = {} # "North East": { "riders": { rider_id: [orders] } } + unassigned_orders = unassigned_orders or [] + + # Merge both for initial processing if you want everything zoned + all_to_process = [] + for o in flat_orders: + all_to_process.append((o, True)) + for o in unassigned_orders: + all_to_process.append((o, False)) + + for order, is_assigned in all_to_process: + # 1. Extract Coords + try: + # Prefer Delivery location for zoning (where the customer is) + lat = float(order.get("deliverylat") or order.get("droplat") or 0) + lon = float(order.get("deliverylong") or order.get("droplon") or 0) + pincode = str(order.get("deliveryzip") or "") + except: + lat, lon, pincode = 0, 0, "" + + # 2. Get Zone + zone_name = self.determine_zone(lat, lon) + order["zone_name"] = zone_name + + # 3. Initialize Zone Bucket + if zone_name not in zones_map: + zones_map[zone_name] = { + "riders_map": {}, + "total_orders": 0, + "assigned_orders": 0, + "unassigned_orders": [], + "total_kms": 0.0, + "total_profit": 0.0 + } + + # 4. Add to Rider bucket within Zone + rider_id = order.get("userid") or order.get("_id") + + # Track kms and profit for this zone + try: + # 'actualkms' is preferred for delivery distance + dist = float(order.get("actualkms", order.get("previouskms", 0))) + zones_map[zone_name]["total_kms"] += dist + + # Individual charge for this order: Fixed Base + Variable Distance + order_amount = float(order.get("orderamount") or order.get("deliveryamount") or 0) + rider_payment = dist * fuel_charge + profit = order_amount - rider_payment + + order["rider_charge"] = round(rider_payment, 2) + order["profit"] = round(profit, 2) + + # ── PROFIT CLASS (separate from ordertype) ─────────────── + # `ordertype` is set by route_optimizer based on delivery + # DISTANCE (Economy ≤5km, Premium ≤12km, Risky >12km). + # Overwriting it here with a profit-based label broke ETA + # calculations and downstream routing logic. + # Use `profit_class` for profit-based analytics instead. + if profit <= 0: + order["profit_class"] = "Loss" + elif profit <= 5: + order["profit_class"] = "Marginal" + elif profit <= 10: + order["profit_class"] = "Profitable" + else: + order["profit_class"] = "HighMargin" + + zones_map[zone_name]["total_profit"] += profit + except: + pass + + # If strictly unassigned order (no rider), put in unassigned + if not is_assigned: + zones_map[zone_name]["unassigned_orders"].append(order) + else: + str_rid = str(rider_id) + if str_rid not in zones_map[zone_name]["riders_map"]: + zones_map[zone_name]["riders_map"][str_rid] = { + "rider_details": { + "id": str_rid, + "name": order.get("username", "Unknown") + }, + "orders": [] + } + zones_map[zone_name]["riders_map"][str_rid]["orders"].append(order) + zones_map[zone_name]["assigned_orders"] += 1 + + zones_map[zone_name]["total_orders"] += 1 + + # 5. Restructure for API Response + output_zones = [] + zone_metrics = [] + + sorted_zone_names = sorted(zones_map.keys()) + + for z_name in sorted_zone_names: + z_data = zones_map[z_name] + + # Flatten riders map + riders_list = [] + for r_id, r_data in z_data["riders_map"].items(): + riders_list.append({ + "rider_id": r_data["rider_details"]["id"], + "rider_name": r_data["rider_details"]["name"], + "orders_count": len(r_data["orders"]), + "orders": r_data["orders"] + }) + + # Create the flat metric summary + metrics = { + "zone_name": z_name, + "total_orders": z_data["total_orders"], + "assigned_orders": z_data["assigned_orders"], + "unassigned_orders_count": len(z_data["unassigned_orders"]), + "active_riders_count": len(riders_list), + "total_delivery_kms": round(z_data["total_kms"], 2), + "total_profit": round(z_data["total_profit"], 2) + } + + zone_metrics.append(metrics) + + # Create the detailed zone object with flattened metrics + zone_obj = { + "zone_name": z_name, + "total_orders": metrics["total_orders"], + "active_riders_count": metrics["active_riders_count"], + "assigned_orders": metrics["assigned_orders"], + "unassigned_orders_count": metrics["unassigned_orders_count"], + "total_delivery_kms": metrics["total_delivery_kms"], + "total_profit": metrics["total_profit"], + "riders": riders_list, + "unassigned_orders": z_data["unassigned_orders"] + } + + output_zones.append(zone_obj) + + return { + "detailed_zones": output_zones, + "zone_analysis": zone_metrics + } diff --git a/app/services/vector/__init__.py b/app/services/vector/__init__.py new file mode 100644 index 0000000..4af7a62 --- /dev/null +++ b/app/services/vector/__init__.py @@ -0,0 +1 @@ +"""Vector services package.""" diff --git a/app/services/vector/__pycache__/__init__.cpython-312.pyc b/app/services/vector/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..5cc7e3a Binary files /dev/null and b/app/services/vector/__pycache__/__init__.cpython-312.pyc differ diff --git a/app/services/vector/__pycache__/delivery_history_store.cpython-312.pyc b/app/services/vector/__pycache__/delivery_history_store.cpython-312.pyc new file mode 100644 index 0000000..b184cb3 Binary files /dev/null and b/app/services/vector/__pycache__/delivery_history_store.cpython-312.pyc differ diff --git a/app/services/vector/__pycache__/faiss_customer_store.cpython-312.pyc b/app/services/vector/__pycache__/faiss_customer_store.cpython-312.pyc new file mode 100644 index 0000000..54edbe4 Binary files /dev/null and b/app/services/vector/__pycache__/faiss_customer_store.cpython-312.pyc differ diff --git a/app/services/vector/delivery_history_store.py b/app/services/vector/delivery_history_store.py new file mode 100644 index 0000000..0a6519d --- /dev/null +++ b/app/services/vector/delivery_history_store.py @@ -0,0 +1,766 @@ +""" +Delivery History Store +====================== +Pattern-first vector rider lookup using 30-day delivery history. +Works on any platform — no faiss-cpu dependency. + +How it works +------------ +At startup the CSV is parsed once and two structures are built: + + 1. PATTERN TABLE (primary, O(1) lookup) + City divided into ~1.1 km grid cells (round coords to 2 d.p.). + For every (kitchen, zone_cell) pair we count how many times each + rider delivered there. A "clear pattern" = one rider owns ≥ 60 % + of all deliveries in that cell AND ≥ 3 total deliveries. + + From the 3 500-row CSV: + • 177 unique (kitchen, zone) cells + • 121 clear dominant-rider patterns (68 %) + • 42 cells where 1 rider owns 100 % + + 2. VECTOR INDEX (fallback, ~0.5 ms) + Pure-NumPy brute-force L2 search over 4D vectors: + [pickuplat, pickuplon, deliverylat, deliverylong] + Used ONLY when the pattern table has no clear answer. + If faiss-cpu is installed it is used instead of NumPy (faster + for very large indexes), but NumPy is the default. + +Disk persistence +---------------- + ml_data/faiss_history/ + delivery_history_vectors.npy – float32 (N, 4) array + delivery_history_records.pkl – list of record dicts + delivery_history.meta – JSON: csv_mtime, counts + +Priority chain in the assignment endpoint: + 1. Pattern table (dominant rider for this kitchen + delivery zone) + 2. Vector K-NN (nearest-neighbour vote, fallback for new areas) + 3. rider_preferences.py hard lock + 4. VRP proximity solver +""" + +import csv +import json +import logging +import os +import pickle +from collections import Counter, defaultdict +from threading import Lock +from typing import Any, Dict, List, Optional, Tuple + +import numpy as np + +logger = logging.getLogger(__name__) + +# --------------------------------------------------------------------------- +# Paths +# --------------------------------------------------------------------------- +CSV_PATH = os.getenv("DELIVERY_HISTORY_CSV", "delivery_details.csv") +CORRECTIONS_PATH = os.getenv("DELIVERY_CORRECTIONS_CSV", "delivery_corrections.csv") + +# Each correction record is already written N times in the corrections CSV +# (currently 5× per unique delivery) so they naturally outweigh noisy history. +# Setting CORRECTION_WEIGHT > 1 here adds a further runtime multiplier on top. +_CORRECTION_WEIGHT = int(os.getenv("CORRECTION_WEIGHT", "1")) + +_STORE_DIR = os.getenv("FAISS_HISTORY_DIR", "ml_data/faiss_history") +_VECTORS_PATH = os.path.join(_STORE_DIR, "delivery_history_vectors.npy") +_RECORDS_PATH = os.path.join(_STORE_DIR, "delivery_history_records.pkl") +_META_PATH = os.path.join(_STORE_DIR, "delivery_history.meta") + +# --------------------------------------------------------------------------- +# Thresholds +# --------------------------------------------------------------------------- +_K_NEIGHBORS = 15 +_MIN_KNN_CONFIDENCE = 0.50 # vector fallback: top rider wins ≥ 50 % of votes +_MIN_PATTERN_DOMINANCE = 0.60 # pattern table: rider owns ≥ 60 % of zone +_MIN_PATTERN_VOLUME = 3 # pattern table: at least 3 deliveries in zone + + +# --------------------------------------------------------------------------- +# Pure-NumPy L2 index — drop-in replacement for faiss.IndexFlatL2 +# --------------------------------------------------------------------------- + +class _NumpyL2Index: + """ + Brute-force L2 nearest-neighbour search using NumPy. + Same interface as faiss.IndexFlatL2 so both paths share one code. + For 3 000–5 000 vectors each query takes < 1 ms — fast enough. + """ + + def __init__(self, d: int): + self.d = d + self.ntotal = 0 + self._vecs: Optional[np.ndarray] = None # shape (N, d) float32 + + def add(self, vectors: np.ndarray) -> None: + self._vecs = vectors.astype(np.float32) + self.ntotal = len(self._vecs) + + def search(self, query: np.ndarray, k: int) -> Tuple[np.ndarray, np.ndarray]: + """Return (distances, indices) shaped (1, k), same as faiss.""" + if self._vecs is None or self.ntotal == 0: + return (np.array([[]], dtype=np.float32), + np.array([[-1]], dtype=np.int64)) + + q = query.astype(np.float32) # (1, d) + diff = self._vecs - q # (N, d) broadcasting + sq_dists = np.einsum("ij,ij->i", diff, diff) # (N,) squared L2 + + actual_k = min(k, self.ntotal) + if actual_k < self.ntotal: + part = np.argpartition(sq_dists, actual_k)[:actual_k] + top_idxs = part[np.argsort(sq_dists[part])] + else: + top_idxs = np.argsort(sq_dists) + + return (sq_dists[top_idxs].reshape(1, -1), + top_idxs.reshape(1, -1).astype(np.int64)) + + +def _build_index(vectors: np.ndarray) -> Any: + """ + Build the best available index for the given float32 vector array. + Tries faiss first; falls back to NumPy silently. + """ + try: + import faiss as _faiss + idx = _faiss.IndexFlatL2(vectors.shape[1]) + idx.add(vectors) + logger.info("[DeliveryHistory] Using faiss-cpu index.") + return idx + except Exception: + idx = _NumpyL2Index(vectors.shape[1]) + idx.add(vectors) + logger.info("[DeliveryHistory] Using NumPy L2 index (faiss-cpu not available).") + return idx + + +# --------------------------------------------------------------------------- +# Main store +# --------------------------------------------------------------------------- + +class DeliveryHistoryStore: + """ + Pattern-first, vector-fallback rider lookup. + + Public API + ---------- + store.find_rider(kitchen, plat, plon, dlat, dlon) -> dict | None + store.record_count() -> int + store.pattern_count() -> int + store.get_pattern_stats() -> list + store.reload_from_csv() -> int + """ + + def __init__(self): + self._lock = Lock() + self._records: List[Dict] = [] + self._index = None + + # Pattern table: (kitchen_lower, zone_lat, zone_lon) → pattern dict + self._patterns: Dict[Tuple, Dict] = {} + + # Zone index: (zone_lat, zone_lon) → [pattern keys at that cell] + self._zone_index: Dict[Tuple, List[Tuple]] = defaultdict(list) + + self._load() + + # ------------------------------------------------------------------ + # Startup + # ------------------------------------------------------------------ + + def _load(self) -> None: + os.makedirs(_STORE_DIR, exist_ok=True) + + if self._saved_files_are_current(): + if self._load_from_disk(): + return + logger.warning( + "[DeliveryHistory] Saved files corrupt — rebuilding from CSV." + ) + + records = self._parse_csv() + if not records: + return + self._build_and_save(records) + + def _saved_files_are_current(self) -> bool: + for path in (_VECTORS_PATH, _RECORDS_PATH, _META_PATH): + if not os.path.isfile(path): + return False + try: + with open(_META_PATH, "r", encoding="utf-8") as f: + meta = json.load(f) + if not os.path.isfile(CSV_PATH): + return True + return abs(os.path.getmtime(CSV_PATH) - meta.get("csv_mtime", 0)) < 1.0 + except Exception: + return False + + def _load_from_disk(self) -> bool: + try: + vectors = np.load(_VECTORS_PATH) # (N, 4) float32 + with open(_RECORDS_PATH, "rb") as f: + records = pickle.load(f) + + if not records or len(vectors) != len(records): + return False + + index = _build_index(vectors) + patterns, zone_index = self._compute_patterns(records) + + with self._lock: + self._records = records + self._index = index + self._patterns = patterns + self._zone_index = zone_index + + clear = sum( + 1 for p in patterns.values() + if p["dominance"] >= _MIN_PATTERN_DOMINANCE + and p["total_deliveries"] >= _MIN_PATTERN_VOLUME + ) + logger.info( + f"[DeliveryHistory] Loaded {len(records)} records from disk. " + f"Pattern table: {len(patterns)} zones, {clear} with clear dominant rider." + ) + return True + except Exception as e: + logger.warning(f"[DeliveryHistory] Disk load failed: {e}") + return False + + def _parse_csv_file(self, path: str, label: str = "CSV") -> List[Dict]: + """Parse any delivery CSV (main history or corrections) into records list.""" + records: List[Dict] = [] + for encoding in ("utf-8", "latin-1", "cp1252"): + try: + with open(path, newline="", encoding=encoding) as fh: + for row in csv.DictReader(fh): + try: + plat = float(row.get("pickuplat") or 0) + plon = float(row.get("pickuplon") or 0) + dlat = float(row.get("deliverylat") or 0) + dlon = float(row.get("deliverylong") or 0) + uid = int(float(row.get("userid") or 0)) + if not plat or not dlat or uid == 0: + continue + # Skip rows where the delivery destination IS a kitchen + dcust = (row.get("deliverycustomer") or "").strip().lower() + if "kitchen" in dcust or "selvarani" in dcust: + continue + records.append({ + "kitchen": (row.get("pickupcustomer") or "").strip().lower(), + "pickuplat": plat, "pickuplon": plon, + "deliverylat": dlat, "deliverylong": dlon, + "userid": uid, + "ridername": (row.get("ridername") or "").strip(), + }) + except Exception: + continue + break + except (UnicodeDecodeError, FileNotFoundError) as e: + if isinstance(e, FileNotFoundError): + logger.warning(f"[DeliveryHistory] {label} not found at '{path}'.") + return [] + records = [] + + if records: + logger.info(f"[DeliveryHistory] Parsed {len(records)} rows from {label} '{path}'.") + else: + logger.warning(f"[DeliveryHistory] {label} at '{path}' contained no valid rows.") + return records + + def _parse_csv(self) -> List[Dict]: + """Parse main history CSV, then merge manually-corrected records on top.""" + main_records = self._parse_csv_file(CSV_PATH, label="Main CSV") + if not main_records: + return [] + + # Load manually-corrected assignments and merge with runtime weight multiplier + if os.path.isfile(CORRECTIONS_PATH): + corr = self._parse_csv_file(CORRECTIONS_PATH, label="Corrections CSV") + if corr: + weighted = corr * _CORRECTION_WEIGHT # extra amplification if configured + main_records = main_records + weighted + logger.info( + f"[DeliveryHistory] Merged {len(corr)} correction rows " + f"(×{_CORRECTION_WEIGHT} weight) into {len(main_records)} total records." + ) + else: + logger.debug( + f"[DeliveryHistory] No corrections file at '{CORRECTIONS_PATH}' — " + "using main CSV only." + ) + + return main_records + + def _compute_patterns( + self, records: List[Dict] + ) -> Tuple[Dict, Dict]: + """ + Build pattern table from records. + + Pattern dict keys + ----------------- + userid, ridername, dominance, total_deliveries, + top_deliveries, pattern_score, all_riders + """ + zone_counts: Dict[Tuple, Dict[int, int]] = defaultdict(lambda: defaultdict(int)) + zone_names: Dict[Tuple, Dict[int, str]] = defaultdict(lambda: defaultdict(str)) + + for rec in records: + key = (rec["kitchen"], + round(rec["deliverylat"], 2), + round(rec["deliverylong"], 2)) + zone_counts[key][rec["userid"]] += 1 + zone_names[key][rec["userid"]] = rec["ridername"] + + patterns: Dict[Tuple, Dict] = {} + zone_index: Dict[Tuple, List[Tuple]] = defaultdict(list) + + for key, rider_counts in zone_counts.items(): + kitchen, zone_lat, zone_lon = key + total = sum(rider_counts.values()) + top_rid = max(rider_counts, key=rider_counts.get) + top_count = rider_counts[top_rid] + dominance = top_count / total + # Penalise thin data: full score only at ≥ 5 deliveries + pattern_score = dominance * min(1.0, total / 5.0) + + patterns[key] = { + "userid": top_rid, + "ridername": zone_names[key].get(top_rid, ""), + "dominance": round(dominance, 4), + "total_deliveries": total, + "top_deliveries": top_count, + "pattern_score": round(pattern_score, 4), + "all_riders": dict(rider_counts), + } + zone_index[(zone_lat, zone_lon)].append(key) + + return patterns, zone_index + + def _build_and_save(self, records: List[Dict]) -> None: + vectors = np.array( + [[r["pickuplat"], r["pickuplon"], r["deliverylat"], r["deliverylong"]] + for r in records], + dtype=np.float32, + ) + index = _build_index(vectors) + patterns, zone_index = self._compute_patterns(records) + + with self._lock: + self._records = records + self._index = index + self._patterns = patterns + self._zone_index = zone_index + + clear = sum( + 1 for p in patterns.values() + if p["dominance"] >= _MIN_PATTERN_DOMINANCE + and p["total_deliveries"] >= _MIN_PATTERN_VOLUME + ) + sole = sum( + 1 for p in patterns.values() + if p["dominance"] == 1.0 + and p["total_deliveries"] >= _MIN_PATTERN_VOLUME + ) + logger.info( + f"[DeliveryHistory] Pattern table: {len(patterns)} zones, " + f"{clear} clear patterns (≥60% dominance), {sole} sole-owner zones." + ) + + try: + np.save(_VECTORS_PATH, vectors) + with open(_RECORDS_PATH, "wb") as f: + pickle.dump(records, f, protocol=pickle.HIGHEST_PROTOCOL) + csv_mtime = os.path.getmtime(CSV_PATH) if os.path.isfile(CSV_PATH) else 0 + with open(_META_PATH, "w", encoding="utf-8") as f: + json.dump({ + "csv_mtime": csv_mtime, + "record_count": len(records), + "pattern_zones": len(patterns), + "clear_patterns": clear, + }, f, indent=2) + logger.info( + f"[DeliveryHistory] Saved to '{_STORE_DIR}'. " + "Next startup loads from disk." + ) + except Exception as e: + logger.warning( + f"[DeliveryHistory] Could not save to disk (non-fatal): {e}" + ) + + # ------------------------------------------------------------------ + # Public API + # ------------------------------------------------------------------ + + def find_rider( + self, + kitchen_name: str, + pickup_lat: float, + pickup_lon: float, + delivery_lat: float, + delivery_lon: float, + k: int = _K_NEIGHBORS, + min_confidence: float = _MIN_KNN_CONFIDENCE, + ) -> Optional[Dict[str, Any]]: + """ + Return the best historical rider, or None. + + Step 1 — pattern table (O(1)): + Clear dominant rider for this kitchen + 1.1 km delivery zone. + + Step 2 — vector K-NN (fallback): + Brute-force 4D search, kitchen-filtered vote. + + Return keys: userid, ridername, confidence, match_count, top_votes, source + """ + if not delivery_lat: + return None + + kitchen_lower = (kitchen_name or "").strip().lower() + + result = self._pattern_lookup(kitchen_lower, delivery_lat, delivery_lon) + if result: + return result + + if self._index is None or not self._records: + return None + if not pickup_lat: + return None + + return self._vector_knn( + kitchen_lower, pickup_lat, pickup_lon, + delivery_lat, delivery_lon, k, min_confidence + ) + + def _pattern_lookup( + self, + kitchen_lower: str, + delivery_lat: float, + delivery_lon: float, + ) -> Optional[Dict[str, Any]]: + zone_pos = (round(delivery_lat, 2), round(delivery_lon, 2)) + + with self._lock: + candidate_keys = self._zone_index.get(zone_pos, []) + + best_pattern = None + best_score = -1.0 + + for key in candidate_keys: + key_kitchen = key[0] + if kitchen_lower and key_kitchen: + if (kitchen_lower not in key_kitchen + and key_kitchen not in kitchen_lower): + continue + + with self._lock: + pat = self._patterns.get(key) + if not pat: + continue + + if (pat["dominance"] >= _MIN_PATTERN_DOMINANCE + and pat["total_deliveries"] >= _MIN_PATTERN_VOLUME + and pat["pattern_score"] > best_score): + best_pattern = pat + best_score = pat["pattern_score"] + + if not best_pattern: + return None + + return { + "userid": best_pattern["userid"], + "ridername": best_pattern["ridername"], + "confidence": best_pattern["dominance"], + "match_count": best_pattern["total_deliveries"], + "top_votes": best_pattern["top_deliveries"], + "source": "pattern", + } + + def _vector_knn( + self, + kitchen_lower: str, + pickup_lat: float, + pickup_lon: float, + delivery_lat: float, + delivery_lon: float, + k: int, + min_confidence: float, + ) -> Optional[Dict[str, Any]]: + with self._lock: + query = np.array( + [[pickup_lat, pickup_lon, delivery_lat, delivery_lon]], + dtype=np.float32, + ) + actual_k = min(k, len(self._records)) + _, indices = self._index.search(query, actual_k) + + matched: List[Dict] = [] + for idx in indices[0]: + idx = int(idx) + if idx < 0 or idx >= len(self._records): + continue + rec = self._records[idx] + if kitchen_lower and rec["kitchen"]: + if (kitchen_lower not in rec["kitchen"] + and rec["kitchen"] not in kitchen_lower): + continue + matched.append(rec) + + if not matched: + return None + + votes = Counter(rec["userid"] for rec in matched) + top_uid, top_count = votes.most_common(1)[0] + confidence = top_count / len(matched) + + if confidence < min_confidence: + return None + + ridername = next( + (r["ridername"] for r in matched if r["userid"] == top_uid), "" + ) + return { + "userid": top_uid, + "ridername": ridername, + "confidence": round(confidence, 3), + "match_count": len(matched), + "top_votes": top_count, + "source": "vector_knn", + } + + # ------------------------------------------------------------------ + # Analytics + # ------------------------------------------------------------------ + + def record_count(self) -> int: + return len(self._records) + + def pattern_count(self) -> int: + return sum( + 1 for p in self._patterns.values() + if p["dominance"] >= _MIN_PATTERN_DOMINANCE + and p["total_deliveries"] >= _MIN_PATTERN_VOLUME + ) + + def get_pattern_stats(self) -> List[Dict]: + stats = [] + with self._lock: + for (kitchen, zlat, zlon), pat in self._patterns.items(): + if (pat["dominance"] < _MIN_PATTERN_DOMINANCE + or pat["total_deliveries"] < _MIN_PATTERN_VOLUME): + continue + stats.append({ + "kitchen": kitchen, + "zone_lat": zlat, + "zone_lon": zlon, + "userid": pat["userid"], + "ridername": pat["ridername"], + "dominance": pat["dominance"], + "total_deliveries": pat["total_deliveries"], + "top_deliveries": pat["top_deliveries"], + "pattern_score": pat["pattern_score"], + "all_riders": pat["all_riders"], + }) + return sorted(stats, key=lambda x: x["pattern_score"], reverse=True) + + # ------------------------------------------------------------------ + # Rider Efficiency Scores + # ------------------------------------------------------------------ + + def get_rider_efficiency_scores(self) -> Dict[int, Dict]: + """ + Compute a per-rider efficiency score from the 30-day CSV history. + + Metrics per rider + ----------------- + delivery_count — total deliveries in CSV + avg_km — average Haversine distance (pickup → delivery) + unique_zones — number of distinct 1.1 km delivery cells covered + efficiency_score — normalised 0..1 composite score: + more deliveries × lower avg km × more zones = higher score + + A rider who completes many deliveries efficiently across many zones + scores highest. Used as a tiebreaker during solo consolidation + and Phase-0 host selection. + """ + from math import radians, cos, sin, asin, sqrt as _sqrt + + def _hav(la1, lo1, la2, lo2): + try: + la1, lo1, la2, lo2 = map(radians, [la1, lo1, la2, lo2]) + a = sin((la2-la1)/2)**2 + cos(la1)*cos(la2)*sin((lo2-lo1)/2)**2 + return 2 * asin(min(1.0, _sqrt(a))) * 6371.0 + except Exception: + return 0.0 + + with self._lock: + records = list(self._records) # snapshot under lock + + if not records: + return {} + + stats: Dict[int, Dict] = {} + for rec in records: + uid = rec["userid"] + km = _hav(rec["pickuplat"], rec["pickuplon"], + rec["deliverylat"], rec["deliverylong"]) + zone = (round(rec["deliverylat"], 2), round(rec["deliverylong"], 2)) + + if uid not in stats: + stats[uid] = { + "ridername": rec["ridername"], + "delivery_count": 0, + "total_km": 0.0, + "zones": set(), + } + s = stats[uid] + s["delivery_count"] += 1 + s["total_km"] += km + s["zones"].add(zone) + + # Build scores + result: Dict[int, Dict] = {} + raw_scores: Dict[int, float] = {} + + for uid, s in stats.items(): + n = s["delivery_count"] + avg_km = s["total_km"] / n if n else 0.0 + zone_count = len(s["zones"]) + # Raw: many deliveries, low km per delivery, wide zone coverage + raw = n / (1.0 + avg_km) * (1.0 + zone_count ** 0.5) + raw_scores[uid] = raw + result[uid] = { + "ridername": s["ridername"], + "delivery_count": n, + "avg_km": round(avg_km, 2), + "unique_zones": zone_count, + } + + # Normalise 0..1 + max_raw = max(raw_scores.values()) if raw_scores else 1.0 + for uid in result: + result[uid]["efficiency_score"] = round( + raw_scores[uid] / max_raw, 4 + ) + + return result + + def get_rider_score(self, rider_id: int) -> float: + """Convenience: return a single rider's efficiency_score (0..1), or 0.5 if unknown.""" + scores = self.get_rider_efficiency_scores() + return scores.get(rider_id, {}).get("efficiency_score", 0.5) + + # ------------------------------------------------------------------ + # Reload + # ------------------------------------------------------------------ + + def reload_from_csv(self) -> int: + """Rebuild index from main CSV + corrections (if present).""" + logger.info("[DeliveryHistory] Force-reload from CSV requested.") + records = self._parse_csv() # already merges corrections internally + if not records: + return 0 + self._build_and_save(records) + return len(records) + + def inject_corrections(self, corrections_path: str = CORRECTIONS_PATH, + weight: int = 5) -> Dict: + """ + Hot-inject a correction CSV into the live store without a full CSV reload. + + Each row in the corrections file is counted `weight` times so manually + verified assignments quickly dominate the pattern table for those zones. + + Returns a summary dict with old/new record counts and pattern changes. + """ + if not os.path.isfile(corrections_path): + raise FileNotFoundError(f"Corrections file not found: {corrections_path}") + + corr = self._parse_csv_file(corrections_path, label="Corrections") + if not corr: + return {"status": "error", "message": "No valid rows in corrections file."} + + weighted = corr * weight + + with self._lock: + old_count = len(self._records) + # Remove any existing correction rows for the same zones to avoid + # double-injection (identify by source: corrections have no + # "source" field — we use a tag approach). + # Simplest safe approach: just append (first inject from scratch). + merged = list(self._records) + weighted + + patterns, zone_index = self._compute_patterns(merged) + old_clear = sum( + 1 for p in self._patterns.values() + if p["dominance"] >= _MIN_PATTERN_DOMINANCE + and p["total_deliveries"] >= _MIN_PATTERN_VOLUME + ) + new_clear = sum( + 1 for p in patterns.values() + if p["dominance"] >= _MIN_PATTERN_DOMINANCE + and p["total_deliveries"] >= _MIN_PATTERN_VOLUME + ) + + vectors = np.array( + [[r["pickuplat"], r["pickuplon"], r["deliverylat"], r["deliverylong"]] + for r in merged], + dtype=np.float32, + ) + index = _build_index(vectors) + + with self._lock: + self._records = merged + self._index = index + self._patterns = patterns + self._zone_index = zone_index + + # Save to disk so next restart includes corrections + try: + np.save(_VECTORS_PATH, vectors) + with open(_RECORDS_PATH, "wb") as f: + pickle.dump(merged, f) + csv_mtime = os.path.getmtime(CSV_PATH) if os.path.isfile(CSV_PATH) else 0 + with open(_META_PATH, "w", encoding="utf-8") as f: + json.dump({"csv_mtime": csv_mtime, "record_count": len(merged), + "pattern_count": len(patterns)}, f) + logger.info( + f"[DeliveryHistory] Corrections injected and saved — " + f"records: {old_count} → {len(merged)}, " + f"clear patterns: {old_clear} → {new_clear}" + ) + except Exception as e: + logger.warning(f"[DeliveryHistory] Save after inject failed: {e}") + + return { + "status": "ok", + "unique_corrections": len(corr), + "weight": weight, + "records_before": old_count, + "records_after": len(merged), + "clear_patterns_before": old_clear, + "clear_patterns_after": new_clear, + "zones_total": len(patterns), + } + + +# ------------------------------------------------------------------ +# Module-level singleton +# ------------------------------------------------------------------ + +_store: Optional[DeliveryHistoryStore] = None +_store_lock: Lock = Lock() + + +def get_delivery_history_store() -> DeliveryHistoryStore: + global _store + if _store is None: + with _store_lock: + if _store is None: + _store = DeliveryHistoryStore() + return _store diff --git a/app/services/vector/faiss_customer_store.py b/app/services/vector/faiss_customer_store.py new file mode 100644 index 0000000..d56904e --- /dev/null +++ b/app/services/vector/faiss_customer_store.py @@ -0,0 +1,182 @@ +""" +Customer coordinate store. + +Purpose: + For each incoming order, look up the customer's phone number. + If a previous verified delivery exists (rider coords on file), use those + coords instead of the (possibly noisy) input delivery coords. + If no record exists, create one so future calls benefit from it. + +Storage: + Pure dict + JSON — no FAISS dependency. + phone_meta.json maps phone -> {name, rider_lat, rider_lon}. + Coord lookup key is phone number, not coordinates, so vector search + was never needed; FAISS has been removed. +""" + +import os +import json +import logging +from math import radians, cos, sin, asin, sqrt +from threading import Lock + +logger = logging.getLogger(__name__) + +STORE_DIR = os.getenv("CUSTOMER_STORE_DIR", "ml_data/faiss_customer") +META_PATH = os.path.join(STORE_DIR, "phone_meta.json") + +# Within this distance the stored rider coords are considered the real delivery point +SIMILARITY_THRESHOLD_KM = float(os.getenv("FAISS_SIMILARITY_KM", "0.5")) + + +def _haversine(lat1: float, lon1: float, lat2: float, lon2: float) -> float: + """Great-circle distance in km.""" + try: + lon1, lat1, lon2, lat2 = map(radians, [float(lon1), float(lat1), float(lon2), float(lat2)]) + dlon = lon2 - lon1 + dlat = lat2 - lat1 + a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2 + return 2 * asin(min(1.0, sqrt(a))) * 6371 + except Exception: + return float("inf") + + +class CustomerCoordStore: + """ + Thread-safe customer delivery coordinate store (dict + JSON backend). + + Primary flow (called per order before assignment): + verified_lat, verified_lon, corrected = store.get_verified_coords( + phone, customer_name, input_lat, input_lon + ) + """ + + def __init__(self): + self._lock = Lock() + os.makedirs(STORE_DIR, exist_ok=True) + self._meta: dict = {} # phone -> {name, rider_lat, rider_lon} + self._load() + + # ------------------------------------------------------------------ + # Persistence + # ------------------------------------------------------------------ + + def _load(self): + if os.path.exists(META_PATH): + try: + with open(META_PATH, "r", encoding="utf-8") as f: + self._meta = json.load(f) + logger.info(f"[CustomerStore] Loaded {len(self._meta)} customer records.") + except Exception as e: + logger.warning(f"[CustomerStore] Could not load {META_PATH}: {e} — starting fresh.") + self._meta = {} + else: + self._meta = {} + logger.info("[CustomerStore] No existing store found — starting fresh.") + + def _save(self): + try: + with open(META_PATH, "w", encoding="utf-8") as f: + json.dump(self._meta, f, indent=2) + except Exception as e: + logger.warning(f"[CustomerStore] Save failed: {e}") + + # ------------------------------------------------------------------ + # Public API + # ------------------------------------------------------------------ + + def get_verified_coords( + self, + phone: str, + customer_name: str, + input_lat: float, + input_lon: float, + ) -> tuple: + """ + Verify / correct delivery coordinates using stored history. + + Returns: + (lat, lon, was_corrected) + was_corrected=True → coords replaced with verified stored coords + was_corrected=False → input coords used (new customer or new location) + """ + if not phone or not input_lat or not input_lon: + return input_lat, input_lon, False + + phone = str(phone).strip() + + with self._lock: + record = self._meta.get(phone) + + if record: + stored_lat = record["rider_lat"] + stored_lon = record["rider_lon"] + dist_km = _haversine(stored_lat, stored_lon, input_lat, input_lon) + + if dist_km <= SIMILARITY_THRESHOLD_KM: + # Stored rider coords match input → they represent the real door + logger.info( + f"[CustomerStore] {phone}: verified coords used " + f"(stored↔input dist={dist_km:.3f}km, within {SIMILARITY_THRESHOLD_KM}km)" + ) + return stored_lat, stored_lon, True + else: + # Customer location changed significantly, trust new input + logger.info( + f"[CustomerStore] {phone}: location changed " + f"(dist={dist_km:.3f}km > {SIMILARITY_THRESHOLD_KM}km), using input coords" + ) + return input_lat, input_lon, False + else: + # New customer — create record with input coords + self._create_record(phone, customer_name, input_lat, input_lon) + logger.info(f"[CustomerStore] {phone}: new record created ({input_lat}, {input_lon})") + return input_lat, input_lon, False + + def update_rider_coords(self, phone: str, rider_lat: float, rider_lon: float): + """ + Called when a delivery is confirmed to update with actual rider GPS. + This is what makes stored coords progressively more accurate. + """ + phone = str(phone).strip() + with self._lock: + if phone in self._meta: + record = self._meta[phone] + record["rider_lat"] = rider_lat + record["rider_lon"] = rider_lon + self._save() + logger.info(f"[CustomerStore] {phone}: rider coords updated ({rider_lat}, {rider_lon})") + + def record_count(self) -> int: + return len(self._meta) + + # ------------------------------------------------------------------ + # Internal helpers + # ------------------------------------------------------------------ + + def _create_record(self, phone: str, name: str, lat: float, lon: float): + self._meta[phone] = { + "name": name, + "rider_lat": lat, + "rider_lon": lon, + } + self._save() + + +# Singleton — keep old name for backward compatibility with any imports +_store_instance: "CustomerCoordStore | None" = None +_store_lock = Lock() + + +def get_faiss_store() -> CustomerCoordStore: + """Returns the singleton CustomerCoordStore (backward-compat name).""" + global _store_instance + if _store_instance is None: + with _store_lock: + if _store_instance is None: + _store_instance = CustomerCoordStore() + return _store_instance + + +# Also expose under new name +get_customer_store = get_faiss_store diff --git a/app/templates/ml_dashboard.html b/app/templates/ml_dashboard.html new file mode 100644 index 0000000..b30f3c9 --- /dev/null +++ b/app/templates/ml_dashboard.html @@ -0,0 +1,1522 @@ + + + + + + + MILETRUTH — Logistics Intelligence + + + + + + + + +
+ +
+
+ CONNECTING +
+ + + + +
+
+ +
+ + +
+
+
Training Records
+
+
+
+
+
Avg Quality (last 50)
+
+
+
+
+
Model Trust
+
+
+
+
+
R² Score
+
+
Prediction accuracy
+
+
+
MAE
+
+
Avg prediction error (pts)
+
+
+
ML-Tuned Params
+
+
+
+
+
SLA Breaches
+
+
Recent window
+
+
+
Avg Latency
+
+
Assignment call (ms)
+
+
+ + + +
+
+
+ Quality Trend — last 50 calls + LIVE +
+
+
+
+
Active Hyperparameters
+
+
+ Loading params...
+
+
+
+ + + +
+
+
Feature Importance
+
+
+
+
+ Strategy Mode + +
+
+ +
+
+
Multi-Objective Pareto
+
+
+
+
+
+ ID3 Behavior Rules + 0 rules +
+
+
+ Waiting for trained tree...
+
+
+
+ + + +
+
+
Quality Heatmap — by Hour
+
+
+
+
Quality Distribution
+
+
+
+
Strategy Comparison
+
+ + + + + + + + + + + + + + + +
StrategyCallsAvg QUnassignedAvg km
Loading... +
+
+
+
+ + + +
+
+
Zone Performance
+
+ + + + + + + + + + + + + + + +
ZoneCallsAvg QSLA BreachesAvg km
Loading... +
+
+
+
+
Top Optuna Trials
+
+ + + + + + + + + + + + + +
#Predicted QKey Params
Run retrain + to see trials
+
+
+
+
Model Health Audit
+
+
+ Train the model to see audit data
+
+
+
+ + + +
+
+
Unassigned Orders — Recent Calls
+
+
+
+
Assignment Latency (ms)
+
+
+
+ + +
+ + +
+ +
+ +
+ + + + + \ No newline at end of file diff --git a/data/snapshots/route_1780481192.parquet b/data/snapshots/route_1780481192.parquet new file mode 100644 index 0000000..4b329af Binary files /dev/null and b/data/snapshots/route_1780481192.parquet differ diff --git a/delivery_corrections.csv b/delivery_corrections.csv new file mode 100644 index 0000000..834e0c8 --- /dev/null +++ b/delivery_corrections.csv @@ -0,0 +1,546 @@ +pickupcustomer,pickuplat,pickuplon,deliverylat,deliverylong,userid,ridername +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.9450125,76.9696719,1036,Vignesh S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.94669601,76.95759796,1036,Vignesh S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.9887125,76.9470469,1036,Vignesh S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.9931375,76.9305156,1036,Vignesh S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.1015,76.9907,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.1020098,76.9911354,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.1022,77.0328,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.06662342,77.03174932,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.0568241,77.0117323,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.0583375,76.9869531,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.04665266,76.97522061,950,Jayasabesh Kumar S +Vidhya kitchen,11.0163268,77.0147763,11.01962586,76.97291096,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.01067171,76.97995486,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.0105,76.98,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.01136931,76.98546701,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.01912568,76.99127706,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.02609076,76.99829646,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.0315832,77.0005771,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.05688855,77.01173596,1114,Tamilazhagan K +Vidhya kitchen,11.0163268,77.0147763,11.0251802,77.0198024,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.0241383,77.0184563,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.0207363,77.0220709,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.01933791,77.02415225,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.01976096,77.02560246,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,10.99833125,77.04464503,753,Manikandan P +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.0982,76.9388,897,Varun Edward +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.03363077,76.95163819,897,Varun Edward +Vidhya kitchen,11.0163268,77.0147763,11.04087375,77.0441414,1114,Tamilazhagan K +Vidhya kitchen,11.0163268,77.0147763,11.03240253,77.01003422,1114,Tamilazhagan K +Vidhya kitchen,11.0163268,77.0147763,11.030602,77.0101567,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.00337671,76.98414912,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,11.00489956,76.9763452,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,10.9696875,76.9852969,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,10.9796458,76.9984631,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,11.00715552,77.00965818,1111,Murali P +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.954112,76.971378,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.953686,76.977448,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.959578,76.974968,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.987899,76.963916,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.992573,76.951532,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.993525,76.957746,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.998688,76.964609,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,11.004156,76.948803,1036,Vignesh S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.026892,76.966249,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.022944,76.965336,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.02175,76.959374,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.026683,76.951522,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.014699,76.95387,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.014613,76.952428,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.01472,76.946499,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.025516,76.93813,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.030312,76.937785,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.0328,76.94,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.092864,76.969353,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.100762,76.990228,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.085915,77.001789,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.08899,77.005847,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.078727,77.013065,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.051535,76.991253,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.049939,76.991482,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.04784,76.977667,950,Jayasabesh Kumar S +Vidhya kitchen,11.016327,77.0147763,11.041572,77.008658,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.045286,77.013972,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.037263,77.016578,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,10.998805,77.030932,753,Manikandan P +Vidhya kitchen,11.016327,77.0147763,11.001598,77.027294,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.0097457,77.0193997,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,11.02699,77.019569,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,10.9677,76.9824,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.993077,76.983896,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.997526,76.982992,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.996813,76.9872,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.999621,76.995464,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.992602,76.998915,1111,Murali P +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.09215,76.915563,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.07997,76.945454,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.073727,76.960564,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.067513,76.938611,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.059067,76.929848,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.045562,76.941542,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.044538,76.945141,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.029436,76.948991,897,Varun Edward +Vidhya kitchen,11.016327,77.0147763,11.044512,77.041391,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.029355,77.001825,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.020589,76.998631,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.017405,76.991556,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.01436,76.98148,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.012762,76.980884,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.012272,76.980682,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.011559,76.984664,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.011855,76.985068,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.013227,76.995483,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.05159714,77.03965376,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.023461,76.988675,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.025103,77.000074,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.009746,77.0194,753,Manikandan P +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.007204,76.947376,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.014011,76.956777,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.020508,76.952259,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.022968,76.946565,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.033671,76.947109,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.027641,76.941552,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.025516,76.93813,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.02584,76.93533,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.101341,76.989437,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.094303,76.998085,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.052616,77.003142,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.041241,77.003104,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.030476,76.970333,950,Jayasabesh Kumar S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.9450125,76.9696719,1036,Vignesh S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.94669601,76.95759796,1036,Vignesh S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.9887125,76.9470469,1036,Vignesh S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.9931375,76.9305156,1036,Vignesh S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.1015,76.9907,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.1020098,76.9911354,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.1022,77.0328,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.06662342,77.03174932,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.0568241,77.0117323,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.0583375,76.9869531,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.04665266,76.97522061,950,Jayasabesh Kumar S +Vidhya kitchen,11.0163268,77.0147763,11.01962586,76.97291096,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.01067171,76.97995486,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.0105,76.98,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.01136931,76.98546701,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.01912568,76.99127706,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.02609076,76.99829646,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.0315832,77.0005771,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.05688855,77.01173596,1114,Tamilazhagan K +Vidhya kitchen,11.0163268,77.0147763,11.0251802,77.0198024,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.0241383,77.0184563,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.0207363,77.0220709,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.01933791,77.02415225,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.01976096,77.02560246,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,10.99833125,77.04464503,753,Manikandan P +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.0982,76.9388,897,Varun Edward +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.03363077,76.95163819,897,Varun Edward +Vidhya kitchen,11.0163268,77.0147763,11.04087375,77.0441414,1114,Tamilazhagan K +Vidhya kitchen,11.0163268,77.0147763,11.03240253,77.01003422,1114,Tamilazhagan K +Vidhya kitchen,11.0163268,77.0147763,11.030602,77.0101567,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.00337671,76.98414912,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,11.00489956,76.9763452,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,10.9696875,76.9852969,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,10.9796458,76.9984631,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,11.00715552,77.00965818,1111,Murali P +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.954112,76.971378,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.953686,76.977448,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.959578,76.974968,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.987899,76.963916,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.992573,76.951532,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.993525,76.957746,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.998688,76.964609,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,11.004156,76.948803,1036,Vignesh S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.026892,76.966249,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.022944,76.965336,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.02175,76.959374,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.026683,76.951522,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.014699,76.95387,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.014613,76.952428,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.01472,76.946499,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.025516,76.93813,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.030312,76.937785,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.0328,76.94,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.092864,76.969353,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.100762,76.990228,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.085915,77.001789,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.08899,77.005847,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.078727,77.013065,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.051535,76.991253,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.049939,76.991482,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.04784,76.977667,950,Jayasabesh Kumar S +Vidhya kitchen,11.016327,77.0147763,11.041572,77.008658,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.045286,77.013972,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.037263,77.016578,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,10.998805,77.030932,753,Manikandan P +Vidhya kitchen,11.016327,77.0147763,11.001598,77.027294,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.0097457,77.0193997,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,11.02699,77.019569,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,10.9677,76.9824,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.993077,76.983896,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.997526,76.982992,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.996813,76.9872,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.999621,76.995464,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.992602,76.998915,1111,Murali P +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.09215,76.915563,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.07997,76.945454,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.073727,76.960564,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.067513,76.938611,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.059067,76.929848,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.045562,76.941542,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.044538,76.945141,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.029436,76.948991,897,Varun Edward +Vidhya kitchen,11.016327,77.0147763,11.044512,77.041391,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.029355,77.001825,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.020589,76.998631,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.017405,76.991556,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.01436,76.98148,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.012762,76.980884,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.012272,76.980682,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.011559,76.984664,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.011855,76.985068,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.013227,76.995483,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.05159714,77.03965376,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.023461,76.988675,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.025103,77.000074,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.009746,77.0194,753,Manikandan P +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.007204,76.947376,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.014011,76.956777,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.020508,76.952259,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.022968,76.946565,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.033671,76.947109,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.027641,76.941552,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.025516,76.93813,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.02584,76.93533,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.101341,76.989437,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.094303,76.998085,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.052616,77.003142,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.041241,77.003104,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.030476,76.970333,950,Jayasabesh Kumar S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.9450125,76.9696719,1036,Vignesh S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.94669601,76.95759796,1036,Vignesh S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.9887125,76.9470469,1036,Vignesh S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.9931375,76.9305156,1036,Vignesh S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.1015,76.9907,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.1020098,76.9911354,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.1022,77.0328,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.06662342,77.03174932,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.0568241,77.0117323,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.0583375,76.9869531,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.04665266,76.97522061,950,Jayasabesh Kumar S +Vidhya kitchen,11.0163268,77.0147763,11.01962586,76.97291096,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.01067171,76.97995486,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.0105,76.98,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.01136931,76.98546701,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.01912568,76.99127706,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.02609076,76.99829646,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.0315832,77.0005771,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.05688855,77.01173596,1114,Tamilazhagan K +Vidhya kitchen,11.0163268,77.0147763,11.0251802,77.0198024,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.0241383,77.0184563,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.0207363,77.0220709,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.01933791,77.02415225,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.01976096,77.02560246,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,10.99833125,77.04464503,753,Manikandan P +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.0982,76.9388,897,Varun Edward +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.03363077,76.95163819,897,Varun Edward +Vidhya kitchen,11.0163268,77.0147763,11.04087375,77.0441414,1114,Tamilazhagan K +Vidhya kitchen,11.0163268,77.0147763,11.03240253,77.01003422,1114,Tamilazhagan K +Vidhya kitchen,11.0163268,77.0147763,11.030602,77.0101567,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.00337671,76.98414912,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,11.00489956,76.9763452,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,10.9696875,76.9852969,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,10.9796458,76.9984631,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,11.00715552,77.00965818,1111,Murali P +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.954112,76.971378,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.953686,76.977448,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.959578,76.974968,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.987899,76.963916,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.992573,76.951532,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.993525,76.957746,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.998688,76.964609,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,11.004156,76.948803,1036,Vignesh S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.026892,76.966249,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.022944,76.965336,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.02175,76.959374,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.026683,76.951522,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.014699,76.95387,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.014613,76.952428,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.01472,76.946499,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.025516,76.93813,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.030312,76.937785,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.0328,76.94,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.092864,76.969353,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.100762,76.990228,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.085915,77.001789,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.08899,77.005847,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.078727,77.013065,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.051535,76.991253,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.049939,76.991482,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.04784,76.977667,950,Jayasabesh Kumar S +Vidhya kitchen,11.016327,77.0147763,11.041572,77.008658,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.045286,77.013972,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.037263,77.016578,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,10.998805,77.030932,753,Manikandan P +Vidhya kitchen,11.016327,77.0147763,11.001598,77.027294,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.0097457,77.0193997,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,11.02699,77.019569,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,10.9677,76.9824,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.993077,76.983896,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.997526,76.982992,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.996813,76.9872,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.999621,76.995464,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.992602,76.998915,1111,Murali P +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.09215,76.915563,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.07997,76.945454,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.073727,76.960564,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.067513,76.938611,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.059067,76.929848,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.045562,76.941542,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.044538,76.945141,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.029436,76.948991,897,Varun Edward +Vidhya kitchen,11.016327,77.0147763,11.044512,77.041391,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.029355,77.001825,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.020589,76.998631,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.017405,76.991556,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.01436,76.98148,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.012762,76.980884,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.012272,76.980682,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.011559,76.984664,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.011855,76.985068,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.013227,76.995483,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.05159714,77.03965376,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.023461,76.988675,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.025103,77.000074,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.009746,77.0194,753,Manikandan P +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.007204,76.947376,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.014011,76.956777,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.020508,76.952259,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.022968,76.946565,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.033671,76.947109,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.027641,76.941552,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.025516,76.93813,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.02584,76.93533,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.101341,76.989437,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.094303,76.998085,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.052616,77.003142,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.041241,77.003104,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.030476,76.970333,950,Jayasabesh Kumar S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.9450125,76.9696719,1036,Vignesh S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.94669601,76.95759796,1036,Vignesh S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.9887125,76.9470469,1036,Vignesh S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.9931375,76.9305156,1036,Vignesh S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.1015,76.9907,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.1020098,76.9911354,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.1022,77.0328,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.06662342,77.03174932,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.0568241,77.0117323,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.0583375,76.9869531,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.04665266,76.97522061,950,Jayasabesh Kumar S +Vidhya kitchen,11.0163268,77.0147763,11.01962586,76.97291096,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.01067171,76.97995486,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.0105,76.98,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.01136931,76.98546701,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.01912568,76.99127706,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.02609076,76.99829646,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.0315832,77.0005771,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.05688855,77.01173596,1114,Tamilazhagan K +Vidhya kitchen,11.0163268,77.0147763,11.0251802,77.0198024,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.0241383,77.0184563,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.0207363,77.0220709,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.01933791,77.02415225,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.01976096,77.02560246,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,10.99833125,77.04464503,753,Manikandan P +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.0982,76.9388,897,Varun Edward +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.03363077,76.95163819,897,Varun Edward +Vidhya kitchen,11.0163268,77.0147763,11.04087375,77.0441414,1114,Tamilazhagan K +Vidhya kitchen,11.0163268,77.0147763,11.03240253,77.01003422,1114,Tamilazhagan K +Vidhya kitchen,11.0163268,77.0147763,11.030602,77.0101567,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.00337671,76.98414912,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,11.00489956,76.9763452,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,10.9696875,76.9852969,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,10.9796458,76.9984631,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,11.00715552,77.00965818,1111,Murali P +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.954112,76.971378,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.953686,76.977448,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.959578,76.974968,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.987899,76.963916,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.992573,76.951532,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.993525,76.957746,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.998688,76.964609,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,11.004156,76.948803,1036,Vignesh S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.026892,76.966249,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.022944,76.965336,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.02175,76.959374,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.026683,76.951522,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.014699,76.95387,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.014613,76.952428,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.01472,76.946499,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.025516,76.93813,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.030312,76.937785,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.0328,76.94,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.092864,76.969353,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.100762,76.990228,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.085915,77.001789,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.08899,77.005847,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.078727,77.013065,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.051535,76.991253,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.049939,76.991482,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.04784,76.977667,950,Jayasabesh Kumar S +Vidhya kitchen,11.016327,77.0147763,11.041572,77.008658,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.045286,77.013972,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.037263,77.016578,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,10.998805,77.030932,753,Manikandan P +Vidhya kitchen,11.016327,77.0147763,11.001598,77.027294,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.0097457,77.0193997,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,11.02699,77.019569,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,10.9677,76.9824,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.993077,76.983896,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.997526,76.982992,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.996813,76.9872,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.999621,76.995464,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.992602,76.998915,1111,Murali P +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.09215,76.915563,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.07997,76.945454,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.073727,76.960564,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.067513,76.938611,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.059067,76.929848,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.045562,76.941542,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.044538,76.945141,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.029436,76.948991,897,Varun Edward +Vidhya kitchen,11.016327,77.0147763,11.044512,77.041391,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.029355,77.001825,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.020589,76.998631,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.017405,76.991556,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.01436,76.98148,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.012762,76.980884,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.012272,76.980682,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.011559,76.984664,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.011855,76.985068,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.013227,76.995483,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.05159714,77.03965376,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.023461,76.988675,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.025103,77.000074,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.009746,77.0194,753,Manikandan P +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.007204,76.947376,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.014011,76.956777,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.020508,76.952259,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.022968,76.946565,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.033671,76.947109,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.027641,76.941552,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.025516,76.93813,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.02584,76.93533,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.101341,76.989437,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.094303,76.998085,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.052616,77.003142,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.041241,77.003104,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.030476,76.970333,950,Jayasabesh Kumar S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.9450125,76.9696719,1036,Vignesh S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.94669601,76.95759796,1036,Vignesh S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.9887125,76.9470469,1036,Vignesh S +Bhuvaneshwari kitchen,11.0035176,76.95454649999999,10.9931375,76.9305156,1036,Vignesh S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.1015,76.9907,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.1020098,76.9911354,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.1022,77.0328,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.06662342,77.03174932,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.0568241,77.0117323,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.0583375,76.9869531,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.04665266,76.97522061,950,Jayasabesh Kumar S +Vidhya kitchen,11.0163268,77.0147763,11.01962586,76.97291096,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.01067171,76.97995486,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.0105,76.98,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.01136931,76.98546701,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.01912568,76.99127706,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.02609076,76.99829646,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.0315832,77.0005771,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.05688855,77.01173596,1114,Tamilazhagan K +Vidhya kitchen,11.0163268,77.0147763,11.0251802,77.0198024,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.0241383,77.0184563,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.0207363,77.0220709,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.01933791,77.02415225,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.01976096,77.02560246,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,10.99833125,77.04464503,753,Manikandan P +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.0982,76.9388,897,Varun Edward +Daily grubs(jayanthi kitchen),11.0388679,76.9300797,11.03363077,76.95163819,897,Varun Edward +Vidhya kitchen,11.0163268,77.0147763,11.04087375,77.0441414,1114,Tamilazhagan K +Vidhya kitchen,11.0163268,77.0147763,11.03240253,77.01003422,1114,Tamilazhagan K +Vidhya kitchen,11.0163268,77.0147763,11.030602,77.0101567,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.00337671,76.98414912,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,11.00489956,76.9763452,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,10.9696875,76.9852969,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,10.9796458,76.9984631,1111,Murali P +Vidhya kitchen,11.0163268,77.0147763,11.00715552,77.00965818,1111,Murali P +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.954112,76.971378,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.953686,76.977448,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.959578,76.974968,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.987899,76.963916,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.992573,76.951532,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.993525,76.957746,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,10.998688,76.964609,1036,Vignesh S +Bhuvaneshwari kitchen,11.003518,76.95454649999999,11.004156,76.948803,1036,Vignesh S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.026892,76.966249,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.022944,76.965336,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.02175,76.959374,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.026683,76.951522,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.014699,76.95387,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.014613,76.952428,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.01472,76.946499,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.025516,76.93813,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.030312,76.937785,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.0328,76.94,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.092864,76.969353,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.100762,76.990228,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.085915,77.001789,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.08899,77.005847,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.078727,77.013065,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.051535,76.991253,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.049939,76.991482,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.04784,76.977667,950,Jayasabesh Kumar S +Vidhya kitchen,11.016327,77.0147763,11.041572,77.008658,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.045286,77.013972,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.037263,77.016578,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,10.998805,77.030932,753,Manikandan P +Vidhya kitchen,11.016327,77.0147763,11.001598,77.027294,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,11.0097457,77.0193997,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,11.02699,77.019569,753,Manikandan P +Vidhya kitchen,11.0163268,77.0147763,10.9677,76.9824,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.993077,76.983896,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.997526,76.982992,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.996813,76.9872,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.999621,76.995464,1111,Murali P +Vidhya kitchen,11.016327,77.0147763,10.992602,76.998915,1111,Murali P +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.09215,76.915563,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.07997,76.945454,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.073727,76.960564,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.067513,76.938611,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.059067,76.929848,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.045562,76.941542,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.044538,76.945141,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.029436,76.948991,897,Varun Edward +Vidhya kitchen,11.016327,77.0147763,11.044512,77.041391,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.029355,77.001825,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.020589,76.998631,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.017405,76.991556,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.01436,76.98148,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.012762,76.980884,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.012272,76.980682,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.011559,76.984664,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.011855,76.985068,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.013227,76.995483,883,Rajan A +Vidhya kitchen,11.0163268,77.0147763,11.05159714,77.03965376,1114,Tamilazhagan K +Vidhya kitchen,11.016327,77.0147763,11.023461,76.988675,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.025103,77.000074,883,Rajan A +Vidhya kitchen,11.016327,77.0147763,11.009746,77.0194,753,Manikandan P +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.007204,76.947376,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.014011,76.956777,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.020508,76.952259,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.022968,76.946565,1062,Nagalakshmi M +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.033671,76.947109,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.027641,76.941552,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.025516,76.93813,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.02584,76.93533,897,Varun Edward +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.101341,76.989437,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.094303,76.998085,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.052616,77.003142,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.041241,77.003104,950,Jayasabesh Kumar S +Daily grubs(jayanthi kitchen),11.038868,76.9300797,11.030476,76.970333,950,Jayasabesh Kumar S diff --git a/delivery_details.csv b/delivery_details.csv new file mode 100644 index 0000000..20c82e6 --- /dev/null +++ b/delivery_details.csv @@ -0,0 +1,3181 @@ +pickupcustomer,pickuplocation,pickuplat,pickuplon,userid,ridername,deliverycustomer,deliverylocation,deliverylat,deliverylong +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Kiran Divagar,,11.026034,76.96713 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,P M PRADEEP,,11.02175,76.959374 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.01472,76.946499 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.0982,76.9388 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Sreedevi,,11.046653,76.975221 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.945013,76.969672 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.946696,76.957598 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.988713,76.947047 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Bharathi M,,10.994947,76.949541 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.016327,77.014776 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.946696,76.957598 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.945013,76.969672 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Gopika,,10.933953,76.980191 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ramakrishnan,,10.953686,76.977448 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.959578,76.974968 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Abinaya,,10.987899,76.963916 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kamalish Muthukumar,,11.054825,77.053586 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kabilan,,11.051597,77.039654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Dr sneha k,,11.044512,77.041391 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Manoharan,,11.037263,77.016578 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Athiradh V Nair,,11.045212,77.014367 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Pranav A,,11.045286,77.013972 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Karthik abilash,,11.041572,77.008658 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kandavelu,,11.032403,77.010034 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Vishalini,,11.02699,77.019569 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Vasu dharani,,11.02518,77.019802 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020736,77.022071 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019626,76.972911 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Divyabharathi D,,11.01436,76.98148 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Siri,,11.012762,76.980884 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Dr.Sivakumar,,11.012272,76.980682 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Anusha,,11.011559,76.984664 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011855,76.985068 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011369,76.985467 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Preethika,,11.01125,76.98707 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sharumathi,,11.017405,76.991556 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Lokesh Lakshmanan,,11.020589,76.998631 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Devikarani,,11.031583,77.000577 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029355,77.001825 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.9677,76.9824 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.969687,76.985297 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Vignesh K B,,10.993077,76.983896 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Prasanna Nagarajan,,10.997526,76.982992 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Aryan Ajith,,10.996813,76.9872 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.992602,76.998915 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Yaswanth Sai Jami,,10.999621,76.995464 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hello Sivi,,11.013227,76.995483 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,backiaraj k,,11.007156,77.009658 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.998805,77.030932 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998331,77.044645 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Shanmugam,,11.009746,77.0194 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Dhivya,,11.09215,76.915563 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.0982,76.9388 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07997,76.945454 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Janaki Velmurugan,,11.073727,76.960564 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Everstage,,11.067513,76.938611 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Lalitha,,11.050699,76.947831 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Anu priyanga,,11.044538,76.945141 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,L. Rajeswari,,11.045562,76.941542 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,CHITHRA,,11.0328,76.94 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Kalaiselvi,,11.026892,76.966249 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Jasper T,,11.022944,76.965336 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,P M PRADEEP,,11.02175,76.959374 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dinesh Kumar,,11.014699,76.95387 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Hari Haran,,11.014613,76.952428 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.01472,76.946499 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Deepa,,11.026683,76.951522 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Rajeshwari,,11.02887,76.949948 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,B.Sakthi,,11.029436,76.948991 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sundar,,11.025516,76.93813 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Akshaya,,11.100762,76.990228 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Siddhiqka Azad,,11.0875,76.991821 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078727,77.013065 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Srihari,,11.066623,77.031749 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Swetha,,11.0572,77.0119 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Shah nisarg,,11.051535,76.991253 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Senthil Kumar N,,11.049939,76.991482 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Saranya S R,,11.04784,76.977667 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Maria venus Thomas,,10.990134,76.943483 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Muthibharathidevi,,10.992573,76.951532 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Saranya,,10.993525,76.957746 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998688,76.964609 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Udayakumar.N,,10.9993,76.9535 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004156,76.948803 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.016327,77.014776 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019626,76.972911 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Anusha Tennyson,,11.011559,76.984664 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011855,76.985068 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vishnu,,11.023461,76.988675 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Dhinesh,,11.025441,76.987199 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.026091,76.998296 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Devikarani,,11.031583,77.000577 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029355,77.001825 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kabilan,,11.051597,77.039654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Swetha,,11.0572,77.0119 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Manoj,,11.056889,77.011736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Karthik abilash,,11.041572,77.008658 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kandavelu,,11.032403,77.010034 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kaleeswaran B,,11.031778,77.018539 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.9677,76.9824 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.969687,76.985297 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.992602,76.998915 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998331,77.044645 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Shanmugam,,11.009746,77.0194 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020736,77.022071 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Varsha,,11.024138,77.018456 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Deebhan,,11.101341,76.989437 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Akshaya,,11.100762,76.990228 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,SuriyaKanthan,,11.094303,76.998085 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Srihari,,11.066623,77.031749 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Rishi,,11.052616,77.003142 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Indira Venkatachalam,,11.041241,77.003104 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Saranya S R,,11.04784,76.977667 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Drona P,,11.026298,76.965093 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,P M PRADEEP,,11.02175,76.959374 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Deepa,,11.026683,76.951522 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Akila,,11.020508,76.952259 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.01472,76.946499 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,VIGNESH,,11.022968,76.946565 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Mahesh Babu,,11.02584,76.93533 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.0982,76.9388 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07997,76.945454 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Annie John,,11.033671,76.947109 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,B.Sakthi,,11.029436,76.948991 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Rajeshwari,,11.02887,76.949948 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sundar,,11.025516,76.93813 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.959578,76.974968 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998688,76.964609 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.988713,76.947047 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004156,76.948803 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.016327,77.014776 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019626,76.972911 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Aishwarya,,11.0105,76.98 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011369,76.985467 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Santosh kumar,,11.019126,76.991277 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.026091,76.998296 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Devikarani,,11.031583,77.000577 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1114,Tamilazhagan K,Barathraj,,11.05929498,77.03019383 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1114,Tamilazhagan K,Manoj,,11.05688855,77.01173596 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1114,Tamilazhagan K,Athiradh V Nair,,11.04521214,77.0143674 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1114,Tamilazhagan K,Kandavelu,,11.03240253,77.01003422 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kaleeswaran B,,11.031778,77.018539 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.969687,76.985297 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Shriram,,11.003377,76.984149 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,backiaraj k,,11.007156,77.009658 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998331,77.044645 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020736,77.022071 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Varsha,,11.024138,77.018456 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Kiran Divagar,,11.026034,76.96713 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Indirani,,11.021355,76.950627 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.01472,76.946499 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,VIGNESH,,11.022968,76.946565 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.0982,76.9388 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Aiswarya S Menon,,11.1015,76.9907 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.10201,76.991135 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Anirudh S Rao,,11.1022,77.0328 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Jothi Nambu G,,11.058462,77.032047 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Bhuvana,,11.069251,77.019709 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Archanaa,,11.058338,76.986953 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Sreedevi,,11.046653,76.975221 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.945013,76.969672 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.946696,76.957598 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.993137,76.930516 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.988713,76.947047 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Bharathi M,,10.994947,76.949541 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.016327,77.014776 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.94781552,76.95753784 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,SIVASANKAR,,10.94616517,76.9693739 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Abinaya,,10.98820671,76.9637316 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998783,76.964411 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Dr.Sivakumar,,11.012352,76.981354 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Siri,,11.012833,76.981552 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Divyabharathi D,,11.014399,76.982136 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sharumathi,,11.017384,76.992013 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hello Sivi,,11.013288,76.995863 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Lokesh Lakshmanan,,11.020505,76.998949 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Devikarani,,11.031283,77.000857 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029098,77.00208 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Anusree Ramesh,,11.025463,77.013943 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vishalini,,11.02678,77.019475 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Vignesh K B,,10.993307,76.984202 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Aryan Ajith,,10.997006,76.987473 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Prasanna Nagarajan,,10.997712,76.983306 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Anusha,,11.011606,76.984962 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Thomson,,11.0119,76.985362 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Manikumar,,11.011418,76.985757 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Preethika,,11.011301,76.987344 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,backiaraj k,,11.007246,77.009709 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Dr sneha k,,11.043957,77.040866 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Vasu,,11.046718,77.041344 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kabilan,,11.050902,77.039164 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Nakkeerar R,,11.046263,77.014363 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Athiradh V Nair,,11.044643,77.014375 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Pranav A,,11.044715,77.013987 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Karthik abilash,,11.041074,77.008778 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kaleeswaran B,,11.031474,77.018465 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Shanmugam,,11.009875,77.019309 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Jeeva,,11.034481,76.966265 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Kalaiselvi,,11.027128,76.965536 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Jasper T,,11.023258,76.964641 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dinesh Kumar,,11.015175,76.953401 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Hari Haran,,11.015091,76.951988 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Deepa,,11.026923,76.951099 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Rajeshwari,,11.029067,76.949556 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sundar,,11.025779,76.937971 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Vishnu Priya,,11.092329,76.968964 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Akshaya,,11.100149,76.989632 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078332,77.012244 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Bhuvana,,11.06895,77.018822 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Prabhuram AR,,11.061187,77.023673 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Jothi Nambu G,,11.058207,77.030694 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Shah nisarg,,11.05141,76.990648 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Saranya S R,,11.047751,76.977196 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Dhivya,,11.0911,76.915849 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Janaki Velmurugan,,11.07304,76.959964 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chandramouleeswaran,,11.072531,76.946732 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Everstage,,11.066949,76.938443 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Monisha,,11.058669,76.929852 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Santhia,,11.058485,76.93057 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Lalitha,,11.050466,76.947481 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,L. Rajeswari,,11.04543,76.941316 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Udhayakumar,,10.993342,76.930989 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Kasi Vishwa,,10.982522,76.933425 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Maria venus Thomas,,10.990398,76.943701 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Muthibharathidevi,,10.992789,76.951591 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Saranya,,10.993722,76.957683 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Udayakumar.N,,10.999383,76.953521 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Anusha Tennyson,,11.011653,76.985258 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vishnu,,11.02332,76.989189 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025898,76.998621 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Devikarani,,11.031283,77.000857 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029098,77.00208 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Vasu,,11.046718,77.041344 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kabilan,,11.050902,77.039164 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Karthik abilash,,11.041074,77.008778 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kandavelu,,11.032086,77.010128 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kaleeswaran B,,11.031474,77.018465 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968658,76.983038 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.993069,76.999228 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Shanmugam,,11.009875,77.019309 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Varsha,,11.023984,77.018384 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Drona P,,11.026422,76.964746 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Akila,,11.02069,76.952039 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.014959,76.946336 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sundar,,11.025648,76.93805 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Deepa,,11.026923,76.951099 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Rajeshwari,,11.029067,76.949556 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Akshaya,,11.099543,76.989043 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,SuriyaKanthan,,11.093211,76.996745 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Bhuvana,,11.068652,77.017943 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Rishi,,11.052345,77.001702 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Indira Venkatachalam,,11.041194,77.001666 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Saranya S R,,11.047663,76.97673 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998783,76.964411 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Manjusha kitchen ,Ganapathy,11.049985,76.991291,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.101495,76.991137 +Manjusha kitchen ,Ganapathy,11.049985,76.991291,950,Jayasabesh Kumar S,Srihari,,11.066459,77.031349 +Manjusha kitchen ,Ganapathy,11.049985,76.991291,950,Jayasabesh Kumar S,Jothi Nambu G,,11.058379,77.031643 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1114,Tamilazhagan K,Barathraj,,11.05844843,77.02989008 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1114,Tamilazhagan K,Manoj,,11.0560894,77.01179586 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1114,Tamilazhagan K,Praveen Das,,11.04465898,77.0143488 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1114,Tamilazhagan K,Athiradh V Nair,,11.04464305,77.01437546 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1114,Tamilazhagan K,Kandavelu,,11.03208581,77.01012765 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1114,Tamilazhagan K,Kaleeswaran B,,11.03147378,77.01846507 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Yaswanth Sai Jami,,11.010728,76.9803 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011418,76.985757 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Santosh kumar,,11.019098,76.99151 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Devikarani,,11.031432,77.000718 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Shriram,,11.003505,76.984452 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,backiaraj k,,11.007246,77.009709 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Varsha,,11.023984,77.018384 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.014959,76.946336 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Indirani,,11.021529,76.950423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024506,76.942392 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,VIGNESH,,11.023281,76.94624 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Anirudh S Rao,,11.101573,77.031783 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Bhuvana,,11.06895,77.018822 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Sreedevi,,11.046576,76.974774 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,SIVASANKAR,,10.94616517,76.9693739 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.94781552,76.95753784 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.99334201,76.93098906 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.98900419,76.94719466 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Bharathi M,,10.99511545,76.94963997 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,1114,Tamilazhagan K,vidhya kitchen,ramlakshman nagar,11.017026,77.014323 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ramakrishnan,,10.954668,76.976997 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998783,76.964411 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Lokesh Lakshmanan,,11.020546,76.99879 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029226,77.001954 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Devikarani,,11.031432,77.000718 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vishalini,,11.026884,77.019522 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Siri,,11.012833,76.981552 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Anusha,,11.011653,76.985258 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Aryan Ajith,,10.997197,76.987743 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,backiaraj k,,11.007336,77.009759 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Karthik abilash,,11.041322,77.008718 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Nilesh,,11.047275,77.048692 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Preethi,,11.043564,77.040569 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kabilan,,11.050902,77.039164 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Athiradh V Nair,,11.044643,77.014375 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Pranav A,,11.044715,77.013987 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Manoharan,,11.03685,77.016543 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kaleeswaran B,,11.031474,77.018465 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kandavelu,,11.032086,77.010128 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Shanmugam,,11.009875,77.019309 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Yashaswini N,,11.00834,76.94171 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Hari Haran,,11.015091,76.951988 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Kishore,,11.025478,76.964981 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Kalaiselvi,,11.027128,76.965536 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Yamuna devi,,11.034199,76.963456 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Rajeshwari,,11.029067,76.949556 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sundar,,11.025779,76.937971 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Janaki Velmurugan,,11.07304,76.959964 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chandramouleeswaran,,11.072531,76.946732 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sundhara Baalaji,,11.062544,76.934595 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Monisha,,11.058669,76.929852 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Santhia,,11.058485,76.93057 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,L. Rajeswari,,11.04543,76.941316 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Vishnu Priya,,11.092329,76.968964 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078332,77.012244 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Bhuvana,,11.06895,77.018822 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Srihari,,11.066349,77.030743 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Jothi Nambu G,,11.058207,77.030694 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Prabhuram AR,,11.061187,77.023673 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Shah nisarg,,11.05141,76.990648 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Saranya S R,,11.047751,76.977196 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Udhayakumar,,10.993342,76.930989 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Maria venus Thomas,,10.990398,76.943701 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Usha S,,10.987264,76.948543 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Muthibharathidevi,,10.992789,76.951591 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Saranya,,10.993722,76.957683 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Udayakumar.N,,10.999383,76.953521 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,1114,Tamilazhagan K,vidhya kitchen,ramlakshman nagar,11.017026,77.014323 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968181,76.982721 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.992837,76.999072 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Anusha Tennyson,,11.011653,76.985258 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vishnu,,11.02332,76.989189 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Devikarani,,11.031283,77.000857 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029098,77.00208 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025539,77.00148 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kabilan,,11.050902,77.039164 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Karthik abilash,,11.041074,77.008778 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kandavelu,,11.032086,77.010128 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1114,Tamilazhagan K,Kaleeswaran B,,11.031474,77.018465 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Narmada,,10.9986858,77.04405656 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Shanmugam,,11.009875,77.019309 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Srihari,,11.066349,77.030743 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Bhuvana,,11.06895,77.018822 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,SuriyaKanthan,,11.093754,76.997411 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Saranya S R,,11.047751,76.977196 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,VIGNESH,,11.023125,76.946402 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Rajeshwari,,11.029067,76.949556 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Rajeswari Kannan,,11.027863,76.941326 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sundar,,11.025779,76.937971 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Drona P,,11.026533,76.964405 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Chandru,,11.014501,76.956251 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Akila,,11.02087,76.951822 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998783,76.964411 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Udayakumar.N,,10.999383,76.953521 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Manoj,,11.056487,77.011766 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Athiradh V Nair,,11.044926,77.014371 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Kandavelu,,11.032243,77.010081 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Kaleeswaran B,,11.031625,77.018502 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Yaswanth Sai Jami,,11.010783,76.980641 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Aishwarya,,11.010615,76.980685 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025898,76.998621 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Devikarani,,11.031283,77.000857 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025539,77.00148 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Shriram,,11.003505,76.984452 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,backiaraj k,,11.007246,77.009709 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Narmada,,10.9986858,77.04405656 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Pooja,,11.01927859,77.02396753 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,M.S.JAVID,,11.02064943,77.02192718 +Manjusha kitchen ,Ganapathy,11.049985,76.991291,950,Jayasabesh Kumar S,Jothi Nambu G,,11.058295,77.031244 +Manjusha kitchen ,Ganapathy,11.049985,76.991291,950,Jayasabesh Kumar S,Srihari,,11.066296,77.030952 +Manjusha kitchen ,Ganapathy,11.049985,76.991291,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.100985,76.991138 +Manjusha kitchen ,Ganapathy,11.049985,76.991291,950,Jayasabesh Kumar S,Aiswarya S Menon,,11.100485,76.990712 +Manjusha kitchen ,Ganapathy,11.049985,76.991291,950,Jayasabesh Kumar S,Archana Manohar,,11.058173,76.987039 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Indirani,,11.0217,76.950222 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Saideep,,11.021301,76.940251 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,VIGNESH,,11.023281,76.94624 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Bhuvana,,11.06895,77.018822 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Sreedevi,,11.046576,76.974774 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,SIVASANKAR,,10.94616517,76.9693739 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.94781552,76.95753784 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.99334201,76.93098906 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.98900419,76.94719466 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Bharathi M,,10.99511545,76.94963997 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.017026,77.014323 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Gopika,,10.935323,76.979685 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Sowdayan,,10.955085,76.971046 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ramakrishnan,,10.954668,76.976997 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968181,76.982721 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.992837,76.999072 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Preethika,,11.011301,76.987344 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Vignesh K B,,10.993307,76.984202 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Aryan Ajith,,10.997006,76.987473 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Yaswanth Sai Jami,,10.999787,76.995655 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,backiaraj k,,11.007246,77.009709 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Siri,,11.012833,76.981552 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Dr.Sivakumar,,11.012352,76.981354 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sharumathi,,11.017384,76.992013 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hello Sivi,,11.013288,76.995863 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Lokesh Lakshmanan,,11.020505,76.998949 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025539,77.00148 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Devikarani,,11.031283,77.000857 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029098,77.00208 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Niroshini K,,11.044962,77.045213 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Dr sneha k,,11.043957,77.040866 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Preethi,,11.043564,77.040569 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Kabilan,,11.050902,77.039164 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Athiradh V Nair,,11.044643,77.014375 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Pranav A,,11.044715,77.013987 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Karthik abilash,,11.041074,77.008778 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Kandavelu,,11.032086,77.010128 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Manoharan,,11.03685,77.016543 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Kaleeswaran B,,11.031474,77.018465 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Shanmugam,,11.009875,77.019309 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Yamuna devi,,11.034152,76.963789 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Kalaiselvi,,11.02701,76.965891 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Suba Surya S,,11.020576,76.965773 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Kaviyarasan,,11.009983,76.963466 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dinesh Kumar,,11.014938,76.953634 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Hari Haran,,11.014854,76.952207 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Yashaswini N,,11.014845,76.952175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.014959,76.946336 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024506,76.942392 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sundar,,11.025648,76.93805 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Hemalatha,,11.033482,76.939862 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Vishnu Priya,,11.092329,76.968964 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078332,77.012244 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Bhuvana,,11.06895,77.018822 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Srihari,,11.066349,77.030743 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Jothi Nambu G,,11.058207,77.030694 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Prabhuram AR,,11.061187,77.023673 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Senthil Kumar N,,11.04983,76.990874 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Saranya S R,,11.047751,76.977196 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Janaki Velmurugan,,11.07304,76.959964 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chandramouleeswaran,,11.072531,76.946732 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Everstage,,11.066949,76.938443 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Monisha,,11.058669,76.929852 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Santhia,,11.058485,76.93057 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,L. Rajeswari,,11.04543,76.941316 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Rajeshwari,,11.029067,76.949556 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,B.Sakthi,,11.029622,76.948618 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Udhayakumar,,10.993342,76.930989 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Maria venus Thomas,,10.990398,76.943701 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Usha S,,10.987264,76.948543 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Muthibharathidevi,,10.992789,76.951591 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Saranya,,10.993722,76.957683 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Udayakumar.N,,10.999383,76.953521 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.017026,77.014323 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Shanmugam,,11.009875,77.019309 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968658,76.983038 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.993069,76.999228 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vishnu,,11.02332,76.989189 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Dhinesh,,11.025261,76.987743 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025898,76.998621 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Devikarani,,11.031283,77.000857 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029098,77.00208 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025539,77.00148 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Niroshini K,,11.045249,77.045517 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Kabilan,,11.051248,77.039407 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Karthik abilash,,11.041322,77.008718 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Harishma,,11.043654,77.001357 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Kandavelu,,11.032243,77.010081 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Kaleeswaran B,,11.031625,77.018502 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Drona P,,11.02641,76.964748 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Akila,,11.02069,76.952039 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.014959,76.946336 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,VIGNESH,,11.023125,76.946402 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024506,76.942392 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Saideep,,11.021125,76.940353 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sundar,,11.025779,76.937971 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Rajeshwari,,11.029067,76.949556 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Rajeswari Kannan,,11.027863,76.941326 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Srihari,,11.066349,77.030743 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Bhuvana,,11.06895,77.018822 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,SuriyaKanthan,,11.093754,76.997411 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Archanaa,,11.058145,76.98639 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Senthil Kumar N,,11.04983,76.990874 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Saranya S R,,11.047751,76.977196 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998783,76.964411 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Udayakumar.N,,10.999383,76.953521 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.016093,77.014683 +Manjusha kitchen ,Ganapathy,11.049985,76.991291,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.101495,76.991137 +Manjusha kitchen ,Ganapathy,11.049985,76.991291,950,Jayasabesh Kumar S,Aiswarya S Menon,,11.10099,76.990706 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Niroshini K,,11.045249,77.045517 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Jothi Nambu G,,11.058045,77.031876 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Barathraj,,11.05887,77.030041 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Srihari,,11.066125,77.031581 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Manoj,,11.056487,77.011766 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Athiradh V Nair,,11.044926,77.014371 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Kandavelu,,11.032243,77.010081 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Yaswanth Sai Jami,,11.010728,76.9803 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Aishwarya,,11.010558,76.980344 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011418,76.985757 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Santosh kumar,,11.019098,76.99151 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025994,76.99846 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025631,77.001348 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Devikarani,,11.031432,77.000718 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sandesh,,11.030444,77.007711 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Shriram,,11.003632,76.984753 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,backiaraj k,,11.007336,77.009759 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Akchith B T,,11.018366,77.021275 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Bharath Kumar T,,11.023663,77.019645 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Suba Surya S,,11.020757,76.96542 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,VIGNESH,,11.023281,76.94624 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Indirani,,11.0217,76.950222 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Bhuvana,,11.06895,77.018822 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Sreedevi,,11.046576,76.974774 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.945592,76.969522 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947259,76.957568 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.988859,76.947121 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.99324,76.930754 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.017026,77.014323 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,772,Nearle Test Rider,Gopika,,10.93464139,76.97993672 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,772,Nearle Test Rider,Ramakrishnan,,10.95417969,76.97722157 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,772,Nearle Test Rider,SIVASANKAR,,10.9455917,76.96952216 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,772,Nearle Test Rider,Lakshmanan Visalakshi,,10.94725855,76.95756775 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,772,Nearle Test Rider,Jai,,10.95987542,76.94902996 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Niroshini K,,11.044962,77.045213 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Dr sneha k,,11.043957,77.040866 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Kabilan,,11.050902,77.039164 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Athiradh V Nair,,11.044643,77.014375 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Pranav A,,11.044715,77.013987 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Karthik abilash,,11.041074,77.008778 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Manoharan,,11.03685,77.016543 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Kandavelu,,11.032086,77.010128 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Dr Ilavarasi,,11.014118,76.97909 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Siri,,11.012798,76.98122 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Dr.Sivakumar,,11.012312,76.981019 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Thomson,,11.0119,76.985362 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Manikumar,,11.011418,76.985757 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Preethika,,11.011301,76.987344 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hello Sivi,,11.013257,76.995674 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sharumathi,,11.017395,76.991786 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Savithri Damodarasamy,,11.022876,76.993678 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Priyanka R,,11.027335,76.993989 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Devikarani,,11.031432,77.000718 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029226,77.001954 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025631,77.001348 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Lokesh Lakshmanan,,11.020546,76.99879 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Akchith B T,,10.996345,76.981434 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Prasanna Nagarajan,,10.997896,76.983618 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Aryan Ajith,,10.997197,76.987743 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Yaswanth Sai Jami,,10.999951,76.995844 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,backiaraj k,,11.007336,77.009759 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998509,77.044349 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.998978,77.030772 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Shanmugam,,11.009811,77.019354 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020693,77.021999 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Kalaiselvi,,11.027128,76.965536 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Jasper T,,11.023258,76.964641 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Suba Surya S,,11.020757,76.96542 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dinesh Kumar,,11.015175,76.953401 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Hari Haran,,11.015091,76.951988 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Yashaswini N,,11.015083,76.951957 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr. Tasneem,,11.014139,76.948561 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Rajeshwari,,11.029067,76.949556 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Hemalatha,,11.033535,76.939765 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Srihari,,11.066349,77.030743 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Jothi Nambu G,,11.058207,77.030694 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Prabhuram AR,,11.061187,77.023673 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Bhuvana,,11.06895,77.018822 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078332,77.012244 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Saranya S R,,11.047751,76.977196 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Vishnu Priya,,11.0918,76.968579 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Janaki Velmurugan,,11.07304,76.959964 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chandramouleeswaran,,11.072531,76.946732 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Benita,,11.077355,76.932408 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Everstage,,11.066949,76.938443 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Monisha,,11.058669,76.929852 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Santhia,,11.058485,76.93057 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Lalitha,,11.050466,76.947481 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,L. Rajeswari,,11.04543,76.941316 +Manjusha kitchen ,Ganapathy,11.0517946,76.9917895,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.01702559,77.01432341 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Niroshini K,,11.045249,77.045517 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Kabilan,,11.051248,77.039407 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Karthik abilash,,11.041322,77.008718 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Harishma,,11.043654,77.001357 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Kandavelu,,11.032243,77.010081 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.0119,76.985362 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Dhinesh,,11.02535,76.987472 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vishnu,,11.02339,76.988933 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Savithri Damodarasamy,,11.022876,76.993678 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025994,76.99846 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Devikarani,,11.031432,77.000718 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029226,77.001954 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025631,77.001348 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968181,76.982721 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Akchith B T,,10.996145,76.9811 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.992837,76.999072 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Shanmugam,,11.009875,77.019309 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Rajeshwari,,11.029067,76.949556 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Rajeswari Kannan,,11.027863,76.941326 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Suba Surya S,,11.020576,76.965773 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.014959,76.946336 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,VIGNESH,,11.023125,76.946402 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024506,76.942392 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,SuriyaKanthan,,11.093754,76.997411 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Bhuvana,,11.06895,77.018822 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Srihari,,11.066349,77.030743 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Senthil Kumar N,,11.04983,76.990874 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,950,Jayasabesh Kumar S,Saranya S R,,11.047751,76.977196 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998783,76.964411 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Udayakumar.N,,10.999383,76.953521 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Shriram,,11.003632,76.984753 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Yaswanth Sai Jami,,11.010783,76.980641 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Aishwarya,,11.010615,76.980685 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Santosh kumar,,11.019071,76.99174 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025898,76.998621 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025539,77.00148 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Akchith B T,,11.018366,77.021275 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.101428,76.99123 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Aiswarya S Menon,,11.100923,76.990799 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066392,77.031442 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jothi Nambu G,,11.058312,77.031736 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Barathraj,,11.059136,77.029902 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046619,76.975473 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1121,Balamurali K,Niroshini K,,11.045515,77.045378 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhuvana,,11.068994,77.019521 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1121,Balamurali K,Manoj,,11.056753,77.011626 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1121,Balamurali K,Athiradh V Nair,,11.045193,77.014232 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1121,Balamurali K,Kandavelu,,11.03251,77.009942 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Devikarani,,11.031813,77.000579 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Balasundaram Doraisami,,11.024776,76.957684 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,VIGNESH,,11.023125,76.946402 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,B.Sakthi,,11.029529,76.948804 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Yashaswini N,,11.00834,76.94171 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Indirani,,11.0217,76.950222 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.993342,76.930989 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Bharathi M,,10.995115,76.94964 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Jai,,10.960307,76.949085 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.94781552,76.95753784 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Sowdayan,,10.955085,76.971046 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ramakrishnan,,10.954668,76.976997 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Abinaya,,10.988207,76.963732 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Vishnu,,10.994086,76.961654 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998783,76.964411 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Udayakumar.N,,10.999383,76.953521 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968181,76.982721 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Vignesh K B,,10.993307,76.984202 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Akchith B T,,10.996145,76.9811 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Prasanna Nagarajan,,10.997712,76.983306 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Aryan Ajith,,10.997006,76.987473 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Yaswanth Sai Jami,,10.999787,76.995655 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.992837,76.999072 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Madhumitha,,10.992888,77.000577 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,S Rengasamy,,11.002874,77.012567 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Siri,,11.012833,76.981552 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sivakumar,,11.012352,76.981354 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Preethika,,11.011351,76.987616 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hello Sivi,,11.013288,76.995863 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sharumathi,,11.017384,76.992013 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Priyanka R,,11.027226,76.994195 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025539,77.00148 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sarath,,11.023359,77.005487 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998509,77.044349 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.998978,77.030772 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020693,77.021999 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Mohamed Rashith,,11.021895,77.013381 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047794,76.977895 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Manikandabalaji,,11.073231,77.002266 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078376,77.012943 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhuvana,,11.068994,77.019521 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066392,77.031442 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jothi Nambu G,,11.05825,77.031393 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Anand Kumar,,11.046833,77.014147 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Athiradh V Nair,,11.045193,77.014232 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1121,Balamurali K,Niroshini K,,11.045493,77.044935 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1121,Balamurali K,Dr sneha k,,11.044487,77.040588 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1121,Balamurali K,Preethi,,11.044095,77.040292 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1121,Balamurali K,Kabilan,,11.051432,77.038886 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1121,Balamurali K,Pranav A,,11.045245,77.01371 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1121,Balamurali K,Manoharan,,11.03738,77.016265 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1121,Balamurali K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1121,Balamurali K,Karthik abilash,,11.041604,77.008501 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029629,77.001803 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Devikarani,,11.031813,77.000579 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Suba Surya S,,11.020576,76.965773 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Jasper T,,11.023102,76.964987 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Kalaiselvi,,11.02701,76.965891 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Balasundaram Doraisami,,11.024776,76.957684 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Hari Haran,,11.014854,76.952207 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Yashaswini N,,11.014845,76.952175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.014959,76.946336 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024506,76.942392 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Rajeshwari,,11.028969,76.949751 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,B.Sakthi,,11.029529,76.948804 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Hemalatha,,11.033482,76.939862 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Janaki Velmurugan,,11.07304,76.959964 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chandramouleeswaran,,11.072531,76.946732 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Pavithra,,11.063898,76.942419 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,SHUNMUGAKANI,,11.062948,76.942439 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Everstage,,11.066949,76.938443 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Monisha,,11.058669,76.929852 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Santhia,,11.058485,76.93057 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Vinesh Karthik,,11.033596,76.950734 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +jayanthi,Edayarpalayam,11.038493,76.9240062,1062,Nagalakshmi M,Bhuvaneshwari kitchen ,R.S. Puram,11.004207,76.953945 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Udhayakumar,,10.993342,76.930989 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Maria venus Thomas,,10.990398,76.943701 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Usha S,,10.987264,76.948543 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Saranya,,10.993722,76.957683 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968181,76.982721 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Akchith B T,,10.996145,76.9811 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.992837,76.999072 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025539,77.00148 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Suba Surya S,,11.020757,76.96542 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Balasundaram Doraisami,,11.024915,76.957411 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Indirani,,11.0217,76.950222 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Yashaswini N,,11.00834,76.94171 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,VIGNESH,,11.023281,76.94624 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Rajeshwari,,11.029067,76.949556 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Rajeswari Kannan,,11.027863,76.941326 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066392,77.031442 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhuvana,,11.068994,77.019521 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,SuriyaKanthan,,11.093797,76.99811 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047794,76.977895 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1121,Balamurali K,Niroshini K,,11.045515,77.045378 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Dhinesh,,11.022099,77.015276 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1121,Balamurali K,Kandavelu,,11.03251,77.009942 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1121,Balamurali K,Karthik abilash,,11.041588,77.008579 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Athira Sooraj,,11.02626,76.99832 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029493,77.001814 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Devikarani,,11.031699,77.000578 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960013,76.974766 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.988859,76.947121 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998735,76.96451 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Udayakumar.N,,10.999342,76.95351 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.00415,76.94886 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Shriram,,11.003505,76.984452 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Rajkumar D,,11.001944,76.997869 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Yaswanth Sai Jami,,11.010728,76.9803 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Aishwarya,,11.010558,76.980344 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011418,76.985757 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025994,76.99846 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025631,77.001348 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Akchith B T,,11.018366,77.021275 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.101428,76.99123 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Aiswarya S Menon,,11.100923,76.990799 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhuvana,,11.068994,77.019521 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066392,77.031442 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jothi Nambu G,,11.058312,77.031736 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Barathraj,,11.059136,77.029902 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046619,76.975473 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Niroshini K,,11.04549256,77.04493511 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Jothi,,11.04005837,77.04362285 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,DR SAAKSHI,,11.0302998,77.03580047 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.03261597,77.00984985 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.04517321,77.01409765 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Anand Kumar,,11.04679753,77.01401334 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Manoj,,11.05661958,77.01151805 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Santosh kumar,,11.019601,76.991462 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Devikarani,,11.031813,77.000579 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Sandesh,,11.030835,77.007503 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Suba Surya S,,11.020757,76.96542 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Balasundaram Doraisami,,11.024915,76.957411 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Yashaswini N,,11.008035,76.941827 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.014959,76.946336 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,VIGNESH,,11.023125,76.946402 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.993342,76.930989 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Bharathi M,,10.995115,76.94964 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Gopika,,10.935323,76.979685 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Sowdayan,,10.955085,76.971046 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SUBRAMANIAN T,,10.960073,76.974205 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Abinaya,,10.988207,76.963732 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Siri,,11.012798,76.98122 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Sivakumar,,11.012312,76.981019 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Thomson,,11.0119,76.985362 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Manikumar,,11.011418,76.985757 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Preethika,,11.011301,76.987344 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Sharumathi,,11.017395,76.991786 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Hello Sivi,,11.013257,76.995674 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Lokesh Lakshmanan,,11.020546,76.99879 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Priyanka R,,11.027335,76.993989 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,S sanbhagavalli,,11.028956,76.993857 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Hema Priya Thangavel,,11.025631,77.001348 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Akchith B T,,10.996345,76.981434 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Vignesh K B,,10.993535,76.984505 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Yaswanth Sai Jami,,10.999951,76.995844 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,S Rengasamy,,11.003007,77.012588 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Narmada,,10.9986858,77.04405656 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Niroshini K,,11.045515,77.045378 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Dr sneha k,,11.0445,77.040988 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Ninusha,,11.029339,77.036359 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Kaleeswaran B,,11.031892,77.018362 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Manoharan,,11.037322,77.016421 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Kandavelu,,11.03251,77.009942 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029493,77.001814 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Devikarani,,11.031699,77.000578 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Karthik abilash,,11.041588,77.008579 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047749,76.978121 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Senthil Kumar N,,11.049807,76.991663 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070216,77.000148 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Manikandabalaji,,11.072934,77.002251 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078028,77.012821 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhuvana,,11.068739,77.019334 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jothi Nambu G,,11.058101,77.031089 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Pranav A,,11.045245,77.01371 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.014959,76.946336 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Yashaswini N,,11.014845,76.952175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Hari Haran,,11.014854,76.952207 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Suba Surya S,,11.020576,76.965773 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Jasper T,,11.023102,76.964987 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Kalaiselvi,,11.02701,76.965891 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Balasundaram Doraisami,,11.024776,76.957684 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Vinesh Karthik,,11.033543,76.950941 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,B.Sakthi,,11.029529,76.948804 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sundar,,11.025648,76.93805 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Hemalatha,,11.033482,76.939862 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Benita,,11.077355,76.932408 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chandramouleeswaran,,11.072531,76.946732 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Pavithra,,11.063898,76.942419 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,SHUNMUGAKANI,,11.062948,76.942439 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Everstage,,11.066949,76.938443 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Monisha,,11.058669,76.929852 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Santhia,,11.058485,76.93057 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Akila,,11.048824,76.941069 +jayanthi,Edayarpalayam,11.038493,76.9240062,1062,Nagalakshmi M,Bhuvaneshwari kitchen ,R.S. Puram,11.004207,76.953945 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Udhayakumar,,10.993342,76.930989 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Maria venus Thomas,,10.990398,76.943701 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Usha S,,10.987264,76.948543 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Saranya,,10.993722,76.957683 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Malarvizhi,,11.00878,76.953483 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998509,77.044349 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019308,77.024059 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020693,77.021999 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.0119,76.985362 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025631,77.001348 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029493,77.001814 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Devikarani,,11.031699,77.000578 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Bhuvana,,11.068739,77.019334 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Niroshini K,,11.045493,77.044935 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.032004,77.018187 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066392,77.031442 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,SuriyaKanthan,,11.093797,76.99811 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047794,76.977895 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Senthil Kumar N,,11.049873,76.991573 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968658,76.983038 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Akchith B T,,10.996345,76.981434 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.993069,76.999228 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Rajkumar D,,11.002086,76.998036 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998783,76.964411 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Suba Surya S,,11.020757,76.96542 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Balasundaram Doraisami,,11.024915,76.957411 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,VIGNESH,,11.023281,76.94624 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sundar,,11.025779,76.937971 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,B.Sakthi,,11.029622,76.948618 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Rajesh Pandian,,11.013786,76.979778 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Yaswanth Sai Jami,,11.010728,76.9803 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Aishwarya,,11.010558,76.980344 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Shriram,,11.003505,76.984452 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Manikumar,,11.011418,76.985757 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Hema Priya Thangavel,,11.02563107,77.00134752 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Javal Gandha,,11.023831,77.020974 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020693,77.021999 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Akchith B T,,11.018386,77.02134 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Aiswarya S Menon,,11.100352,76.990897 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jeeva,,11.096804,76.997213 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070216,77.000148 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Manoj,,11.05662,77.011518 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046585,76.975722 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Niroshini K,,11.045493,77.044935 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Jothi,,11.040058,77.043623 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.032004,77.018187 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Sandesh,,11.030835,77.007503 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Devikarani,,11.031813,77.000579 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Suba Surya S,,11.020757,76.96542 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chiteshkumar s.b,,11.027798,76.966063 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,VIGNESH,,11.023281,76.94624 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Pandiarajan,,11.030569,76.92758 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.993342,76.930989 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Bharathi M,,10.995115,76.94964 +Nandhini s kitchens,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,vidhya kitchen,ramlakshman nagar,11.0165932,77.0146367 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Preethika,,11.011351,76.987616 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Akchith B T,,10.996345,76.981434 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Vignesh K B,,10.993535,76.984505 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Yaswanth Sai Jami,,10.999951,76.995844 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,MohanRaju,,10.997665,76.996664 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.993069,76.999228 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,S Rengasamy,,11.003007,77.012588 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,M.S.JAVID,,11.020649,77.021927 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Rajavidhya,,11.021773,76.977976 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Siri,,11.012833,76.981552 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sivakumar,,11.012352,76.981354 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Hello Sivi,,11.013288,76.995863 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Lokesh Lakshmanan,,11.020505,76.998949 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Priyanka R,,11.027226,76.994195 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,S sanbhagavalli,,11.028831,76.994064 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Hema Priya Thangavel,,11.025539,77.00148 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sarath,,11.023359,77.005487 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Niroshini K,,11.045515,77.045378 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Dr sneha k,,11.0445,77.040988 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Ninusha,,11.029339,77.036359 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.031892,77.018362 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoharan,,11.037322,77.016421 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Pranav A,,11.045265,77.01384 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.03251,77.009942 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Devikarani,,11.031699,77.000578 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047794,76.977895 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070486,77.000143 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078376,77.012943 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Balakrishnan,,11.062171,77.017093 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066392,77.031442 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jothi Nambu G,,11.058312,77.031736 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Athiradh V Nair,,11.045193,77.014232 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthik abilash,,11.041588,77.008579 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Suba Surya S,,11.020757,76.96542 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Jasper T,,11.023258,76.964641 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chandramouleeswaran,,11.072531,76.946732 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Everstage,,11.066949,76.938443 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Pavithra,,11.063898,76.942419 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,SHUNMUGAKANI,,11.062948,76.942439 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Lalitha Lalitha,,11.050466,76.947481 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Monisha,,11.058669,76.929852 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jairus,,11.034097,76.920142 +Nandhini s kitchens,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,vidhya kitchen,ramlakshman nagar,11.01685697,77.01449849 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1036,Vignesh S,Karthik,,11.018836,76.920316 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1036,Vignesh S,Abdul hameed,,11.016043,76.916622 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1036,Vignesh S,Vimal Raj,,11.018122,76.879161 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1036,Vignesh S,Mumtaz,,11.022246,76.887314 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1036,Vignesh S,Vasanthi,,11.036288,76.896416 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Thomson,,11.0119,76.985362 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Akchith B T,,10.996145,76.9811 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,MohanRaju,,10.997478,76.996483 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.992837,76.999072 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Hema Priya Thangavel,,11.025539,77.00148 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Niroshini K,,11.045493,77.044935 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.032004,77.018187 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Devikarani,,11.031813,77.000579 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.04160434,77.00850053 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Muthuraman,,11.06304,77.032933 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066392,77.031442 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,SuriyaKanthan,,11.093797,76.99811 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070486,77.000143 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047794,76.977895 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Senthil Kumar N,,11.049873,76.991573 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960013,76.974766 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.988859,76.947121 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998735,76.96451 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Udayakumar.N,,10.999342,76.95351 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.00415,76.94886 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Suba Surya S,,11.020757,76.96542 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,VIGNESH,,11.023281,76.94624 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Pandiarajan,,11.030569,76.92758 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Rahul Baro,,10.980009,76.998625 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Shriram,,11.003505,76.984452 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Rajesh Pandian,,11.013811,76.980124 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Yaswanth Sai Jami,,11.010783,76.980641 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025539,77.00148 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Madhumitha,,11.021122,77.007887 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Javal Gandha,,11.023757,77.020912 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Akchith B T,,11.018366,77.021275 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Muthuraman,,11.062844,77.032613 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070216,77.000148 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046585,76.975722 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Jothi,,11.040058,77.043623 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Niroshini K,,11.045493,77.044935 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoj,,11.05662,77.011518 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Sandesh,,11.030835,77.007503 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Devikarani,,11.031813,77.000579 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,VIGNESH,,11.023281,76.94624 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Gobi,,11.032978,76.941921 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Suba Surya S,,11.020757,76.96542 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Chiteshkumar s.b,,11.027798,76.966063 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.993342,76.930989 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Bharathi M,,10.995115,76.94964 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1111,Murali P,Akchith B T,,10.9961448,76.98110043 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1111,Murali P,voilet,,11.00416837,76.99083261 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Siri,,11.012833,76.981552 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Priyanka R,,11.027226,76.994195 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,S sanbhagavalli,,11.028831,76.994064 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025539,77.00148 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Lokesh Lakshmanan,,11.020505,76.998949 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Neha shankar,,11.009388,77.023985 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078028,77.012821 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Raghu,,11.079302,76.998273 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070216,77.000148 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Mylswamy,,11.065882,77.001959 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047749,76.978121 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Devikarani,,11.031699,77.000578 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Muthuraman,,11.062844,77.032613 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Pranav A,,11.045245,77.01371 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoharan,,11.03738,77.016265 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Kalaiselvi,,11.027128,76.965536 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Gobi,,11.032978,76.941921 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Micheal nelson J,,11.086282,76.929642 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chandramouleeswaran,,11.072531,76.946732 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,SHUNMUGAKANI,,11.062948,76.942439 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Monisha,,11.058669,76.929852 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Dr Shilpa,,11.037401,76.913703 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Abdul hameed,,11.016043,76.916622 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vimal Raj,,11.018122,76.879161 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Mumtaz,,11.022246,76.887314 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vasanthi,,11.036288,76.896416 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Sowdayan,,10.955085,76.971046 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,VIDYA,,10.975647,76.938357 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Abinaya,,10.988207,76.963732 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Saranya,,10.993722,76.957683 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968658,76.983038 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Akchith B T,,10.996345,76.981434 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004289,76.99107 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.993069,76.999228 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,M.S.JAVID,,11.020649,77.021927 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,SuriyaKanthan,,11.093297,76.998136 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070216,77.000148 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047749,76.978121 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Muthuraman,,11.062844,77.032613 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Devikarani,,11.031699,77.000578 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Suba Surya S,,11.020576,76.965773 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,VIGNESH,,11.023125,76.946402 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,B.Sakthi,,11.029529,76.948804 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Rajeswari Kannan,,11.027863,76.941326 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998783,76.964411 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Udayakumar.N,,10.999383,76.953521 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +latha,Koundampalayam,11.046293,76.9471079,1096,Narayanasamy R,jayanthi,Edayarpalayam,11.038647,76.924461 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Rahul Baro,,10.980009,76.998625 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Shriram,,11.003505,76.984452 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Balachandran P,,11.00074,77.000277 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Yaswanth Sai Jami,,11.010728,76.9803 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Aishwarya,,11.010558,76.980344 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011418,76.985757 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Madhumitha,,11.021169,77.007818 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Narmada,,10.9986858,77.04405656 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Pooja,,11.01927859,77.02396753 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Javal Gandha,,11.02375697,77.02091218 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Akchith B T,,11.01836556,77.02127502 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Muthuraman,,11.062844,77.032613 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.100852,76.991323 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070216,77.000148 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046585,76.975722 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Jothi,,11.040058,77.043623 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoj,,11.05662,77.011518 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Sandesh,,11.030835,77.007503 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Devikarani,,11.031813,77.000579 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Chiteshkumar s.b,,11.027687,76.966423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Suba Surya S,,11.020576,76.965773 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Vinoth Kumar N,,11.01423,76.956703 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,VIGNESH,,11.023125,76.946402 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Pandiarajan,,11.030569,76.92758 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.06746,76.917433 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.993342,76.930989 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Bharathi M,,10.995115,76.94964 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Akchith B T,,10.996145,76.9811 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004168,76.990833 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Balachandran P,,11.00074,77.000277 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,S Rengasamy,,11.002874,77.012567 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Siri,,11.012833,76.981552 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sivakumar,,11.012352,76.981354 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hello Sivi,,11.013288,76.995863 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Priyanka R,,11.027226,76.994195 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,S sanbhagavalli,,11.028831,76.994064 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Lokesh Lakshmanan,,11.020505,76.998949 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Neha shankar,,11.009388,77.023985 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Muthuraman,,11.062844,77.032613 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078028,77.012821 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Raghu,,11.079302,76.998273 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Manikandabalaji,,11.072934,77.002251 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070216,77.000148 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Mylswamy,,11.065882,77.001959 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047749,76.978121 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Anita,,11.050026,76.998834 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Prremanand,,11.040416,77.045887 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Ninusha,,11.029476,77.036005 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Raghuraman,,11.040782,77.022398 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoharan,,11.03738,77.016265 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Pranav A,,11.045245,77.01371 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Devikarani,,11.031813,77.000579 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Karthik,,11.018836,76.920316 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Abdul hameed,,11.016043,76.916622 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vimal Raj,,11.018122,76.879161 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Mumtaz,,11.022246,76.887314 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Rajaram S,,11.02996,76.899157 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vasanthi,,11.036288,76.896416 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Suba Surya S,,11.020757,76.96542 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Jasper T,,11.023258,76.964641 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Kalaiselvi,,11.027128,76.965536 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Vinesh Karthik,,11.033596,76.950734 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chandramouleeswaran,,11.072531,76.946732 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Everstage,,11.066949,76.938443 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,SHUNMUGAKANI,,11.062948,76.942439 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Lalitha Lalitha,,11.050466,76.947481 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Monisha,,11.058669,76.929852 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Dr Shilpa,,11.037401,76.913703 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Gopika,,10.935323,76.979685 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Sowdayan,,10.955085,76.971046 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,VIDYA,,10.975647,76.938357 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Abinaya,,10.988207,76.963732 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Saranya,,10.993722,76.957683 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,1114,Tamilazhagan K,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968658,76.983038 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.993069,76.999228 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Akchith B T,,10.996345,76.981434 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004289,76.99107 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Keerthana,,11.0076,76.992439 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025898,76.998621 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Narmada,,10.9986858,77.04405656 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Sarath,,11.02180615,77.02510505 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Pooja,,11.01927859,77.02396753 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Muthuraman,,11.062844,77.032613 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,SuriyaKanthan,,11.093297,76.998136 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070216,77.000148 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047749,76.978121 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Heera,,11.05175,77.037602 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Raghuraman,,11.04078206,77.02239767 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Devikarani,,11.031813,77.000579 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Suba Surya S,,11.020576,76.965773 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Dr.k.arumugam,,11.024506,76.942392 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Rajeswari Kannan,,11.027753,76.941438 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Yashaswini N,,11.00834,76.94171 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Pandiarajan,,11.030569,76.92758 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.067445,76.917431 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998783,76.964411 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Rahul Baro,,10.980009,76.998625 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Shriram,,11.003505,76.984452 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Keerthana,,11.007513,76.992216 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Balachandran P,,11.00074,77.000277 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,R.K.KAVITHA,,11.001709,77.006876 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Yaswanth Sai Jami,,11.010728,76.9803 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Aishwarya,,11.010558,76.980344 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011418,76.985757 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012934,76.997275 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025994,76.99846 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Pushkar Chauhan,,11.023833,77.007087 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Madhumitha,,11.021169,77.007818 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Narmada,,10.9986858,77.04405656 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Javal Gandha,,11.023757,77.020912 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Muthuraman,,11.062844,77.032613 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.100852,76.991323 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,manikandabalaji,,11.072934,77.002251 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070216,77.000148 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046585,76.975722 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Heera,,11.05175,77.037602 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Jothi Nambu G,,11.058163,77.031429 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Muthu,,11.062796,77.024315 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Manoj,,11.05661958,77.01151805 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.04517321,77.01409765 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Abhishek B,,11.03068,77.009968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Sandesh,,11.030835,77.007503 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Suba Surya S,,11.020576,76.965773 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Chiteshkumar s.b,,11.027687,76.966423 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.01519605,76.94617541 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.02464828,76.94227058 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.06746,76.917433 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.94781552,76.95753784 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.98900419,76.94719466 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.99334201,76.93098906 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Keerthana,,11.0076,76.992439 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004289,76.99107 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Balachandran P,,11.000894,77.000421 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,R.K.KAVITHA,,11.001853,77.006954 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,S Rengasamy,,11.003007,77.012588 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Prabha Senthil,,11.014556,76.982003 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Siri,,11.012833,76.981552 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sivakumar,,11.012352,76.981354 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sharumathi,,11.017384,76.992013 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hello Sivi,,11.013288,76.995863 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012968,76.997448 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Lokesh Lakshmanan,,11.020505,76.998949 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Priyanka R,,11.027226,76.994195 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,S sanbhagavalli,,11.028831,76.994064 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sarath,,11.023359,77.005487 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Neha shankar,,11.009388,77.023985 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Heera,,11.092688,77.031349 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Muthuraman,,11.062844,77.032613 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jothi Nambu G,,11.058163,77.031429 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Muthu,,11.062797,77.024305 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078028,77.012821 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Mylswamy,,11.065882,77.001959 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047749,76.978121 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Anita,,11.050026,76.998834 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Gokila,,11.045494,77.04493 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Ninusha,,11.02947644,77.03600545 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoharan,,11.03738,77.016265 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Pranav A,,11.045245,77.01371 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,S. Rengaraju,,11.055749,77.010306 +Kalpana kitchen,Kasthuri Naickenpalayam,11.0359878,76.9048179,1096,Narayanasamy R,Karthik,,11.01883584,76.92031645 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Abdul hameed,,11.016043,76.916622 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vimal Raj,,11.018122,76.879161 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Mumtaz,,11.022246,76.887314 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Rajaram S,,11.02996,76.899157 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vasanthi,,11.036288,76.896416 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Vigneshwaran,,11.027386,76.941658 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Janaki Velmurugan,,11.07304,76.959964 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chandramouleeswaran,,11.072531,76.946732 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Everstage,,11.066949,76.938443 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,SHUNMUGAKANI,,11.062948,76.942439 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Abinesh,,11.058646,76.950423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Lalitha Lalitha,,11.050466,76.947481 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Monisha,,11.058669,76.929852 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Dr Shilpa,,11.037401,76.913703 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Gopika,,10.935323,76.979685 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,SIVASANKAR,,10.94616517,76.9693739 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Sowdayan,,10.955085,76.971046 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,VIDYA,,10.975647,76.938357 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Abinaya,,10.988207,76.963732 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Saranya,,10.993722,76.957683 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,1114,Tamilazhagan K,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968181,76.982721 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.992837,76.999072 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004168,76.990833 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Keerthana,,11.007513,76.992216 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,R.K.KAVITHA,,11.001709,77.006876 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,P vimal raj,,10.993825,77.013216 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025898,76.998621 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sarath,,11.021806,77.025105 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,SuriyaKanthan,,11.093297,76.998136 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070216,77.000148 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Muthuraman,,11.062844,77.032613 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Muthu,,11.062797,77.024305 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998783,76.964411 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Rajeswari Kannan,,11.027753,76.941438 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Pandiarajan,,11.030569,76.92758 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.067445,76.917431 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Rahul Baro,,10.980009,76.998625 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Shriram,,11.003505,76.984452 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Keerthana,,11.007513,76.992216 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Balachandran P,,11.00074,77.000277 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,R.K.KAVITHA,,11.001709,77.006876 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Prabha senthil,,11.014556,76.982003 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Yaswanth Sai Jami,,11.010783,76.980641 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Rathnasabapathy,,11.018193,76.987097 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012968,76.997448 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025898,76.998621 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029098,77.00208 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Madhumitha,,11.021122,77.007887 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Javal Gandha,,11.023757,77.020912 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Srihari,,11.066392,77.031442 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Muthuraman,,11.06304,77.032933 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Jothi Nambu G,,11.058312,77.031736 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Barathraj,,11.059136,77.029902 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoj,,11.056753,77.011626 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045193,77.014232 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.03251,77.009942 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.100852,76.991323 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Aiswarya S Menon,,11.100352,76.990897 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070216,77.000148 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066759,77.00326 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046585,76.975722 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Sandesh,,11.030835,77.007503 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Chiteshkumar s.b,,11.027687,76.966423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Naveena,,11.022367,76.940419 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Pandiarajan,,11.030486,76.927555 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,SHANKAMESHWAR s,,10.996154,76.947896 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Yashaswini N,,11.00834,76.94171 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.067746,76.917306 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.993342,76.930989 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Bharathi M,,10.995115,76.94964 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,RAJA P S,,10.995489,76.968928 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004168,76.990833 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Keerthana,,11.007513,76.992216 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Abirami,,11.00906,77.004153 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Anitha,,11.013908,76.976786 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sivakumar,,11.012352,76.981354 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Siri,,11.012833,76.981552 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Rathnasabapathy,,11.018193,76.987097 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sharumathi,,11.017384,76.992013 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hello Sivi,,11.013288,76.995863 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012968,76.997448 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Lokesh Lakshmanan,,11.020505,76.998949 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Priyanka R,,11.027226,76.994195 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,S sanbhagavalli,,11.028831,76.994064 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sarath,,11.023359,77.005487 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Neha shankar,,11.009388,77.023985 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Narendiran M,,11.100058,76.989132 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070216,77.000148 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Mylswamy,,11.065882,77.001959 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078028,77.012821 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Muthuraman,,11.062844,77.032613 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jothi Nambu G,,11.058163,77.031429 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029629,77.001803 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Niroshini K,,11.045493,77.044935 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.032004,77.018187 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoharan,,11.03738,77.016265 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Pranav A,,11.045245,77.01371 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Karthik,,11.018836,76.920316 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Abdul hameed,,11.016043,76.916622 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vimal Raj,,11.018122,76.879161 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Mumtaz,,11.022246,76.887314 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vasanthi,,11.036288,76.896416 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Rajaram S,,11.02996,76.899157 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Adith,,11.032341,76.903143 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Jeevitha J,,11.009151,76.964335 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Suba Surya S,,11.020757,76.96542 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Meenakshi,,11.022517,76.950222 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Vinesh Karthik,,11.033596,76.950734 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Vigneshwaran,,11.027386,76.941658 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Dr Shilpa,,11.037401,76.913703 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Monisha,,11.058669,76.929852 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Everstage,,11.066949,76.938443 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chandramouleeswaran,,11.072531,76.946732 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Janaki Velmurugan,,11.07304,76.959964 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Abinesh,,11.058646,76.950423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Lalitha Lalitha,,11.050466,76.947481 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,L. Rajeswari,,11.04543,76.941316 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Sowdayan,,10.955085,76.971046 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Abinaya,,10.988207,76.963732 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,1114,Tamilazhagan K,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968181,76.982721 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.992837,76.999072 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004168,76.990833 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,R.K.KAVITHA,,11.001709,77.006876 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,P vimal raj,,10.993825,77.013216 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,RAJA P S,,10.995696,76.969382 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Rathnasabapathy,,11.018193,76.987097 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025898,76.998621 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sarath,,11.021806,77.025105 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029629,77.001803 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Muthuraman,,11.062844,77.032613 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Purushothaman,,11.059532,77.016443 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070216,77.000148 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Raghuraman,,11.040782,77.022398 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.032004,77.018187 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,SHANKAMESHWAR s,,10.996154,76.947896 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Yashaswini N,,11.00834,76.94171 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Suba Surya S,,11.020576,76.965773 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Chandru,,11.014257,76.956513 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Rajeswari Kannan,,11.027753,76.941438 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.067445,76.917431 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Nagaraj,,10.96001252,76.97476551 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.99873532,76.96450978 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.98885907,76.94712115 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Namachivayam,,11.00414968,76.94885991 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Ajay A,,11.021313,76.988684 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Rahul Baro,,10.980368,76.998784 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Dr.ThivyaRubini,,10.994722,76.987471 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthik,,10.996887,76.983037 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Shriram,,11.003632,76.984753 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Balachandran P,,11.000894,77.000421 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Rajesh Pandian,,11.013786,76.979778 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Yaswanth Sai Jami,,11.010728,76.9803 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Aishwarya,,11.010558,76.980344 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011418,76.985757 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012934,76.997275 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025994,76.99846 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029226,77.001954 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Javal Gandha,,11.023757,77.020912 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.101428,76.99123 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Aiswarya S Menon,,11.100923,76.990799 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066392,77.031442 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Muthuraman,,11.06304,77.032933 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jothi Nambu G,,11.058312,77.031736 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Barathraj,,11.059136,77.029902 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066994,77.003286 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070486,77.000143 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046619,76.975473 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,DR SAAKSHI,,11.03017,77.036152 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.031892,77.018362 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Raghuraman,,11.040758,77.022615 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045193,77.014232 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoj,,11.056753,77.011626 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Sriram,,11.059763,77.010817 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Prithika R,,11.027872,77.013924 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Abhishek B,,11.03068,77.009968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Sandesh,,11.030835,77.007503 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Suba Surya S,,11.020576,76.965773 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Chiteshkumar s.b,,11.027687,76.966423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Yashaswini N,,11.008035,76.941827 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.014959,76.946336 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024506,76.942392 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.067746,76.917306 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Divyadharshana Sundharesan,,10.93597535,76.98806485 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.945592,76.969522 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947259,76.957568 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.988859,76.947121 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.99324,76.930754 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,RAJA P S,,10.995489,76.968928 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthik,,10.996693,76.98272 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.992837,76.999072 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Abirami,,11.00906,77.004153 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Siri,,11.012833,76.981552 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sivakumar,,11.012352,76.981354 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Ajay A,,11.021701,76.988943 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hello Sivi,,11.013288,76.995863 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012968,76.997448 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Lokesh Lakshmanan,,11.020505,76.998949 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sarath,,11.023359,77.005487 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vishnupriya damodharan,,11.021456,77.007594 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Neha shankar,,11.009388,77.023985 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jothi Nambu G,,11.058163,77.031429 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Muthuraman,,11.062844,77.032613 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078028,77.012821 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070216,77.000148 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Priya,,11.079302,76.998273 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Raghu,,11.079302,76.998273 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Vishnu Priya,,11.091886,76.96997 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047749,76.978121 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.032004,77.018187 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoharan,,11.03738,77.016265 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Raghuraman,,11.040782,77.022398 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Pranav A,,11.045245,77.01371 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Anita,,11.050026,76.998834 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029629,77.001803 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vimal Raj,,11.018122,76.879161 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Chitra,,11.017932,76.879609 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Mumtaz,,11.022246,76.887314 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Rajaram S,,11.02996,76.899157 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vasanthi,,11.036288,76.896416 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,avinash,,11.004698,76.964773 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Suba Surya S,,11.020757,76.96542 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Meenakshi,,11.022517,76.950222 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Vinesh Karthik,,11.033596,76.950734 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,selvadurai,,11.036702,76.945058 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Abdul hameed,,11.016297,76.917002 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Meerabai,,11.093727,76.93874 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Janaki Velmurugan,,11.07304,76.959964 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chandramouleeswaran,,11.072531,76.946732 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Everstage,,11.066949,76.938443 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,SHUNMUGAKANI,,11.062948,76.942439 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Abinesh,,11.058646,76.950423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Lalitha Lalitha,,11.050466,76.947481 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,L. Rajeswari,,11.04543,76.941316 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Gopika,,10.93532327,76.97968536 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,SIVASANKAR,,10.94616517,76.9693739 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.94781552,76.95753784 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Sowdayan,,10.95508506,76.97104599 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Nagaraj,,10.96044322,76.97456534 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,1114,Tamilazhagan K,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968658,76.983038 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Noorah Jalal,,10.994875,76.990027 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004289,76.99107 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.993069,76.999228 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,P vimal raj,,10.994048,77.013231 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,RAJA P S,,10.995489,76.968928 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.0119,76.985362 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025994,76.99846 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sarath,,11.021806,77.025105 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Anandhi,,11.017711,77.021939 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Purushothaman,,11.059532,77.016443 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Raghuraman,,11.040782,77.022398 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.032004,77.018187 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Muthuraman,,11.062844,77.032613 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Suraj Kumar,,11.070216,77.000148 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047749,76.978121 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029629,77.001803 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,avinash,,11.004356,76.96512 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Suba Surya S,,11.020576,76.965773 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Pandiarajan,,11.030569,76.92758 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Meerabai,,11.093727,76.93874 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.067445,76.917431 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998783,76.964411 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Rahul Baro,,10.980368,76.998784 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Darpan,,10.993643,77.00023 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997915,76.987455 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthik,,10.996887,76.983037 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Shriram,,11.003632,76.984753 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Balachandran P,,11.000894,77.000421 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Rajesh Pandian,,11.013786,76.979778 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Yaswanth Sai Jami,,11.010728,76.9803 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Aishwarya,,11.010558,76.980344 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011418,76.985757 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012934,76.997275 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025994,76.99846 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029226,77.001954 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Suresh Rajeswaran,,11.020948,77.009031 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Anandhi,,11.017711,77.021939 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Javal Gandha,,11.023757,77.020912 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Muthuraman,,11.06304,77.032933 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Sriram,,11.059763,77.010817 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoj,,11.056753,77.011626 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045193,77.014232 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Raghuraman,,11.040744,77.022564 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.03189164,77.01836235 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.100852,76.991323 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jothi Nambu G,,11.058163,77.031429 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Barathraj,,11.058979,77.029612 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066759,77.00326 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046585,76.975722 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Prithika R,,11.027872,77.013924 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Sandesh,,11.030835,77.007503 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Suba Surya S,,11.020576,76.965773 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Dr.k.arumugam,,11.024506,76.942392 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Subhash,,11.036669,76.929886 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Yashaswini N,,11.00834,76.94171 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Pandiarajan,,11.030569,76.92758 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.94781552,76.95753784 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.99334201,76.93098906 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.98900419,76.94719466 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Bharathi M,,10.99511545,76.94963997 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Boobalan,,10.969017,76.990765 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968658,76.983038 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,RAJA P S,,10.995696,76.969382 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Col. Oinam,,10.998643,76.975857 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997915,76.987455 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004289,76.99107 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Yaswanth Sai Jami,,10.999951,76.995844 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.993069,76.999228 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Balachandran P,,11.000894,77.000421 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Abirami,,11.009132,77.004258 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Siri,,11.012833,76.981552 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sivakumar,,11.012352,76.981354 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sharumathi,,11.017384,76.992013 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hello Sivi,,11.013288,76.995863 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012968,76.997448 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Lokesh Lakshmanan,,11.020505,76.998949 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sarath,,11.023359,77.005487 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vishnupriya damodharan,,11.021456,77.007594 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Suresh Rajeswaran,,11.020902,77.009088 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Rajesh,,11.025052,77.01372 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Annie,,11.000971,77.044171 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Neha shankar,,11.009388,77.023985 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Anandhi,,11.017711,77.021939 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Vishnu Priya,,11.091886,76.96997 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Shailesh,,11.077945,76.999568 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078028,77.012821 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Nishath,,11.097808,77.020803 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066759,77.00326 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Mylswamy,,11.065882,77.001959 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047749,76.978121 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Ponmudi Chelvan,,11.049175,76.994497 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Anita,,11.050026,76.998834 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Niroshini K,,11.045493,77.044935 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Muthuraman,,11.062844,77.032613 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Jothi Nambu G,,11.058163,77.031429 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Raghuraman,,11.040769,77.022348 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.032004,77.018187 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Gowtham Murugesan,,11.035345,77.012003 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoharan,,11.03738,77.016265 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Pranav A,,11.045245,77.01371 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029629,77.001803 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Karthik,,11.018836,76.920316 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Srijanani Prasad,,11.002205,76.900761 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vimal Raj,,11.018122,76.879161 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Mumtaz,,11.022246,76.887314 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Rajaram S,,11.02996,76.899157 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vasanthi,,11.036288,76.896416 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Abdul hameed,,11.016072,76.916872 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Balakumar Arumugam,,11.024662,76.915003 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Jeevitha J,,11.009151,76.964335 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Meenakshi,,11.022517,76.950222 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Vigneshwaran,,11.027386,76.941658 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Vinesh Karthik,,11.033596,76.950734 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,selvadurai,,11.036702,76.945058 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Meerabai,,11.093727,76.93874 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Janaki Velmurugan,,11.07304,76.959964 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chandramouleeswaran,,11.072531,76.946732 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Everstage,,11.066949,76.938443 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,SHUNMUGAKANI,,11.062948,76.942439 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Abinesh,,11.058646,76.950423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Lalitha Lalitha,,11.050466,76.947481 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,L. Rajeswari,,11.04543,76.941316 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Gopika,,10.935323,76.979685 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Sowdayan,,10.955085,76.971046 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,1114,Tamilazhagan K,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968658,76.983038 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Noorah Jalal,,10.994875,76.990027 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997915,76.987455 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004289,76.99107 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.993069,76.999228 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,P vimal raj,,10.994048,77.013231 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,RAJA P S,,10.995696,76.969382 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025898,76.998621 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025539,77.00148 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Suresh Rajeswaran,,11.020902,77.009088 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Narmada,,10.998686,77.044057 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sarath,,11.021806,77.025105 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Purushothaman,,11.059532,77.016443 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Shailesh Sudhakar,,11.069784,76.991815 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047749,76.978121 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Raghuraman,,11.040782,77.022398 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.032004,77.018187 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029629,77.001803 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998783,76.964411 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1062,Nagalakshmi M,Yashaswini N,,11.00834048,76.94171046 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.01519605,76.94617541 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Pandiarajan,,11.030569,76.92758 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Meerabai,,11.093727,76.93874 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.067445,76.917431 +selvarani,ramanathapuram,10.992742,77.0053459,753,Manikandan P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Rahul Baro,,10.980009,76.998625 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Nagalakshmi B,,10.997731,76.987182 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Shriram,,11.003505,76.984452 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Balachandran P,,11.00074,77.000277 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thulasidas,,11.008,77.043363 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Rajesh Pandian,,11.013786,76.979778 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011418,76.985757 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012934,76.997275 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029226,77.001954 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Srihari,,11.06616264,77.03113711 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Jothi Nambu G,,11.05816251,77.03142883 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Barathraj,,11.05897859,77.02961226 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Sriram,,11.05959924,77.0107166 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Manoj,,11.05661958,77.01151805 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.04517321,77.01409765 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.03200395,77.01818725 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.101428,76.99123 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Aiswarya S Menon,,11.100923,76.990799 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066994,77.003286 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046628,76.975476 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Prithika R,,11.027872,77.013924 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1096,Narayanasamy R,Subhash,,11.0366903,76.92988802 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.94781552,76.95753784 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.99334201,76.93098906 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.98900419,76.94719466 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Bharathi M,,10.99511545,76.94963997 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Keerthana M,,10.99622654,76.94872418 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043321,77.000588 +selvarani,ramanathapuram,10.992742,77.0053459,753,Manikandan P,vidhya kitchen,ramlakshman nagar,11.016093,77.014683 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Merlyn,,10.96438,76.981495 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Ulaganathan,,10.968205,76.982993 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Uma Ganesh,,10.992837,76.999072 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Sreejit,,10.991544,76.991601 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Nagalakshmi B,,10.997731,76.987182 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,voilet,,11.004168,76.990833 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Balachandran P,,11.00074,77.000277 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Abirami,,11.00906,77.004153 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011418,76.985757 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012934,76.997275 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Lokesh Lakshmanan,,11.020546,76.99879 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sarath,,11.023429,77.005394 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thulasidas,,11.008,77.043363 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Neha shankar,,11.009388,77.023985 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Vishnu Priya,,11.092372,76.969663 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Priya,,11.079663,76.998249 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078376,77.012943 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Srihari,,11.066392,77.031442 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066994,77.003286 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Mylswamy,,11.066109,77.001971 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047794,76.977895 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Niroshini K,,11.045493,77.044935 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Jothi Nambu G,,11.058163,77.031429 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Rajeswari,,11.05418,77.028638 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.03200395,77.01818725 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoharan,,11.03738,77.016265 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Pranav A,,11.045245,77.01371 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029493,77.001814 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Karthik,,11.018836,76.920316 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vimal Raj,,11.018122,76.879161 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Mumtaz,,11.022246,76.887314 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Rajaram S,,11.02996,76.899157 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vasanthi,,11.036288,76.896416 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Ira Mahadevan,,10.999085,76.964268 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Jeevitha J,,11.008854,76.964677 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr Basher ahmed,,11.02405,76.967816 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Subburathinam,,11.023513,76.962124 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Meenakshi,,11.022354,76.950423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024506,76.942392 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,M.Pappa,,11.032698,76.944438 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,selvadurai,,11.03668,76.945208 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Balakumar Arumugam,,11.024662,76.915003 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Dr Shilpa,,11.037386,76.913539 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Janaki Velmurugan,,11.07304,76.959964 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chandramouleeswaran,,11.072531,76.946732 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sundhara Baalaji,,11.062544,76.934595 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,SHUNMUGAKANI,,11.062948,76.942439 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Abinesh,,11.058646,76.950423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Ranjith,,11.045945,76.956321 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,L. Rajeswari,,11.04543,76.941316 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.94781552,76.95753784 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Sowdayan,,10.95508506,76.97104599 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Nagaraj,,10.96044322,76.97456534 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Raajarajan VP,,10.961807,76.983599 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Muthusamy,,10.968181,76.982721 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Noorah Jalal,,10.994661,76.98978 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Nagalakshmi B,,10.997731,76.987182 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,voilet,,11.004168,76.990833 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,Uma Ganesh,,10.992837,76.999072 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1121,Balamurali K,P vimal raj,,10.993825,77.013216 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thulasidas,,11.008,77.043363 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sarath,,11.021806,77.025105 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Kaleeswaran B,,11.032004,77.018187 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029629,77.001803 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066392,77.031442 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047749,76.978121 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Purushothaman,,11.059532,77.016443 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthik abilash,,11.041604,77.008501 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,VIGNESH,,11.023125,76.946402 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Rajeswari Kannan,,11.027753,76.941438 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Ananthan,,11.009591,76.962775 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Dr Basher Ahmed,,11.02405,76.967816 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Subburathinam,,11.023513,76.962124 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.01495936,76.94633635 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.0245061,76.94239248 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Nagaraj,,10.96044322,76.97456534 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998783,76.964411 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Keerthana M,,10.996227,76.948724 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +selvarani,ramanathapuram,10.992742,77.0053459,753,Manikandan P,vidhya kitchen,ramlakshman nagar,11.016093,77.014683 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1111,Murali P,Karthi,,10.97014923,76.98558875 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1111,Murali P,Rahul Baro,,10.98000894,76.9986246 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1111,Murali P,Darpan,,10.99341658,77.0000844 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1111,Murali P,Nagalakshmi B,,10.99773113,76.98718205 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1111,Murali P,Shriram,,11.00350491,76.98445233 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Rajesh Pandian,,11.013811,76.980124 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Aishwarya,,11.010615,76.980685 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012968,76.997448 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029098,77.00208 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thulasidas,,11.008,77.043363 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Anirudh S Rao,,11.101038,77.032167 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.100852,76.991323 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Aiswarya S Menon,,11.100352,76.990897 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066759,77.00326 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046594,76.975726 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Prithika R,,11.027872,77.013924 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Sandesh,,11.030835,77.007503 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Jothi Nambu G,,11.058163,77.031429 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Sriram,,11.059599,77.010717 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoj,,11.05662,77.011518 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.03200395,77.01818725 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Dr.k.arumugam,,11.024506,76.942392 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,M.Pappa,,11.032698,76.944438 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Pandiarajan,,11.030569,76.92758 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Subhash,,11.03669,76.929888 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.06746,76.917433 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Jose,,10.95341937,76.97825785 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.94781552,76.95753784 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.99334201,76.93098906 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.98900419,76.94719466 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Bharathi M,,10.99511545,76.94963997 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Keerthana M,,10.99622654,76.94872418 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +selvarani,ramanathapuram,10.9927424,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.01586214,77.0145905 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016593,77.014637 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Nagalakshmi B,,10.99773113,76.98718205 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Parandama Reddy,,11.01293393,76.997275 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Lokesh Lakshmanan,,11.02054648,76.9987904 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Sarath,,11.02342899,77.00539382 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Pooja,,11.0193081,77.02405943 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1116,Suresh admin,Thulasidas,,11.007917,77.043648 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Merlyn,,10.96437992,76.98149498 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Muthusamy,,10.96818141,76.98272053 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Ulaganathan,,10.96820517,76.9829928 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Karthi,,10.97014923,76.98558875 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,RAJA P S,,10.99548935,76.9689279 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Kannammal,,11.0195932,76.97332543 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Sivakumar,,11.01231214,76.98101934 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Thomson,,11.01189957,76.98536231 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Manikumar,,11.01141839,76.98575718 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Sharumathi,,11.01739462,76.99178588 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Hello Sivi,,11.01325749,76.9956739 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Dr C Surya,,11.00671213,76.99174456 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,voilet,,11.00416837,76.99083261 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Uma Ganesh,,10.99283671,76.99907232 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Kavitha,,10.99897847,77.03077216 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Sudharsan,,11.00174342,77.02716978 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Neha shankar,,11.00931838,77.0240773 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1116,Suresh admin,Abirami,,11.00906016,77.00415312 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1116,Suresh admin,Vishnupriya damodharan,,11.021508,77.007522 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,Vishnu Priya,,11.09237249,76.9696628 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1245,Andy daily test rider ,Praveenkumar MR,,11.078517,77.005382 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,Yagavi,,11.1002638,76.99043959 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,Priya,,11.07966291,76.99824945 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,Shailesh,,11.07829168,76.99955669 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,Mylswamy,,11.0661088,77.00197144 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1245,Andy daily test rider ,Karthikeyan Subramanian,,11.078376,77.012943 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,Srihari,,11.06639188,77.03144169 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,Jothi Nambu G,,11.05831176,77.03173633 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,Rajeswari,,11.05428948,77.02891761 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,Niroshini K,,11.04551512,77.04537766 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,Ninusha,,11.02933886,77.03635871 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,Kaleeswaran B,,11.03189164,77.01836235 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,Manoharan,,11.03732164,77.01642067 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,Athiradh V Nair,,11.04519258,77.01423186 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,Pranav A,,11.04526536,77.01383994 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,yuthish,,11.02949252,77.00181392 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,Saranya S R,,11.04779437,76.97789528 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,Megalai,,11.05152096,76.99926936 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1242,Karan Test Rider,Lakshmanan Visalakshi,,10.947259,76.957568 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1242,Karan Test Rider,Thiruveragan,,10.952453,76.970832 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1242,Karan Test Rider,Sowdayan,,10.954601,76.971211 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1242,Karan Test Rider,Nagaraj,,10.960013,76.974766 +Kalpana kitchen,Kasthuri Naickenpalayam,11.0359878,76.9048179,1325,Suriya Test Auto,Abdul hameed,,11.01984521,76.92449634 +Kalpana kitchen,Kasthuri Naickenpalayam,11.0359878,76.9048179,1325,Suriya Test Auto,Karthik,,11.01883584,76.92031645 +Kalpana kitchen,Kasthuri Naickenpalayam,11.0359878,76.9048179,1325,Suriya Test Auto,Vimal Raj,,11.01812244,76.87916104 +Kalpana kitchen,Kasthuri Naickenpalayam,11.0359878,76.9048179,1325,Suriya Test Auto,Mumtaz,,11.0222465,76.88731402 +Kalpana kitchen,Kasthuri Naickenpalayam,11.0359878,76.9048179,1325,Suriya Test Auto,Vasanthi,,11.03628776,76.89641637 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,Ira Mahadevan,,10.99908529,76.96426756 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,Jeevitha J,,11.00885352,76.96467709 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,Dr Basher ahmed,,11.02405046,76.96781558 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,Meenakshi,,11.02235384,76.95042337 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,Dr.k.arumugam,,11.0245061,76.94239248 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,Vigneshwaran,,11.02727076,76.94177328 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,M.Pappa,,11.03269781,76.9444377 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,selvadurai,,11.03668002,76.94520822 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,Vinesh Karthik,,11.033543,76.9509409 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,Ranjith,,11.04601606,76.95658363 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,Janaki Velmurugan,,11.0733816,76.96026256 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,Chandramouleeswaran,,11.07286716,76.94689839 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,Everstage,,11.06722941,76.93852704 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,SHUNMUGAKANI,,11.06318911,76.94256258 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,L. Rajeswari,,11.0454955,76.94142821 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,Dr Shilpa,,11.03738596,76.91353945 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1325,Suriya Test Auto,Balakumar Arumugam,,11.02466165,76.91500293 +Nandhini s kitchens,Maniakaram Palayam,11.0432363,77.0006758,1245,Andy daily test rider ,vidhya kitchen,ramlakshman nagar,11.0165932,77.0146367 +selvarani,ramanathapuram,10.9927424,77.0053459,1116,Suresh admin,vidhya kitchen,ramlakshman nagar,11.01609331,77.01468294 +Manjusha kitchen ,Ganapathy,11.0517946,76.9917895,1245,Andy daily test rider ,Nandhini s kitchens,Maniakaram Palayam,11.04332103,77.00058783 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Raajarajan VP,,10.962347,76.983907 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Muthusamy,,10.968658,76.983038 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968682,76.983307 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Noorah Jalal,,10.994875,76.990027 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997915,76.987455 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004289,76.99107 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Dr C Surya,,11.006807,76.991973 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.993069,76.999228 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,P vimal raj,,10.994048,77.013231 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,RAJA P S,,10.995696,76.969382 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Muthumugil,,11.028274,76.995902 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025898,76.998621 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thulasidas,,11.008,77.043363 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sarath,,11.021806,77.025105 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Purushothaman,,11.059532,77.016443 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Yagavi,,11.100264,76.99044 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Shailesh Sudhakar,,11.07005,76.991726 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047794,76.977895 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029493,77.001814 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Dr Basher Ahmed,,11.02405,76.967816 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Chandru,,11.014257,76.956513 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,VIGNESH,,11.023125,76.946402 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,M.Pappa,,11.032698,76.944438 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Elayaraja,,11.009686,76.954117 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Rajeswari Kannan,,11.027863,76.941326 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.067445,76.917431 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Thiruveragan,,10.95295827,76.97067058 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Nagaraj,,10.96044322,76.97456534 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.99878266,76.96441114 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.98900419,76.94719466 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Keerthana M,,10.996227,76.948724 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Rahul Baro,,10.980009,76.998625 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Darpan,,10.993417,77.000084 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997731,76.987182 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011418,76.985757 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012934,76.997275 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029226,77.001954 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Pushkar Chauhan,,11.023833,77.007087 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thulasidas,,11.008,77.043363 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Anirudh S Rao,,11.101038,77.032167 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.100852,76.991323 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Aiswarya S Menon,,11.100352,76.990897 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066759,77.00326 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046594,76.975726 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Barathraj,,11.058887,77.029601 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Sriram,,11.059599,77.010717 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoj,,11.05662,77.011518 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.032004,77.018187 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Prithika R,,11.027872,77.013924 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Abhishek B,,11.03068,77.009968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Sandesh,,11.030835,77.007503 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Athira Sooraj,,11.026429,76.998343 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Balasundaram Doraisami,,11.024776,76.957684 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Bala,,11.023125,76.946402 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,B.Sakthi,,11.029529,76.948804 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Pandiarajan,,11.030569,76.92758 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Subhash,,11.03669,76.929888 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.067746,76.917306 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Monisha,,11.058867,76.92985 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947259,76.957568 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.99324,76.930754 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.988859,76.947121 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Keerthana M,,10.996154,76.948666 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016593,77.014637 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Merlyn,,10.96438,76.981495 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968205,76.982993 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.992837,76.999072 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997731,76.987182 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004168,76.990833 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Abirami,,11.00906,77.004153 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,RAJA P S,,10.995696,76.969382 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sivakumar,,11.012352,76.981354 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hello Sivi,,11.013288,76.995863 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012968,76.997448 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Lokesh Lakshmanan,,11.020505,76.998949 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sarath,,11.023359,77.005487 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vishnupriya damodharan,,11.021456,77.007594 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thulasidas,,11.007917,77.043648 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.998978,77.030772 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001743,77.02717 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Neha shankar,,11.009318,77.024077 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019308,77.024059 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Priya,,11.079302,76.998273 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Shailesh,,11.077945,76.999568 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Praveenkumar MR,,11.078167,77.005336 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078028,77.012821 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066759,77.00326 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Mylswamy,,11.065882,77.001959 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Megalai,,11.051439,76.999283 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047749,76.978121 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029629,77.001803 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Niroshini K,,11.045493,77.044935 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Ninusha,,11.029476,77.036005 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.032004,77.018187 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoharan,,11.03738,77.016265 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Pranav A,,11.045245,77.01371 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Ira Mahadevan,,10.999479,76.963929 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Jeevitha J,,11.009151,76.964335 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr Basher ahmed,,11.024197,76.967442 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Balasundaram Doraisami,,11.024915,76.957411 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Meenakshi,,11.022517,76.950222 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Vigneshwaran,,11.027386,76.941658 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,selvadurai,,11.036702,76.945058 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Vimal Raj,,11.018151,76.879411 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Mumtaz,,11.022275,76.887564 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Vasanthi,,11.036316,76.896666 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Dr Shilpa,,11.037386,76.913539 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Balakumar Arumugam,,11.024662,76.915003 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Karthik,,11.018864,76.920567 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Abdul hameed,,11.019874,76.924746 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Janaki Velmurugan,,11.07304,76.959964 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chandramouleeswaran,,11.072531,76.946732 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,SHUNMUGAKANI,,11.062948,76.942439 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Abinesh,,11.058646,76.950423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Ranjith,,11.045945,76.956321 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,L. Rajeswari,,11.04543,76.941316 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Gopika,,10.935323,76.979685 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Thiruveragan,,10.952958,76.970671 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Sowdayan,,10.955085,76.971046 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,1114,Tamilazhagan K,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Raajarajan VP,,10.962347,76.983907 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968682,76.983307 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Noorah Jalal,,10.994875,76.990027 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997915,76.987455 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004289,76.99107 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.993069,76.999228 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,P vimal raj,,10.994048,77.013231 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,RAJA P S,,10.995696,76.969382 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Muthumugil,,11.028274,76.995902 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Athira Sooraj,,11.025898,76.998621 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thulasidas,,11.008,77.043363 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sarath,,11.021806,77.025105 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Ramanathan,,11.019209,77.023967 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Shailesh Sudhakar,,11.07005,76.991726 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047794,76.977895 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthik abilash,,11.041588,77.008579 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Srihari,,11.066392,77.031442 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Purushothaman,,11.059695,77.0166 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.03251,77.009942 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029493,77.001814 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Dr Basher Ahmed,,11.02405,76.967816 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Balasundaram Doraisami,,11.024776,76.957684 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,VIGNESH,,11.023125,76.946402 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,B.Sakthi,,11.029529,76.948804 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Elayaraja,,11.009395,76.954357 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.014959,76.946336 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024506,76.942392 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Pandiarajan,,11.030486,76.927555 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.067445,76.917431 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Thiruveragan,,10.952958,76.970671 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998783,76.964411 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Keerthana M,,10.996227,76.948724 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Rahul Baro,,10.980009,76.998625 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Darpan,,10.993417,77.000084 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997731,76.987182 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,S.Vijendran,,11.000045,76.996248 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thulasidas,,11.007917,77.043648 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Mohammed Muzzammil,,11.000566,77.029147 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001743,77.02717 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Prathamesh Belgaonkar,,11.003144,77.027872 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019308,77.024059 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Aishwarya,,11.010558,76.980344 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011418,76.985757 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012934,76.997275 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029226,77.001954 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Anirudh S Rao,,11.101038,77.032167 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.100852,76.991323 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Aiswarya S Menon,,11.100352,76.990897 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066759,77.00326 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Sriram,,11.059599,77.010717 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046594,76.975726 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Srihari,,11.066392,77.031442 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Barathraj,,11.059043,77.02989 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045193,77.014232 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.031892,77.018362 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Sanju,,11.033403,77.015599 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Prithika R,,11.027718,77.014057 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Vinaya Balakrishnan,,11.030764,77.010055 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Sandesh,,11.030711,77.007572 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Athira Sooraj,,11.02626,76.99832 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Jovitha,,11.024056,76.957821 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Balasundaram Doraisami,,11.024915,76.957411 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Meenakshi,,11.022517,76.950222 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Bala,,11.023281,76.94624 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Vinoth kumar,,11.000962,76.943824 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Pandiarajan,,11.030569,76.92758 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Subhash,,11.03669,76.929888 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.067746,76.917306 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Rachana Kamble,,11.04011,76.937385 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.94725855,76.95756775 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.99324026,76.93075351 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.98885907,76.94712115 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Bharathi M,,10.99503144,76.94959091 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Keerthana M,,10.99615364,76.94866596 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016593,77.014637 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Merlyn,,10.96438,76.981495 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968205,76.982993 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,srikar varma,,10.991137,76.978825 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997731,76.987182 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004168,76.990833 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,S.Vijendran,,11.000045,76.996248 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Abirami,,11.00906,77.004153 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,RAJA P S,,10.995696,76.969382 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Manikumar,,11.011467,76.986044 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Abhinaya S J,,11.021263,76.988943 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sharumathi,,11.017384,76.992013 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hello Sivi,,11.013288,76.995863 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012968,76.997448 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Lokesh Lakshmanan,,11.020505,76.998949 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Venkatesan.K,,11.024098,77.003058 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sarath,,11.023359,77.005487 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vishnupriya damodharan,,11.021456,77.007594 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thulasidas,,11.008,77.043363 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Neha shankar,,11.009388,77.023985 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Vishnu Priya,,11.091886,76.96997 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Muruganandam,,11.096171,77.003195 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Priya,,11.079302,76.998273 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Shailesh,,11.077945,76.999568 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Praveenkumar MR,,11.078167,77.005336 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078028,77.012821 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066759,77.00326 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Mylswamy,,11.065882,77.001959 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Megalai,,11.051439,76.999283 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047749,76.978121 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Niroshini K,,11.045493,77.044935 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,LEGA SRI,,11.042537,77.044737 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Ninusha,,11.029476,77.036005 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoharan,,11.03738,77.016265 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Pranav A,,11.045245,77.01371 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029629,77.001803 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Sivashankari Lakshmanan,,11.017386,76.924899 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Abdul hameed,,11.019845,76.924496 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Karthik,,11.018836,76.920316 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vimal Raj,,11.018122,76.879161 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Mumtaz,,11.022246,76.887314 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vasanthi,,11.036288,76.896416 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Vinoth kumar,,11.000962,76.943824 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Dinesh Kumar,,11.015175,76.953401 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeevitha J,,11.009151,76.964335 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Chiteshkumar s.b,,11.018607,76.968135 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Dr Basher ahmed,,11.024197,76.967442 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Arun,,11.0244,76.967511 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Balasundaram Doraisami,,11.024915,76.957411 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Meenakshi,,11.022517,76.950222 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,selvadurai,,11.036702,76.945058 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Balakumar Arumugam,,11.024662,76.915003 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.94781552,76.95753784 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Thiruveragan,,10.95295827,76.97067058 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Sowdayan,,10.95508506,76.97104599 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Nagaraj,,10.96044322,76.97456534 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,1114,Tamilazhagan K,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,RAJA P S,,10.995489,76.968928 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vivekanandan,,11.014161,76.984954 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Muthumugil,,11.028394,76.995713 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Raajarajan VP,,10.962347,76.983907 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968682,76.983307 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Noorah Jalal,,10.994875,76.990027 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997915,76.987455 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004289,76.99107 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,S.Vijendran,,11.000206,76.996432 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,P vimal raj,,10.994048,77.013231 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thulasidas,,11.008,77.043363 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Mohammed Muzzammil,,11.000722,77.029004 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sarath,,11.021806,77.025105 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Shailesh Sudhakar,,11.069784,76.991815 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047749,76.978121 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029629,77.001803 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.032004,77.018187 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoj,,11.05662,77.011518 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Arun,,11.024256,76.967885 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Dr Basher Ahmed,,11.02405,76.967816 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Balasundaram Doraisami,,11.024776,76.957684 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,B.Sakthi,,11.029529,76.948804 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Vinoth kumar,,11.000962,76.943824 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,VIGNESH,,11.023281,76.94624 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.067445,76.917431 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Thiruveragan,,10.95295827,76.97067058 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Nagaraj,,10.96044322,76.97456534 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.99878266,76.96441114 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.98900419,76.94719466 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Keerthana M,,10.996227,76.948724 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.004143,76.948916 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Rahul Baro,,10.980009,76.998625 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Darpan,,10.993417,77.000084 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997731,76.987182 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Aishwarya,,11.010615,76.980685 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012968,76.997448 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029098,77.00208 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Pushkar Chauhan,,11.023759,77.007164 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thulasidas,,11.008,77.043363 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Mohammed Muzzammil,,11.000722,77.029004 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Anirudh S Rao,,11.101038,77.032167 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.100852,76.991323 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Aiswarya S Menon,,11.100352,76.990897 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066759,77.00326 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046594,76.975726 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Athira Sooraj,,11.026429,76.998343 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Sandesh,,11.030835,77.007503 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Priya,,11.039803,77.0182 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.032004,77.018187 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Balasundaram Doraisami,,11.024776,76.957684 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Meenakshi,,11.022354,76.950423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Bala,,11.023125,76.946402 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,B.Sakthi,,11.029529,76.948804 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Subhash,,11.03669,76.929888 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.06746,76.917433 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Monisha,,11.058669,76.929852 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.993342,76.930989 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Bharathi M,,10.995115,76.94964 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Keerthana M,,10.996227,76.948724 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043321,77.000588 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Merlyn,,10.964894,76.981824 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968682,76.983307 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997915,76.987455 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004289,76.99107 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sivakumar,,11.012352,76.981354 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Aishwarya,,11.010615,76.980685 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vebhenesh,,11.01208,76.985875 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hello Sivi,,11.013288,76.995863 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012968,76.997448 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sharumathi,,11.017384,76.992013 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Abhinaya S J,,11.021263,76.988943 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Abirami,,11.020943,76.995091 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Venkatesan.K,,11.024098,77.003058 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sarath,,11.023359,77.005487 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vishnupriya damodharan,,11.021456,77.007594 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thulasidas,,11.008,77.043363 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Ramya Devarajan,,11.00848,77.023942 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Neha shankar,,11.009388,77.023985 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066392,77.031442 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078376,77.012943 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Praveenkumar MR,,11.078517,77.005382 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Priya,,11.079663,76.998249 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Shailesh,,11.078292,76.999557 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066994,77.003286 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Megalai,,11.051521,76.999269 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047794,76.977895 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029493,77.001814 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Niroshini K,,11.045515,77.045378 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Dr. Niveditha,,11.04431,77.040018 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Rohan Krishna S,,11.040072,77.033466 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Ninusha,,11.029339,77.036359 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.031892,77.018362 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.03251,77.009942 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoharan,,11.037322,77.016421 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045193,77.014232 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Pranav A,,11.045265,77.01384 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Abdul hameed,,11.019845,76.924496 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vimal Raj,,11.018122,76.879161 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Mumtaz,,11.022246,76.887314 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Rajaram S,,11.02996,76.899157 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vasanthi,,11.036288,76.896416 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Jeevitha J,,11.008854,76.964677 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Chiteshkumar s.b,,11.018405,76.968516 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr Basher ahmed,,11.02405,76.967816 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Arul,,11.023186,76.960023 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Balasundaram Doraisami,,11.024776,76.957684 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Meenakshi,,11.022354,76.950423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,B.Sakthi,,11.029529,76.948804 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024506,76.942392 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Vigneshwaran,,11.027271,76.941773 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Balakumar Arumugam,,11.024662,76.915003 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Yamuna,,11.06609,76.887071 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.06773,76.917305 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097613,76.938714 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.079563,76.945301 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Gopika,,10.935323,76.979685 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Thiruveragan,,10.952958,76.970671 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Sowdayan,,10.955085,76.971046 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Manjusha kitchen ,Ganapathy,11.0517946,76.9917895,1114,Tamilazhagan K,Nandhini s kitchens,Maniakaram Palayam,11.04340492,77.00050073 +jayanthi,Edayarpalayam,11.038493,76.9240062,1062,Nagalakshmi M,Bhuvaneshwari kitchen ,R.S. Puram,11.003864,76.954244 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vivekanandan,,11.014161,76.984954 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Muthumugil,,11.028394,76.995713 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968205,76.982993 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Raajarajan VP,,10.962347,76.983907 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997915,76.987455 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004289,76.99107 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Madhumitha,,10.99312,77.000718 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,P vimal raj,,10.994048,77.013231 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thulasidas,,11.008,77.043363 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Mohammed Muzzammil,,11.000722,77.029004 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sarath,,11.021806,77.025105 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029629,77.001803 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Shailesh Sudhakar,,11.069784,76.991815 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047749,76.978121 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Athira Sooraj,,11.026429,76.998343 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.032004,77.018187 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoj,,11.05662,77.011518 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Dr Basher Ahmed,,11.02405,76.967816 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Balasundaram Doraisami,,11.024776,76.957684 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Meenakshi,,11.022354,76.950423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,B.Sakthi,,11.029529,76.948804 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,VIGNESH,,11.023281,76.94624 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr.k.arumugam,,11.024648,76.942271 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Pandiarajan,,11.030569,76.92758 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Jeya Balaji,,11.067445,76.917431 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Thiruveragan,,10.952958,76.970671 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Keerthana M,,10.996227,76.948724 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998783,76.964411 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Rahul Baro,,10.980009,76.998625 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Darpan,,10.993417,77.000084 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997731,76.987182 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Aishwarya,,11.010558,76.980344 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012934,76.997275 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Karthik Sivakumar,,11.025366,76.995948 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,yuthish,,11.029226,77.001954 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thulasidas,,11.008,77.043363 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Mohammed Muzzammil,,11.000722,77.029004 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Javal Gandha,,11.023757,77.020912 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Anirudh S Rao,,11.101616,77.032482 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.101428,76.99123 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Aiswarya S Menon,,11.100923,76.990799 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066994,77.003286 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046628,76.975476 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Srihari,,11.06616264,77.03113711 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Mukilan M,,11.05025886,77.03481389 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Jothi,,11.04005837,77.04362285 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.03200395,77.01818725 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.04517321,77.01409765 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Athira Sooraj,,11.02626,76.99832 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Sandesh,,11.030711,77.007572 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1096,Narayanasamy R,Meenakshi,,11.02235384,76.95042337 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1096,Narayanasamy R,Bala,,11.02312526,76.94640155 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1096,Narayanasamy R,B.Sakthi,,11.02952927,76.9488038 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr S Ramesh,,11.023264,76.943789 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Pandiarajan,,11.030569,76.92758 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Subhash,,11.03669,76.929888 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Abinesh,,11.058646,76.950423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,SHUNMUGAKANI,,11.062948,76.942439 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Dr Shriram,,11.064638,76.940346 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sundhara Baalaji,,11.062544,76.934595 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Deepika,,11.047907,76.92803 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sivasankari,,11.045813,76.932972 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.945592,76.969522 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947259,76.957568 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.99324,76.930754 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.988859,76.947121 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Bharathi M,,10.995031,76.949591 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Keerthana M,,10.996154,76.948666 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,883,Rajan A,RAJA P S,,10.99569564,76.9693818 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,883,Rajan A,Kannammal,,11.01956086,76.97373579 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,883,Rajan A,Thomson,,11.0119434,76.98565351 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,883,Rajan A,Vivekanandan,,11.01418247,76.98524956 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,883,Rajan A,Muthumugil,,11.02827418,76.99590203 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1111,Murali P,Raajarajan VP,,10.96234667,76.9839072 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1111,Murali P,Ulaganathan,,10.96868157,76.98330746 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1111,Murali P,Karthi,,10.97060639,76.98587771 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1111,Murali P,Noorah Jalal,,10.99487523,76.99002736 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1111,Murali P,Nagalakshmi B,,10.99791523,76.98745523 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1111,Murali P,voilet,,11.00428874,76.99106965 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,1111,Murali P,P vimal raj,,10.99404777,77.01323106 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Thulasidas,,11.00800005,77.04336258 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Mohammed Muzzammil,,11.00072202,77.02900434 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Sarath,,11.02180615,77.02510505 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Pooja,,11.01927859,77.02396753 +Vidhya kitchen,uppilipalayam ,11.0163268,77.0147763,753,Manikandan P,Janane,,11.0150679,77.015652 +latha,Koundampalayam,11.046293,76.9471079,1096,Narayanasamy R,jayanthi,Edayarpalayam,11.03857012,76.92423491 +selvarani,ramanathapuram,10.9927424,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.01586214,77.0145905 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.06616264,77.03113711 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,950,Jayasabesh Kumar S,Manoj,,11.05661958,77.01151805 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,950,Jayasabesh Kumar S,Shailesh Sudhakar,,11.06978414,76.99181469 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.04774925,76.97812081 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,883,Rajan A,yuthish,,11.02949252,77.00181392 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Jothi,,11.04005837,77.04362285 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.03200395,77.01818725 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.03261597,77.00984985 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.04160434,77.00850053 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1096,Narayanasamy R,Dr Basher Ahmed,,11.02405046,76.96781558 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1096,Narayanasamy R,Meenakshi,,11.02235384,76.95042337 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1096,Narayanasamy R,B.Sakthi,,11.02952927,76.9488038 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.01495936,76.94633635 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1062,Nagalakshmi M,VIGNESH,,11.02312526,76.94640155 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,897,Varun Edward,Sri Gokul,,11.09703104,76.93862819 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,897,Varun Edward,Janaki Velmurugan,,11.07303991,76.95996375 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,897,Varun Edward,Dhinesh,,11.0717175,76.94785003 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,897,Varun Edward,Dr Shriram,,11.0646385,76.94034639 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,897,Varun Edward,Monisha,,11.05866946,76.92985218 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,897,Varun Edward,R Venkatesh,,11.04831935,76.94280495 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Don Jackson,,10.94380019,76.9291112 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Thiruveragan,,10.95295827,76.97067058 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Nagaraj,,10.96044322,76.97456534 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.99878266,76.96441114 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.98900419,76.94719466 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Keerthana M,,10.99622654,76.94872418 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Namachivayam,,11.00414342,76.94891621 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Merlyn,,10.96438,76.981495 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968205,76.982993 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997731,76.987182 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,voilet,,11.004168,76.990833 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sivakumar,,11.012312,76.981019 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Abhinaya S J,,11.021313,76.988684 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sharumathi,,11.017395,76.991786 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hello Sivi,,11.013257,76.995674 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012934,76.997275 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Abirami,,11.020989,76.994894 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Sarath,,11.023429,77.005394 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vishnupriya damodharan,,11.021508,77.007522 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Thulasidas,,11.008,77.043363 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Ramya Devarajan,,11.00848,77.023942 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Neha shankar,,11.009388,77.023985 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Janane,,11.015068,77.015652 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066392,77.031442 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078376,77.012943 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Praveenkumar MR,,11.078517,77.005382 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Shailesh,,11.078292,76.999557 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066994,77.003286 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Mylswamy,,11.066109,77.001971 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Anisha,,11.054292,77.003435 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Megalai,,11.051521,76.999269 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Saranya S R,,11.047794,76.977895 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,yuthish,,11.029629,77.001803 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Abarna,,11.060256,77.052286 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Niroshini K,,11.045493,77.044935 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Prremanand,,11.040416,77.045887 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Jothi,,11.040058,77.043623 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Dr. Niveditha,,11.0443,77.039628 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Mukilan M,,11.050259,77.034814 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Rohan Krishna S,,11.040103,77.033142 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Ninusha,,11.029476,77.036005 +Daily grubs nandhini,Maniakaram Palayam,11.0432363,77.0006758,1114,Tamilazhagan K,Kaleeswaran B,,11.03200395,77.01818725 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoharan,,11.03738,77.016265 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Pranav A,,11.045245,77.01371 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Dhinesh Kumar,,11.012149,76.923603 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Abdul hameed,,11.019845,76.924496 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Karthik,,11.018836,76.920316 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vimal Raj,,11.018122,76.879161 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Mumtaz,,11.022246,76.887314 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Rajaram S,,11.02996,76.899157 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vasanthi,,11.036288,76.896416 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Jeevitha J,,11.008854,76.964677 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Chiteshkumar s.b,,11.018405,76.968516 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr Basher ahmed,,11.02405,76.967816 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Meenakshi,,11.022354,76.950423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,B.Sakthi,,11.029529,76.948804 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Balakumar Arumugam,,11.024662,76.915003 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Yamuna,,11.065821,76.887496 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Monisha,,11.058669,76.929852 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Everstage,,11.066949,76.938443 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Janaki Velmurugan,,11.07304,76.959964 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Abinesh,,11.058646,76.950423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,R Venkatesh,,11.048319,76.942805 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Anu priyanga,,11.044426,76.944844 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,L. Rajeswari,,11.04543,76.941316 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Don Jackson,,10.9438,76.929111 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Gopika,,10.935323,76.979685 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Thiruveragan,,10.952958,76.970671 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Sowdayan,,10.955085,76.971046 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Manjusha kitchen ,Ganapathy,11.0517946,76.9917895,1114,Tamilazhagan K,Nandhini s kitchens,Maniakaram Palayam,11.04340492,77.00050073 +jayanthi,Edayarpalayam,11.038493,76.9240062,1062,Nagalakshmi M,Bhuvaneshwari kitchen ,R.S. Puram,11.004207,76.953945 +latha,Koundampalayam,11.046293,76.9471079,1062,Nagalakshmi M,jayanthi,Edayarpalayam,11.038647,76.924461 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Rahul Baro,,10.980009,76.998625 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997731,76.987182 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Mohammed Muzzammil,,11.000722,77.029004 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Javal Gandha,,11.023757,77.020912 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Yaswanth Sai Jami,,11.010728,76.9803 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012934,76.997275 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Karthik Sivakumar,,11.025366,76.995948 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025631,77.001348 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066759,77.00326 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046594,76.975726 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Sedhuram,,11.036925,77.038098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Mukilan M,,11.050259,77.034814 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Sandesh,,11.030711,77.007572 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1096,Narayanasamy R,Kishore Kumar,,11.03415216,76.96378945 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1096,Narayanasamy R,Meenakshi,,11.02235384,76.95042337 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1096,Narayanasamy R,B.Sakthi,,11.02952927,76.9488038 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Bala,,11.023281,76.94624 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Subhash,,11.03669,76.929888 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,SHUNMUGAKANI,,11.063189,76.942563 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Monisha,,11.058867,76.92985 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.993342,76.930989 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Keerthana M,,10.996227,76.948724 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Merlyn,,10.964894,76.981824 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968682,76.983307 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.993069,76.999228 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997915,76.987455 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Yaswanth Sai Jami,,10.999951,76.995844 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Abirami,,11.009132,77.004258 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,RAJA P S,,10.995489,76.968928 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Gopisetty Siri,,11.012798,76.98122 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Ramagopalan,,11.011741,76.984076 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012934,76.997275 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025631,77.001348 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Ramya Devarajan,,11.00848,77.023942 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Janane,,11.015068,77.015652 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jayasri. N,,11.083883,76.980407 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Muruganandam,,11.096171,77.003195 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Praveenkumar MR,,11.078167,77.005336 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078028,77.012821 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066759,77.00326 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Mylswamy,,11.065882,77.001959 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Megalai,,11.051439,76.999283 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Mukilan M,,11.050259,77.034814 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Sedhuram,,11.036925,77.038098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Rohan Krishna S,,11.040103,77.033142 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoharan,,11.03738,77.016265 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Rushyendramani,,11.038292,77.013339 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Dhinesh Kumar,,11.012149,76.923603 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Abdul hameed,,11.019845,76.924496 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Karthik,,11.018836,76.920316 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vimal Raj,,11.018122,76.879161 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Mumtaz,,11.022246,76.887314 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Rajaram S,,11.02996,76.899157 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vasanthi,,11.036288,76.896416 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Ms. S. Hannah,,11.026658,76.965216 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr Basher ahmed,,11.024197,76.967442 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,sankar R,,11.022822,76.968625 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Chiteshkumar s.b,,11.018607,76.968135 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Priyanka,,11.015167,76.9498 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Meenakshi,,11.022517,76.950222 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Yamuna,,11.06609,76.887071 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097613,76.938714 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.079563,76.945301 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Thiruveragan,,10.952958,76.970671 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Sowdayan,,10.955085,76.971046 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968205,76.982993 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ramagopalan,,10.996912,76.979963 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997731,76.987182 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Noorah Jalal,,10.994661,76.98978 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.992837,76.999072 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vivekanandan,,11.014161,76.984954 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Muthumugil,,11.028394,76.995713 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025631,77.001348 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Mohammed Muzzammil,,11.000722,77.029004 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Janane,,11.015068,77.015652 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Dr Basher Ahmed,,11.02405,76.967816 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Meenakshi,,11.022354,76.950423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,B.Sakthi,,11.029529,76.948804 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Sedhuram,,11.036925,77.038098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Manoj,,11.05662,77.011518 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Priyanka,,11.015167,76.9498 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,VIGNESH,,11.023281,76.94624 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097613,76.938714 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Meera Bai,,11.094275,76.938827 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Thiruveragan,,10.952453,76.970832 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.988859,76.947121 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Keerthana M,,10.996154,76.948666 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Namachivayam,,11.00415,76.94886 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.998735,76.96451 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Rahul Baro,,10.980009,76.998625 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ramagopalan,,10.996912,76.979963 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997731,76.987182 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Mohammed Muzzammil,,11.000566,77.029147 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019308,77.024059 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Javal Gandha,,11.023831,77.020974 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kandavelu,,11.032243,77.010081 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Yaswanth Sai Jami,,11.010728,76.9803 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012934,76.997275 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Karthik Sivakumar,,11.025366,76.995948 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025631,77.001348 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Pushkar Chauhan,,11.023833,77.007087 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001743,77.02717 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Guru Krishna,,11.082638,76.964918 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Bhaswar Tudu,,11.100852,76.991323 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066759,77.00326 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Sreedevi,,11.046594,76.975726 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,Sandesh,,11.030711,77.007572 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Mukilan M,,11.050259,77.034814 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Sedhuram,,11.036925,77.038098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1096,Narayanasamy R,Meenakshi,,11.02251733,76.95022197 +Daily grubs(jayanthi kitchen),Kavandam,11.0388679,76.9300797,1096,Narayanasamy R,B.Sakthi,,11.02962172,76.94861843 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Bala,,11.023281,76.94624 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,SHUNMUGAKANI,,11.062948,76.942439 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Monisha,,11.058669,76.929852 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Kavvyasruthi U J,,10.993342,76.930989 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.989004,76.947195 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Vinodbabu M,,10.999868,76.953663 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,950,Jayasabesh Kumar S,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Merlyn,,10.96438,76.981495 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968205,76.982993 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970149,76.985589 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997731,76.987182 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Yaswanth Sai Jami,,10.999787,76.995655 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.992837,76.999072 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019593,76.973325 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Gopisetty Siri,,11.012798,76.98122 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hello Sivi,,11.013257,76.995674 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Parandama Reddy,,11.012934,76.997275 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Abirami,,11.020989,76.994894 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vijayalakshmi,,11.025734,76.998798 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025631,77.001348 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Kavitha,,10.99915,77.030614 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Sudharsan,,11.001888,77.027047 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Raja,,11.001694,77.024112 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Ramya Devarajan,,11.00848,77.023942 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Janane,,11.015068,77.015652 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Abinaya,,11.082638,76.964918 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jayasri. N,,11.083883,76.980407 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Praveenkumar MR,,11.078167,77.005336 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Karthikeyan Subramanian,,11.078028,77.012821 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066163,77.031137 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Jagadhish Jj,,11.066759,77.00326 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Mylswamy,,11.065882,77.001959 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Anisha,,11.054183,77.003408 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Mukilan M,,11.050259,77.034814 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Rohan Krishna S,,11.040103,77.033142 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Sedhuram,,11.036925,77.038098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Ninusha,,11.029476,77.036005 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,SRUJAN,,11.024605,77.024821 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.032616,77.00985 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Rushyendramani,,11.038292,77.013339 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Manoharan,,11.03738,77.016265 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Athiradh V Nair,,11.045173,77.014098 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041604,77.008501 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Dhinesh Kumar,,11.012385,76.923417 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Abdul hameed,,11.020005,76.924302 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Karthik,,11.019006,76.920163 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vimal Raj,,11.018299,76.879415 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Mumtaz,,11.022383,76.887487 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Rajaram S,,11.03002,76.899213 +Kalpana kitchen,Kasthuri Naickenpalayam,11.035988,76.9048179,1096,Narayanasamy R,Vasanthi,,11.036285,76.8965 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Chiteshkumar s.b,,11.018607,76.968135 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,sankar R,,11.022822,76.968625 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Dr Basher Ahmed,,11.024197,76.967442 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Meenakshi,,11.022517,76.950222 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,B.Sakthi,,11.029622,76.948618 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Yamuna,,11.065821,76.887496 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Meera Bai,,11.093727,76.93874 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Kishore,,11.07916,76.945151 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Sunil,,10.95102,76.95628 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Lakshmanan Visalakshi,,10.947816,76.957538 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,SIVASANKAR,,10.946165,76.969374 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Thiruveragan,,10.952958,76.970671 +Bhuvaneshwari kitchen ,R.S. Puram,11.003518,76.9545465,1036,Vignesh S,Nagaraj,,10.960443,76.974565 +Nandhini s kitchens,Maniakaram Palayam,11.043236,77.0006758,883,Rajan A,vidhya kitchen,ramlakshman nagar,11.016857,77.014498 +Manjusha kitchen ,Ganapathy,11.051795,76.9917895,1114,Tamilazhagan K,Nandhini s kitchens,Maniakaram Palayam,11.043405,77.000501 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Sedhuram,,11.036862,77.038473 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,SRUJAN,,11.024419,77.025063 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Kandavelu,,11.03251,77.009942 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Manoj,,11.056753,77.011626 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,950,Jayasabesh Kumar S,Srihari,,11.066392,77.031442 +Daily grubs nandhini,Maniakaram Palayam,11.043236,77.0006758,1114,Tamilazhagan K,Karthik abilash,,11.041588,77.008579 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Thiruveragan,,10.95295827,76.97067058 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Nagaraj,,10.96044322,76.97456534 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,R. VIJAYAKUMAR,,10.98900419,76.94719466 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Ira Mahadevan,,10.99878266,76.96441114 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Vinodbabu M,,10.99986785,76.95366267 +Bhuvaneshwari kitchen ,R.S. Puram,11.0035176,76.9545465,1036,Vignesh S,Namachivayam,,11.00414342,76.94891621 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ulaganathan,,10.968682,76.983307 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Karthi,,10.970606,76.985878 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Ramagopalan,,10.997104,76.980307 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Nagalakshmi B,,10.997915,76.987455 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Noorah Jalal,,10.994875,76.990027 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,Uma Ganesh,,10.993069,76.999228 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,1111,Murali P,P vimal raj,,10.994048,77.013231 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Kannammal,,11.019561,76.973736 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Thomson,,11.011943,76.985654 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Vivekanandan,,11.014182,76.98525 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Muthumugil,,11.028274,76.995902 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,883,Rajan A,Hema Priya Thangavel,,11.025539,77.00148 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Mohammed Muzzammil,,11.000722,77.029004 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Pooja,,11.019279,77.023968 +Vidhya kitchen,uppilipalayam ,11.016327,77.0147763,753,Manikandan P,Janane,,11.015068,77.015652 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,sankar R,,11.022662,76.969011 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Dr Basher Ahmed,,11.02405,76.967816 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,Meenakshi,,11.022354,76.950423 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1096,Narayanasamy R,B.Sakthi,,11.029529,76.948804 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Sivasubramanian,,11.015196,76.946175 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,VIGNESH,,11.023281,76.94624 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,1062,Nagalakshmi M,Rajeswari Kannan,,11.027863,76.941326 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Sri Gokul,,11.097031,76.938628 +Daily grubs(jayanthi kitchen),Kavandam,11.038868,76.9300797,897,Varun Edward,Meera Bai,,11.093727,76.93874 +selvarani,ramanathapuram,10.992742,77.0053459,1111,Murali P,vidhya kitchen,ramlakshman nagar,11.015862,77.01459 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..7a7d77a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,44 @@ +version: "3.9" + +networks: + frontend: + external: true + +services: + routes_api: + build: + context: . + dockerfile: Dockerfile + image: routes-api:latest + container_name: routes_api + restart: unless-stopped + environment: + - UVICORN_WORKERS=2 + - REDIS_URL=redis://:${REDIS_PASSWORD}@routes_redis:6379/0 + # Optional: Set cache TTL in seconds (default: 300 = 5 min, 86400 = 24h) + # Uncomment and set in .env file: REDIS_CACHE_TTL_SECONDS=86400 + # - REDIS_CACHE_TTL_SECONDS=${REDIS_CACHE_TTL_SECONDS} + # Google Maps API key for accurate road distance calculation (actualkms) + # Set in .env file: GOOGLE_MAPS_API_KEY=your_api_key_here + - GOOGLE_MAPS_API_KEY=${GOOGLE_MAPS_API_KEY} + # nearledb (read-only) — source for empirical ETA learning + - DB_HOST=${DB_HOST} + - DB_PORT=${DB_PORT} + - DB_NAME=${DB_NAME} + - DB_USER=${DB_USER} + - DB_PASSWORD=${DB_PASSWORD} + labels: + - traefik.enable=true + - traefik.http.routers.routes_api.rule=Host(`routes.workolik.com`) + - traefik.http.routers.routes_api.entrypoints=websecure + - traefik.http.routers.routes_api.tls.certresolver=letsencrypt + - traefik.http.services.routes_api.loadbalancer.server.port=8002 + - traefik.docker.network=frontend + volumes: + - ./ml_data:/app/ml_data + - ./rider_history.pkl:/app/rider_history.pkl + - ./rider_active_state.pkl:/app/rider_active_state.pkl + - ./delivery_details.csv:/app/delivery_details.csv:ro + - ./delivery_corrections.csv:/app/delivery_corrections.csv:ro + networks: + - frontend diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100644 index 0000000..a677b25 --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,11 @@ +#!/bin/sh +set -e + +# Get number of workers from environment or default to 1 +WORKERS=${UVICORN_WORKERS:-1} + +echo "Starting Route Optimization API with ${WORKERS} worker(s)..." + +# Start uvicorn +exec uvicorn app.main:app --host 0.0.0.0 --port 8002 --workers ${WORKERS} + diff --git a/input b/input new file mode 100644 index 0000000..9b172bc --- /dev/null +++ b/input @@ -0,0 +1,3554 @@ +[ + { + "orderheaderid": 138008, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107084", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "5", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Uma Ganesh", + "deliverycontactno": "9884937068", + "deliverylocationid": 0, + "deliveryaddress": "24, Subbiah Layout, Ramanathapuram Near EB office", + "deliverysuburb": "", + "droplat": "10.9926018318957", + "droplon": "76.9989152943438", + "deliverylat": "10.9926018318957", + "deliverylong": "76.9989152943438", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 1, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 138007, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107083", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "8", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Narmada", + "deliverycontactno": "9003722257", + "deliverylocationid": 0, + "deliveryaddress": "Mothers village apartment B104 b block pattanam itteri road Ondipudur Coimbatore Road opposite to kings home", + "deliverysuburb": "", + "droplat": "10.9983312492398", + "droplon": "77.0446450333236", + "deliverylat": "10.9983312492398", + "deliverylong": "77.0446450333236", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 2, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 138006, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107082", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "7", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Kannammal", + "deliverycontactno": "8884366950", + "deliverylocationid": 0, + "deliveryaddress": "47 Ambika Layout, New Siddhapudur Opp to Kaleeswari Broiler", + "deliverysuburb": "", + "droplat": "11.0196258620096", + "droplon": "76.9729109577317", + "deliverylat": "11.0196258620096", + "deliverylong": "76.9729109577317", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 3, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 138005, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107081", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "5", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Vishnu", + "deliverycontactno": "9626227555", + "deliverylocationid": 0, + "deliveryaddress": "702, 7th Floor, Sree Daksha Darza , Nava india road , Avarampalayam Opp SNR Marriage hall", + "deliverysuburb": "", + "droplat": "11.0234608", + "droplon": "76.9886746", + "deliverylat": "11.0234608", + "deliverylong": "76.9886746", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 4, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 138004, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107080", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "5", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Thomson", + "deliverycontactno": "7358427429", + "deliverylocationid": 0, + "deliveryaddress": "Door No. 657, Ground floor, Tristar Tower Dbs bank avinashi road branch ", + "deliverysuburb": "", + "droplat": "11.0118553", + "droplon": "76.9850682", + "deliverylat": "11.0118553", + "deliverylong": "76.9850682", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 5, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 138003, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107079", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "10", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 42, + "orderamount": 42, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Ulaganathan", + "deliverycontactno": "9789826626", + "deliverylocationid": 0, + "deliveryaddress": "Sakthi illam, Satyanarayanagar Podanur Near rail nagar( Sai nagar)", + "deliverysuburb": "", + "droplat": "10.9677", + "droplon": "76.9824", + "deliverylat": "10.9677", + "deliverylong": "76.9824", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 6, + "pickuplon": "77.0147763", + "deliverycharges": 42, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 138002, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107078", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "5", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Anusha Tennyson", + "deliverycontactno": "8925177754", + "deliverylocationid": 0, + "deliveryaddress": "3rd Floor, Haritha Centre, Avinashi Road, Opp to GKNM IOP, COimbatore Sony Centre Building", + "deliverysuburb": "", + "droplat": "11.0115588", + "droplon": "76.9846643", + "deliverylat": "11.0115588", + "deliverylong": "76.9846643", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 7, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 138001, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107077", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "2", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Shanmugam", + "deliverycontactno": "9942753367", + "deliverylocationid": 0, + "deliveryaddress": "Vistara Homes 71 & 72 Sri Mookambikai Nagar Uppilipalayam post Coimbatore - 641 015 Opposite Harsha Kalyaan Mandapam Uppilipalayam Road", + "deliverysuburb": "", + "droplat": "11.0097457", + "droplon": "77.0193997", + "deliverylat": "11.0097457", + "deliverylong": "77.0193997", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 8, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 138000, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107076", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "10", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 42, + "orderamount": 42, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Karthi", + "deliverycontactno": "9362625249", + "deliverylocationid": 0, + "deliveryaddress": "42, 10th cross street, Satyanarayana Nagar, Podanur Opposite to Podanur Indian Bank", + "deliverysuburb": "", + "droplat": "10.9696875", + "droplon": "76.9852969", + "deliverylat": "10.9696875", + "deliverylong": "76.9852969", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 2, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 9, + "pickuplon": "77.0147763", + "deliverycharges": 42, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 137999, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107075", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Kaleeswaran B", + "deliverycontactno": "7339231410", + "deliverylocationid": 0, + "deliveryaddress": "Accenture Tidel park, coimbatore ", + "deliverysuburb": "", + "droplat": "11.0317782", + "droplon": "77.0185392", + "deliverylat": "11.0317782", + "deliverylong": "77.0185392", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 10, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 137998, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107074", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Varsha", + "deliverycontactno": "9944397248", + "deliverylocationid": 0, + "deliveryaddress": "Masakalipalayam road,No.12,kalyana Sundara street New Iyengar bakery cut", + "deliverysuburb": "", + "droplat": "11.0241383", + "droplon": "77.0184563", + "deliverylat": "11.0241383", + "deliverylong": "77.0184563", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 11, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 137997, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107073", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "1", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "M.S.JAVID", + "deliverycontactno": "7558120192", + "deliverylocationid": 0, + "deliveryaddress": "ROOM No-21, J.K COMPLEX, 386/A3, KAMARAJAR ROAD, PEELAMEDU, COIMBATORE-641004, NEAR BY SPAZEONE, NNRC ELDER CARE & RHR HOTEL", + "deliverysuburb": "", + "droplat": "11.0207363", + "droplon": "77.0220709", + "deliverylat": "11.0207363", + "deliverylong": "77.0220709", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 12, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 137996, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107072", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "7", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Kabilan", + "deliverycontactno": "9952332560", + "deliverylocationid": 0, + "deliveryaddress": "Door no :72, 7th street, Nehru nagar East, Kalapatti main road, Coimbatore -641014 Road OPP. KVB bank, ", + "deliverysuburb": "", + "droplat": "11.0515971425312", + "droplon": "77.0396537597456", + "deliverylat": "11.0515971425312", + "deliverylong": "77.0396537597456", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 13, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 137995, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107071", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Kandavelu", + "deliverycontactno": "9443913591", + "deliverylocationid": 0, + "deliveryaddress": "35 Jai Nagar 2nd street, Peelamedu Call 9443913591", + "deliverysuburb": "", + "droplat": "11.0324025295475", + "droplon": "77.0100342241114", + "deliverylat": "11.0324025295475", + "deliverylong": "77.0100342241114", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 2, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 14, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 137994, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107070", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Devikarani", + "deliverycontactno": "9940666706", + "deliverylocationid": 0, + "deliveryaddress": "229 Giriamman kovil street Peelamedu - near Peelamedu railway station call 9940666706", + "deliverysuburb": "", + "droplat": "11.0315832", + "droplon": "77.0005771", + "deliverylat": "11.0315832", + "deliverylong": "77.0005771", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 15, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 137993, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107069", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Athira Sooraj", + "deliverycontactno": "9847568898", + "deliverylocationid": 0, + "deliveryaddress": "80, Murugan Kovil street, Avarampalayam Road, Peelamedu Next to Akashmalli apartments", + "deliverysuburb": "", + "droplat": "11.0260907635561", + "droplon": "76.9982964559619", + "deliverylat": "11.0260907635561", + "deliverylong": "76.9982964559619", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 16, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 137992, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107068", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "5", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Karthik abilash", + "deliverycontactno": "9626377171", + "deliverylocationid": 0, + "deliveryaddress": "287/2, Peelamedu, Gauthama Puri Nagar, Coimbatore, Tamil Nadu 641006, India Nivasan springs ", + "deliverysuburb": "", + "droplat": "11.041571543", + "droplon": "77.00865779", + "deliverylat": "11.041571543", + "deliverylong": "77.00865779", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 17, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 137991, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107067", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "7", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Vasu", + "deliverycontactno": "9442614480", + "deliverylocationid": 0, + "deliveryaddress": "No 9 Meenakshi Thunai Rajagopal street Near Covai Tech park ", + "deliverysuburb": "", + "droplat": "11.0473292", + "droplon": "77.0418779", + "deliverylat": "11.0473292", + "deliverylong": "77.0418779", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 139, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 18, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 137990, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107066", + "orderdate": "2026-05-25T16:05:20+05:30", + "deliverydate": "2026-05-25 10:35:20", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "yuthish", + "deliverycontactno": "9363334531", + "deliverylocationid": 0, + "deliveryaddress": "Room No:C-4,Second Floor, Kaniagam Mansion,Keerthi Corner, Vetrilaikara St, Peelamedu, Coimbatore, Tamil Nadu 641004 Search Kaniagam mansion in google map", + "deliverysuburb": "", + "droplat": "11.0293551", + "droplon": "77.0018253", + "deliverylat": "11.0293551", + "deliverylong": "77.0018253", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 19, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "" + }, + { + "orderheaderid": 137988, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107064", + "orderdate": "2026-05-25T16:04:18+05:30", + "deliverydate": "2026-05-25 10:34:18", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "6", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Drona P", + "deliverycontactno": "9025628047", + "deliverylocationid": 0, + "deliveryaddress": "195 sanganoor main road, Rathinapuri 7th street Extn, Coimbatore- 641027 Thandu mariyaman temple, Marathi plazza", + "deliverysuburb": "", + "droplat": "11.0262978", + "droplon": "76.965093", + "deliverylat": "11.0262978", + "deliverylong": "76.965093", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 20, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "" + }, + { + "orderheaderid": 137987, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107063", + "orderdate": "2026-05-25T16:04:18+05:30", + "deliverydate": "2026-05-25 10:34:18", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Sundar", + "deliverycontactno": "9943315000", + "deliverylocationid": 0, + "deliveryaddress": "No 60 sai gangotri apartments Opp union bank ", + "deliverysuburb": "", + "droplat": "11.0255155902287", + "droplon": "76.9381298432463", + "deliverylat": "11.0255155902287", + "deliverylong": "76.9381298432463", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 21, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "" + }, + { + "orderheaderid": 137986, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107062", + "orderdate": "2026-05-25T16:04:18+05:30", + "deliverydate": "2026-05-25 10:34:18", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Deepa", + "deliverycontactno": "8903114181", + "deliverylocationid": 0, + "deliveryaddress": "C3 Saibaba colony police station Mettupalayam road ", + "deliverysuburb": "", + "droplat": "11.0266829565851", + "droplon": "76.9515216477048", + "deliverylat": "11.0266829565851", + "deliverylong": "76.9515216477048", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 22, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "" + }, + { + "orderheaderid": 137985, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107061", + "orderdate": "2026-05-25T16:04:18+05:30", + "deliverydate": "2026-05-25 10:34:18", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "14", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 66, + "orderamount": 66, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "SuriyaKanthan", + "deliverycontactno": "601126106261", + "deliverylocationid": 0, + "deliveryaddress": "Bethel Nagar , Keeranatham Road VKV Kumaraguru Nagar , Saravanampatti , Coimbatore 641036", + "deliverysuburb": "", + "droplat": "11.094303", + "droplon": "76.9980845", + "deliverylat": "11.094303", + "deliverylong": "76.9980845", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 23, + "pickuplon": "76.9300797", + "deliverycharges": 66, + "pickuplocation": "Kavandam", + "deliverylocation": "" + }, + { + "orderheaderid": 137984, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107060", + "orderdate": "2026-05-25T16:04:18+05:30", + "deliverydate": "2026-05-25 10:34:18", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "13", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 60, + "orderamount": 60, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Akshaya", + "deliverycontactno": "7871139083", + "deliverylocationid": 0, + "deliveryaddress": "CD905, Coral D, Kgisl Metropolis appartments, Chil Sez IT park road, Keeranatham village, Coimbatore - 641035 Near to chil sez IT Park", + "deliverysuburb": "", + "droplat": "11.1007621", + "droplon": "76.9902276", + "deliverylat": "11.1007621", + "deliverylong": "76.9902276", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 24, + "pickuplon": "76.9300797", + "deliverycharges": 60, + "pickuplocation": "Kavandam", + "deliverylocation": "" + }, + { + "orderheaderid": 137983, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107059", + "orderdate": "2026-05-25T16:04:18+05:30", + "deliverydate": "2026-05-25 10:34:18", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Sivasubramanian", + "deliverycontactno": "9994425347", + "deliverylocationid": 0, + "deliveryaddress": "72-1 Cowley Brown Road, RS Puram, CBE-2 Come inside gate east of Champion Physiotherapy then 1st house to the right", + "deliverysuburb": "", + "droplat": "11.0147203", + "droplon": "76.9464989", + "deliverylat": "11.0147203", + "deliverylong": "76.9464989", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 25, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "" + }, + { + "orderheaderid": 137982, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107058", + "orderdate": "2026-05-25T16:04:18+05:30", + "deliverydate": "2026-05-25 10:34:18", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "5", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Akila", + "deliverycontactno": "9994671202", + "deliverylocationid": 0, + "deliveryaddress": "29 Brindavan, Mettupalayam road, Ramalingam colony, coimbatore Near avinashilingam university there is benz showroom opposite to benz showroom there is cut road ", + "deliverysuburb": "", + "droplat": "11.0205082397774", + "droplon": "76.9522586020065", + "deliverylat": "11.0205082397774", + "deliverylong": "76.9522586020065", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 26, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "" + }, + { + "orderheaderid": 137981, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107057", + "orderdate": "2026-05-25T16:04:18+05:30", + "deliverydate": "2026-05-25 10:34:18", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "6", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Saranya S R", + "deliverycontactno": "9962311667", + "deliverylocationid": 0, + "deliveryaddress": "46, Rabindranath Tagore Road, Maniakarampalayam, Ganapathy, Coimbatore - 641006 Near Ananda's bakery and opposite to Lavi Ville", + "deliverysuburb": "", + "droplat": "11.0478399509368", + "droplon": "76.9776675024711", + "deliverylat": "11.0478399509368", + "deliverylong": "76.9776675024711", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 27, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "" + }, + { + "orderheaderid": 137980, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107056", + "orderdate": "2026-05-25T16:04:18+05:30", + "deliverydate": "2026-05-25 10:34:18", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "10", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 42, + "orderamount": 42, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Indira Venkatachalam", + "deliverycontactno": "7639024322", + "deliverylocationid": 0, + "deliveryaddress": "Door number :1671, LIG II, housing unit ,gandhimaa Nagar ,Coimbatore Next to Karuna departmental store line ", + "deliverysuburb": "", + "droplat": "11.0412407970465", + "droplon": "77.0031042507416", + "deliverylat": "11.0412407970465", + "deliverylong": "77.0031042507416", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 28, + "pickuplon": "76.9300797", + "deliverycharges": 42, + "pickuplocation": "Kavandam", + "deliverylocation": "" + }, + { + "orderheaderid": 137979, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107055", + "orderdate": "2026-05-25T16:04:18+05:30", + "deliverydate": "2026-05-25 10:34:18", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "9", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 36, + "orderamount": 36, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Sri Gokul", + "deliverycontactno": "9080187878", + "deliverylocationid": 0, + "deliveryaddress": "The focus room,Mettupalayam Rd, Daniel Nagar, Thoppampatti Pirivu, K. Vadamadurai, Coimbatore, Tamil Nadu 641017 Thudiyalur Dmart ", + "deliverysuburb": "", + "droplat": "11.0982", + "droplon": "76.9388", + "deliverylat": "11.0982", + "deliverylong": "76.9388", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 29, + "pickuplon": "76.9300797", + "deliverycharges": 36, + "pickuplocation": "Kavandam", + "deliverylocation": "" + }, + { + "orderheaderid": 137978, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107054", + "orderdate": "2026-05-25T16:04:18+05:30", + "deliverydate": "2026-05-25 10:34:18", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Rajeshwari", + "deliverycontactno": "7418264154", + "deliverylocationid": 0, + "deliveryaddress": "S7 Meenakshi Manor apartments ,Arunachalam street KK Pudur Saibaba colony Come to the gate and call 7418264154", + "deliverysuburb": "", + "droplat": "11.0288703", + "droplon": "76.9499478", + "deliverylat": "11.0288703", + "deliverylong": "76.9499478", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 2, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 30, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "" + }, + { + "orderheaderid": 137977, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107053", + "orderdate": "2026-05-25T16:04:18+05:30", + "deliverydate": "2026-05-25 10:34:18", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "B.Sakthi", + "deliverycontactno": "9363103387", + "deliverylocationid": 0, + "deliveryaddress": "35, chinna subanna street, Kuppakonam Pudur, Coimbatore, Tamil Nadu 641038, India Left side house, door no 35, opposite to kerala style house. ", + "deliverysuburb": "", + "droplat": "11.029435888545", + "droplon": "76.9489910178604", + "deliverylat": "11.029435888545", + "deliverylong": "76.9489910178604", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 31, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "" + }, + { + "orderheaderid": 137976, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107052", + "orderdate": "2026-05-25T16:04:18+05:30", + "deliverydate": "2026-05-25 10:34:18", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "11", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 48, + "orderamount": 48, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Bhuvana", + "deliverycontactno": "9894898978", + "deliverylocationid": 0, + "deliveryaddress": "E106, casagrand Nextown, Villankurichi, coimbatore Behind RJ school ", + "deliverysuburb": "", + "droplat": "11.0692511", + "droplon": "77.019709", + "deliverylat": "11.0692511", + "deliverylong": "77.019709", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 32, + "pickuplon": "76.9300797", + "deliverycharges": 48, + "pickuplocation": "Kavandam", + "deliverylocation": "" + }, + { + "orderheaderid": 137975, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107051", + "orderdate": "2026-05-25T16:04:18+05:30", + "deliverydate": "2026-05-25 10:34:18", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "9", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 36, + "orderamount": 36, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Rishi", + "deliverycontactno": "8122164539", + "deliverylocationid": 0, + "deliveryaddress": "MD 504 3RD BLOCK TNHB Ganapathy Managar Ganapathy Coimbatore Bhanari Amman temple backside road", + "deliverysuburb": "", + "droplat": "11.0526158790232", + "droplon": "77.0031416416168", + "deliverylat": "11.0526158790232", + "deliverylong": "77.0031416416168", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 2, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 33, + "pickuplon": "76.9300797", + "deliverycharges": 36, + "pickuplocation": "Kavandam", + "deliverylocation": "" + }, + { + "orderheaderid": 137974, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 1076, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107050", + "orderdate": "2026-05-25T16:03:50+05:30", + "deliverydate": "2026-05-25 10:33:50", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "7", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Bhuvaneshwari kitchen ", + "pickupcontactno": "9597843220", + "pickuplocationid": 1076, + "pickupaddress": "Coimbatore, Light House Road, Kollupuram, Sukrawar Pettai, R.S. Puram, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "R.S. Puram", + "pickupcity": "Coimbatore", + "pickuplat": "11.0035176", + "pickuplong": "76.95454649999999", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Nagaraj", + "deliverycontactno": "7401008787", + "deliverylocationid": 0, + "deliveryaddress": "3/10,13d Andaal thotham,MurugaNagar,Sundarapuram Take left cut after Anandaas hotel,and straight dead end", + "deliverysuburb": "", + "droplat": "10.959577516", + "droplon": "76.9749676783705", + "deliverylat": "10.959577516", + "deliverylong": "76.9749676783705", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Bhuvaneshwari kitchen ", + "locationsuburb": "R.S. Puram", + "locationcity": "Coimbatore", + "locationcontactno": "9597843220", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 34, + "pickuplon": "76.95454649999999", + "deliverycharges": 30, + "pickuplocation": "R.S. Puram", + "deliverylocation": "" + }, + { + "orderheaderid": 137973, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 1076, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107049", + "orderdate": "2026-05-25T16:03:50+05:30", + "deliverydate": "2026-05-25 10:33:50", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Bhuvaneshwari kitchen ", + "pickupcontactno": "9597843220", + "pickuplocationid": 1076, + "pickupaddress": "Coimbatore, Light House Road, Kollupuram, Sukrawar Pettai, R.S. Puram, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "R.S. Puram", + "pickupcity": "Coimbatore", + "pickuplat": "11.0035176", + "pickuplong": "76.95454649999999", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "R. VIJAYAKUMAR", + "deliverycontactno": "9894145933", + "deliverylocationid": 0, + "deliveryaddress": "1st block G3 ( ground floor) Vishwa apartment Prabhu Nagar sandaka Muthoot bypass road Coimbatore Opp Selvapuram Government Higher Secondary School", + "deliverysuburb": "", + "droplat": "10.9887125", + "droplon": "76.9470469", + "deliverylat": "10.9887125", + "deliverylong": "76.9470469", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Bhuvaneshwari kitchen ", + "locationsuburb": "R.S. Puram", + "locationcity": "Coimbatore", + "locationcontactno": "9597843220", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 35, + "pickuplon": "76.95454649999999", + "deliverycharges": 30, + "pickuplocation": "R.S. Puram", + "deliverylocation": "" + }, + { + "orderheaderid": 137972, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 1076, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107048", + "orderdate": "2026-05-25T16:03:50+05:30", + "deliverydate": "2026-05-25 10:33:50", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "2", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Bhuvaneshwari kitchen ", + "pickupcontactno": "9597843220", + "pickuplocationid": 1076, + "pickupaddress": "Coimbatore, Light House Road, Kollupuram, Sukrawar Pettai, R.S. Puram, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "R.S. Puram", + "pickupcity": "Coimbatore", + "pickuplat": "11.0035176", + "pickuplong": "76.95454649999999", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Ira Mahadevan", + "deliverycontactno": "6382801087", + "deliverylocationid": 0, + "deliveryaddress": "3-4/5 Goods shed Road, Near HeadPost office, Coimbatore Near Head post office (backside of main Railway Station)", + "deliverysuburb": "", + "droplat": "10.9986875", + "droplon": "76.9646094", + "deliverylat": "10.9986875", + "deliverylong": "76.9646094", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Bhuvaneshwari kitchen ", + "locationsuburb": "R.S. Puram", + "locationcity": "Coimbatore", + "locationcontactno": "9597843220", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 36, + "pickuplon": "76.95454649999999", + "deliverycharges": 30, + "pickuplocation": "R.S. Puram", + "deliverylocation": "" + }, + { + "orderheaderid": 137971, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 1076, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107047", + "orderdate": "2026-05-25T16:03:50+05:30", + "deliverydate": "2026-05-25 10:33:50", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "1", + "actualkms": "", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-25 16:35:30", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Bhuvaneshwari kitchen ", + "pickupcontactno": "9597843220", + "pickuplocationid": 1076, + "pickupaddress": "Coimbatore, Light House Road, Kollupuram, Sukrawar Pettai, R.S. Puram, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "R.S. Puram", + "pickupcity": "Coimbatore", + "pickuplat": "11.0035176", + "pickuplong": "76.95454649999999", + "pickupslot": "2026-05-25 08:00 AM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Namachivayam", + "deliverycontactno": "8508132454", + "deliverylocationid": 0, + "deliveryaddress": "185 Ramalingam Road West Near JSR Pet Hospital", + "deliverysuburb": "", + "droplat": "11.0041559966172", + "droplon": "76.9488030448094", + "deliverylat": "11.0041559966172", + "deliverylong": "76.9488030448094", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Bhuvaneshwari kitchen ", + "locationsuburb": "R.S. Puram", + "locationcity": "Coimbatore", + "locationcontactno": "9597843220", + "locationaddress": "", + "rider": "", + "ridercontactno": "", + "riderkms": "", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "previouskms": 0, + "cumulativekms": 0, + "step": 0, + "eta": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 37, + "pickuplon": "76.95454649999999", + "deliverycharges": 30, + "pickuplocation": "R.S. Puram", + "deliverylocation": "" + } +] \ No newline at end of file diff --git a/ml_data/faiss_history/delivery_history.meta b/ml_data/faiss_history/delivery_history.meta new file mode 100644 index 0000000..798829c --- /dev/null +++ b/ml_data/faiss_history/delivery_history.meta @@ -0,0 +1,6 @@ +{ + "csv_mtime": 1779805148.3161151, + "record_count": 3610, + "pattern_zones": 173, + "clear_patterns": 127 +} \ No newline at end of file diff --git a/ml_data/faiss_history/delivery_history_records.pkl b/ml_data/faiss_history/delivery_history_records.pkl new file mode 100644 index 0000000..20dc926 Binary files /dev/null and b/ml_data/faiss_history/delivery_history_records.pkl differ diff --git a/ml_data/faiss_history/delivery_history_vectors.npy b/ml_data/faiss_history/delivery_history_vectors.npy new file mode 100644 index 0000000..932e29e Binary files /dev/null and b/ml_data/faiss_history/delivery_history_vectors.npy differ diff --git a/ml_data/ml_store.db b/ml_data/ml_store.db new file mode 100644 index 0000000..383d74d Binary files /dev/null and b/ml_data/ml_store.db differ diff --git a/ml_data/reports/tuning_20260406_101305.json b/ml_data/reports/tuning_20260406_101305.json new file mode 100644 index 0000000..fd42e97 --- /dev/null +++ b/ml_data/reports/tuning_20260406_101305.json @@ -0,0 +1,193 @@ +{ + "timestamp": "2026-04-06T10:13:05.823653", + "training_rows": 42, + "n_trials": 150, + "best_predicted_quality": 74.73, + "best_params": { + "max_pickup_distance_km": 7.314920981190028, + "max_kitchen_distance_km": 4.8848250212533415, + "max_orders_per_rider": 17, + "ideal_load": 6, + "workload_balance_threshold": 0.5921999872066053, + "workload_penalty_weight": 169.06315001171424, + "distance_penalty_weight": 1.1915857216557537, + "cluster_radius_km": 3.558231774658527, + "search_time_limit_seconds": 9, + "road_factor": 1.3099009557863963 + }, + "validation": { + "r2_score": 0.5681, + "mae": 8.266, + "folds": 5, + "trust_level": "acceptable", + "trust_score": 2, + "interpretation": "Predictions off by +/-8.3 pts (R2=0.57, trust=acceptable)" + }, + "baseline_stats": { + "avg_quality": 57.09, + "best_quality": 94.11, + "worst_quality": 30.0, + "sample_size": 42 + }, + "feature_importance": { + "rolling_avg_quality_5": 38.71, + "quality_delta_10": 20.33, + "num_orders": 19.03, + "hour": 13.32, + "num_riders": 7.86, + "day_of_week": 0.75 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 7.314920981190028, + "max_kitchen_distance_km": 4.8848250212533415, + "max_orders_per_rider": 17, + "ideal_load": 6, + "workload_balance_threshold": 0.5921999872066053, + "workload_penalty_weight": 169.06315001171424, + "distance_penalty_weight": 1.1915857216557537, + "cluster_radius_km": 3.558231774658527, + "search_time_limit_seconds": 9, + "road_factor": 1.3099009557863963 + }, + "score": 74.7316665649414 + }, + { + "params": { + "max_pickup_distance_km": 7.237104762434787, + "max_kitchen_distance_km": 7.550474896953535, + "max_orders_per_rider": 17, + "ideal_load": 6, + "workload_balance_threshold": 0.5890554510417833, + "workload_penalty_weight": 185.96752993783272, + "distance_penalty_weight": 1.31602349600973, + "cluster_radius_km": 3.8526888873500074, + "search_time_limit_seconds": 9, + "road_factor": 1.319424296170459 + }, + "score": 74.7316665649414 + }, + { + "params": { + "max_pickup_distance_km": 7.436288448216707, + "max_kitchen_distance_km": 4.919546048309047, + "max_orders_per_rider": 17, + "ideal_load": 6, + "workload_balance_threshold": 0.591148300459874, + "workload_penalty_weight": 168.30230726961742, + "distance_penalty_weight": 1.2493078409207465, + "cluster_radius_km": 3.556472953280938, + "search_time_limit_seconds": 9, + "road_factor": 1.3302725639166417 + }, + "score": 74.7316665649414 + }, + { + "params": { + "max_pickup_distance_km": 7.325529314582726, + "max_kitchen_distance_km": 4.649587629606767, + "max_orders_per_rider": 17, + "ideal_load": 6, + "workload_balance_threshold": 0.590873440986851, + "workload_penalty_weight": 168.438723345984, + "distance_penalty_weight": 1.1422464826358736, + "cluster_radius_km": 3.849796402096792, + "search_time_limit_seconds": 9, + "road_factor": 1.3098146276588136 + }, + "score": 74.7316665649414 + }, + { + "params": { + "max_pickup_distance_km": 7.280718743288656, + "max_kitchen_distance_km": 4.619748595285139, + "max_orders_per_rider": 17, + "ideal_load": 6, + "workload_balance_threshold": 0.5876942359983096, + "workload_penalty_weight": 175.5427402190054, + "distance_penalty_weight": 1.234091340676156, + "cluster_radius_km": 3.596367136362332, + "search_time_limit_seconds": 9, + "road_factor": 1.3269755250627069 + }, + "score": 74.7316665649414 + }, + { + "params": { + "max_pickup_distance_km": 7.492629035525449, + "max_kitchen_distance_km": 4.249165472314659, + "max_orders_per_rider": 17, + "ideal_load": 6, + "workload_balance_threshold": 0.6002837964896123, + "workload_penalty_weight": 173.37495123965752, + "distance_penalty_weight": 1.1908166833096747, + "cluster_radius_km": 3.543115179563585, + "search_time_limit_seconds": 9, + "road_factor": 1.3281385493416102 + }, + "score": 74.7316665649414 + }, + { + "params": { + "max_pickup_distance_km": 7.171116733882171, + "max_kitchen_distance_km": 4.315631232490625, + "max_orders_per_rider": 17, + "ideal_load": 6, + "workload_balance_threshold": 0.5943191618773355, + "workload_penalty_weight": 167.9049180092559, + "distance_penalty_weight": 1.173862334055753, + "cluster_radius_km": 3.596417271778823, + "search_time_limit_seconds": 9, + "road_factor": 1.310786907921741 + }, + "score": 74.7316665649414 + }, + { + "params": { + "max_pickup_distance_km": 7.398947077752536, + "max_kitchen_distance_km": 4.573012985025286, + "max_orders_per_rider": 17, + "ideal_load": 6, + "workload_balance_threshold": 0.588382785737964, + "workload_penalty_weight": 171.56836325664975, + "distance_penalty_weight": 1.2420650483510813, + "cluster_radius_km": 3.821463414056532, + "search_time_limit_seconds": 9, + "road_factor": 1.3094083355796955 + }, + "score": 74.7316665649414 + }, + { + "params": { + "max_pickup_distance_km": 7.413205466370695, + "max_kitchen_distance_km": 4.882557712376696, + "max_orders_per_rider": 17, + "ideal_load": 6, + "workload_balance_threshold": 0.5938285091458789, + "workload_penalty_weight": 169.18170748664954, + "distance_penalty_weight": 1.2065256426925077, + "cluster_radius_km": 3.567236434547114, + "search_time_limit_seconds": 9, + "road_factor": 1.3261515305765197 + }, + "score": 74.7316665649414 + }, + { + "params": { + "max_pickup_distance_km": 7.321140036068694, + "max_kitchen_distance_km": 4.591113450191565, + "max_orders_per_rider": 17, + "ideal_load": 6, + "workload_balance_threshold": 0.595465392809937, + "workload_penalty_weight": 168.84486091695908, + "distance_penalty_weight": 1.1874534780471975, + "cluster_radius_km": 3.5809336353167915, + "search_time_limit_seconds": 9, + "road_factor": 1.3136308854673249 + }, + "score": 74.7316665649414 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260406_111521.json b/ml_data/reports/tuning_20260406_111521.json new file mode 100644 index 0000000..2e76270 --- /dev/null +++ b/ml_data/reports/tuning_20260406_111521.json @@ -0,0 +1,195 @@ +{ + "timestamp": "2026-04-06T11:15:21.558462", + "training_rows": 46, + "n_trials": 100, + "best_predicted_quality": 86.11, + "best_params": { + "max_pickup_distance_km": 6.392662787995912, + "max_kitchen_distance_km": 4.190289209141789, + "max_orders_per_rider": 16, + "ideal_load": 6, + "workload_balance_threshold": 0.5872426915922554, + "workload_penalty_weight": 159.52479411472802, + "distance_penalty_weight": 1.3976431795210602, + "cluster_radius_km": 3.8669714076918487, + "search_time_limit_seconds": 10, + "road_factor": 1.351027788721731 + }, + "validation": { + "r2_score": 0.6054, + "mae": 7.772, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-7.8 pts (R2=0.61, trust=good)" + }, + "baseline_stats": { + "avg_quality": 60.17, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 46 + }, + "feature_importance": { + "rolling_avg_quality_5": 37.57, + "quality_delta_10": 20.49, + "num_orders": 19.39, + "hour": 14.34, + "num_riders": 7.31, + "day_of_week": 0.7, + "max_pickup_distance_km": 0.11, + "max_kitchen_distance_km": 0.09 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 6.392662787995912, + "max_kitchen_distance_km": 4.190289209141789, + "max_orders_per_rider": 16, + "ideal_load": 6, + "workload_balance_threshold": 0.5872426915922554, + "workload_penalty_weight": 159.52479411472802, + "distance_penalty_weight": 1.3976431795210602, + "cluster_radius_km": 3.8669714076918487, + "search_time_limit_seconds": 10, + "road_factor": 1.351027788721731 + }, + "score": 86.11234283447266 + }, + { + "params": { + "max_pickup_distance_km": 6.297815963257037, + "max_kitchen_distance_km": 3.8505754898634783, + "max_orders_per_rider": 16, + "ideal_load": 6, + "workload_balance_threshold": 0.5777296561934621, + "workload_penalty_weight": 158.4868458705779, + "distance_penalty_weight": 1.1423080241802208, + "cluster_radius_km": 3.8767987765353027, + "search_time_limit_seconds": 10, + "road_factor": 1.3590795828321593 + }, + "score": 86.11234283447266 + }, + { + "params": { + "max_pickup_distance_km": 5.755525935494492, + "max_kitchen_distance_km": 3.602878250833593, + "max_orders_per_rider": 16, + "ideal_load": 6, + "workload_balance_threshold": 0.5810550224170309, + "workload_penalty_weight": 158.33102695144956, + "distance_penalty_weight": 0.8359797517849566, + "cluster_radius_km": 4.070265749604756, + "search_time_limit_seconds": 11, + "road_factor": 1.3679995251023478 + }, + "score": 86.11234283447266 + }, + { + "params": { + "max_pickup_distance_km": 5.668048149252538, + "max_kitchen_distance_km": 3.757664730583838, + "max_orders_per_rider": 15, + "ideal_load": 6, + "workload_balance_threshold": 0.5760811821610472, + "workload_penalty_weight": 151.63492791057107, + "distance_penalty_weight": 0.5702726198142655, + "cluster_radius_km": 4.072347742407765, + "search_time_limit_seconds": 10, + "road_factor": 1.3745093953873153 + }, + "score": 86.11234283447266 + }, + { + "params": { + "max_pickup_distance_km": 6.234799364645242, + "max_kitchen_distance_km": 3.608238936343494, + "max_orders_per_rider": 16, + "ideal_load": 6, + "workload_balance_threshold": 0.5751866568653705, + "workload_penalty_weight": 157.49526762895485, + "distance_penalty_weight": 0.6684963010048837, + "cluster_radius_km": 4.563846747791826, + "search_time_limit_seconds": 10, + "road_factor": 1.3851224149782055 + }, + "score": 86.11234283447266 + }, + { + "params": { + "max_pickup_distance_km": 5.778552719231634, + "max_kitchen_distance_km": 3.985822473534986, + "max_orders_per_rider": 15, + "ideal_load": 6, + "workload_balance_threshold": 0.5421608115737091, + "workload_penalty_weight": 152.2200014192961, + "distance_penalty_weight": 0.5061267867737343, + "cluster_radius_km": 4.504093235986498, + "search_time_limit_seconds": 11, + "road_factor": 1.3752847449065841 + }, + "score": 86.11234283447266 + }, + { + "params": { + "max_pickup_distance_km": 5.544498941283227, + "max_kitchen_distance_km": 3.526639801749269, + "max_orders_per_rider": 15, + "ideal_load": 6, + "workload_balance_threshold": 0.5366736949070521, + "workload_penalty_weight": 143.0095516901684, + "distance_penalty_weight": 0.576086222260539, + "cluster_radius_km": 4.650857718738661, + "search_time_limit_seconds": 11, + "road_factor": 1.4022032523207215 + }, + "score": 86.11234283447266 + }, + { + "params": { + "max_pickup_distance_km": 5.834348418882515, + "max_kitchen_distance_km": 3.727707528717965, + "max_orders_per_rider": 15, + "ideal_load": 6, + "workload_balance_threshold": 0.5313909879772015, + "workload_penalty_weight": 146.66435736231995, + "distance_penalty_weight": 0.5890932671599473, + "cluster_radius_km": 4.566568289844027, + "search_time_limit_seconds": 11, + "road_factor": 1.3767549301227895 + }, + "score": 86.11234283447266 + }, + { + "params": { + "max_pickup_distance_km": 5.887294356657819, + "max_kitchen_distance_km": 3.446156802802312, + "max_orders_per_rider": 15, + "ideal_load": 6, + "workload_balance_threshold": 0.4956698206614236, + "workload_penalty_weight": 145.08886239416043, + "distance_penalty_weight": 0.5619044128499937, + "cluster_radius_km": 4.741476812566594, + "search_time_limit_seconds": 11, + "road_factor": 1.3958241864702816 + }, + "score": 86.11234283447266 + }, + { + "params": { + "max_pickup_distance_km": 5.7337206831750684, + "max_kitchen_distance_km": 3.448896621982922, + "max_orders_per_rider": 16, + "ideal_load": 6, + "workload_balance_threshold": 0.5305940896716139, + "workload_penalty_weight": 145.6036252229628, + "distance_penalty_weight": 0.5686017128719028, + "cluster_radius_km": 4.581905382792808, + "search_time_limit_seconds": 11, + "road_factor": 1.3816713599748103 + }, + "score": 86.11234283447266 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260406_112705.json b/ml_data/reports/tuning_20260406_112705.json new file mode 100644 index 0000000..4b4a893 --- /dev/null +++ b/ml_data/reports/tuning_20260406_112705.json @@ -0,0 +1,195 @@ +{ + "timestamp": "2026-04-06T11:27:05.547790", + "training_rows": 56, + "n_trials": 100, + "best_predicted_quality": 86.86, + "best_params": { + "max_pickup_distance_km": 5.754228294857152, + "max_kitchen_distance_km": 3.5401397044432863, + "max_orders_per_rider": 16, + "ideal_load": 5, + "workload_balance_threshold": 0.5303258275965647, + "workload_penalty_weight": 148.2974521657742, + "distance_penalty_weight": 0.8448126470984346, + "cluster_radius_km": 5.116539293876776, + "search_time_limit_seconds": 11, + "road_factor": 1.400897182838108 + }, + "validation": { + "r2_score": 0.7062, + "mae": 6.737, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-6.7 pts (R2=0.71, trust=good)" + }, + "baseline_stats": { + "avg_quality": 65.28, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 56 + }, + "feature_importance": { + "rolling_avg_quality_5": 36.88, + "quality_delta_10": 21.26, + "num_orders": 19.48, + "hour": 14.46, + "num_riders": 6.75, + "day_of_week": 0.65, + "max_pickup_distance_km": 0.36, + "max_kitchen_distance_km": 0.17 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 5.754228294857152, + "max_kitchen_distance_km": 3.5401397044432863, + "max_orders_per_rider": 16, + "ideal_load": 5, + "workload_balance_threshold": 0.5303258275965647, + "workload_penalty_weight": 148.2974521657742, + "distance_penalty_weight": 0.8448126470984346, + "cluster_radius_km": 5.116539293876776, + "search_time_limit_seconds": 11, + "road_factor": 1.400897182838108 + }, + "score": 86.86381530761719 + }, + { + "params": { + "max_pickup_distance_km": 5.9946340351245615, + "max_kitchen_distance_km": 3.5718829801604155, + "max_orders_per_rider": 16, + "ideal_load": 5, + "workload_balance_threshold": 0.531860400747863, + "workload_penalty_weight": 156.33441133773653, + "distance_penalty_weight": 0.8685997952158602, + "cluster_radius_km": 5.198614116122955, + "search_time_limit_seconds": 12, + "road_factor": 1.4018892215050491 + }, + "score": 86.86381530761719 + }, + { + "params": { + "max_pickup_distance_km": 6.105258536422472, + "max_kitchen_distance_km": 3.6976829030462475, + "max_orders_per_rider": 16, + "ideal_load": 5, + "workload_balance_threshold": 0.5388030619730716, + "workload_penalty_weight": 157.01841824594652, + "distance_penalty_weight": 0.8722055219643643, + "cluster_radius_km": 5.255269567532107, + "search_time_limit_seconds": 13, + "road_factor": 1.4187048027518931 + }, + "score": 86.86381530761719 + }, + { + "params": { + "max_pickup_distance_km": 6.1086693731841635, + "max_kitchen_distance_km": 3.8697437187246932, + "max_orders_per_rider": 16, + "ideal_load": 5, + "workload_balance_threshold": 0.5386198223243897, + "workload_penalty_weight": 155.03608813276117, + "distance_penalty_weight": 0.9008859330224005, + "cluster_radius_km": 5.394163081995417, + "search_time_limit_seconds": 13, + "road_factor": 1.4236552114446452 + }, + "score": 86.86381530761719 + }, + { + "params": { + "max_pickup_distance_km": 6.128213089295225, + "max_kitchen_distance_km": 3.849163463086135, + "max_orders_per_rider": 16, + "ideal_load": 5, + "workload_balance_threshold": 0.5441620345096512, + "workload_penalty_weight": 156.83172650936578, + "distance_penalty_weight": 0.8871558854958876, + "cluster_radius_km": 5.073434533857966, + "search_time_limit_seconds": 13, + "road_factor": 1.435827692627751 + }, + "score": 86.86381530761719 + }, + { + "params": { + "max_pickup_distance_km": 6.340483581316396, + "max_kitchen_distance_km": 3.9034377978970274, + "max_orders_per_rider": 16, + "ideal_load": 5, + "workload_balance_threshold": 0.5442832933506564, + "workload_penalty_weight": 154.74461044822505, + "distance_penalty_weight": 0.8860393814330001, + "cluster_radius_km": 5.423331802727045, + "search_time_limit_seconds": 13, + "road_factor": 1.4320444686252563 + }, + "score": 86.86381530761719 + }, + { + "params": { + "max_pickup_distance_km": 6.354116300119992, + "max_kitchen_distance_km": 3.8842834181273576, + "max_orders_per_rider": 16, + "ideal_load": 5, + "workload_balance_threshold": 0.5437101399226733, + "workload_penalty_weight": 156.68291617578234, + "distance_penalty_weight": 0.8795681893638614, + "cluster_radius_km": 5.428404376648247, + "search_time_limit_seconds": 13, + "road_factor": 1.4529085299702669 + }, + "score": 86.86381530761719 + }, + { + "params": { + "max_pickup_distance_km": 6.351668559299965, + "max_kitchen_distance_km": 3.863707133424694, + "max_orders_per_rider": 16, + "ideal_load": 5, + "workload_balance_threshold": 0.5440550956654271, + "workload_penalty_weight": 156.93143052929284, + "distance_penalty_weight": 0.8888601449255451, + "cluster_radius_km": 5.485806856584574, + "search_time_limit_seconds": 13, + "road_factor": 1.430060874518316 + }, + "score": 86.86381530761719 + }, + { + "params": { + "max_pickup_distance_km": 6.36340684056692, + "max_kitchen_distance_km": 3.8544747047074113, + "max_orders_per_rider": 16, + "ideal_load": 5, + "workload_balance_threshold": 0.5477473200120031, + "workload_penalty_weight": 156.75808775095646, + "distance_penalty_weight": 0.9210789943267018, + "cluster_radius_km": 5.660715379307142, + "search_time_limit_seconds": 13, + "road_factor": 1.4449700025276115 + }, + "score": 86.86381530761719 + }, + { + "params": { + "max_pickup_distance_km": 6.337201751606118, + "max_kitchen_distance_km": 3.9155047746745466, + "max_orders_per_rider": 16, + "ideal_load": 5, + "workload_balance_threshold": 0.5460757043805732, + "workload_penalty_weight": 157.44456134140316, + "distance_penalty_weight": 0.8990546723563242, + "cluster_radius_km": 5.452152416986682, + "search_time_limit_seconds": 13, + "road_factor": 1.4450395913087812 + }, + "score": 86.86381530761719 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260406_113420.json b/ml_data/reports/tuning_20260406_113420.json new file mode 100644 index 0000000..b47c0ac --- /dev/null +++ b/ml_data/reports/tuning_20260406_113420.json @@ -0,0 +1,197 @@ +{ + "timestamp": "2026-04-06T11:34:20.840607", + "training_rows": 57, + "n_trials": 150, + "best_predicted_quality": 89.24, + "best_params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "validation": { + "r2_score": 0.741, + "mae": 6.313, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-6.3 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 65.71, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 57 + }, + "feature_importance": { + "rolling_avg_quality_5": 36.34, + "quality_delta_10": 21.91, + "num_orders": 19.6, + "hour": 14.36, + "num_riders": 6.2, + "max_pickup_distance_km": 0.69, + "day_of_week": 0.59, + "max_kitchen_distance_km": 0.24, + "workload_balance_threshold": 0.07, + "distance_penalty_weight": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "score": 89.23719024658203 + }, + { + "params": { + "max_pickup_distance_km": 6.841710404740362, + "max_kitchen_distance_km": 4.198812185585421, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8052332485018651, + "workload_penalty_weight": 165.15689218876625, + "distance_penalty_weight": 1.4435780491881305, + "cluster_radius_km": 5.072181010489, + "search_time_limit_seconds": 12, + "road_factor": 1.5088037965000476 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.820924491481588, + "max_kitchen_distance_km": 4.2236188681147215, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9412844641881769, + "workload_penalty_weight": 164.41212568224842, + "distance_penalty_weight": 1.80390299391351, + "cluster_radius_km": 5.068709178325149, + "search_time_limit_seconds": 12, + "road_factor": 1.5114592113174095 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.771003849233631, + "max_kitchen_distance_km": 4.260033470051556, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9419209792018807, + "workload_penalty_weight": 163.16077813565002, + "distance_penalty_weight": 2.009287785194642, + "cluster_radius_km": 5.059599874516481, + "search_time_limit_seconds": 12, + "road_factor": 1.510934727861319 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.865086023552823, + "max_kitchen_distance_km": 4.2300955001234835, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9485099501223543, + "workload_penalty_weight": 113.50121305628458, + "distance_penalty_weight": 2.217076259867863, + "cluster_radius_km": 5.0206807120073345, + "search_time_limit_seconds": 12, + "road_factor": 1.5158307797044195 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.809685584778185, + "max_kitchen_distance_km": 4.2054614892522615, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9498351517670537, + "workload_penalty_weight": 121.30396082659882, + "distance_penalty_weight": 2.3357136947778963, + "cluster_radius_km": 5.0512215296804115, + "search_time_limit_seconds": 12, + "road_factor": 1.5116252292771089 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.813005359405248, + "max_kitchen_distance_km": 4.1953195698102, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9408856743556727, + "workload_penalty_weight": 112.5369693779748, + "distance_penalty_weight": 2.2557510241755763, + "cluster_radius_km": 5.072844374062231, + "search_time_limit_seconds": 12, + "road_factor": 1.5122502590292002 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.804074242310791, + "max_kitchen_distance_km": 4.206409080848127, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9468038885349329, + "workload_penalty_weight": 118.93403357911558, + "distance_penalty_weight": 2.2764083947813107, + "cluster_radius_km": 5.044194353666736, + "search_time_limit_seconds": 12, + "road_factor": 1.5146413175465638 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.83707314646065, + "max_kitchen_distance_km": 4.23929386242376, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9453355580279756, + "workload_penalty_weight": 116.37037778507518, + "distance_penalty_weight": 2.4693040098737296, + "cluster_radius_km": 5.072886824671098, + "search_time_limit_seconds": 12, + "road_factor": 1.5159033836084548 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.830306126015477, + "max_kitchen_distance_km": 4.217592923048695, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9455786388966734, + "workload_penalty_weight": 114.0384093899957, + "distance_penalty_weight": 2.2458270153688256, + "cluster_radius_km": 5.072205045478337, + "search_time_limit_seconds": 12, + "road_factor": 1.5099991858145683 + }, + "score": 89.02847290039062 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260407_015938.json b/ml_data/reports/tuning_20260407_015938.json new file mode 100644 index 0000000..b4a5621 --- /dev/null +++ b/ml_data/reports/tuning_20260407_015938.json @@ -0,0 +1,201 @@ +{ + "timestamp": "2026-04-07T01:59:38.951100", + "training_rows": 67, + "n_trials": 100, + "best_predicted_quality": 89.24, + "best_params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "validation": { + "r2_score": 0.7524, + "mae": 5.994, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-6.0 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 67.97, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 67 + }, + "feature_importance": { + "rolling_avg_quality_5": 35.23, + "quality_delta_10": 22.24, + "num_orders": 19.32, + "hour": 14.27, + "num_riders": 5.97, + "max_pickup_distance_km": 1.1, + "day_of_week": 0.86, + "ideal_load": 0.38, + "max_kitchen_distance_km": 0.29, + "workload_balance_threshold": 0.2, + "distance_penalty_weight": 0.08, + "max_orders_per_rider": 0.03, + "search_time_limit_seconds": 0.03, + "is_peak": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "score": 89.23719024658203 + }, + { + "params": { + "max_pickup_distance_km": 6.841710404740362, + "max_kitchen_distance_km": 4.198812185585421, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8052332485018651, + "workload_penalty_weight": 165.15689218876625, + "distance_penalty_weight": 1.4435780491881305, + "cluster_radius_km": 5.072181010489, + "search_time_limit_seconds": 12, + "road_factor": 1.5088037965000476 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.820924491481588, + "max_kitchen_distance_km": 4.2236188681147215, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9412844641881769, + "workload_penalty_weight": 164.41212568224842, + "distance_penalty_weight": 1.80390299391351, + "cluster_radius_km": 5.068709178325149, + "search_time_limit_seconds": 12, + "road_factor": 1.5114592113174095 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.771003849233631, + "max_kitchen_distance_km": 4.260033470051556, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9419209792018807, + "workload_penalty_weight": 163.16077813565002, + "distance_penalty_weight": 2.009287785194642, + "cluster_radius_km": 5.059599874516481, + "search_time_limit_seconds": 12, + "road_factor": 1.510934727861319 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.865086023552823, + "max_kitchen_distance_km": 4.2300955001234835, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9485099501223543, + "workload_penalty_weight": 113.50121305628458, + "distance_penalty_weight": 2.217076259867863, + "cluster_radius_km": 5.0206807120073345, + "search_time_limit_seconds": 12, + "road_factor": 1.5158307797044195 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.809685584778185, + "max_kitchen_distance_km": 4.2054614892522615, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9498351517670537, + "workload_penalty_weight": 121.30396082659882, + "distance_penalty_weight": 2.3357136947778963, + "cluster_radius_km": 5.0512215296804115, + "search_time_limit_seconds": 12, + "road_factor": 1.5116252292771089 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.813005359405248, + "max_kitchen_distance_km": 4.1953195698102, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9408856743556727, + "workload_penalty_weight": 112.5369693779748, + "distance_penalty_weight": 2.2557510241755763, + "cluster_radius_km": 5.072844374062231, + "search_time_limit_seconds": 12, + "road_factor": 1.5122502590292002 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.804074242310791, + "max_kitchen_distance_km": 4.206409080848127, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9468038885349329, + "workload_penalty_weight": 118.93403357911558, + "distance_penalty_weight": 2.2764083947813107, + "cluster_radius_km": 5.044194353666736, + "search_time_limit_seconds": 12, + "road_factor": 1.5146413175465638 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.83707314646065, + "max_kitchen_distance_km": 4.23929386242376, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9453355580279756, + "workload_penalty_weight": 116.37037778507518, + "distance_penalty_weight": 2.4693040098737296, + "cluster_radius_km": 5.072886824671098, + "search_time_limit_seconds": 12, + "road_factor": 1.5159033836084548 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.830306126015477, + "max_kitchen_distance_km": 4.217592923048695, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9455786388966734, + "workload_penalty_weight": 114.0384093899957, + "distance_penalty_weight": 2.2458270153688256, + "cluster_radius_km": 5.072205045478337, + "search_time_limit_seconds": 12, + "road_factor": 1.5099991858145683 + }, + "score": 89.02847290039062 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260407_044422.json b/ml_data/reports/tuning_20260407_044422.json new file mode 100644 index 0000000..33d2a6b --- /dev/null +++ b/ml_data/reports/tuning_20260407_044422.json @@ -0,0 +1,201 @@ +{ + "timestamp": "2026-04-07T04:44:22.624847", + "training_rows": 70, + "n_trials": 150, + "best_predicted_quality": 89.24, + "best_params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "validation": { + "r2_score": 0.7574, + "mae": 5.954, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-6.0 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 68.57, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 70 + }, + "feature_importance": { + "rolling_avg_quality_5": 34.94, + "quality_delta_10": 21.89, + "num_orders": 17.3, + "hour": 10.45, + "num_riders": 7.5, + "day_of_week": 2.97, + "max_pickup_distance_km": 2.95, + "max_kitchen_distance_km": 1.16, + "max_orders_per_rider": 0.23, + "workload_penalty_weight": 0.21, + "ideal_load": 0.14, + "distance_penalty_weight": 0.14, + "workload_balance_threshold": 0.07, + "is_peak": 0.05 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "score": 89.23719024658203 + }, + { + "params": { + "max_pickup_distance_km": 6.841710404740362, + "max_kitchen_distance_km": 4.198812185585421, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8052332485018651, + "workload_penalty_weight": 165.15689218876625, + "distance_penalty_weight": 1.4435780491881305, + "cluster_radius_km": 5.072181010489, + "search_time_limit_seconds": 12, + "road_factor": 1.5088037965000476 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.820924491481588, + "max_kitchen_distance_km": 4.2236188681147215, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9412844641881769, + "workload_penalty_weight": 164.41212568224842, + "distance_penalty_weight": 1.80390299391351, + "cluster_radius_km": 5.068709178325149, + "search_time_limit_seconds": 12, + "road_factor": 1.5114592113174095 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.771003849233631, + "max_kitchen_distance_km": 4.260033470051556, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9419209792018807, + "workload_penalty_weight": 163.16077813565002, + "distance_penalty_weight": 2.009287785194642, + "cluster_radius_km": 5.059599874516481, + "search_time_limit_seconds": 12, + "road_factor": 1.510934727861319 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.865086023552823, + "max_kitchen_distance_km": 4.2300955001234835, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9485099501223543, + "workload_penalty_weight": 113.50121305628458, + "distance_penalty_weight": 2.217076259867863, + "cluster_radius_km": 5.0206807120073345, + "search_time_limit_seconds": 12, + "road_factor": 1.5158307797044195 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.809685584778185, + "max_kitchen_distance_km": 4.2054614892522615, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9498351517670537, + "workload_penalty_weight": 121.30396082659882, + "distance_penalty_weight": 2.3357136947778963, + "cluster_radius_km": 5.0512215296804115, + "search_time_limit_seconds": 12, + "road_factor": 1.5116252292771089 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.813005359405248, + "max_kitchen_distance_km": 4.1953195698102, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9408856743556727, + "workload_penalty_weight": 112.5369693779748, + "distance_penalty_weight": 2.2557510241755763, + "cluster_radius_km": 5.072844374062231, + "search_time_limit_seconds": 12, + "road_factor": 1.5122502590292002 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.804074242310791, + "max_kitchen_distance_km": 4.206409080848127, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9468038885349329, + "workload_penalty_weight": 118.93403357911558, + "distance_penalty_weight": 2.2764083947813107, + "cluster_radius_km": 5.044194353666736, + "search_time_limit_seconds": 12, + "road_factor": 1.5146413175465638 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.83707314646065, + "max_kitchen_distance_km": 4.23929386242376, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9453355580279756, + "workload_penalty_weight": 116.37037778507518, + "distance_penalty_weight": 2.4693040098737296, + "cluster_radius_km": 5.072886824671098, + "search_time_limit_seconds": 12, + "road_factor": 1.5159033836084548 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.830306126015477, + "max_kitchen_distance_km": 4.217592923048695, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9455786388966734, + "workload_penalty_weight": 114.0384093899957, + "distance_penalty_weight": 2.2458270153688256, + "cluster_radius_km": 5.072205045478337, + "search_time_limit_seconds": 12, + "road_factor": 1.5099991858145683 + }, + "score": 89.02847290039062 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260407_053406.json b/ml_data/reports/tuning_20260407_053406.json new file mode 100644 index 0000000..24bd4af --- /dev/null +++ b/ml_data/reports/tuning_20260407_053406.json @@ -0,0 +1,201 @@ +{ + "timestamp": "2026-04-07T05:34:06.339200", + "training_rows": 70, + "n_trials": 150, + "best_predicted_quality": 89.24, + "best_params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "validation": { + "r2_score": 0.7574, + "mae": 5.954, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-6.0 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 68.57, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 70 + }, + "feature_importance": { + "rolling_avg_quality_5": 34.58, + "quality_delta_10": 22.11, + "num_orders": 18.73, + "hour": 14.0, + "num_riders": 6.28, + "max_pickup_distance_km": 1.43, + "day_of_week": 1.24, + "ideal_load": 0.61, + "max_kitchen_distance_km": 0.5, + "workload_balance_threshold": 0.26, + "distance_penalty_weight": 0.12, + "max_orders_per_rider": 0.05, + "is_peak": 0.04, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "score": 89.23719024658203 + }, + { + "params": { + "max_pickup_distance_km": 6.841710404740362, + "max_kitchen_distance_km": 4.198812185585421, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8052332485018651, + "workload_penalty_weight": 165.15689218876625, + "distance_penalty_weight": 1.4435780491881305, + "cluster_radius_km": 5.072181010489, + "search_time_limit_seconds": 12, + "road_factor": 1.5088037965000476 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.820924491481588, + "max_kitchen_distance_km": 4.2236188681147215, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9412844641881769, + "workload_penalty_weight": 164.41212568224842, + "distance_penalty_weight": 1.80390299391351, + "cluster_radius_km": 5.068709178325149, + "search_time_limit_seconds": 12, + "road_factor": 1.5114592113174095 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.771003849233631, + "max_kitchen_distance_km": 4.260033470051556, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9419209792018807, + "workload_penalty_weight": 163.16077813565002, + "distance_penalty_weight": 2.009287785194642, + "cluster_radius_km": 5.059599874516481, + "search_time_limit_seconds": 12, + "road_factor": 1.510934727861319 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.865086023552823, + "max_kitchen_distance_km": 4.2300955001234835, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9485099501223543, + "workload_penalty_weight": 113.50121305628458, + "distance_penalty_weight": 2.217076259867863, + "cluster_radius_km": 5.0206807120073345, + "search_time_limit_seconds": 12, + "road_factor": 1.5158307797044195 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.809685584778185, + "max_kitchen_distance_km": 4.2054614892522615, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9498351517670537, + "workload_penalty_weight": 121.30396082659882, + "distance_penalty_weight": 2.3357136947778963, + "cluster_radius_km": 5.0512215296804115, + "search_time_limit_seconds": 12, + "road_factor": 1.5116252292771089 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.813005359405248, + "max_kitchen_distance_km": 4.1953195698102, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9408856743556727, + "workload_penalty_weight": 112.5369693779748, + "distance_penalty_weight": 2.2557510241755763, + "cluster_radius_km": 5.072844374062231, + "search_time_limit_seconds": 12, + "road_factor": 1.5122502590292002 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.804074242310791, + "max_kitchen_distance_km": 4.206409080848127, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9468038885349329, + "workload_penalty_weight": 118.93403357911558, + "distance_penalty_weight": 2.2764083947813107, + "cluster_radius_km": 5.044194353666736, + "search_time_limit_seconds": 12, + "road_factor": 1.5146413175465638 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.83707314646065, + "max_kitchen_distance_km": 4.23929386242376, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9453355580279756, + "workload_penalty_weight": 116.37037778507518, + "distance_penalty_weight": 2.4693040098737296, + "cluster_radius_km": 5.072886824671098, + "search_time_limit_seconds": 12, + "road_factor": 1.5159033836084548 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.830306126015477, + "max_kitchen_distance_km": 4.217592923048695, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9455786388966734, + "workload_penalty_weight": 114.0384093899957, + "distance_penalty_weight": 2.2458270153688256, + "cluster_radius_km": 5.072205045478337, + "search_time_limit_seconds": 12, + "road_factor": 1.5099991858145683 + }, + "score": 89.02847290039062 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260407_055038.json b/ml_data/reports/tuning_20260407_055038.json new file mode 100644 index 0000000..d703111 --- /dev/null +++ b/ml_data/reports/tuning_20260407_055038.json @@ -0,0 +1,202 @@ +{ + "timestamp": "2026-04-07T05:50:38.347689", + "training_rows": 77, + "n_trials": 100, + "best_predicted_quality": 89.24, + "best_params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "validation": { + "r2_score": 0.7538, + "mae": 6.159, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-6.2 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 67.8, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 77 + }, + "feature_importance": { + "rolling_avg_quality_5": 33.69, + "quality_delta_10": 22.59, + "num_orders": 18.35, + "hour": 13.78, + "num_riders": 6.32, + "day_of_week": 1.86, + "max_pickup_distance_km": 1.42, + "ideal_load": 0.79, + "max_kitchen_distance_km": 0.61, + "workload_balance_threshold": 0.26, + "distance_penalty_weight": 0.16, + "max_orders_per_rider": 0.05, + "search_time_limit_seconds": 0.05, + "is_peak": 0.04, + "workload_penalty_weight": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "score": 89.23719024658203 + }, + { + "params": { + "max_pickup_distance_km": 6.841710404740362, + "max_kitchen_distance_km": 4.198812185585421, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8052332485018651, + "workload_penalty_weight": 165.15689218876625, + "distance_penalty_weight": 1.4435780491881305, + "cluster_radius_km": 5.072181010489, + "search_time_limit_seconds": 12, + "road_factor": 1.5088037965000476 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.820924491481588, + "max_kitchen_distance_km": 4.2236188681147215, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9412844641881769, + "workload_penalty_weight": 164.41212568224842, + "distance_penalty_weight": 1.80390299391351, + "cluster_radius_km": 5.068709178325149, + "search_time_limit_seconds": 12, + "road_factor": 1.5114592113174095 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.771003849233631, + "max_kitchen_distance_km": 4.260033470051556, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9419209792018807, + "workload_penalty_weight": 163.16077813565002, + "distance_penalty_weight": 2.009287785194642, + "cluster_radius_km": 5.059599874516481, + "search_time_limit_seconds": 12, + "road_factor": 1.510934727861319 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.865086023552823, + "max_kitchen_distance_km": 4.2300955001234835, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9485099501223543, + "workload_penalty_weight": 113.50121305628458, + "distance_penalty_weight": 2.217076259867863, + "cluster_radius_km": 5.0206807120073345, + "search_time_limit_seconds": 12, + "road_factor": 1.5158307797044195 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.809685584778185, + "max_kitchen_distance_km": 4.2054614892522615, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9498351517670537, + "workload_penalty_weight": 121.30396082659882, + "distance_penalty_weight": 2.3357136947778963, + "cluster_radius_km": 5.0512215296804115, + "search_time_limit_seconds": 12, + "road_factor": 1.5116252292771089 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.813005359405248, + "max_kitchen_distance_km": 4.1953195698102, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9408856743556727, + "workload_penalty_weight": 112.5369693779748, + "distance_penalty_weight": 2.2557510241755763, + "cluster_radius_km": 5.072844374062231, + "search_time_limit_seconds": 12, + "road_factor": 1.5122502590292002 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.804074242310791, + "max_kitchen_distance_km": 4.206409080848127, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9468038885349329, + "workload_penalty_weight": 118.93403357911558, + "distance_penalty_weight": 2.2764083947813107, + "cluster_radius_km": 5.044194353666736, + "search_time_limit_seconds": 12, + "road_factor": 1.5146413175465638 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.83707314646065, + "max_kitchen_distance_km": 4.23929386242376, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9453355580279756, + "workload_penalty_weight": 116.37037778507518, + "distance_penalty_weight": 2.4693040098737296, + "cluster_radius_km": 5.072886824671098, + "search_time_limit_seconds": 12, + "road_factor": 1.5159033836084548 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.830306126015477, + "max_kitchen_distance_km": 4.217592923048695, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9455786388966734, + "workload_penalty_weight": 114.0384093899957, + "distance_penalty_weight": 2.2458270153688256, + "cluster_radius_km": 5.072205045478337, + "search_time_limit_seconds": 12, + "road_factor": 1.5099991858145683 + }, + "score": 89.02847290039062 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260407_055520.json b/ml_data/reports/tuning_20260407_055520.json new file mode 100644 index 0000000..54c73f0 --- /dev/null +++ b/ml_data/reports/tuning_20260407_055520.json @@ -0,0 +1,202 @@ +{ + "timestamp": "2026-04-07T05:55:20.028939", + "training_rows": 79, + "n_trials": 150, + "best_predicted_quality": 89.24, + "best_params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "validation": { + "r2_score": 0.7895, + "mae": 5.74, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-5.7 pts (R2=0.79, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 67.25, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 79 + }, + "feature_importance": { + "rolling_avg_quality_5": 33.16, + "quality_delta_10": 23.13, + "num_orders": 17.92, + "hour": 13.47, + "num_riders": 6.38, + "day_of_week": 2.31, + "max_pickup_distance_km": 1.46, + "ideal_load": 0.92, + "max_kitchen_distance_km": 0.62, + "workload_balance_threshold": 0.28, + "distance_penalty_weight": 0.16, + "is_peak": 0.06, + "max_orders_per_rider": 0.04, + "workload_penalty_weight": 0.04, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "score": 89.23719024658203 + }, + { + "params": { + "max_pickup_distance_km": 6.841710404740362, + "max_kitchen_distance_km": 4.198812185585421, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8052332485018651, + "workload_penalty_weight": 165.15689218876625, + "distance_penalty_weight": 1.4435780491881305, + "cluster_radius_km": 5.072181010489, + "search_time_limit_seconds": 12, + "road_factor": 1.5088037965000476 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.820924491481588, + "max_kitchen_distance_km": 4.2236188681147215, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9412844641881769, + "workload_penalty_weight": 164.41212568224842, + "distance_penalty_weight": 1.80390299391351, + "cluster_radius_km": 5.068709178325149, + "search_time_limit_seconds": 12, + "road_factor": 1.5114592113174095 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.771003849233631, + "max_kitchen_distance_km": 4.260033470051556, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9419209792018807, + "workload_penalty_weight": 163.16077813565002, + "distance_penalty_weight": 2.009287785194642, + "cluster_radius_km": 5.059599874516481, + "search_time_limit_seconds": 12, + "road_factor": 1.510934727861319 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.865086023552823, + "max_kitchen_distance_km": 4.2300955001234835, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9485099501223543, + "workload_penalty_weight": 113.50121305628458, + "distance_penalty_weight": 2.217076259867863, + "cluster_radius_km": 5.0206807120073345, + "search_time_limit_seconds": 12, + "road_factor": 1.5158307797044195 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.809685584778185, + "max_kitchen_distance_km": 4.2054614892522615, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9498351517670537, + "workload_penalty_weight": 121.30396082659882, + "distance_penalty_weight": 2.3357136947778963, + "cluster_radius_km": 5.0512215296804115, + "search_time_limit_seconds": 12, + "road_factor": 1.5116252292771089 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.813005359405248, + "max_kitchen_distance_km": 4.1953195698102, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9408856743556727, + "workload_penalty_weight": 112.5369693779748, + "distance_penalty_weight": 2.2557510241755763, + "cluster_radius_km": 5.072844374062231, + "search_time_limit_seconds": 12, + "road_factor": 1.5122502590292002 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.804074242310791, + "max_kitchen_distance_km": 4.206409080848127, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9468038885349329, + "workload_penalty_weight": 118.93403357911558, + "distance_penalty_weight": 2.2764083947813107, + "cluster_radius_km": 5.044194353666736, + "search_time_limit_seconds": 12, + "road_factor": 1.5146413175465638 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.83707314646065, + "max_kitchen_distance_km": 4.23929386242376, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9453355580279756, + "workload_penalty_weight": 116.37037778507518, + "distance_penalty_weight": 2.4693040098737296, + "cluster_radius_km": 5.072886824671098, + "search_time_limit_seconds": 12, + "road_factor": 1.5159033836084548 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.830306126015477, + "max_kitchen_distance_km": 4.217592923048695, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9455786388966734, + "workload_penalty_weight": 114.0384093899957, + "distance_penalty_weight": 2.2458270153688256, + "cluster_radius_km": 5.072205045478337, + "search_time_limit_seconds": 12, + "road_factor": 1.5099991858145683 + }, + "score": 89.02847290039062 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260407_061251.json b/ml_data/reports/tuning_20260407_061251.json new file mode 100644 index 0000000..dd8dc82 --- /dev/null +++ b/ml_data/reports/tuning_20260407_061251.json @@ -0,0 +1,203 @@ +{ + "timestamp": "2026-04-07T06:12:51.914811", + "training_rows": 89, + "n_trials": 100, + "best_predicted_quality": 89.24, + "best_params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "validation": { + "r2_score": 0.6857, + "mae": 7.752, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-7.8 pts (R2=0.69, trust=good)" + }, + "baseline_stats": { + "avg_quality": 66.45, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 89 + }, + "feature_importance": { + "rolling_avg_quality_5": 32.79, + "quality_delta_10": 23.41, + "num_orders": 18.02, + "hour": 13.23, + "num_riders": 6.32, + "day_of_week": 2.58, + "max_pickup_distance_km": 1.47, + "ideal_load": 0.89, + "max_kitchen_distance_km": 0.65, + "workload_balance_threshold": 0.28, + "distance_penalty_weight": 0.15, + "is_peak": 0.05, + "max_orders_per_rider": 0.05, + "workload_penalty_weight": 0.05, + "search_time_limit_seconds": 0.04, + "cluster_radius_km": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "score": 89.23719024658203 + }, + { + "params": { + "max_pickup_distance_km": 6.841710404740362, + "max_kitchen_distance_km": 4.198812185585421, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8052332485018651, + "workload_penalty_weight": 165.15689218876625, + "distance_penalty_weight": 1.4435780491881305, + "cluster_radius_km": 5.072181010489, + "search_time_limit_seconds": 12, + "road_factor": 1.5088037965000476 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.820924491481588, + "max_kitchen_distance_km": 4.2236188681147215, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9412844641881769, + "workload_penalty_weight": 164.41212568224842, + "distance_penalty_weight": 1.80390299391351, + "cluster_radius_km": 5.068709178325149, + "search_time_limit_seconds": 12, + "road_factor": 1.5114592113174095 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.771003849233631, + "max_kitchen_distance_km": 4.260033470051556, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9419209792018807, + "workload_penalty_weight": 163.16077813565002, + "distance_penalty_weight": 2.009287785194642, + "cluster_radius_km": 5.059599874516481, + "search_time_limit_seconds": 12, + "road_factor": 1.510934727861319 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.865086023552823, + "max_kitchen_distance_km": 4.2300955001234835, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9485099501223543, + "workload_penalty_weight": 113.50121305628458, + "distance_penalty_weight": 2.217076259867863, + "cluster_radius_km": 5.0206807120073345, + "search_time_limit_seconds": 12, + "road_factor": 1.5158307797044195 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.809685584778185, + "max_kitchen_distance_km": 4.2054614892522615, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9498351517670537, + "workload_penalty_weight": 121.30396082659882, + "distance_penalty_weight": 2.3357136947778963, + "cluster_radius_km": 5.0512215296804115, + "search_time_limit_seconds": 12, + "road_factor": 1.5116252292771089 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.813005359405248, + "max_kitchen_distance_km": 4.1953195698102, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9408856743556727, + "workload_penalty_weight": 112.5369693779748, + "distance_penalty_weight": 2.2557510241755763, + "cluster_radius_km": 5.072844374062231, + "search_time_limit_seconds": 12, + "road_factor": 1.5122502590292002 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.804074242310791, + "max_kitchen_distance_km": 4.206409080848127, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9468038885349329, + "workload_penalty_weight": 118.93403357911558, + "distance_penalty_weight": 2.2764083947813107, + "cluster_radius_km": 5.044194353666736, + "search_time_limit_seconds": 12, + "road_factor": 1.5146413175465638 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.83707314646065, + "max_kitchen_distance_km": 4.23929386242376, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9453355580279756, + "workload_penalty_weight": 116.37037778507518, + "distance_penalty_weight": 2.4693040098737296, + "cluster_radius_km": 5.072886824671098, + "search_time_limit_seconds": 12, + "road_factor": 1.5159033836084548 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.830306126015477, + "max_kitchen_distance_km": 4.217592923048695, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9455786388966734, + "workload_penalty_weight": 114.0384093899957, + "distance_penalty_weight": 2.2458270153688256, + "cluster_radius_km": 5.072205045478337, + "search_time_limit_seconds": 12, + "road_factor": 1.5099991858145683 + }, + "score": 89.02847290039062 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260407_072654.json b/ml_data/reports/tuning_20260407_072654.json new file mode 100644 index 0000000..1f4fdea --- /dev/null +++ b/ml_data/reports/tuning_20260407_072654.json @@ -0,0 +1,203 @@ +{ + "timestamp": "2026-04-07T07:26:54.875923", + "training_rows": 97, + "n_trials": 150, + "best_predicted_quality": 89.24, + "best_params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "validation": { + "r2_score": 0.7088, + "mae": 6.684, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-6.7 pts (R2=0.71, trust=good)" + }, + "baseline_stats": { + "avg_quality": 68.32, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 97 + }, + "feature_importance": { + "rolling_avg_quality_5": 32.52, + "quality_delta_10": 23.45, + "num_orders": 17.89, + "hour": 13.29, + "num_riders": 6.31, + "day_of_week": 2.86, + "max_pickup_distance_km": 1.51, + "ideal_load": 0.87, + "max_kitchen_distance_km": 0.69, + "workload_balance_threshold": 0.26, + "distance_penalty_weight": 0.15, + "workload_penalty_weight": 0.06, + "is_peak": 0.05, + "max_orders_per_rider": 0.05, + "search_time_limit_seconds": 0.04, + "cluster_radius_km": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "score": 89.23719024658203 + }, + { + "params": { + "max_pickup_distance_km": 6.841710404740362, + "max_kitchen_distance_km": 4.198812185585421, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8052332485018651, + "workload_penalty_weight": 165.15689218876625, + "distance_penalty_weight": 1.4435780491881305, + "cluster_radius_km": 5.072181010489, + "search_time_limit_seconds": 12, + "road_factor": 1.5088037965000476 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.820924491481588, + "max_kitchen_distance_km": 4.2236188681147215, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9412844641881769, + "workload_penalty_weight": 164.41212568224842, + "distance_penalty_weight": 1.80390299391351, + "cluster_radius_km": 5.068709178325149, + "search_time_limit_seconds": 12, + "road_factor": 1.5114592113174095 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.771003849233631, + "max_kitchen_distance_km": 4.260033470051556, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9419209792018807, + "workload_penalty_weight": 163.16077813565002, + "distance_penalty_weight": 2.009287785194642, + "cluster_radius_km": 5.059599874516481, + "search_time_limit_seconds": 12, + "road_factor": 1.510934727861319 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.865086023552823, + "max_kitchen_distance_km": 4.2300955001234835, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9485099501223543, + "workload_penalty_weight": 113.50121305628458, + "distance_penalty_weight": 2.217076259867863, + "cluster_radius_km": 5.0206807120073345, + "search_time_limit_seconds": 12, + "road_factor": 1.5158307797044195 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.809685584778185, + "max_kitchen_distance_km": 4.2054614892522615, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9498351517670537, + "workload_penalty_weight": 121.30396082659882, + "distance_penalty_weight": 2.3357136947778963, + "cluster_radius_km": 5.0512215296804115, + "search_time_limit_seconds": 12, + "road_factor": 1.5116252292771089 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.813005359405248, + "max_kitchen_distance_km": 4.1953195698102, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9408856743556727, + "workload_penalty_weight": 112.5369693779748, + "distance_penalty_weight": 2.2557510241755763, + "cluster_radius_km": 5.072844374062231, + "search_time_limit_seconds": 12, + "road_factor": 1.5122502590292002 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.804074242310791, + "max_kitchen_distance_km": 4.206409080848127, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9468038885349329, + "workload_penalty_weight": 118.93403357911558, + "distance_penalty_weight": 2.2764083947813107, + "cluster_radius_km": 5.044194353666736, + "search_time_limit_seconds": 12, + "road_factor": 1.5146413175465638 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.83707314646065, + "max_kitchen_distance_km": 4.23929386242376, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9453355580279756, + "workload_penalty_weight": 116.37037778507518, + "distance_penalty_weight": 2.4693040098737296, + "cluster_radius_km": 5.072886824671098, + "search_time_limit_seconds": 12, + "road_factor": 1.5159033836084548 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.830306126015477, + "max_kitchen_distance_km": 4.217592923048695, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9455786388966734, + "workload_penalty_weight": 114.0384093899957, + "distance_penalty_weight": 2.2458270153688256, + "cluster_radius_km": 5.072205045478337, + "search_time_limit_seconds": 12, + "road_factor": 1.5099991858145683 + }, + "score": 89.02847290039062 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260407_073036.json b/ml_data/reports/tuning_20260407_073036.json new file mode 100644 index 0000000..f73bad2 --- /dev/null +++ b/ml_data/reports/tuning_20260407_073036.json @@ -0,0 +1,203 @@ +{ + "timestamp": "2026-04-07T07:30:36.399076", + "training_rows": 97, + "n_trials": 150, + "best_predicted_quality": 89.24, + "best_params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "validation": { + "r2_score": 0.7088, + "mae": 6.684, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-6.7 pts (R2=0.71, trust=good)" + }, + "baseline_stats": { + "avg_quality": 68.32, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 97 + }, + "feature_importance": { + "rolling_avg_quality_5": 32.37, + "quality_delta_10": 23.52, + "num_orders": 17.69, + "hour": 13.16, + "num_riders": 6.24, + "day_of_week": 3.27, + "max_pickup_distance_km": 1.52, + "ideal_load": 0.88, + "max_kitchen_distance_km": 0.74, + "workload_balance_threshold": 0.26, + "distance_penalty_weight": 0.15, + "workload_penalty_weight": 0.06, + "is_peak": 0.05, + "max_orders_per_rider": 0.04, + "search_time_limit_seconds": 0.04, + "cluster_radius_km": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "score": 89.23719024658203 + }, + { + "params": { + "max_pickup_distance_km": 6.841710404740362, + "max_kitchen_distance_km": 4.198812185585421, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8052332485018651, + "workload_penalty_weight": 165.15689218876625, + "distance_penalty_weight": 1.4435780491881305, + "cluster_radius_km": 5.072181010489, + "search_time_limit_seconds": 12, + "road_factor": 1.5088037965000476 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.820924491481588, + "max_kitchen_distance_km": 4.2236188681147215, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9412844641881769, + "workload_penalty_weight": 164.41212568224842, + "distance_penalty_weight": 1.80390299391351, + "cluster_radius_km": 5.068709178325149, + "search_time_limit_seconds": 12, + "road_factor": 1.5114592113174095 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.771003849233631, + "max_kitchen_distance_km": 4.260033470051556, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9419209792018807, + "workload_penalty_weight": 163.16077813565002, + "distance_penalty_weight": 2.009287785194642, + "cluster_radius_km": 5.059599874516481, + "search_time_limit_seconds": 12, + "road_factor": 1.510934727861319 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.865086023552823, + "max_kitchen_distance_km": 4.2300955001234835, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9485099501223543, + "workload_penalty_weight": 113.50121305628458, + "distance_penalty_weight": 2.217076259867863, + "cluster_radius_km": 5.0206807120073345, + "search_time_limit_seconds": 12, + "road_factor": 1.5158307797044195 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.809685584778185, + "max_kitchen_distance_km": 4.2054614892522615, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9498351517670537, + "workload_penalty_weight": 121.30396082659882, + "distance_penalty_weight": 2.3357136947778963, + "cluster_radius_km": 5.0512215296804115, + "search_time_limit_seconds": 12, + "road_factor": 1.5116252292771089 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.813005359405248, + "max_kitchen_distance_km": 4.1953195698102, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9408856743556727, + "workload_penalty_weight": 112.5369693779748, + "distance_penalty_weight": 2.2557510241755763, + "cluster_radius_km": 5.072844374062231, + "search_time_limit_seconds": 12, + "road_factor": 1.5122502590292002 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.804074242310791, + "max_kitchen_distance_km": 4.206409080848127, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9468038885349329, + "workload_penalty_weight": 118.93403357911558, + "distance_penalty_weight": 2.2764083947813107, + "cluster_radius_km": 5.044194353666736, + "search_time_limit_seconds": 12, + "road_factor": 1.5146413175465638 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.83707314646065, + "max_kitchen_distance_km": 4.23929386242376, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9453355580279756, + "workload_penalty_weight": 116.37037778507518, + "distance_penalty_weight": 2.4693040098737296, + "cluster_radius_km": 5.072886824671098, + "search_time_limit_seconds": 12, + "road_factor": 1.5159033836084548 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.830306126015477, + "max_kitchen_distance_km": 4.217592923048695, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9455786388966734, + "workload_penalty_weight": 114.0384093899957, + "distance_penalty_weight": 2.2458270153688256, + "cluster_radius_km": 5.072205045478337, + "search_time_limit_seconds": 12, + "road_factor": 1.5099991858145683 + }, + "score": 89.02847290039062 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260407_083837.json b/ml_data/reports/tuning_20260407_083837.json new file mode 100644 index 0000000..733349b --- /dev/null +++ b/ml_data/reports/tuning_20260407_083837.json @@ -0,0 +1,203 @@ +{ + "timestamp": "2026-04-07T08:38:37.380580", + "training_rows": 97, + "n_trials": 150, + "best_predicted_quality": 89.24, + "best_params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "validation": { + "r2_score": 0.7088, + "mae": 6.684, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-6.7 pts (R2=0.71, trust=good)" + }, + "baseline_stats": { + "avg_quality": 68.32, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 97 + }, + "feature_importance": { + "rolling_avg_quality_5": 32.5, + "quality_delta_10": 23.4, + "num_orders": 17.57, + "hour": 12.99, + "num_riders": 6.14, + "day_of_week": 3.61, + "max_pickup_distance_km": 1.56, + "ideal_load": 0.89, + "max_kitchen_distance_km": 0.75, + "workload_balance_threshold": 0.26, + "distance_penalty_weight": 0.15, + "workload_penalty_weight": 0.06, + "is_peak": 0.05, + "max_orders_per_rider": 0.04, + "search_time_limit_seconds": 0.03, + "cluster_radius_km": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 6.735532343839225, + "max_kitchen_distance_km": 4.197619251759459, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.5214245551586657, + "workload_penalty_weight": 163.0140787394627, + "distance_penalty_weight": 1.3934513637108987, + "cluster_radius_km": 5.037360156635181, + "search_time_limit_seconds": 12, + "road_factor": 1.5171200156937537 + }, + "score": 89.23719024658203 + }, + { + "params": { + "max_pickup_distance_km": 6.841710404740362, + "max_kitchen_distance_km": 4.198812185585421, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8052332485018651, + "workload_penalty_weight": 165.15689218876625, + "distance_penalty_weight": 1.4435780491881305, + "cluster_radius_km": 5.072181010489, + "search_time_limit_seconds": 12, + "road_factor": 1.5088037965000476 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.820924491481588, + "max_kitchen_distance_km": 4.2236188681147215, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9412844641881769, + "workload_penalty_weight": 164.41212568224842, + "distance_penalty_weight": 1.80390299391351, + "cluster_radius_km": 5.068709178325149, + "search_time_limit_seconds": 12, + "road_factor": 1.5114592113174095 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.771003849233631, + "max_kitchen_distance_km": 4.260033470051556, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9419209792018807, + "workload_penalty_weight": 163.16077813565002, + "distance_penalty_weight": 2.009287785194642, + "cluster_radius_km": 5.059599874516481, + "search_time_limit_seconds": 12, + "road_factor": 1.510934727861319 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.865086023552823, + "max_kitchen_distance_km": 4.2300955001234835, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9485099501223543, + "workload_penalty_weight": 113.50121305628458, + "distance_penalty_weight": 2.217076259867863, + "cluster_radius_km": 5.0206807120073345, + "search_time_limit_seconds": 12, + "road_factor": 1.5158307797044195 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.809685584778185, + "max_kitchen_distance_km": 4.2054614892522615, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9498351517670537, + "workload_penalty_weight": 121.30396082659882, + "distance_penalty_weight": 2.3357136947778963, + "cluster_radius_km": 5.0512215296804115, + "search_time_limit_seconds": 12, + "road_factor": 1.5116252292771089 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.813005359405248, + "max_kitchen_distance_km": 4.1953195698102, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9408856743556727, + "workload_penalty_weight": 112.5369693779748, + "distance_penalty_weight": 2.2557510241755763, + "cluster_radius_km": 5.072844374062231, + "search_time_limit_seconds": 12, + "road_factor": 1.5122502590292002 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.804074242310791, + "max_kitchen_distance_km": 4.206409080848127, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9468038885349329, + "workload_penalty_weight": 118.93403357911558, + "distance_penalty_weight": 2.2764083947813107, + "cluster_radius_km": 5.044194353666736, + "search_time_limit_seconds": 12, + "road_factor": 1.5146413175465638 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.83707314646065, + "max_kitchen_distance_km": 4.23929386242376, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9453355580279756, + "workload_penalty_weight": 116.37037778507518, + "distance_penalty_weight": 2.4693040098737296, + "cluster_radius_km": 5.072886824671098, + "search_time_limit_seconds": 12, + "road_factor": 1.5159033836084548 + }, + "score": 89.02847290039062 + }, + { + "params": { + "max_pickup_distance_km": 6.830306126015477, + "max_kitchen_distance_km": 4.217592923048695, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.9455786388966734, + "workload_penalty_weight": 114.0384093899957, + "distance_penalty_weight": 2.2458270153688256, + "cluster_radius_km": 5.072205045478337, + "search_time_limit_seconds": 12, + "road_factor": 1.5099991858145683 + }, + "score": 89.02847290039062 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260407_100305.json b/ml_data/reports/tuning_20260407_100305.json new file mode 100644 index 0000000..d276a32 --- /dev/null +++ b/ml_data/reports/tuning_20260407_100305.json @@ -0,0 +1,203 @@ +{ + "timestamp": "2026-04-07T10:03:05.667921", + "training_rows": 97, + "n_trials": 150, + "best_predicted_quality": 89.4, + "best_params": { + "max_pickup_distance_km": 7.130020162334684, + "max_kitchen_distance_km": 4.280839128384073, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8854582632265207, + "workload_penalty_weight": 105.43303608103864, + "distance_penalty_weight": 2.3152400473443335, + "cluster_radius_km": 4.722786290266237, + "search_time_limit_seconds": 13, + "road_factor": 1.5274307417515143 + }, + "validation": { + "r2_score": 0.7088, + "mae": 6.684, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-6.7 pts (R2=0.71, trust=good)" + }, + "baseline_stats": { + "avg_quality": 68.32, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 97 + }, + "feature_importance": { + "rolling_avg_quality_5": 32.72, + "quality_delta_10": 23.53, + "num_orders": 17.26, + "hour": 12.84, + "num_riders": 6.04, + "day_of_week": 3.81, + "max_pickup_distance_km": 1.59, + "ideal_load": 0.85, + "max_kitchen_distance_km": 0.73, + "workload_balance_threshold": 0.27, + "distance_penalty_weight": 0.15, + "workload_penalty_weight": 0.07, + "is_peak": 0.05, + "search_time_limit_seconds": 0.05, + "max_orders_per_rider": 0.04, + "cluster_radius_km": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 7.130020162334684, + "max_kitchen_distance_km": 4.280839128384073, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8854582632265207, + "workload_penalty_weight": 105.43303608103864, + "distance_penalty_weight": 2.3152400473443335, + "cluster_radius_km": 4.722786290266237, + "search_time_limit_seconds": 13, + "road_factor": 1.5274307417515143 + }, + "score": 89.39888000488281 + }, + { + "params": { + "max_pickup_distance_km": 7.159371587069677, + "max_kitchen_distance_km": 4.033386033322248, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.863536050890365, + "workload_penalty_weight": 97.43265762258073, + "distance_penalty_weight": 1.9100499560802082, + "cluster_radius_km": 4.511755856356149, + "search_time_limit_seconds": 14, + "road_factor": 1.4939199795886327 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.237839336535851, + "max_kitchen_distance_km": 3.663365702556132, + "max_orders_per_rider": 16, + "ideal_load": 4, + "workload_balance_threshold": 0.8735336296938158, + "workload_penalty_weight": 87.18895234690117, + "distance_penalty_weight": 1.902615724431142, + "cluster_radius_km": 4.135522505489794, + "search_time_limit_seconds": 14, + "road_factor": 1.4941578228086358 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.209008794453106, + "max_kitchen_distance_km": 3.5871901473162935, + "max_orders_per_rider": 17, + "ideal_load": 4, + "workload_balance_threshold": 0.8636601075743638, + "workload_penalty_weight": 86.88314997861353, + "distance_penalty_weight": 1.713990617922939, + "cluster_radius_km": 3.9805610734693078, + "search_time_limit_seconds": 14, + "road_factor": 1.4709255743019745 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.293606340881382, + "max_kitchen_distance_km": 3.6099841904143544, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8391162982772516, + "workload_penalty_weight": 81.78402384933284, + "distance_penalty_weight": 1.4924949118149284, + "cluster_radius_km": 4.004081091262425, + "search_time_limit_seconds": 15, + "road_factor": 1.4950180193418494 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.231818308493086, + "max_kitchen_distance_km": 3.5987025683885814, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8679819345591729, + "workload_penalty_weight": 84.66571137735836, + "distance_penalty_weight": 1.7142915230680047, + "cluster_radius_km": 3.9216203223089767, + "search_time_limit_seconds": 14, + "road_factor": 1.4831054798161563 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.300424964430984, + "max_kitchen_distance_km": 3.6131608968543274, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8475063079023154, + "workload_penalty_weight": 84.06676343906496, + "distance_penalty_weight": 1.5413441475020342, + "cluster_radius_km": 3.911615413718933, + "search_time_limit_seconds": 14, + "road_factor": 1.4812141284424145 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.265650750564059, + "max_kitchen_distance_km": 3.590986817226879, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8536491441751559, + "workload_penalty_weight": 83.53289668387433, + "distance_penalty_weight": 1.529774802118949, + "cluster_radius_km": 3.572233786654972, + "search_time_limit_seconds": 15, + "road_factor": 1.485395954896316 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.263343465055543, + "max_kitchen_distance_km": 3.7746106852600296, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8456925598017999, + "workload_penalty_weight": 86.05760075611829, + "distance_penalty_weight": 1.5496670626377171, + "cluster_radius_km": 3.4692879161186077, + "search_time_limit_seconds": 15, + "road_factor": 1.4938443091991387 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.225549460912673, + "max_kitchen_distance_km": 3.546815323022868, + "max_orders_per_rider": 17, + "ideal_load": 2, + "workload_balance_threshold": 0.8538034239262067, + "workload_penalty_weight": 79.43517045634971, + "distance_penalty_weight": 1.3116923117558434, + "cluster_radius_km": 3.88979206962715, + "search_time_limit_seconds": 14, + "road_factor": 1.4911856069021672 + }, + "score": 89.29891967773438 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260407_110353.json b/ml_data/reports/tuning_20260407_110353.json new file mode 100644 index 0000000..d9c012e --- /dev/null +++ b/ml_data/reports/tuning_20260407_110353.json @@ -0,0 +1,203 @@ +{ + "timestamp": "2026-04-07T11:03:53.039644", + "training_rows": 100, + "n_trials": 100, + "best_predicted_quality": 89.4, + "best_params": { + "max_pickup_distance_km": 7.130020162334684, + "max_kitchen_distance_km": 4.280839128384073, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8854582632265207, + "workload_penalty_weight": 105.43303608103864, + "distance_penalty_weight": 2.3152400473443335, + "cluster_radius_km": 4.722786290266237, + "search_time_limit_seconds": 13, + "road_factor": 1.5274307417515143 + }, + "validation": { + "r2_score": 0.6699, + "mae": 7.393, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-7.4 pts (R2=0.67, trust=good)" + }, + "baseline_stats": { + "avg_quality": 68.97, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 100 + }, + "feature_importance": { + "rolling_avg_quality_5": 32.86, + "quality_delta_10": 23.57, + "num_orders": 17.08, + "hour": 12.54, + "num_riders": 5.97, + "day_of_week": 3.87, + "max_pickup_distance_km": 1.6, + "ideal_load": 0.84, + "max_kitchen_distance_km": 0.7, + "workload_balance_threshold": 0.56, + "distance_penalty_weight": 0.2, + "workload_penalty_weight": 0.07, + "search_time_limit_seconds": 0.07, + "is_peak": 0.04, + "max_orders_per_rider": 0.04, + "cluster_radius_km": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 7.130020162334684, + "max_kitchen_distance_km": 4.280839128384073, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8854582632265207, + "workload_penalty_weight": 105.43303608103864, + "distance_penalty_weight": 2.3152400473443335, + "cluster_radius_km": 4.722786290266237, + "search_time_limit_seconds": 13, + "road_factor": 1.5274307417515143 + }, + "score": 89.39888000488281 + }, + { + "params": { + "max_pickup_distance_km": 7.159371587069677, + "max_kitchen_distance_km": 4.033386033322248, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.863536050890365, + "workload_penalty_weight": 97.43265762258073, + "distance_penalty_weight": 1.9100499560802082, + "cluster_radius_km": 4.511755856356149, + "search_time_limit_seconds": 14, + "road_factor": 1.4939199795886327 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.237839336535851, + "max_kitchen_distance_km": 3.663365702556132, + "max_orders_per_rider": 16, + "ideal_load": 4, + "workload_balance_threshold": 0.8735336296938158, + "workload_penalty_weight": 87.18895234690117, + "distance_penalty_weight": 1.902615724431142, + "cluster_radius_km": 4.135522505489794, + "search_time_limit_seconds": 14, + "road_factor": 1.4941578228086358 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.209008794453106, + "max_kitchen_distance_km": 3.5871901473162935, + "max_orders_per_rider": 17, + "ideal_load": 4, + "workload_balance_threshold": 0.8636601075743638, + "workload_penalty_weight": 86.88314997861353, + "distance_penalty_weight": 1.713990617922939, + "cluster_radius_km": 3.9805610734693078, + "search_time_limit_seconds": 14, + "road_factor": 1.4709255743019745 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.293606340881382, + "max_kitchen_distance_km": 3.6099841904143544, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8391162982772516, + "workload_penalty_weight": 81.78402384933284, + "distance_penalty_weight": 1.4924949118149284, + "cluster_radius_km": 4.004081091262425, + "search_time_limit_seconds": 15, + "road_factor": 1.4950180193418494 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.231818308493086, + "max_kitchen_distance_km": 3.5987025683885814, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8679819345591729, + "workload_penalty_weight": 84.66571137735836, + "distance_penalty_weight": 1.7142915230680047, + "cluster_radius_km": 3.9216203223089767, + "search_time_limit_seconds": 14, + "road_factor": 1.4831054798161563 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.300424964430984, + "max_kitchen_distance_km": 3.6131608968543274, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8475063079023154, + "workload_penalty_weight": 84.06676343906496, + "distance_penalty_weight": 1.5413441475020342, + "cluster_radius_km": 3.911615413718933, + "search_time_limit_seconds": 14, + "road_factor": 1.4812141284424145 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.265650750564059, + "max_kitchen_distance_km": 3.590986817226879, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8536491441751559, + "workload_penalty_weight": 83.53289668387433, + "distance_penalty_weight": 1.529774802118949, + "cluster_radius_km": 3.572233786654972, + "search_time_limit_seconds": 15, + "road_factor": 1.485395954896316 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.263343465055543, + "max_kitchen_distance_km": 3.7746106852600296, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8456925598017999, + "workload_penalty_weight": 86.05760075611829, + "distance_penalty_weight": 1.5496670626377171, + "cluster_radius_km": 3.4692879161186077, + "search_time_limit_seconds": 15, + "road_factor": 1.4938443091991387 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.225549460912673, + "max_kitchen_distance_km": 3.546815323022868, + "max_orders_per_rider": 17, + "ideal_load": 2, + "workload_balance_threshold": 0.8538034239262067, + "workload_penalty_weight": 79.43517045634971, + "distance_penalty_weight": 1.3116923117558434, + "cluster_radius_km": 3.88979206962715, + "search_time_limit_seconds": 14, + "road_factor": 1.4911856069021672 + }, + "score": 89.29891967773438 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260407_111751.json b/ml_data/reports/tuning_20260407_111751.json new file mode 100644 index 0000000..5bd3996 --- /dev/null +++ b/ml_data/reports/tuning_20260407_111751.json @@ -0,0 +1,203 @@ +{ + "timestamp": "2026-04-07T11:17:51.094393", + "training_rows": 110, + "n_trials": 100, + "best_predicted_quality": 89.4, + "best_params": { + "max_pickup_distance_km": 7.130020162334684, + "max_kitchen_distance_km": 4.280839128384073, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8854582632265207, + "workload_penalty_weight": 105.43303608103864, + "distance_penalty_weight": 2.3152400473443335, + "cluster_radius_km": 4.722786290266237, + "search_time_limit_seconds": 13, + "road_factor": 1.5274307417515143 + }, + "validation": { + "r2_score": 0.6382, + "mae": 7.893, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-7.9 pts (R2=0.64, trust=good)" + }, + "baseline_stats": { + "avg_quality": 70.8, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 110 + }, + "feature_importance": { + "rolling_avg_quality_5": 33.0, + "quality_delta_10": 23.79, + "num_orders": 16.93, + "hour": 12.16, + "num_riders": 5.79, + "day_of_week": 3.89, + "max_pickup_distance_km": 1.57, + "ideal_load": 0.83, + "workload_balance_threshold": 0.82, + "max_kitchen_distance_km": 0.75, + "distance_penalty_weight": 0.25, + "search_time_limit_seconds": 0.08, + "workload_penalty_weight": 0.07, + "is_peak": 0.04, + "max_orders_per_rider": 0.03, + "cluster_radius_km": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 7.130020162334684, + "max_kitchen_distance_km": 4.280839128384073, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8854582632265207, + "workload_penalty_weight": 105.43303608103864, + "distance_penalty_weight": 2.3152400473443335, + "cluster_radius_km": 4.722786290266237, + "search_time_limit_seconds": 13, + "road_factor": 1.5274307417515143 + }, + "score": 89.39888000488281 + }, + { + "params": { + "max_pickup_distance_km": 7.159371587069677, + "max_kitchen_distance_km": 4.033386033322248, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.863536050890365, + "workload_penalty_weight": 97.43265762258073, + "distance_penalty_weight": 1.9100499560802082, + "cluster_radius_km": 4.511755856356149, + "search_time_limit_seconds": 14, + "road_factor": 1.4939199795886327 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.237839336535851, + "max_kitchen_distance_km": 3.663365702556132, + "max_orders_per_rider": 16, + "ideal_load": 4, + "workload_balance_threshold": 0.8735336296938158, + "workload_penalty_weight": 87.18895234690117, + "distance_penalty_weight": 1.902615724431142, + "cluster_radius_km": 4.135522505489794, + "search_time_limit_seconds": 14, + "road_factor": 1.4941578228086358 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.209008794453106, + "max_kitchen_distance_km": 3.5871901473162935, + "max_orders_per_rider": 17, + "ideal_load": 4, + "workload_balance_threshold": 0.8636601075743638, + "workload_penalty_weight": 86.88314997861353, + "distance_penalty_weight": 1.713990617922939, + "cluster_radius_km": 3.9805610734693078, + "search_time_limit_seconds": 14, + "road_factor": 1.4709255743019745 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.293606340881382, + "max_kitchen_distance_km": 3.6099841904143544, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8391162982772516, + "workload_penalty_weight": 81.78402384933284, + "distance_penalty_weight": 1.4924949118149284, + "cluster_radius_km": 4.004081091262425, + "search_time_limit_seconds": 15, + "road_factor": 1.4950180193418494 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.231818308493086, + "max_kitchen_distance_km": 3.5987025683885814, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8679819345591729, + "workload_penalty_weight": 84.66571137735836, + "distance_penalty_weight": 1.7142915230680047, + "cluster_radius_km": 3.9216203223089767, + "search_time_limit_seconds": 14, + "road_factor": 1.4831054798161563 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.300424964430984, + "max_kitchen_distance_km": 3.6131608968543274, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8475063079023154, + "workload_penalty_weight": 84.06676343906496, + "distance_penalty_weight": 1.5413441475020342, + "cluster_radius_km": 3.911615413718933, + "search_time_limit_seconds": 14, + "road_factor": 1.4812141284424145 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.265650750564059, + "max_kitchen_distance_km": 3.590986817226879, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8536491441751559, + "workload_penalty_weight": 83.53289668387433, + "distance_penalty_weight": 1.529774802118949, + "cluster_radius_km": 3.572233786654972, + "search_time_limit_seconds": 15, + "road_factor": 1.485395954896316 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.263343465055543, + "max_kitchen_distance_km": 3.7746106852600296, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8456925598017999, + "workload_penalty_weight": 86.05760075611829, + "distance_penalty_weight": 1.5496670626377171, + "cluster_radius_km": 3.4692879161186077, + "search_time_limit_seconds": 15, + "road_factor": 1.4938443091991387 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.225549460912673, + "max_kitchen_distance_km": 3.546815323022868, + "max_orders_per_rider": 17, + "ideal_load": 2, + "workload_balance_threshold": 0.8538034239262067, + "workload_penalty_weight": 79.43517045634971, + "distance_penalty_weight": 1.3116923117558434, + "cluster_radius_km": 3.88979206962715, + "search_time_limit_seconds": 14, + "road_factor": 1.4911856069021672 + }, + "score": 89.29891967773438 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260407_140402.json b/ml_data/reports/tuning_20260407_140402.json new file mode 100644 index 0000000..7eaf443 --- /dev/null +++ b/ml_data/reports/tuning_20260407_140402.json @@ -0,0 +1,203 @@ +{ + "timestamp": "2026-04-07T14:04:02.609922", + "training_rows": 114, + "n_trials": 150, + "best_predicted_quality": 89.4, + "best_params": { + "max_pickup_distance_km": 7.130020162334684, + "max_kitchen_distance_km": 4.280839128384073, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8854582632265207, + "workload_penalty_weight": 105.43303608103864, + "distance_penalty_weight": 2.3152400473443335, + "cluster_radius_km": 4.722786290266237, + "search_time_limit_seconds": 13, + "road_factor": 1.5274307417515143 + }, + "validation": { + "r2_score": 0.6981, + "mae": 7.183, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-7.2 pts (R2=0.70, trust=good)" + }, + "baseline_stats": { + "avg_quality": 71.4, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 114 + }, + "feature_importance": { + "rolling_avg_quality_5": 33.4, + "quality_delta_10": 23.95, + "num_orders": 16.78, + "hour": 11.7, + "num_riders": 5.57, + "day_of_week": 3.82, + "max_pickup_distance_km": 1.6, + "workload_balance_threshold": 0.99, + "max_kitchen_distance_km": 0.86, + "ideal_load": 0.81, + "distance_penalty_weight": 0.29, + "search_time_limit_seconds": 0.08, + "workload_penalty_weight": 0.06, + "is_peak": 0.04, + "max_orders_per_rider": 0.03, + "cluster_radius_km": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 7.130020162334684, + "max_kitchen_distance_km": 4.280839128384073, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.8854582632265207, + "workload_penalty_weight": 105.43303608103864, + "distance_penalty_weight": 2.3152400473443335, + "cluster_radius_km": 4.722786290266237, + "search_time_limit_seconds": 13, + "road_factor": 1.5274307417515143 + }, + "score": 89.39888000488281 + }, + { + "params": { + "max_pickup_distance_km": 7.159371587069677, + "max_kitchen_distance_km": 4.033386033322248, + "max_orders_per_rider": 16, + "ideal_load": 3, + "workload_balance_threshold": 0.863536050890365, + "workload_penalty_weight": 97.43265762258073, + "distance_penalty_weight": 1.9100499560802082, + "cluster_radius_km": 4.511755856356149, + "search_time_limit_seconds": 14, + "road_factor": 1.4939199795886327 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.237839336535851, + "max_kitchen_distance_km": 3.663365702556132, + "max_orders_per_rider": 16, + "ideal_load": 4, + "workload_balance_threshold": 0.8735336296938158, + "workload_penalty_weight": 87.18895234690117, + "distance_penalty_weight": 1.902615724431142, + "cluster_radius_km": 4.135522505489794, + "search_time_limit_seconds": 14, + "road_factor": 1.4941578228086358 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.209008794453106, + "max_kitchen_distance_km": 3.5871901473162935, + "max_orders_per_rider": 17, + "ideal_load": 4, + "workload_balance_threshold": 0.8636601075743638, + "workload_penalty_weight": 86.88314997861353, + "distance_penalty_weight": 1.713990617922939, + "cluster_radius_km": 3.9805610734693078, + "search_time_limit_seconds": 14, + "road_factor": 1.4709255743019745 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.293606340881382, + "max_kitchen_distance_km": 3.6099841904143544, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8391162982772516, + "workload_penalty_weight": 81.78402384933284, + "distance_penalty_weight": 1.4924949118149284, + "cluster_radius_km": 4.004081091262425, + "search_time_limit_seconds": 15, + "road_factor": 1.4950180193418494 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.231818308493086, + "max_kitchen_distance_km": 3.5987025683885814, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8679819345591729, + "workload_penalty_weight": 84.66571137735836, + "distance_penalty_weight": 1.7142915230680047, + "cluster_radius_km": 3.9216203223089767, + "search_time_limit_seconds": 14, + "road_factor": 1.4831054798161563 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.300424964430984, + "max_kitchen_distance_km": 3.6131608968543274, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8475063079023154, + "workload_penalty_weight": 84.06676343906496, + "distance_penalty_weight": 1.5413441475020342, + "cluster_radius_km": 3.911615413718933, + "search_time_limit_seconds": 14, + "road_factor": 1.4812141284424145 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.265650750564059, + "max_kitchen_distance_km": 3.590986817226879, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8536491441751559, + "workload_penalty_weight": 83.53289668387433, + "distance_penalty_weight": 1.529774802118949, + "cluster_radius_km": 3.572233786654972, + "search_time_limit_seconds": 15, + "road_factor": 1.485395954896316 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.263343465055543, + "max_kitchen_distance_km": 3.7746106852600296, + "max_orders_per_rider": 19, + "ideal_load": 2, + "workload_balance_threshold": 0.8456925598017999, + "workload_penalty_weight": 86.05760075611829, + "distance_penalty_weight": 1.5496670626377171, + "cluster_radius_km": 3.4692879161186077, + "search_time_limit_seconds": 15, + "road_factor": 1.4938443091991387 + }, + "score": 89.3228530883789 + }, + { + "params": { + "max_pickup_distance_km": 7.225549460912673, + "max_kitchen_distance_km": 3.546815323022868, + "max_orders_per_rider": 17, + "ideal_load": 2, + "workload_balance_threshold": 0.8538034239262067, + "workload_penalty_weight": 79.43517045634971, + "distance_penalty_weight": 1.3116923117558434, + "cluster_radius_km": 3.88979206962715, + "search_time_limit_seconds": 14, + "road_factor": 1.4911856069021672 + }, + "score": 89.29891967773438 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260408_015925.json b/ml_data/reports/tuning_20260408_015925.json new file mode 100644 index 0000000..d5600fa --- /dev/null +++ b/ml_data/reports/tuning_20260408_015925.json @@ -0,0 +1,203 @@ +{ + "timestamp": "2026-04-08T01:59:25.823452", + "training_rows": 120, + "n_trials": 100, + "best_predicted_quality": 92.25, + "best_params": { + "max_pickup_distance_km": 8.06481043213385, + "max_kitchen_distance_km": 3.4015023381031066, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8854774976463162, + "workload_penalty_weight": 71.31874178529236, + "distance_penalty_weight": 5.251800998756471, + "cluster_radius_km": 3.1742579527544135, + "search_time_limit_seconds": 15, + "road_factor": 1.4514851515502691 + }, + "validation": { + "r2_score": 0.616, + "mae": 7.429, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-7.4 pts (R2=0.62, trust=good)" + }, + "baseline_stats": { + "avg_quality": 72.2, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 120 + }, + "feature_importance": { + "rolling_avg_quality_5": 33.36, + "quality_delta_10": 23.75, + "num_orders": 16.69, + "hour": 11.65, + "num_riders": 5.46, + "day_of_week": 4.1, + "max_pickup_distance_km": 1.61, + "workload_balance_threshold": 1.09, + "max_kitchen_distance_km": 0.96, + "ideal_load": 0.78, + "distance_penalty_weight": 0.32, + "search_time_limit_seconds": 0.09, + "workload_penalty_weight": 0.07, + "is_peak": 0.04, + "max_orders_per_rider": 0.03, + "cluster_radius_km": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.06481043213385, + "max_kitchen_distance_km": 3.4015023381031066, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8854774976463162, + "workload_penalty_weight": 71.31874178529236, + "distance_penalty_weight": 5.251800998756471, + "cluster_radius_km": 3.1742579527544135, + "search_time_limit_seconds": 15, + "road_factor": 1.4514851515502691 + }, + "score": 92.25444030761719 + }, + { + "params": { + "max_pickup_distance_km": 8.192046567640352, + "max_kitchen_distance_km": 3.255736910817752, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8861488034083437, + "workload_penalty_weight": 64.69295331787431, + "distance_penalty_weight": 4.885948258458615, + "cluster_radius_km": 3.2315218916206643, + "search_time_limit_seconds": 15, + "road_factor": 1.4489842722670299 + }, + "score": 92.25444030761719 + }, + { + "params": { + "max_pickup_distance_km": 8.465745263942209, + "max_kitchen_distance_km": 3.1508636771017096, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8865213031808884, + "workload_penalty_weight": 73.71163228634174, + "distance_penalty_weight": 4.967498460686126, + "cluster_radius_km": 3.1698973794905356, + "search_time_limit_seconds": 15, + "road_factor": 1.422456216687863 + }, + "score": 92.25444030761719 + }, + { + "params": { + "max_pickup_distance_km": 8.658751131791412, + "max_kitchen_distance_km": 3.1289847468246923, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8890167428098635, + "workload_penalty_weight": 59.53054150526803, + "distance_penalty_weight": 5.07974040945962, + "cluster_radius_km": 2.8353557151054263, + "search_time_limit_seconds": 15, + "road_factor": 1.4182651473905141 + }, + "score": 92.25444030761719 + }, + { + "params": { + "max_pickup_distance_km": 8.577015198480908, + "max_kitchen_distance_km": 2.78301183338396, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8877654202870595, + "workload_penalty_weight": 51.21011204233429, + "distance_penalty_weight": 4.9175274061818355, + "cluster_radius_km": 2.6312971349957284, + "search_time_limit_seconds": 15, + "road_factor": 1.4249666800020322 + }, + "score": 92.25444030761719 + }, + { + "params": { + "max_pickup_distance_km": 8.532598643804405, + "max_kitchen_distance_km": 2.6280764984826943, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8869941742261025, + "workload_penalty_weight": 56.52753449139206, + "distance_penalty_weight": 4.802785620267564, + "cluster_radius_km": 2.8517992927555738, + "search_time_limit_seconds": 15, + "road_factor": 1.4242780622502393 + }, + "score": 92.25444030761719 + }, + { + "params": { + "max_pickup_distance_km": 8.673634610211629, + "max_kitchen_distance_km": 2.8412478114367823, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.889386447087841, + "workload_penalty_weight": 53.3795093968611, + "distance_penalty_weight": 4.621048761108392, + "cluster_radius_km": 2.77752450644401, + "search_time_limit_seconds": 15, + "road_factor": 1.4126712411250215 + }, + "score": 92.25444030761719 + }, + { + "params": { + "max_pickup_distance_km": 8.430990051063922, + "max_kitchen_distance_km": 2.9355029612495747, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8898317648909523, + "workload_penalty_weight": 54.5117727580679, + "distance_penalty_weight": 4.667163256985533, + "cluster_radius_km": 2.4951293970125565, + "search_time_limit_seconds": 15, + "road_factor": 1.4187885549435315 + }, + "score": 92.25444030761719 + }, + { + "params": { + "max_pickup_distance_km": 8.695868295786404, + "max_kitchen_distance_km": 2.736527002166546, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8869639543238491, + "workload_penalty_weight": 54.467432219870865, + "distance_penalty_weight": 4.652311237990631, + "cluster_radius_km": 2.5861719561037835, + "search_time_limit_seconds": 15, + "road_factor": 1.4175015822588442 + }, + "score": 92.25444030761719 + }, + { + "params": { + "max_pickup_distance_km": 8.665798467617625, + "max_kitchen_distance_km": 2.824631639618233, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8882049414309126, + "workload_penalty_weight": 56.35229400942434, + "distance_penalty_weight": 4.667281906791758, + "cluster_radius_km": 2.3924771955092528, + "search_time_limit_seconds": 15, + "road_factor": 1.4284644715328136 + }, + "score": 92.25444030761719 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260408_054840.json b/ml_data/reports/tuning_20260408_054840.json new file mode 100644 index 0000000..d034edd --- /dev/null +++ b/ml_data/reports/tuning_20260408_054840.json @@ -0,0 +1,203 @@ +{ + "timestamp": "2026-04-08T05:48:40.849512", + "training_rows": 130, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.6574, + "mae": 6.701, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-6.7 pts (R2=0.66, trust=good)" + }, + "baseline_stats": { + "avg_quality": 73.37, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 130 + }, + "feature_importance": { + "rolling_avg_quality_5": 33.09, + "quality_delta_10": 23.84, + "num_orders": 16.42, + "hour": 11.65, + "num_riders": 5.34, + "day_of_week": 4.32, + "max_pickup_distance_km": 1.58, + "workload_balance_threshold": 1.17, + "max_kitchen_distance_km": 1.0, + "ideal_load": 0.8, + "distance_penalty_weight": 0.33, + "max_orders_per_rider": 0.26, + "search_time_limit_seconds": 0.09, + "workload_penalty_weight": 0.06, + "is_peak": 0.04, + "cluster_radius_km": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260408_060150.json b/ml_data/reports/tuning_20260408_060150.json new file mode 100644 index 0000000..cb2b9d1 --- /dev/null +++ b/ml_data/reports/tuning_20260408_060150.json @@ -0,0 +1,203 @@ +{ + "timestamp": "2026-04-08T06:01:50.655317", + "training_rows": 135, + "n_trials": 150, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.6748, + "mae": 6.88, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-6.9 pts (R2=0.67, trust=good)" + }, + "baseline_stats": { + "avg_quality": 73.75, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 135 + }, + "feature_importance": { + "rolling_avg_quality_5": 33.49, + "quality_delta_10": 22.54, + "num_orders": 16.72, + "hour": 10.72, + "num_riders": 6.87, + "day_of_week": 3.69, + "max_pickup_distance_km": 2.66, + "max_kitchen_distance_km": 1.07, + "workload_balance_threshold": 0.55, + "ideal_load": 0.4, + "distance_penalty_weight": 0.4, + "max_orders_per_rider": 0.29, + "workload_penalty_weight": 0.23, + "road_factor": 0.17, + "cluster_radius_km": 0.15, + "is_peak": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260408_061410.json b/ml_data/reports/tuning_20260408_061410.json new file mode 100644 index 0000000..f56af7f --- /dev/null +++ b/ml_data/reports/tuning_20260408_061410.json @@ -0,0 +1,203 @@ +{ + "timestamp": "2026-04-08T06:14:10.256562", + "training_rows": 140, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.6832, + "mae": 6.562, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-6.6 pts (R2=0.68, trust=good)" + }, + "baseline_stats": { + "avg_quality": 74.26, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 140 + }, + "feature_importance": { + "rolling_avg_quality_5": 32.77, + "quality_delta_10": 23.82, + "num_orders": 16.26, + "hour": 11.68, + "num_riders": 5.17, + "day_of_week": 4.37, + "max_pickup_distance_km": 1.56, + "workload_balance_threshold": 1.29, + "max_kitchen_distance_km": 1.24, + "ideal_load": 0.82, + "max_orders_per_rider": 0.47, + "distance_penalty_weight": 0.34, + "search_time_limit_seconds": 0.1, + "workload_penalty_weight": 0.07, + "is_peak": 0.03, + "cluster_radius_km": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260408_080516.json b/ml_data/reports/tuning_20260408_080516.json new file mode 100644 index 0000000..4857258 --- /dev/null +++ b/ml_data/reports/tuning_20260408_080516.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-08T08:05:16.291778", + "training_rows": 144, + "n_trials": 150, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.8091, + "mae": 5.063, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-5.1 pts (R2=0.81, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 74.63, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 144 + }, + "feature_importance": { + "rolling_avg_quality_5": 32.54, + "quality_delta_10": 23.81, + "num_orders": 16.06, + "hour": 11.64, + "num_riders": 5.03, + "day_of_week": 4.54, + "max_pickup_distance_km": 1.55, + "max_kitchen_distance_km": 1.55, + "workload_balance_threshold": 1.34, + "ideal_load": 0.81, + "max_orders_per_rider": 0.61, + "distance_penalty_weight": 0.34, + "search_time_limit_seconds": 0.09, + "workload_penalty_weight": 0.07, + "is_peak": 0.03, + "cluster_radius_km": 0.01, + "road_factor": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260408_120544.json b/ml_data/reports/tuning_20260408_120544.json new file mode 100644 index 0000000..7b62bb7 --- /dev/null +++ b/ml_data/reports/tuning_20260408_120544.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-08T12:05:44.523551", + "training_rows": 152, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.6953, + "mae": 5.522, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-5.5 pts (R2=0.70, trust=good)" + }, + "baseline_stats": { + "avg_quality": 75.03, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 152 + }, + "feature_importance": { + "rolling_avg_quality_5": 32.41, + "quality_delta_10": 23.58, + "num_orders": 15.76, + "hour": 12.0, + "num_riders": 4.87, + "day_of_week": 4.56, + "max_kitchen_distance_km": 1.83, + "max_pickup_distance_km": 1.6, + "workload_balance_threshold": 1.36, + "ideal_load": 0.8, + "max_orders_per_rider": 0.68, + "distance_penalty_weight": 0.33, + "search_time_limit_seconds": 0.09, + "is_peak": 0.07, + "workload_penalty_weight": 0.07, + "cluster_radius_km": 0.01, + "road_factor": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260408_122052.json b/ml_data/reports/tuning_20260408_122052.json new file mode 100644 index 0000000..202e337 --- /dev/null +++ b/ml_data/reports/tuning_20260408_122052.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-08T12:20:52.868913", + "training_rows": 162, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7575, + "mae": 5.373, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-5.4 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 75.6, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 162 + }, + "feature_importance": { + "rolling_avg_quality_5": 32.38, + "quality_delta_10": 23.56, + "num_orders": 15.58, + "hour": 12.2, + "num_riders": 4.68, + "day_of_week": 4.52, + "max_kitchen_distance_km": 2.03, + "max_pickup_distance_km": 1.62, + "workload_balance_threshold": 1.35, + "ideal_load": 0.78, + "max_orders_per_rider": 0.71, + "distance_penalty_weight": 0.32, + "is_peak": 0.11, + "search_time_limit_seconds": 0.08, + "workload_penalty_weight": 0.07, + "cluster_radius_km": 0.01, + "road_factor": 0.0 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260408_122141.json b/ml_data/reports/tuning_20260408_122141.json new file mode 100644 index 0000000..bf93885 --- /dev/null +++ b/ml_data/reports/tuning_20260408_122141.json @@ -0,0 +1,203 @@ +{ + "timestamp": "2026-04-08T12:21:41.970035", + "training_rows": 163, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.731, + "mae": 5.408, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-5.4 pts (R2=0.73, trust=good)" + }, + "baseline_stats": { + "avg_quality": 75.62, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 163 + }, + "feature_importance": { + "rolling_avg_quality_5": 32.82, + "quality_delta_10": 23.04, + "num_orders": 16.45, + "hour": 11.2, + "num_riders": 6.22, + "day_of_week": 4.0, + "max_pickup_distance_km": 2.56, + "max_kitchen_distance_km": 1.18, + "workload_balance_threshold": 0.67, + "ideal_load": 0.43, + "max_orders_per_rider": 0.42, + "distance_penalty_weight": 0.37, + "workload_penalty_weight": 0.19, + "cluster_radius_km": 0.18, + "road_factor": 0.18, + "is_peak": 0.08 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260408_132513.json b/ml_data/reports/tuning_20260408_132513.json new file mode 100644 index 0000000..1e958cf --- /dev/null +++ b/ml_data/reports/tuning_20260408_132513.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-08T13:25:13.311096", + "training_rows": 163, + "n_trials": 150, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.731, + "mae": 5.408, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-5.4 pts (R2=0.73, trust=good)" + }, + "baseline_stats": { + "avg_quality": 75.62, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 163 + }, + "feature_importance": { + "rolling_avg_quality_5": 32.56, + "quality_delta_10": 23.42, + "num_orders": 15.56, + "hour": 12.21, + "num_riders": 4.5, + "day_of_week": 4.48, + "max_kitchen_distance_km": 2.14, + "max_pickup_distance_km": 1.65, + "workload_balance_threshold": 1.33, + "max_orders_per_rider": 0.78, + "ideal_load": 0.75, + "distance_penalty_weight": 0.31, + "is_peak": 0.15, + "search_time_limit_seconds": 0.08, + "workload_penalty_weight": 0.07, + "cluster_radius_km": 0.01, + "road_factor": 0.0 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260409_015639.json b/ml_data/reports/tuning_20260409_015639.json new file mode 100644 index 0000000..dbbc303 --- /dev/null +++ b/ml_data/reports/tuning_20260409_015639.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-09T01:56:39.596409", + "training_rows": 173, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7102, + "mae": 5.393, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-5.4 pts (R2=0.71, trust=good)" + }, + "baseline_stats": { + "avg_quality": 75.95, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 173 + }, + "feature_importance": { + "rolling_avg_quality_5": 32.28, + "quality_delta_10": 23.34, + "num_orders": 15.52, + "hour": 12.41, + "day_of_week": 4.64, + "num_riders": 4.46, + "max_kitchen_distance_km": 2.19, + "max_pickup_distance_km": 1.63, + "workload_balance_threshold": 1.33, + "max_orders_per_rider": 0.81, + "ideal_load": 0.74, + "distance_penalty_weight": 0.3, + "is_peak": 0.19, + "search_time_limit_seconds": 0.08, + "workload_penalty_weight": 0.06, + "cluster_radius_km": 0.01, + "road_factor": 0.0 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260409_054959.json b/ml_data/reports/tuning_20260409_054959.json new file mode 100644 index 0000000..067a745 --- /dev/null +++ b/ml_data/reports/tuning_20260409_054959.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-09T05:49:59.012537", + "training_rows": 183, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7171, + "mae": 5.359, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-5.4 pts (R2=0.72, trust=good)" + }, + "baseline_stats": { + "avg_quality": 76.21, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 183 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.93, + "quality_delta_10": 23.31, + "num_orders": 15.45, + "hour": 12.61, + "day_of_week": 4.83, + "num_riders": 4.47, + "max_kitchen_distance_km": 2.25, + "max_pickup_distance_km": 1.58, + "workload_balance_threshold": 1.31, + "max_orders_per_rider": 0.84, + "ideal_load": 0.73, + "distance_penalty_weight": 0.3, + "is_peak": 0.24, + "search_time_limit_seconds": 0.08, + "workload_penalty_weight": 0.06, + "cluster_radius_km": 0.01, + "road_factor": 0.0 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260409_061037.json b/ml_data/reports/tuning_20260409_061037.json new file mode 100644 index 0000000..38c843f --- /dev/null +++ b/ml_data/reports/tuning_20260409_061037.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-09T06:10:37.922473", + "training_rows": 193, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.6191, + "mae": 5.769, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-5.8 pts (R2=0.62, trust=good)" + }, + "baseline_stats": { + "avg_quality": 76.21, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 193 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.82, + "quality_delta_10": 23.25, + "num_orders": 15.33, + "hour": 12.81, + "day_of_week": 5.08, + "num_riders": 4.36, + "max_kitchen_distance_km": 2.28, + "max_pickup_distance_km": 1.53, + "workload_balance_threshold": 1.3, + "max_orders_per_rider": 0.83, + "ideal_load": 0.7, + "distance_penalty_weight": 0.29, + "is_peak": 0.26, + "search_time_limit_seconds": 0.08, + "workload_penalty_weight": 0.06, + "cluster_radius_km": 0.02, + "road_factor": 0.0 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260409_114639.json b/ml_data/reports/tuning_20260409_114639.json new file mode 100644 index 0000000..a0a30ac --- /dev/null +++ b/ml_data/reports/tuning_20260409_114639.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-09T11:46:39.113092", + "training_rows": 204, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7589, + "mae": 5.129, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-5.1 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 76.45, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 204 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.67, + "quality_delta_10": 23.28, + "num_orders": 15.27, + "hour": 12.94, + "day_of_week": 5.31, + "num_riders": 4.21, + "max_kitchen_distance_km": 2.32, + "max_pickup_distance_km": 1.51, + "workload_balance_threshold": 1.26, + "max_orders_per_rider": 0.82, + "ideal_load": 0.67, + "distance_penalty_weight": 0.29, + "is_peak": 0.28, + "search_time_limit_seconds": 0.07, + "workload_penalty_weight": 0.06, + "cluster_radius_km": 0.02, + "road_factor": 0.0 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260410_014905.json b/ml_data/reports/tuning_20260410_014905.json new file mode 100644 index 0000000..f935476 --- /dev/null +++ b/ml_data/reports/tuning_20260410_014905.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-10T01:49:05.855440", + "training_rows": 218, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7494, + "mae": 4.873, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-4.9 pts (R2=0.75, trust=good)" + }, + "baseline_stats": { + "avg_quality": 76.82, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 218 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.54, + "quality_delta_10": 23.22, + "num_orders": 15.09, + "hour": 13.12, + "day_of_week": 5.59, + "num_riders": 4.17, + "max_kitchen_distance_km": 2.34, + "max_pickup_distance_km": 1.51, + "workload_balance_threshold": 1.23, + "max_orders_per_rider": 0.83, + "ideal_load": 0.65, + "is_peak": 0.28, + "distance_penalty_weight": 0.28, + "search_time_limit_seconds": 0.07, + "workload_penalty_weight": 0.06, + "cluster_radius_km": 0.02, + "road_factor": 0.0 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260410_055729.json b/ml_data/reports/tuning_20260410_055729.json new file mode 100644 index 0000000..4b64163 --- /dev/null +++ b/ml_data/reports/tuning_20260410_055729.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-10T05:57:29.803436", + "training_rows": 229, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7527, + "mae": 5.039, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-5.0 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 77.03, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 229 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.49, + "quality_delta_10": 23.24, + "num_orders": 14.9, + "hour": 13.17, + "day_of_week": 5.9, + "num_riders": 4.14, + "max_kitchen_distance_km": 2.33, + "max_pickup_distance_km": 1.5, + "workload_balance_threshold": 1.2, + "max_orders_per_rider": 0.8, + "ideal_load": 0.63, + "is_peak": 0.27, + "distance_penalty_weight": 0.27, + "search_time_limit_seconds": 0.07, + "workload_penalty_weight": 0.06, + "cluster_radius_km": 0.02, + "road_factor": 0.0 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260410_061442.json b/ml_data/reports/tuning_20260410_061442.json new file mode 100644 index 0000000..1afb1a1 --- /dev/null +++ b/ml_data/reports/tuning_20260410_061442.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-10T06:14:42.873102", + "training_rows": 239, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7729, + "mae": 4.771, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-4.8 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 77.02, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 239 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.48, + "quality_delta_10": 23.26, + "num_orders": 14.8, + "hour": 13.2, + "day_of_week": 6.2, + "num_riders": 4.07, + "max_kitchen_distance_km": 2.3, + "max_pickup_distance_km": 1.47, + "workload_balance_threshold": 1.17, + "max_orders_per_rider": 0.77, + "ideal_load": 0.61, + "is_peak": 0.27, + "distance_penalty_weight": 0.26, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "cluster_radius_km": 0.02, + "road_factor": 0.0 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260410_122110.json b/ml_data/reports/tuning_20260410_122110.json new file mode 100644 index 0000000..d2a0e21 --- /dev/null +++ b/ml_data/reports/tuning_20260410_122110.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-10T12:21:10.509651", + "training_rows": 250, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7474, + "mae": 4.817, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-4.8 pts (R2=0.75, trust=good)" + }, + "baseline_stats": { + "avg_quality": 77.21, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 250 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.46, + "quality_delta_10": 23.35, + "num_orders": 14.72, + "hour": 13.21, + "day_of_week": 6.42, + "num_riders": 3.96, + "max_kitchen_distance_km": 2.28, + "max_pickup_distance_km": 1.43, + "workload_balance_threshold": 1.13, + "max_orders_per_rider": 0.76, + "ideal_load": 0.58, + "is_peak": 0.31, + "distance_penalty_weight": 0.26, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "cluster_radius_km": 0.02, + "road_factor": 0.0 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260411_015238.json b/ml_data/reports/tuning_20260411_015238.json new file mode 100644 index 0000000..360d8fc --- /dev/null +++ b/ml_data/reports/tuning_20260411_015238.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-11T01:52:38.015808", + "training_rows": 260, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7424, + "mae": 4.785, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-4.8 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 77.43, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 260 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.37, + "quality_delta_10": 23.4, + "num_orders": 14.66, + "hour": 13.13, + "day_of_week": 6.74, + "num_riders": 3.88, + "max_kitchen_distance_km": 2.28, + "max_pickup_distance_km": 1.4, + "workload_balance_threshold": 1.11, + "max_orders_per_rider": 0.74, + "ideal_load": 0.57, + "is_peak": 0.34, + "distance_penalty_weight": 0.25, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "cluster_radius_km": 0.02, + "road_factor": 0.0 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260411_015600.json b/ml_data/reports/tuning_20260411_015600.json new file mode 100644 index 0000000..9f47a9a --- /dev/null +++ b/ml_data/reports/tuning_20260411_015600.json @@ -0,0 +1,203 @@ +{ + "timestamp": "2026-04-11T01:56:00.191128", + "training_rows": 264, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7586, + "mae": 4.561, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-4.6 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 77.4, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 264 + }, + "feature_importance": { + "rolling_avg_quality_5": 32.28, + "quality_delta_10": 23.47, + "num_orders": 15.89, + "hour": 11.23, + "num_riders": 5.93, + "day_of_week": 5.24, + "max_pickup_distance_km": 2.28, + "max_kitchen_distance_km": 1.23, + "workload_balance_threshold": 0.69, + "max_orders_per_rider": 0.41, + "ideal_load": 0.38, + "distance_penalty_weight": 0.36, + "cluster_radius_km": 0.19, + "road_factor": 0.17, + "workload_penalty_weight": 0.16, + "is_peak": 0.08 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260411_054545.json b/ml_data/reports/tuning_20260411_054545.json new file mode 100644 index 0000000..22be51f --- /dev/null +++ b/ml_data/reports/tuning_20260411_054545.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-11T05:45:45.885609", + "training_rows": 274, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7997, + "mae": 4.408, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-4.4 pts (R2=0.80, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 77.64, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 274 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.41, + "quality_delta_10": 23.44, + "num_orders": 14.58, + "hour": 13.07, + "day_of_week": 6.91, + "num_riders": 3.85, + "max_kitchen_distance_km": 2.27, + "max_pickup_distance_km": 1.37, + "workload_balance_threshold": 1.09, + "max_orders_per_rider": 0.73, + "ideal_load": 0.55, + "is_peak": 0.35, + "distance_penalty_weight": 0.24, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "cluster_radius_km": 0.02, + "road_factor": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260411_055753.json b/ml_data/reports/tuning_20260411_055753.json new file mode 100644 index 0000000..c121e5a --- /dev/null +++ b/ml_data/reports/tuning_20260411_055753.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-11T05:57:53.656907", + "training_rows": 284, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7304, + "mae": 4.834, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-4.8 pts (R2=0.73, trust=good)" + }, + "baseline_stats": { + "avg_quality": 77.58, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 284 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.55, + "quality_delta_10": 23.61, + "num_orders": 14.52, + "hour": 13.04, + "day_of_week": 6.92, + "num_riders": 3.76, + "max_kitchen_distance_km": 2.23, + "max_pickup_distance_km": 1.38, + "workload_balance_threshold": 1.06, + "max_orders_per_rider": 0.71, + "ideal_load": 0.53, + "is_peak": 0.34, + "distance_penalty_weight": 0.23, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "cluster_radius_km": 0.02, + "road_factor": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260411_061149.json b/ml_data/reports/tuning_20260411_061149.json new file mode 100644 index 0000000..a32150e --- /dev/null +++ b/ml_data/reports/tuning_20260411_061149.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-11T06:11:49.929066", + "training_rows": 294, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7362, + "mae": 4.597, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-4.6 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 77.82, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 294 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.58, + "quality_delta_10": 23.69, + "num_orders": 14.48, + "hour": 13.03, + "day_of_week": 7.0, + "num_riders": 3.7, + "max_kitchen_distance_km": 2.2, + "max_pickup_distance_km": 1.38, + "workload_balance_threshold": 1.02, + "max_orders_per_rider": 0.69, + "ideal_load": 0.51, + "is_peak": 0.34, + "distance_penalty_weight": 0.23, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "cluster_radius_km": 0.02, + "road_factor": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260411_112244.json b/ml_data/reports/tuning_20260411_112244.json new file mode 100644 index 0000000..2ceb658 --- /dev/null +++ b/ml_data/reports/tuning_20260411_112244.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-11T11:22:44.585485", + "training_rows": 304, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7524, + "mae": 4.427, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-4.4 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 77.93, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 304 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.49, + "quality_delta_10": 23.78, + "num_orders": 14.43, + "hour": 13.03, + "day_of_week": 7.11, + "num_riders": 3.75, + "max_kitchen_distance_km": 2.15, + "max_pickup_distance_km": 1.39, + "workload_balance_threshold": 0.99, + "max_orders_per_rider": 0.68, + "ideal_load": 0.5, + "is_peak": 0.33, + "distance_penalty_weight": 0.22, + "workload_penalty_weight": 0.06, + "search_time_limit_seconds": 0.06, + "cluster_radius_km": 0.01, + "road_factor": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260413_015615.json b/ml_data/reports/tuning_20260413_015615.json new file mode 100644 index 0000000..c88709f --- /dev/null +++ b/ml_data/reports/tuning_20260413_015615.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-13T01:56:15.959725", + "training_rows": 314, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7324, + "mae": 4.64, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-4.6 pts (R2=0.73, trust=good)" + }, + "baseline_stats": { + "avg_quality": 78.03, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 314 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.46, + "quality_delta_10": 23.79, + "num_orders": 14.36, + "hour": 12.93, + "day_of_week": 7.26, + "num_riders": 3.78, + "max_kitchen_distance_km": 2.19, + "max_pickup_distance_km": 1.39, + "workload_balance_threshold": 0.97, + "max_orders_per_rider": 0.68, + "ideal_load": 0.49, + "is_peak": 0.33, + "distance_penalty_weight": 0.21, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "cluster_radius_km": 0.01, + "road_factor": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260413_055256.json b/ml_data/reports/tuning_20260413_055256.json new file mode 100644 index 0000000..7fee9dd --- /dev/null +++ b/ml_data/reports/tuning_20260413_055256.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-13T05:52:56.488145", + "training_rows": 324, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7582, + "mae": 4.342, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-4.3 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 78.1, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 324 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.28, + "quality_delta_10": 23.92, + "num_orders": 14.27, + "hour": 12.89, + "day_of_week": 7.49, + "num_riders": 3.76, + "max_kitchen_distance_km": 2.2, + "max_pickup_distance_km": 1.37, + "workload_balance_threshold": 0.95, + "max_orders_per_rider": 0.69, + "ideal_load": 0.48, + "is_peak": 0.33, + "distance_penalty_weight": 0.21, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "road_factor": 0.02, + "cluster_radius_km": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260413_061522.json b/ml_data/reports/tuning_20260413_061522.json new file mode 100644 index 0000000..16b3ddb --- /dev/null +++ b/ml_data/reports/tuning_20260413_061522.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-13T06:15:22.408131", + "training_rows": 336, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7603, + "mae": 4.362, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-4.4 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 78.12, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 336 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.33, + "quality_delta_10": 23.95, + "num_orders": 14.19, + "hour": 12.83, + "day_of_week": 7.56, + "num_riders": 3.79, + "max_kitchen_distance_km": 2.21, + "max_pickup_distance_km": 1.37, + "workload_balance_threshold": 0.94, + "max_orders_per_rider": 0.69, + "ideal_load": 0.47, + "is_peak": 0.32, + "distance_penalty_weight": 0.2, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "road_factor": 0.02, + "cluster_radius_km": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260413_112726.json b/ml_data/reports/tuning_20260413_112726.json new file mode 100644 index 0000000..4585967 --- /dev/null +++ b/ml_data/reports/tuning_20260413_112726.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-13T11:27:26.980742", + "training_rows": 347, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7503, + "mae": 4.327, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-4.3 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 78.33, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 347 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.22, + "quality_delta_10": 24.08, + "num_orders": 14.08, + "hour": 12.87, + "day_of_week": 7.62, + "num_riders": 3.81, + "max_kitchen_distance_km": 2.21, + "max_pickup_distance_km": 1.38, + "workload_balance_threshold": 0.92, + "max_orders_per_rider": 0.67, + "ideal_load": 0.46, + "is_peak": 0.32, + "distance_penalty_weight": 0.2, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "road_factor": 0.02, + "cluster_radius_km": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260413_114616.json b/ml_data/reports/tuning_20260413_114616.json new file mode 100644 index 0000000..c4c030f --- /dev/null +++ b/ml_data/reports/tuning_20260413_114616.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-13T11:46:16.734739", + "training_rows": 359, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7742, + "mae": 4.15, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-4.1 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 78.44, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 359 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.07, + "quality_delta_10": 24.23, + "num_orders": 14.08, + "hour": 12.77, + "day_of_week": 7.74, + "num_riders": 3.8, + "max_kitchen_distance_km": 2.2, + "max_pickup_distance_km": 1.43, + "workload_balance_threshold": 0.89, + "max_orders_per_rider": 0.67, + "ideal_load": 0.45, + "is_peak": 0.32, + "distance_penalty_weight": 0.21, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "road_factor": 0.02, + "cluster_radius_km": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260413_120123.json b/ml_data/reports/tuning_20260413_120123.json new file mode 100644 index 0000000..cc8eb88 --- /dev/null +++ b/ml_data/reports/tuning_20260413_120123.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-13T12:01:23.368680", + "training_rows": 370, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7562, + "mae": 4.254, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-4.3 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 78.6, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 370 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.07, + "quality_delta_10": 24.32, + "num_orders": 13.99, + "hour": 12.81, + "day_of_week": 7.82, + "num_riders": 3.75, + "max_kitchen_distance_km": 2.18, + "max_pickup_distance_km": 1.44, + "workload_balance_threshold": 0.88, + "max_orders_per_rider": 0.65, + "ideal_load": 0.44, + "is_peak": 0.31, + "distance_penalty_weight": 0.2, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "cluster_radius_km": 0.02, + "road_factor": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260414_015956.json b/ml_data/reports/tuning_20260414_015956.json new file mode 100644 index 0000000..dfd0ce2 --- /dev/null +++ b/ml_data/reports/tuning_20260414_015956.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-14T01:59:56.908270", + "training_rows": 381, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7696, + "mae": 4.087, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-4.1 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 78.72, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 381 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.99, + "quality_delta_10": 24.28, + "num_orders": 13.95, + "hour": 12.73, + "day_of_week": 7.91, + "num_riders": 3.85, + "max_kitchen_distance_km": 2.16, + "max_pickup_distance_km": 1.51, + "workload_balance_threshold": 0.86, + "max_orders_per_rider": 0.64, + "ideal_load": 0.46, + "is_peak": 0.31, + "distance_penalty_weight": 0.2, + "search_time_limit_seconds": 0.07, + "workload_penalty_weight": 0.05, + "cluster_radius_km": 0.02, + "road_factor": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260414_060856.json b/ml_data/reports/tuning_20260414_060856.json new file mode 100644 index 0000000..3c758c4 --- /dev/null +++ b/ml_data/reports/tuning_20260414_060856.json @@ -0,0 +1,203 @@ +{ + "timestamp": "2026-04-14T06:08:56.503649", + "training_rows": 392, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.768, + "mae": 4.008, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-4.0 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 78.75, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 392 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.62, + "quality_delta_10": 24.14, + "num_orders": 15.25, + "hour": 11.38, + "day_of_week": 5.81, + "num_riders": 5.44, + "max_pickup_distance_km": 2.29, + "max_kitchen_distance_km": 1.64, + "workload_balance_threshold": 0.65, + "max_orders_per_rider": 0.55, + "ideal_load": 0.35, + "distance_penalty_weight": 0.33, + "cluster_radius_km": 0.16, + "road_factor": 0.16, + "workload_penalty_weight": 0.15, + "is_peak": 0.09 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260414_061618.json b/ml_data/reports/tuning_20260414_061618.json new file mode 100644 index 0000000..7a51efc --- /dev/null +++ b/ml_data/reports/tuning_20260414_061618.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-14T06:16:18.909310", + "training_rows": 394, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7665, + "mae": 4.043, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-4.0 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 78.81, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 394 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.89, + "quality_delta_10": 24.27, + "num_orders": 13.87, + "hour": 12.68, + "day_of_week": 8.12, + "num_riders": 3.87, + "max_kitchen_distance_km": 2.16, + "max_pickup_distance_km": 1.57, + "workload_balance_threshold": 0.84, + "max_orders_per_rider": 0.64, + "ideal_load": 0.45, + "is_peak": 0.3, + "distance_penalty_weight": 0.19, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "cluster_radius_km": 0.02, + "road_factor": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260414_111856.json b/ml_data/reports/tuning_20260414_111856.json new file mode 100644 index 0000000..3d318dc --- /dev/null +++ b/ml_data/reports/tuning_20260414_111856.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-14T11:18:56.315775", + "training_rows": 404, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7736, + "mae": 4.038, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-4.0 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 78.94, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 404 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.85, + "quality_delta_10": 24.17, + "num_orders": 13.92, + "hour": 12.64, + "day_of_week": 8.2, + "num_riders": 3.9, + "max_kitchen_distance_km": 2.15, + "max_pickup_distance_km": 1.63, + "workload_balance_threshold": 0.82, + "max_orders_per_rider": 0.64, + "ideal_load": 0.44, + "is_peak": 0.29, + "distance_penalty_weight": 0.19, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "cluster_radius_km": 0.02, + "road_factor": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260414_112815.json b/ml_data/reports/tuning_20260414_112815.json new file mode 100644 index 0000000..9aa1c4c --- /dev/null +++ b/ml_data/reports/tuning_20260414_112815.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-14T11:28:15.974848", + "training_rows": 414, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7691, + "mae": 4.028, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-4.0 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 78.94, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 414 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.8, + "quality_delta_10": 24.23, + "num_orders": 13.9, + "hour": 12.6, + "day_of_week": 8.3, + "num_riders": 3.86, + "max_kitchen_distance_km": 2.14, + "max_pickup_distance_km": 1.68, + "workload_balance_threshold": 0.81, + "max_orders_per_rider": 0.63, + "ideal_load": 0.43, + "is_peak": 0.29, + "distance_penalty_weight": 0.19, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "cluster_radius_km": 0.02, + "road_factor": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260415_020035.json b/ml_data/reports/tuning_20260415_020035.json new file mode 100644 index 0000000..5075725 --- /dev/null +++ b/ml_data/reports/tuning_20260415_020035.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-15T02:00:35.622619", + "training_rows": 425, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7298, + "mae": 4.069, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-4.1 pts (R2=0.73, trust=good)" + }, + "baseline_stats": { + "avg_quality": 79.02, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 425 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.7, + "quality_delta_10": 24.21, + "num_orders": 13.83, + "hour": 12.64, + "day_of_week": 8.37, + "num_riders": 3.92, + "max_kitchen_distance_km": 2.11, + "max_pickup_distance_km": 1.76, + "workload_balance_threshold": 0.79, + "max_orders_per_rider": 0.63, + "ideal_load": 0.42, + "is_peak": 0.28, + "distance_penalty_weight": 0.18, + "search_time_limit_seconds": 0.07, + "workload_penalty_weight": 0.05, + "cluster_radius_km": 0.02, + "road_factor": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260415_060639.json b/ml_data/reports/tuning_20260415_060639.json new file mode 100644 index 0000000..dbf7b2f --- /dev/null +++ b/ml_data/reports/tuning_20260415_060639.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-15T06:06:39.423177", + "training_rows": 438, + "n_trials": 100, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.7019, + "mae": 4.228, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-4.2 pts (R2=0.70, trust=good)" + }, + "baseline_stats": { + "avg_quality": 79.08, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 438 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.61, + "quality_delta_10": 24.24, + "num_orders": 13.75, + "hour": 12.61, + "day_of_week": 8.44, + "num_riders": 4.0, + "max_kitchen_distance_km": 2.07, + "max_pickup_distance_km": 1.83, + "workload_balance_threshold": 0.78, + "max_orders_per_rider": 0.63, + "ideal_load": 0.41, + "is_peak": 0.28, + "distance_penalty_weight": 0.18, + "search_time_limit_seconds": 0.07, + "workload_penalty_weight": 0.05, + "cluster_radius_km": 0.02, + "road_factor": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260415_093147.json b/ml_data/reports/tuning_20260415_093147.json new file mode 100644 index 0000000..1e381e8 --- /dev/null +++ b/ml_data/reports/tuning_20260415_093147.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-15T09:31:47.472849", + "training_rows": 443, + "n_trials": 150, + "best_predicted_quality": 92.49, + "best_params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "validation": { + "r2_score": 0.6997, + "mae": 4.334, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-4.3 pts (R2=0.70, trust=good)" + }, + "baseline_stats": { + "avg_quality": 79.03, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 443 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.59, + "quality_delta_10": 24.23, + "num_orders": 13.75, + "hour": 12.6, + "day_of_week": 8.48, + "num_riders": 4.04, + "max_kitchen_distance_km": 2.06, + "max_pickup_distance_km": 1.84, + "workload_balance_threshold": 0.76, + "max_orders_per_rider": 0.64, + "ideal_load": 0.4, + "is_peak": 0.27, + "distance_penalty_weight": 0.18, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "road_factor": 0.03, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.97552336109477, + "max_kitchen_distance_km": 2.7877044648340705, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8903020193864128, + "workload_penalty_weight": 53.40488265276959, + "distance_penalty_weight": 4.354470281012198, + "cluster_radius_km": 2.2678837392223077, + "search_time_limit_seconds": 15, + "road_factor": 1.4157581126349794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.210519212090116, + "max_kitchen_distance_km": 2.795071874344803, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.890954590372547, + "workload_penalty_weight": 57.30546495575571, + "distance_penalty_weight": 4.2825502929828625, + "cluster_radius_km": 2.2309970986531154, + "search_time_limit_seconds": 15, + "road_factor": 1.407023035324782 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.223563826442748, + "max_kitchen_distance_km": 2.808717963029326, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.892196769560021, + "workload_penalty_weight": 57.15330538045706, + "distance_penalty_weight": 4.282867731690668, + "cluster_radius_km": 2.2270651869785745, + "search_time_limit_seconds": 15, + "road_factor": 1.403707328692158 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.157491797214524, + "max_kitchen_distance_km": 2.810126480283359, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8917683811761372, + "workload_penalty_weight": 57.74787593216373, + "distance_penalty_weight": 4.3249511318795255, + "cluster_radius_km": 2.1959915582659053, + "search_time_limit_seconds": 15, + "road_factor": 1.4003360081268916 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.16568429375528, + "max_kitchen_distance_km": 2.8090951982962844, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8909300879611156, + "workload_penalty_weight": 57.96924359592614, + "distance_penalty_weight": 4.356115233659841, + "cluster_radius_km": 2.1640543998081037, + "search_time_limit_seconds": 15, + "road_factor": 1.4050040294906794 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.259104291226768, + "max_kitchen_distance_km": 2.338588217223744, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8941495097259085, + "workload_penalty_weight": 58.30632718290698, + "distance_penalty_weight": 4.317355430608995, + "cluster_radius_km": 2.160490975141093, + "search_time_limit_seconds": 15, + "road_factor": 1.3994981879420294 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.318117638956453, + "max_kitchen_distance_km": 2.8273035648398968, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.88987932201009, + "workload_penalty_weight": 57.82043331508467, + "distance_penalty_weight": 4.317908076902964, + "cluster_radius_km": 2.165564764616809, + "search_time_limit_seconds": 15, + "road_factor": 1.398943484975189 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.30238269859597, + "max_kitchen_distance_km": 2.8712278434223046, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8892855074968387, + "workload_penalty_weight": 59.298723357157364, + "distance_penalty_weight": 4.253012634451528, + "cluster_radius_km": 1.962817701799511, + "search_time_limit_seconds": 15, + "road_factor": 1.3987881342234323 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.228587208865775, + "max_kitchen_distance_km": 2.7902336946097517, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8931229523479859, + "workload_penalty_weight": 58.672651882896744, + "distance_penalty_weight": 4.295307426122445, + "cluster_radius_km": 1.993660839663039, + "search_time_limit_seconds": 15, + "road_factor": 1.3993241972723316 + }, + "score": 92.48632049560547 + }, + { + "params": { + "max_pickup_distance_km": 9.199491733110056, + "max_kitchen_distance_km": 2.8798175414522116, + "max_orders_per_rider": 18, + "ideal_load": 2, + "workload_balance_threshold": 0.8907560961453739, + "workload_penalty_weight": 59.605005662034905, + "distance_penalty_weight": 4.267902417175325, + "cluster_radius_km": 2.0020539902282946, + "search_time_limit_seconds": 15, + "road_factor": 1.3959721302394685 + }, + "score": 92.48632049560547 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260415_110442.json b/ml_data/reports/tuning_20260415_110442.json new file mode 100644 index 0000000..5b4880f --- /dev/null +++ b/ml_data/reports/tuning_20260415_110442.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-15T11:04:42.732588", + "training_rows": 448, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.709, + "mae": 4.296, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-4.3 pts (R2=0.71, trust=good)" + }, + "baseline_stats": { + "avg_quality": 79.05, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 448 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.54, + "quality_delta_10": 24.27, + "num_orders": 13.71, + "hour": 12.64, + "day_of_week": 8.49, + "num_riders": 4.08, + "max_kitchen_distance_km": 2.04, + "max_pickup_distance_km": 1.86, + "workload_balance_threshold": 0.75, + "max_orders_per_rider": 0.63, + "ideal_load": 0.4, + "is_peak": 0.27, + "distance_penalty_weight": 0.17, + "search_time_limit_seconds": 0.06, + "workload_penalty_weight": 0.05, + "road_factor": 0.03, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260415_111415.json b/ml_data/reports/tuning_20260415_111415.json new file mode 100644 index 0000000..db7f4c3 --- /dev/null +++ b/ml_data/reports/tuning_20260415_111415.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-15T11:14:15.770990", + "training_rows": 458, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7164, + "mae": 4.179, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-4.2 pts (R2=0.72, trust=good)" + }, + "baseline_stats": { + "avg_quality": 79.2, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 458 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.52, + "quality_delta_10": 24.3, + "num_orders": 13.71, + "hour": 12.61, + "day_of_week": 8.44, + "num_riders": 4.08, + "max_kitchen_distance_km": 2.02, + "max_pickup_distance_km": 1.86, + "workload_balance_threshold": 0.77, + "max_orders_per_rider": 0.71, + "ideal_load": 0.39, + "is_peak": 0.27, + "distance_penalty_weight": 0.17, + "search_time_limit_seconds": 0.07, + "workload_penalty_weight": 0.05, + "road_factor": 0.03, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260415_112338.json b/ml_data/reports/tuning_20260415_112338.json new file mode 100644 index 0000000..b052595 --- /dev/null +++ b/ml_data/reports/tuning_20260415_112338.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-15T11:23:38.601107", + "training_rows": 468, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7406, + "mae": 4.075, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-4.1 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 79.39, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 468 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.5, + "quality_delta_10": 24.29, + "num_orders": 13.74, + "hour": 12.54, + "day_of_week": 8.36, + "num_riders": 4.16, + "max_kitchen_distance_km": 1.99, + "max_pickup_distance_km": 1.89, + "workload_balance_threshold": 0.77, + "max_orders_per_rider": 0.75, + "ideal_load": 0.39, + "is_peak": 0.27, + "distance_penalty_weight": 0.17, + "search_time_limit_seconds": 0.07, + "workload_penalty_weight": 0.05, + "road_factor": 0.03, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260415_114305.json b/ml_data/reports/tuning_20260415_114305.json new file mode 100644 index 0000000..f03f0fe --- /dev/null +++ b/ml_data/reports/tuning_20260415_114305.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-15T11:43:05.910334", + "training_rows": 478, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7167, + "mae": 4.222, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-4.2 pts (R2=0.72, trust=good)" + }, + "baseline_stats": { + "avg_quality": 79.59, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 478 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.54, + "quality_delta_10": 24.33, + "num_orders": 13.75, + "hour": 12.44, + "day_of_week": 8.3, + "num_riders": 4.2, + "max_kitchen_distance_km": 1.96, + "max_pickup_distance_km": 1.92, + "max_orders_per_rider": 0.77, + "workload_balance_threshold": 0.76, + "ideal_load": 0.39, + "is_peak": 0.27, + "distance_penalty_weight": 0.17, + "search_time_limit_seconds": 0.07, + "road_factor": 0.06, + "workload_penalty_weight": 0.05, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260415_115219.json b/ml_data/reports/tuning_20260415_115219.json new file mode 100644 index 0000000..b84075a --- /dev/null +++ b/ml_data/reports/tuning_20260415_115219.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-15T11:52:19.594657", + "training_rows": 488, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7495, + "mae": 3.892, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.9 pts (R2=0.75, trust=good)" + }, + "baseline_stats": { + "avg_quality": 79.74, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 488 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.58, + "quality_delta_10": 24.34, + "num_orders": 13.73, + "hour": 12.41, + "day_of_week": 8.26, + "num_riders": 4.22, + "max_pickup_distance_km": 1.94, + "max_kitchen_distance_km": 1.94, + "max_orders_per_rider": 0.78, + "workload_balance_threshold": 0.75, + "ideal_load": 0.41, + "is_peak": 0.26, + "distance_penalty_weight": 0.17, + "search_time_limit_seconds": 0.07, + "workload_penalty_weight": 0.06, + "road_factor": 0.06, + "cluster_radius_km": 0.01 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260415_121849.json b/ml_data/reports/tuning_20260415_121849.json new file mode 100644 index 0000000..243dfc8 --- /dev/null +++ b/ml_data/reports/tuning_20260415_121849.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-15T12:18:49.269333", + "training_rows": 492, + "n_trials": 150, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7547, + "mae": 3.859, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.9 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 79.81, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 492 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.63, + "quality_delta_10": 24.33, + "num_orders": 13.72, + "hour": 12.37, + "day_of_week": 8.2, + "num_riders": 4.27, + "max_pickup_distance_km": 1.98, + "max_kitchen_distance_km": 1.92, + "max_orders_per_rider": 0.79, + "workload_balance_threshold": 0.74, + "ideal_load": 0.41, + "is_peak": 0.26, + "distance_penalty_weight": 0.16, + "search_time_limit_seconds": 0.07, + "road_factor": 0.07, + "workload_penalty_weight": 0.05, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260416_020008.json b/ml_data/reports/tuning_20260416_020008.json new file mode 100644 index 0000000..56a4c1b --- /dev/null +++ b/ml_data/reports/tuning_20260416_020008.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-16T02:00:08.057763", + "training_rows": 499, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7471, + "mae": 3.851, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.9 pts (R2=0.75, trust=good)" + }, + "baseline_stats": { + "avg_quality": 79.94, + "best_quality": 95.0, + "worst_quality": 30.0, + "sample_size": 499 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.61, + "quality_delta_10": 24.32, + "num_orders": 13.71, + "hour": 12.28, + "day_of_week": 8.15, + "num_riders": 4.33, + "max_pickup_distance_km": 2.03, + "max_kitchen_distance_km": 1.89, + "max_orders_per_rider": 0.87, + "workload_balance_threshold": 0.75, + "ideal_load": 0.42, + "is_peak": 0.26, + "distance_penalty_weight": 0.16, + "search_time_limit_seconds": 0.08, + "road_factor": 0.07, + "workload_penalty_weight": 0.06, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260416_055639.json b/ml_data/reports/tuning_20260416_055639.json new file mode 100644 index 0000000..9c327b9 --- /dev/null +++ b/ml_data/reports/tuning_20260416_055639.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-16T05:56:39.237020", + "training_rows": 511, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7481, + "mae": 3.943, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.9 pts (R2=0.75, trust=good)" + }, + "baseline_stats": { + "avg_quality": 80.1, + "best_quality": 95.5, + "worst_quality": 30.0, + "sample_size": 511 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.66, + "quality_delta_10": 24.35, + "num_orders": 13.75, + "hour": 12.28, + "day_of_week": 8.03, + "num_riders": 4.3, + "max_pickup_distance_km": 2.03, + "max_kitchen_distance_km": 1.87, + "max_orders_per_rider": 0.93, + "workload_balance_threshold": 0.76, + "ideal_load": 0.42, + "is_peak": 0.25, + "distance_penalty_weight": 0.16, + "search_time_limit_seconds": 0.08, + "road_factor": 0.07, + "workload_penalty_weight": 0.06, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260416_060745.json b/ml_data/reports/tuning_20260416_060745.json new file mode 100644 index 0000000..43a1a3f --- /dev/null +++ b/ml_data/reports/tuning_20260416_060745.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-16T06:07:45.204689", + "training_rows": 521, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7583, + "mae": 3.815, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.8 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 80.16, + "best_quality": 95.5, + "worst_quality": 30.0, + "sample_size": 521 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.62, + "quality_delta_10": 24.4, + "num_orders": 13.78, + "hour": 12.34, + "day_of_week": 7.93, + "num_riders": 4.27, + "max_pickup_distance_km": 2.03, + "max_kitchen_distance_km": 1.84, + "max_orders_per_rider": 0.99, + "workload_balance_threshold": 0.77, + "ideal_load": 0.41, + "is_peak": 0.25, + "distance_penalty_weight": 0.16, + "search_time_limit_seconds": 0.08, + "workload_penalty_weight": 0.06, + "road_factor": 0.06, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260416_062540.json b/ml_data/reports/tuning_20260416_062540.json new file mode 100644 index 0000000..c2ede26 --- /dev/null +++ b/ml_data/reports/tuning_20260416_062540.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-16T06:25:40.660111", + "training_rows": 531, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7668, + "mae": 3.771, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.8 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 80.33, + "best_quality": 95.5, + "worst_quality": 30.0, + "sample_size": 531 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.62, + "quality_delta_10": 24.38, + "num_orders": 13.85, + "hour": 12.33, + "day_of_week": 7.84, + "num_riders": 4.27, + "max_pickup_distance_km": 2.05, + "max_kitchen_distance_km": 1.81, + "max_orders_per_rider": 1.05, + "workload_balance_threshold": 0.78, + "ideal_load": 0.4, + "is_peak": 0.24, + "distance_penalty_weight": 0.15, + "search_time_limit_seconds": 0.08, + "workload_penalty_weight": 0.06, + "road_factor": 0.06, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260416_100021.json b/ml_data/reports/tuning_20260416_100021.json new file mode 100644 index 0000000..370d369 --- /dev/null +++ b/ml_data/reports/tuning_20260416_100021.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-16T10:00:21.048875", + "training_rows": 541, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.775, + "mae": 3.654, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.7 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 80.44, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 541 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.57, + "quality_delta_10": 24.44, + "num_orders": 13.79, + "hour": 12.36, + "day_of_week": 7.77, + "num_riders": 4.27, + "max_pickup_distance_km": 2.05, + "max_kitchen_distance_km": 1.78, + "max_orders_per_rider": 1.08, + "workload_balance_threshold": 0.79, + "ideal_load": 0.42, + "is_peak": 0.3, + "distance_penalty_weight": 0.15, + "search_time_limit_seconds": 0.1, + "workload_penalty_weight": 0.07, + "road_factor": 0.06, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260416_124747.json b/ml_data/reports/tuning_20260416_124747.json new file mode 100644 index 0000000..234e232 --- /dev/null +++ b/ml_data/reports/tuning_20260416_124747.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-16T12:47:47.139199", + "training_rows": 552, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7317, + "mae": 3.95, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.9 pts (R2=0.73, trust=good)" + }, + "baseline_stats": { + "avg_quality": 80.57, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 552 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.53, + "quality_delta_10": 24.41, + "num_orders": 13.77, + "hour": 12.45, + "day_of_week": 7.72, + "num_riders": 4.24, + "max_pickup_distance_km": 2.04, + "max_kitchen_distance_km": 1.74, + "max_orders_per_rider": 1.13, + "workload_balance_threshold": 0.79, + "ideal_load": 0.42, + "is_peak": 0.33, + "distance_penalty_weight": 0.15, + "search_time_limit_seconds": 0.11, + "workload_penalty_weight": 0.07, + "road_factor": 0.06, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260416_124825.json b/ml_data/reports/tuning_20260416_124825.json new file mode 100644 index 0000000..27f9fb5 --- /dev/null +++ b/ml_data/reports/tuning_20260416_124825.json @@ -0,0 +1,203 @@ +{ + "timestamp": "2026-04-16T12:48:25.998483", + "training_rows": 553, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7385, + "mae": 3.853, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.9 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 80.58, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 553 + }, + "feature_importance": { + "rolling_avg_quality_5": 31.0, + "quality_delta_10": 24.78, + "num_orders": 15.07, + "hour": 11.5, + "day_of_week": 5.79, + "num_riders": 5.32, + "max_pickup_distance_km": 2.22, + "max_kitchen_distance_km": 1.6, + "max_orders_per_rider": 0.8, + "workload_balance_threshold": 0.67, + "ideal_load": 0.35, + "distance_penalty_weight": 0.29, + "is_peak": 0.19, + "workload_penalty_weight": 0.14, + "cluster_radius_km": 0.14, + "road_factor": 0.14 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260416_132603.json b/ml_data/reports/tuning_20260416_132603.json new file mode 100644 index 0000000..c597168 --- /dev/null +++ b/ml_data/reports/tuning_20260416_132603.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-16T13:26:03.184404", + "training_rows": 560, + "n_trials": 150, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7685, + "mae": 3.721, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.7 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 80.67, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 560 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.5, + "quality_delta_10": 24.38, + "num_orders": 13.76, + "hour": 12.5, + "day_of_week": 7.7, + "num_riders": 4.24, + "max_pickup_distance_km": 2.08, + "max_kitchen_distance_km": 1.72, + "max_orders_per_rider": 1.14, + "workload_balance_threshold": 0.78, + "ideal_load": 0.43, + "is_peak": 0.34, + "distance_penalty_weight": 0.15, + "search_time_limit_seconds": 0.11, + "workload_penalty_weight": 0.07, + "road_factor": 0.07, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260417_014552.json b/ml_data/reports/tuning_20260417_014552.json new file mode 100644 index 0000000..df58fb0 --- /dev/null +++ b/ml_data/reports/tuning_20260417_014552.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-17T01:45:52.789546", + "training_rows": 563, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7547, + "mae": 3.715, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.7 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 80.71, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 563 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.49, + "quality_delta_10": 24.34, + "num_orders": 13.75, + "hour": 12.47, + "day_of_week": 7.73, + "num_riders": 4.26, + "max_pickup_distance_km": 2.11, + "max_kitchen_distance_km": 1.71, + "max_orders_per_rider": 1.15, + "workload_balance_threshold": 0.78, + "ideal_load": 0.45, + "is_peak": 0.35, + "distance_penalty_weight": 0.15, + "search_time_limit_seconds": 0.11, + "workload_penalty_weight": 0.07, + "road_factor": 0.07, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260417_055530.json b/ml_data/reports/tuning_20260417_055530.json new file mode 100644 index 0000000..f490c57 --- /dev/null +++ b/ml_data/reports/tuning_20260417_055530.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-17T05:55:30.525741", + "training_rows": 575, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7517, + "mae": 3.613, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.6 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 80.87, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 575 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.44, + "quality_delta_10": 24.34, + "num_orders": 13.78, + "hour": 12.44, + "day_of_week": 7.69, + "num_riders": 4.31, + "max_pickup_distance_km": 2.16, + "max_kitchen_distance_km": 1.69, + "max_orders_per_rider": 1.15, + "workload_balance_threshold": 0.78, + "ideal_load": 0.46, + "is_peak": 0.34, + "distance_penalty_weight": 0.15, + "search_time_limit_seconds": 0.11, + "workload_penalty_weight": 0.07, + "road_factor": 0.07, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260417_060942.json b/ml_data/reports/tuning_20260417_060942.json new file mode 100644 index 0000000..a229c82 --- /dev/null +++ b/ml_data/reports/tuning_20260417_060942.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-17T06:09:42.266970", + "training_rows": 585, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7399, + "mae": 3.61, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.6 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 80.92, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 585 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.4, + "quality_delta_10": 24.29, + "num_orders": 13.79, + "hour": 12.44, + "day_of_week": 7.71, + "num_riders": 4.33, + "max_pickup_distance_km": 2.19, + "max_kitchen_distance_km": 1.67, + "max_orders_per_rider": 1.17, + "workload_balance_threshold": 0.79, + "ideal_load": 0.47, + "is_peak": 0.34, + "distance_penalty_weight": 0.15, + "search_time_limit_seconds": 0.11, + "workload_penalty_weight": 0.07, + "road_factor": 0.07, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260417_100605.json b/ml_data/reports/tuning_20260417_100605.json new file mode 100644 index 0000000..d3d1faf --- /dev/null +++ b/ml_data/reports/tuning_20260417_100605.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-17T10:06:05.877246", + "training_rows": 595, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7084, + "mae": 3.679, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.7 pts (R2=0.71, trust=good)" + }, + "baseline_stats": { + "avg_quality": 81.04, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 595 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.4, + "quality_delta_10": 24.29, + "num_orders": 13.77, + "hour": 12.44, + "day_of_week": 7.68, + "num_riders": 4.34, + "max_pickup_distance_km": 2.21, + "max_kitchen_distance_km": 1.66, + "max_orders_per_rider": 1.18, + "workload_balance_threshold": 0.79, + "ideal_load": 0.46, + "is_peak": 0.34, + "distance_penalty_weight": 0.14, + "search_time_limit_seconds": 0.11, + "workload_penalty_weight": 0.07, + "road_factor": 0.07, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260417_115814.json b/ml_data/reports/tuning_20260417_115814.json new file mode 100644 index 0000000..ccdaf56 --- /dev/null +++ b/ml_data/reports/tuning_20260417_115814.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-17T11:58:14.732043", + "training_rows": 605, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7464, + "mae": 3.668, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.7 pts (R2=0.75, trust=good)" + }, + "baseline_stats": { + "avg_quality": 81.22, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 605 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.4, + "quality_delta_10": 24.26, + "num_orders": 13.77, + "hour": 12.42, + "day_of_week": 7.67, + "num_riders": 4.39, + "max_pickup_distance_km": 2.24, + "max_kitchen_distance_km": 1.65, + "max_orders_per_rider": 1.19, + "workload_balance_threshold": 0.79, + "ideal_load": 0.46, + "is_peak": 0.34, + "distance_penalty_weight": 0.15, + "search_time_limit_seconds": 0.12, + "workload_penalty_weight": 0.07, + "road_factor": 0.07, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260417_124616.json b/ml_data/reports/tuning_20260417_124616.json new file mode 100644 index 0000000..b7f10e6 --- /dev/null +++ b/ml_data/reports/tuning_20260417_124616.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-17T12:46:16.237305", + "training_rows": 617, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7521, + "mae": 3.655, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.7 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 81.37, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 617 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.36, + "quality_delta_10": 24.27, + "num_orders": 13.76, + "hour": 12.4, + "day_of_week": 7.66, + "num_riders": 4.44, + "max_pickup_distance_km": 2.25, + "max_kitchen_distance_km": 1.64, + "max_orders_per_rider": 1.18, + "workload_balance_threshold": 0.78, + "ideal_load": 0.48, + "is_peak": 0.34, + "distance_penalty_weight": 0.14, + "search_time_limit_seconds": 0.13, + "workload_penalty_weight": 0.07, + "road_factor": 0.07, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260418_015019.json b/ml_data/reports/tuning_20260418_015019.json new file mode 100644 index 0000000..d73504d --- /dev/null +++ b/ml_data/reports/tuning_20260418_015019.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-18T01:50:19.938250", + "training_rows": 628, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7408, + "mae": 3.546, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.5 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 81.5, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 628 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.35, + "quality_delta_10": 24.23, + "num_orders": 13.77, + "hour": 12.44, + "day_of_week": 7.67, + "num_riders": 4.42, + "max_pickup_distance_km": 2.29, + "max_kitchen_distance_km": 1.62, + "max_orders_per_rider": 1.18, + "workload_balance_threshold": 0.78, + "ideal_load": 0.48, + "is_peak": 0.35, + "distance_penalty_weight": 0.14, + "search_time_limit_seconds": 0.13, + "workload_penalty_weight": 0.07, + "road_factor": 0.07, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260418_060650.json b/ml_data/reports/tuning_20260418_060650.json new file mode 100644 index 0000000..729fca9 --- /dev/null +++ b/ml_data/reports/tuning_20260418_060650.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-18T06:06:50.884919", + "training_rows": 640, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7563, + "mae": 3.52, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.5 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 81.63, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 640 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.39, + "quality_delta_10": 24.15, + "num_orders": 13.76, + "hour": 12.44, + "day_of_week": 7.7, + "num_riders": 4.42, + "max_pickup_distance_km": 2.32, + "max_kitchen_distance_km": 1.61, + "max_orders_per_rider": 1.18, + "workload_balance_threshold": 0.77, + "ideal_load": 0.48, + "is_peak": 0.35, + "distance_penalty_weight": 0.14, + "search_time_limit_seconds": 0.13, + "road_factor": 0.08, + "workload_penalty_weight": 0.07, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260418_062541.json b/ml_data/reports/tuning_20260418_062541.json new file mode 100644 index 0000000..1b4f2be --- /dev/null +++ b/ml_data/reports/tuning_20260418_062541.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-18T06:25:41.982890", + "training_rows": 650, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7707, + "mae": 3.542, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.5 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 81.68, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 650 + }, + "feature_importance": { + "rolling_avg_quality_5": 30.39, + "quality_delta_10": 24.11, + "num_orders": 13.79, + "hour": 12.39, + "day_of_week": 7.72, + "num_riders": 4.39, + "max_pickup_distance_km": 2.36, + "max_kitchen_distance_km": 1.61, + "max_orders_per_rider": 1.19, + "workload_balance_threshold": 0.78, + "ideal_load": 0.47, + "is_peak": 0.35, + "distance_penalty_weight": 0.14, + "search_time_limit_seconds": 0.13, + "workload_penalty_weight": 0.08, + "road_factor": 0.08, + "cluster_radius_km": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260418_065516.json b/ml_data/reports/tuning_20260418_065516.json new file mode 100644 index 0000000..5980dc0 --- /dev/null +++ b/ml_data/reports/tuning_20260418_065516.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-18T06:55:16.965238", + "training_rows": 654, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7448, + "mae": 3.664, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.7 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 81.71, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 654 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.78, + "quality_delta_10": 24.85, + "num_orders": 15.13, + "hour": 11.71, + "day_of_week": 8.08, + "num_riders": 4.08, + "max_pickup_distance_km": 4.08, + "max_orders_per_rider": 1.33, + "max_kitchen_distance_km": 1.21, + "workload_balance_threshold": 0.78, + "ideal_load": 0.75, + "is_peak": 0.67, + "workload_penalty_weight": 0.18, + "road_factor": 0.18, + "distance_penalty_weight": 0.06, + "cluster_radius_km": 0.06, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260418_115156.json b/ml_data/reports/tuning_20260418_115156.json new file mode 100644 index 0000000..dfd9412 --- /dev/null +++ b/ml_data/reports/tuning_20260418_115156.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-18T11:51:56.865655", + "training_rows": 664, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7689, + "mae": 3.511, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.5 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 81.8, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 664 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.15, + "quality_delta_10": 25.47, + "num_orders": 14.78, + "hour": 11.61, + "day_of_week": 7.98, + "num_riders": 4.15, + "max_pickup_distance_km": 3.71, + "max_orders_per_rider": 1.23, + "max_kitchen_distance_km": 1.22, + "workload_balance_threshold": 0.77, + "ideal_load": 0.67, + "is_peak": 0.64, + "workload_penalty_weight": 0.22, + "road_factor": 0.21, + "distance_penalty_weight": 0.09, + "cluster_radius_km": 0.06, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260420_043638.json b/ml_data/reports/tuning_20260420_043638.json new file mode 100644 index 0000000..78ccb67 --- /dev/null +++ b/ml_data/reports/tuning_20260420_043638.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-20T04:36:38.137699", + "training_rows": 671, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7776, + "mae": 3.506, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.5 pts (R2=0.78, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 81.86, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 671 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.55, + "quality_delta_10": 24.84, + "num_orders": 15.39, + "hour": 11.88, + "day_of_week": 7.49, + "num_riders": 4.59, + "max_pickup_distance_km": 3.92, + "max_orders_per_rider": 1.45, + "max_kitchen_distance_km": 1.2, + "is_peak": 0.78, + "workload_balance_threshold": 0.73, + "ideal_load": 0.7, + "road_factor": 0.15, + "workload_penalty_weight": 0.13, + "cluster_radius_km": 0.12, + "search_time_limit_seconds": 0.06, + "distance_penalty_weight": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260420_054150.json b/ml_data/reports/tuning_20260420_054150.json new file mode 100644 index 0000000..07e5e20 --- /dev/null +++ b/ml_data/reports/tuning_20260420_054150.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-20T05:41:50.920567", + "training_rows": 681, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.783, + "mae": 3.367, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.4 pts (R2=0.78, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 81.98, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 681 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.77, + "quality_delta_10": 25.04, + "num_orders": 14.7, + "hour": 12.01, + "day_of_week": 7.71, + "num_riders": 4.65, + "max_pickup_distance_km": 3.8, + "max_orders_per_rider": 1.36, + "max_kitchen_distance_km": 1.22, + "workload_balance_threshold": 0.8, + "is_peak": 0.75, + "ideal_load": 0.62, + "workload_penalty_weight": 0.17, + "road_factor": 0.17, + "cluster_radius_km": 0.1, + "search_time_limit_seconds": 0.06, + "distance_penalty_weight": 0.05 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260420_062855.json b/ml_data/reports/tuning_20260420_062855.json new file mode 100644 index 0000000..6c9c440 --- /dev/null +++ b/ml_data/reports/tuning_20260420_062855.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-20T06:28:55.565856", + "training_rows": 692, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7636, + "mae": 3.524, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.5 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 82.05, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 692 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.81, + "quality_delta_10": 25.38, + "num_orders": 14.44, + "hour": 12.12, + "day_of_week": 7.83, + "num_riders": 4.59, + "max_pickup_distance_km": 3.65, + "max_orders_per_rider": 1.32, + "max_kitchen_distance_km": 1.18, + "workload_balance_threshold": 0.78, + "is_peak": 0.71, + "ideal_load": 0.58, + "road_factor": 0.2, + "workload_penalty_weight": 0.19, + "cluster_radius_km": 0.1, + "search_time_limit_seconds": 0.09, + "distance_penalty_weight": 0.05 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260420_064448.json b/ml_data/reports/tuning_20260420_064448.json new file mode 100644 index 0000000..ce4b6ca --- /dev/null +++ b/ml_data/reports/tuning_20260420_064448.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-20T06:44:48.273529", + "training_rows": 702, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7709, + "mae": 3.388, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.4 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 82.13, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 702 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.17, + "quality_delta_10": 25.5, + "num_orders": 14.16, + "hour": 12.11, + "day_of_week": 7.9, + "num_riders": 4.53, + "max_pickup_distance_km": 3.44, + "max_orders_per_rider": 1.33, + "max_kitchen_distance_km": 1.22, + "workload_balance_threshold": 0.76, + "is_peak": 0.69, + "ideal_load": 0.58, + "road_factor": 0.19, + "workload_penalty_weight": 0.18, + "cluster_radius_km": 0.11, + "search_time_limit_seconds": 0.08, + "distance_penalty_weight": 0.05 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260420_101819.json b/ml_data/reports/tuning_20260420_101819.json new file mode 100644 index 0000000..05eda3a --- /dev/null +++ b/ml_data/reports/tuning_20260420_101819.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-20T10:18:19.642255", + "training_rows": 712, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7963, + "mae": 3.189, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.2 pts (R2=0.80, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 82.18, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 712 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.48, + "quality_delta_10": 25.72, + "num_orders": 13.94, + "hour": 12.04, + "day_of_week": 7.99, + "num_riders": 4.38, + "max_pickup_distance_km": 3.33, + "max_orders_per_rider": 1.32, + "max_kitchen_distance_km": 1.16, + "workload_balance_threshold": 0.81, + "is_peak": 0.64, + "ideal_load": 0.58, + "road_factor": 0.2, + "workload_penalty_weight": 0.18, + "cluster_radius_km": 0.11, + "search_time_limit_seconds": 0.1, + "distance_penalty_weight": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260420_111636.json b/ml_data/reports/tuning_20260420_111636.json new file mode 100644 index 0000000..8aaafb1 --- /dev/null +++ b/ml_data/reports/tuning_20260420_111636.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-20T11:16:36.458715", + "training_rows": 723, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.8098, + "mae": 3.276, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.3 pts (R2=0.81, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 82.29, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 723 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.59, + "quality_delta_10": 25.9, + "num_orders": 13.93, + "hour": 12.1, + "day_of_week": 7.94, + "num_riders": 4.24, + "max_pickup_distance_km": 3.26, + "max_orders_per_rider": 1.3, + "max_kitchen_distance_km": 1.14, + "workload_balance_threshold": 0.78, + "is_peak": 0.62, + "ideal_load": 0.56, + "road_factor": 0.21, + "workload_penalty_weight": 0.18, + "cluster_radius_km": 0.1, + "search_time_limit_seconds": 0.1, + "distance_penalty_weight": 0.06 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260420_113128.json b/ml_data/reports/tuning_20260420_113128.json new file mode 100644 index 0000000..30225a0 --- /dev/null +++ b/ml_data/reports/tuning_20260420_113128.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-20T11:31:28.482565", + "training_rows": 734, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.8098, + "mae": 3.245, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.2 pts (R2=0.81, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 82.37, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 734 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.97, + "quality_delta_10": 26.05, + "num_orders": 13.76, + "hour": 12.02, + "day_of_week": 7.89, + "num_riders": 4.2, + "max_pickup_distance_km": 3.13, + "max_orders_per_rider": 1.26, + "max_kitchen_distance_km": 1.2, + "workload_balance_threshold": 0.75, + "is_peak": 0.59, + "ideal_load": 0.55, + "road_factor": 0.21, + "workload_penalty_weight": 0.18, + "cluster_radius_km": 0.09, + "search_time_limit_seconds": 0.09, + "distance_penalty_weight": 0.06 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260421_021448.json b/ml_data/reports/tuning_20260421_021448.json new file mode 100644 index 0000000..b7f6656 --- /dev/null +++ b/ml_data/reports/tuning_20260421_021448.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-21T02:14:48.190443", + "training_rows": 744, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.8054, + "mae": 3.266, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.3 pts (R2=0.81, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 82.46, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 744 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.98, + "quality_delta_10": 26.1, + "num_orders": 13.64, + "hour": 12.11, + "day_of_week": 7.95, + "num_riders": 4.17, + "max_pickup_distance_km": 3.07, + "max_orders_per_rider": 1.28, + "max_kitchen_distance_km": 1.16, + "workload_balance_threshold": 0.72, + "is_peak": 0.61, + "ideal_load": 0.54, + "workload_penalty_weight": 0.22, + "road_factor": 0.22, + "search_time_limit_seconds": 0.09, + "cluster_radius_km": 0.08, + "distance_penalty_weight": 0.06 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260421_061042.json b/ml_data/reports/tuning_20260421_061042.json new file mode 100644 index 0000000..4b05855 --- /dev/null +++ b/ml_data/reports/tuning_20260421_061042.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-21T06:10:42.176782", + "training_rows": 754, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7894, + "mae": 3.328, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.3 pts (R2=0.79, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 82.57, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 754 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.96, + "quality_delta_10": 26.24, + "num_orders": 13.47, + "hour": 12.14, + "day_of_week": 8.08, + "num_riders": 4.22, + "max_pickup_distance_km": 3.0, + "max_orders_per_rider": 1.23, + "max_kitchen_distance_km": 1.14, + "workload_balance_threshold": 0.72, + "is_peak": 0.6, + "ideal_load": 0.54, + "workload_penalty_weight": 0.21, + "road_factor": 0.21, + "search_time_limit_seconds": 0.1, + "distance_penalty_weight": 0.08, + "cluster_radius_km": 0.08 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260421_062533.json b/ml_data/reports/tuning_20260421_062533.json new file mode 100644 index 0000000..0a418aa --- /dev/null +++ b/ml_data/reports/tuning_20260421_062533.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-21T06:25:33.500305", + "training_rows": 765, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7838, + "mae": 3.278, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.3 pts (R2=0.78, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 82.59, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 765 + }, + "feature_importance": { + "rolling_avg_quality_5": 28.01, + "quality_delta_10": 26.29, + "num_orders": 13.44, + "hour": 12.14, + "day_of_week": 8.09, + "num_riders": 4.3, + "max_pickup_distance_km": 2.95, + "max_orders_per_rider": 1.2, + "max_kitchen_distance_km": 1.12, + "workload_balance_threshold": 0.71, + "is_peak": 0.57, + "ideal_load": 0.52, + "workload_penalty_weight": 0.21, + "road_factor": 0.2, + "search_time_limit_seconds": 0.09, + "distance_penalty_weight": 0.08, + "cluster_radius_km": 0.07 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260421_102012.json b/ml_data/reports/tuning_20260421_102012.json new file mode 100644 index 0000000..c149aa1 --- /dev/null +++ b/ml_data/reports/tuning_20260421_102012.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-21T10:20:12.993710", + "training_rows": 775, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7896, + "mae": 3.254, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.3 pts (R2=0.79, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 82.66, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 775 + }, + "feature_importance": { + "rolling_avg_quality_5": 28.13, + "quality_delta_10": 26.3, + "num_orders": 13.4, + "hour": 12.17, + "day_of_week": 8.12, + "num_riders": 4.32, + "max_pickup_distance_km": 2.85, + "max_orders_per_rider": 1.21, + "max_kitchen_distance_km": 1.07, + "workload_balance_threshold": 0.72, + "is_peak": 0.57, + "ideal_load": 0.51, + "workload_penalty_weight": 0.21, + "road_factor": 0.19, + "search_time_limit_seconds": 0.1, + "distance_penalty_weight": 0.07, + "cluster_radius_km": 0.07 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260421_115334.json b/ml_data/reports/tuning_20260421_115334.json new file mode 100644 index 0000000..a0e1f29 --- /dev/null +++ b/ml_data/reports/tuning_20260421_115334.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-21T11:53:34.288610", + "training_rows": 786, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7736, + "mae": 3.308, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.3 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 82.76, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 786 + }, + "feature_importance": { + "rolling_avg_quality_5": 28.18, + "quality_delta_10": 26.33, + "num_orders": 13.3, + "hour": 12.3, + "day_of_week": 8.19, + "num_riders": 4.32, + "max_pickup_distance_km": 2.78, + "max_orders_per_rider": 1.18, + "max_kitchen_distance_km": 1.04, + "workload_balance_threshold": 0.71, + "is_peak": 0.56, + "ideal_load": 0.5, + "workload_penalty_weight": 0.21, + "road_factor": 0.18, + "search_time_limit_seconds": 0.09, + "distance_penalty_weight": 0.07, + "cluster_radius_km": 0.06 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260421_120149.json b/ml_data/reports/tuning_20260421_120149.json new file mode 100644 index 0000000..11972d0 --- /dev/null +++ b/ml_data/reports/tuning_20260421_120149.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-21T12:01:49.062177", + "training_rows": 797, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7598, + "mae": 3.399, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.4 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 82.85, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 797 + }, + "feature_importance": { + "rolling_avg_quality_5": 28.21, + "quality_delta_10": 26.33, + "num_orders": 13.29, + "hour": 12.36, + "day_of_week": 8.23, + "num_riders": 4.34, + "max_pickup_distance_km": 2.71, + "max_orders_per_rider": 1.17, + "max_kitchen_distance_km": 1.01, + "workload_balance_threshold": 0.69, + "is_peak": 0.55, + "ideal_load": 0.52, + "workload_penalty_weight": 0.21, + "road_factor": 0.18, + "search_time_limit_seconds": 0.09, + "distance_penalty_weight": 0.07, + "cluster_radius_km": 0.06 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260422_062048.json b/ml_data/reports/tuning_20260422_062048.json new file mode 100644 index 0000000..e6c24b8 --- /dev/null +++ b/ml_data/reports/tuning_20260422_062048.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-22T06:20:48.225729", + "training_rows": 810, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7703, + "mae": 3.314, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.3 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 82.93, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 810 + }, + "feature_importance": { + "rolling_avg_quality_5": 28.37, + "quality_delta_10": 26.27, + "num_orders": 13.28, + "hour": 12.31, + "day_of_week": 8.32, + "num_riders": 4.37, + "max_pickup_distance_km": 2.65, + "max_orders_per_rider": 1.13, + "max_kitchen_distance_km": 0.97, + "workload_balance_threshold": 0.67, + "is_peak": 0.56, + "ideal_load": 0.52, + "workload_penalty_weight": 0.19, + "road_factor": 0.18, + "search_time_limit_seconds": 0.09, + "distance_penalty_weight": 0.07, + "cluster_radius_km": 0.06 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260422_122338.json b/ml_data/reports/tuning_20260422_122338.json new file mode 100644 index 0000000..2c628e8 --- /dev/null +++ b/ml_data/reports/tuning_20260422_122338.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-22T12:23:38.983023", + "training_rows": 820, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7602, + "mae": 3.376, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.4 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 82.95, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 820 + }, + "feature_importance": { + "rolling_avg_quality_5": 28.37, + "quality_delta_10": 26.23, + "num_orders": 13.24, + "hour": 12.32, + "day_of_week": 8.37, + "num_riders": 4.46, + "max_pickup_distance_km": 2.62, + "max_orders_per_rider": 1.14, + "max_kitchen_distance_km": 0.96, + "workload_balance_threshold": 0.67, + "is_peak": 0.53, + "ideal_load": 0.51, + "workload_penalty_weight": 0.2, + "road_factor": 0.17, + "search_time_limit_seconds": 0.09, + "distance_penalty_weight": 0.06, + "cluster_radius_km": 0.05 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260422_122932.json b/ml_data/reports/tuning_20260422_122932.json new file mode 100644 index 0000000..5b60961 --- /dev/null +++ b/ml_data/reports/tuning_20260422_122932.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-22T12:29:32.927429", + "training_rows": 830, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7822, + "mae": 3.244, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.2 pts (R2=0.78, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.11, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 830 + }, + "feature_importance": { + "rolling_avg_quality_5": 28.49, + "quality_delta_10": 26.24, + "num_orders": 13.12, + "hour": 12.5, + "day_of_week": 8.3, + "num_riders": 4.4, + "max_pickup_distance_km": 2.56, + "max_orders_per_rider": 1.12, + "max_kitchen_distance_km": 0.97, + "workload_balance_threshold": 0.66, + "is_peak": 0.56, + "ideal_load": 0.52, + "workload_penalty_weight": 0.19, + "road_factor": 0.17, + "search_time_limit_seconds": 0.09, + "distance_penalty_weight": 0.06, + "cluster_radius_km": 0.05 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260422_123656.json b/ml_data/reports/tuning_20260422_123656.json new file mode 100644 index 0000000..4ce4dd1 --- /dev/null +++ b/ml_data/reports/tuning_20260422_123656.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-22T12:36:56.203328", + "training_rows": 840, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7812, + "mae": 3.223, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.2 pts (R2=0.78, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.19, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 840 + }, + "feature_importance": { + "rolling_avg_quality_5": 28.68, + "quality_delta_10": 26.31, + "num_orders": 13.09, + "hour": 12.45, + "day_of_week": 8.25, + "num_riders": 4.39, + "max_pickup_distance_km": 2.51, + "max_orders_per_rider": 1.1, + "max_kitchen_distance_km": 0.96, + "workload_balance_threshold": 0.64, + "is_peak": 0.6, + "ideal_load": 0.49, + "workload_penalty_weight": 0.19, + "road_factor": 0.16, + "search_time_limit_seconds": 0.08, + "distance_penalty_weight": 0.06, + "cluster_radius_km": 0.05 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260422_123711.json b/ml_data/reports/tuning_20260422_123711.json new file mode 100644 index 0000000..8a3dc07 --- /dev/null +++ b/ml_data/reports/tuning_20260422_123711.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-22T12:37:11.096400", + "training_rows": 841, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.793, + "mae": 3.186, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.2 pts (R2=0.79, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.19, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 841 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.85, + "quality_delta_10": 24.92, + "num_orders": 15.03, + "hour": 11.64, + "day_of_week": 8.3, + "num_riders": 4.02, + "max_pickup_distance_km": 3.88, + "max_orders_per_rider": 1.46, + "max_kitchen_distance_km": 1.14, + "is_peak": 0.78, + "workload_balance_threshold": 0.78, + "ideal_load": 0.67, + "road_factor": 0.22, + "workload_penalty_weight": 0.16, + "distance_penalty_weight": 0.05, + "cluster_radius_km": 0.05, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260424_015839.json b/ml_data/reports/tuning_20260424_015839.json new file mode 100644 index 0000000..5f1c2b2 --- /dev/null +++ b/ml_data/reports/tuning_20260424_015839.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-24T01:58:39.232473", + "training_rows": 854, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7735, + "mae": 3.236, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.2 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.28, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 854 + }, + "feature_importance": { + "rolling_avg_quality_5": 28.85, + "quality_delta_10": 26.22, + "num_orders": 12.98, + "hour": 12.47, + "day_of_week": 8.27, + "num_riders": 4.43, + "max_pickup_distance_km": 2.49, + "max_orders_per_rider": 1.08, + "max_kitchen_distance_km": 0.95, + "workload_balance_threshold": 0.63, + "is_peak": 0.59, + "ideal_load": 0.5, + "workload_penalty_weight": 0.19, + "road_factor": 0.16, + "search_time_limit_seconds": 0.08, + "distance_penalty_weight": 0.06, + "cluster_radius_km": 0.05 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260424_061245.json b/ml_data/reports/tuning_20260424_061245.json new file mode 100644 index 0000000..0b500b8 --- /dev/null +++ b/ml_data/reports/tuning_20260424_061245.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-24T06:12:45.089351", + "training_rows": 867, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7725, + "mae": 3.292, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.3 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.32, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 867 + }, + "feature_importance": { + "rolling_avg_quality_5": 28.96, + "quality_delta_10": 26.21, + "num_orders": 13.0, + "hour": 12.36, + "day_of_week": 8.27, + "num_riders": 4.53, + "max_pickup_distance_km": 2.45, + "max_orders_per_rider": 1.07, + "max_kitchen_distance_km": 0.93, + "workload_balance_threshold": 0.63, + "is_peak": 0.57, + "ideal_load": 0.5, + "workload_penalty_weight": 0.18, + "road_factor": 0.16, + "search_time_limit_seconds": 0.08, + "distance_penalty_weight": 0.06, + "cluster_radius_km": 0.05 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260424_120007.json b/ml_data/reports/tuning_20260424_120007.json new file mode 100644 index 0000000..2aafef0 --- /dev/null +++ b/ml_data/reports/tuning_20260424_120007.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-24T12:00:07.729707", + "training_rows": 880, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7682, + "mae": 3.239, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.2 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.4, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 880 + }, + "feature_importance": { + "rolling_avg_quality_5": 28.98, + "quality_delta_10": 26.06, + "num_orders": 12.98, + "hour": 12.48, + "day_of_week": 8.26, + "num_riders": 4.61, + "max_pickup_distance_km": 2.47, + "max_orders_per_rider": 1.04, + "max_kitchen_distance_km": 0.93, + "workload_balance_threshold": 0.62, + "is_peak": 0.57, + "ideal_load": 0.5, + "workload_penalty_weight": 0.18, + "road_factor": 0.15, + "search_time_limit_seconds": 0.08, + "distance_penalty_weight": 0.06, + "cluster_radius_km": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260425_014608.json b/ml_data/reports/tuning_20260425_014608.json new file mode 100644 index 0000000..4f922be --- /dev/null +++ b/ml_data/reports/tuning_20260425_014608.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-25T01:46:08.037620", + "training_rows": 887, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7784, + "mae": 3.201, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.2 pts (R2=0.78, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.43, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 887 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.22, + "quality_delta_10": 24.85, + "num_orders": 14.69, + "hour": 11.48, + "day_of_week": 8.33, + "num_riders": 4.45, + "max_pickup_distance_km": 3.68, + "max_orders_per_rider": 1.51, + "max_kitchen_distance_km": 1.07, + "workload_balance_threshold": 0.8, + "is_peak": 0.7, + "ideal_load": 0.68, + "road_factor": 0.22, + "workload_penalty_weight": 0.15, + "distance_penalty_weight": 0.07, + "cluster_radius_km": 0.06, + "search_time_limit_seconds": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260425_015427.json b/ml_data/reports/tuning_20260425_015427.json new file mode 100644 index 0000000..220f4fe --- /dev/null +++ b/ml_data/reports/tuning_20260425_015427.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-25T01:54:27.097597", + "training_rows": 891, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.793, + "mae": 3.163, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.2 pts (R2=0.79, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.45, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 891 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.0, + "quality_delta_10": 25.9, + "num_orders": 12.93, + "hour": 12.5, + "day_of_week": 8.32, + "num_riders": 4.79, + "max_pickup_distance_km": 2.46, + "max_orders_per_rider": 1.02, + "max_kitchen_distance_km": 0.92, + "workload_balance_threshold": 0.6, + "is_peak": 0.56, + "ideal_load": 0.49, + "workload_penalty_weight": 0.17, + "road_factor": 0.15, + "search_time_limit_seconds": 0.07, + "distance_penalty_weight": 0.06, + "cluster_radius_km": 0.05 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260425_061128.json b/ml_data/reports/tuning_20260425_061128.json new file mode 100644 index 0000000..410c9b9 --- /dev/null +++ b/ml_data/reports/tuning_20260425_061128.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-25T06:11:28.468711", + "training_rows": 904, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7575, + "mae": 3.304, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.3 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.52, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 904 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.08, + "quality_delta_10": 25.8, + "num_orders": 12.88, + "hour": 12.47, + "day_of_week": 8.36, + "num_riders": 4.97, + "max_pickup_distance_km": 2.43, + "max_orders_per_rider": 1.0, + "max_kitchen_distance_km": 0.9, + "workload_balance_threshold": 0.6, + "is_peak": 0.55, + "ideal_load": 0.48, + "workload_penalty_weight": 0.17, + "road_factor": 0.15, + "search_time_limit_seconds": 0.07, + "distance_penalty_weight": 0.06, + "cluster_radius_km": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260425_113311.json b/ml_data/reports/tuning_20260425_113311.json new file mode 100644 index 0000000..5f94b5f --- /dev/null +++ b/ml_data/reports/tuning_20260425_113311.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-25T11:33:11.754468", + "training_rows": 916, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7456, + "mae": 3.281, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.3 pts (R2=0.75, trust=good)" + }, + "baseline_stats": { + "avg_quality": 83.58, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 916 + }, + "feature_importance": { + "rolling_avg_quality_5": 28.92, + "quality_delta_10": 25.84, + "num_orders": 12.9, + "hour": 12.45, + "day_of_week": 8.41, + "num_riders": 5.14, + "max_pickup_distance_km": 2.4, + "max_orders_per_rider": 0.99, + "max_kitchen_distance_km": 0.87, + "workload_balance_threshold": 0.59, + "is_peak": 0.54, + "ideal_load": 0.48, + "workload_penalty_weight": 0.16, + "road_factor": 0.15, + "search_time_limit_seconds": 0.07, + "distance_penalty_weight": 0.05, + "cluster_radius_km": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260427_015316.json b/ml_data/reports/tuning_20260427_015316.json new file mode 100644 index 0000000..ebd58ce --- /dev/null +++ b/ml_data/reports/tuning_20260427_015316.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-27T01:53:16.033218", + "training_rows": 927, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7539, + "mae": 3.258, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.3 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.62, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 927 + }, + "feature_importance": { + "rolling_avg_quality_5": 28.95, + "quality_delta_10": 25.81, + "num_orders": 12.88, + "hour": 12.32, + "day_of_week": 8.46, + "num_riders": 5.25, + "max_pickup_distance_km": 2.39, + "max_orders_per_rider": 0.98, + "max_kitchen_distance_km": 0.87, + "workload_balance_threshold": 0.6, + "is_peak": 0.53, + "ideal_load": 0.48, + "workload_penalty_weight": 0.16, + "road_factor": 0.15, + "search_time_limit_seconds": 0.07, + "distance_penalty_weight": 0.05, + "cluster_radius_km": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260427_061139.json b/ml_data/reports/tuning_20260427_061139.json new file mode 100644 index 0000000..883e062 --- /dev/null +++ b/ml_data/reports/tuning_20260427_061139.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-27T06:11:39.470682", + "training_rows": 937, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7597, + "mae": 3.207, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.2 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.66, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 937 + }, + "feature_importance": { + "rolling_avg_quality_5": 28.9, + "quality_delta_10": 25.79, + "num_orders": 12.84, + "hour": 12.29, + "day_of_week": 8.54, + "num_riders": 5.36, + "max_pickup_distance_km": 2.38, + "max_orders_per_rider": 0.96, + "max_kitchen_distance_km": 0.86, + "workload_balance_threshold": 0.6, + "is_peak": 0.52, + "ideal_load": 0.48, + "workload_penalty_weight": 0.16, + "road_factor": 0.15, + "search_time_limit_seconds": 0.07, + "distance_penalty_weight": 0.05, + "cluster_radius_km": 0.05 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260427_121959.json b/ml_data/reports/tuning_20260427_121959.json new file mode 100644 index 0000000..897a7f6 --- /dev/null +++ b/ml_data/reports/tuning_20260427_121959.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-27T12:19:59.793864", + "training_rows": 947, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.728, + "mae": 3.319, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.3 pts (R2=0.73, trust=good)" + }, + "baseline_stats": { + "avg_quality": 83.73, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 947 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.0, + "quality_delta_10": 25.77, + "num_orders": 12.82, + "hour": 12.24, + "day_of_week": 8.57, + "num_riders": 5.36, + "max_pickup_distance_km": 2.38, + "max_orders_per_rider": 0.94, + "max_kitchen_distance_km": 0.86, + "workload_balance_threshold": 0.61, + "is_peak": 0.52, + "ideal_load": 0.47, + "workload_penalty_weight": 0.16, + "road_factor": 0.15, + "search_time_limit_seconds": 0.06, + "distance_penalty_weight": 0.05, + "cluster_radius_km": 0.05 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260428_015209.json b/ml_data/reports/tuning_20260428_015209.json new file mode 100644 index 0000000..4781d56 --- /dev/null +++ b/ml_data/reports/tuning_20260428_015209.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-28T01:52:09.678912", + "training_rows": 958, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7327, + "mae": 3.306, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.3 pts (R2=0.73, trust=good)" + }, + "baseline_stats": { + "avg_quality": 83.77, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 958 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.03, + "quality_delta_10": 25.73, + "num_orders": 12.72, + "hour": 12.23, + "day_of_week": 8.68, + "num_riders": 5.42, + "max_pickup_distance_km": 2.36, + "max_orders_per_rider": 0.95, + "max_kitchen_distance_km": 0.84, + "workload_balance_threshold": 0.61, + "is_peak": 0.52, + "ideal_load": 0.46, + "workload_penalty_weight": 0.16, + "road_factor": 0.15, + "search_time_limit_seconds": 0.06, + "distance_penalty_weight": 0.05, + "cluster_radius_km": 0.05 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260428_055936.json b/ml_data/reports/tuning_20260428_055936.json new file mode 100644 index 0000000..bf12278 --- /dev/null +++ b/ml_data/reports/tuning_20260428_055936.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-28T05:59:36.301976", + "training_rows": 970, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7804, + "mae": 3.074, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.78, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.83, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 970 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.06, + "quality_delta_10": 25.64, + "num_orders": 12.72, + "hour": 12.23, + "day_of_week": 8.75, + "num_riders": 5.43, + "max_pickup_distance_km": 2.35, + "max_orders_per_rider": 0.95, + "max_kitchen_distance_km": 0.84, + "workload_balance_threshold": 0.6, + "is_peak": 0.51, + "ideal_load": 0.46, + "workload_penalty_weight": 0.15, + "road_factor": 0.15, + "search_time_limit_seconds": 0.06, + "distance_penalty_weight": 0.05, + "cluster_radius_km": 0.05 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260428_060746.json b/ml_data/reports/tuning_20260428_060746.json new file mode 100644 index 0000000..0ab40d1 --- /dev/null +++ b/ml_data/reports/tuning_20260428_060746.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-28T06:07:46.349690", + "training_rows": 980, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.787, + "mae": 3.065, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.79, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.82, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 980 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.05, + "quality_delta_10": 25.64, + "num_orders": 12.74, + "hour": 12.22, + "day_of_week": 8.78, + "num_riders": 5.48, + "max_pickup_distance_km": 2.32, + "max_orders_per_rider": 0.95, + "max_kitchen_distance_km": 0.83, + "workload_balance_threshold": 0.59, + "is_peak": 0.5, + "ideal_load": 0.45, + "workload_penalty_weight": 0.15, + "road_factor": 0.15, + "search_time_limit_seconds": 0.06, + "cluster_radius_km": 0.05, + "distance_penalty_weight": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260428_062327.json b/ml_data/reports/tuning_20260428_062327.json new file mode 100644 index 0000000..6f35327 --- /dev/null +++ b/ml_data/reports/tuning_20260428_062327.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-28T06:23:27.764359", + "training_rows": 990, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7939, + "mae": 3.096, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.79, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.85, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 990 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.1, + "quality_delta_10": 25.6, + "num_orders": 12.72, + "hour": 12.21, + "day_of_week": 8.74, + "num_riders": 5.54, + "max_pickup_distance_km": 2.31, + "max_orders_per_rider": 0.99, + "max_kitchen_distance_km": 0.81, + "workload_balance_threshold": 0.59, + "is_peak": 0.49, + "ideal_load": 0.45, + "workload_penalty_weight": 0.15, + "road_factor": 0.15, + "search_time_limit_seconds": 0.06, + "cluster_radius_km": 0.05, + "distance_penalty_weight": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260428_122029.json b/ml_data/reports/tuning_20260428_122029.json new file mode 100644 index 0000000..2cf785e --- /dev/null +++ b/ml_data/reports/tuning_20260428_122029.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-28T12:20:29.448486", + "training_rows": 1000, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7751, + "mae": 3.172, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.2 pts (R2=0.78, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.87, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1000 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.1, + "quality_delta_10": 25.57, + "num_orders": 12.67, + "hour": 12.21, + "day_of_week": 8.78, + "num_riders": 5.61, + "max_pickup_distance_km": 2.3, + "max_orders_per_rider": 1.0, + "max_kitchen_distance_km": 0.8, + "workload_balance_threshold": 0.57, + "is_peak": 0.49, + "ideal_load": 0.44, + "workload_penalty_weight": 0.15, + "road_factor": 0.15, + "search_time_limit_seconds": 0.06, + "distance_penalty_weight": 0.05, + "cluster_radius_km": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260428_122711.json b/ml_data/reports/tuning_20260428_122711.json new file mode 100644 index 0000000..b68b3c4 --- /dev/null +++ b/ml_data/reports/tuning_20260428_122711.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-28T12:27:11.025038", + "training_rows": 1010, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7808, + "mae": 3.118, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.78, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.93, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1010 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.1, + "quality_delta_10": 25.65, + "num_orders": 12.6, + "hour": 12.22, + "day_of_week": 8.8, + "num_riders": 5.63, + "max_pickup_distance_km": 2.28, + "max_orders_per_rider": 0.99, + "max_kitchen_distance_km": 0.79, + "workload_balance_threshold": 0.57, + "is_peak": 0.49, + "ideal_load": 0.44, + "workload_penalty_weight": 0.15, + "road_factor": 0.14, + "search_time_limit_seconds": 0.06, + "distance_penalty_weight": 0.05, + "cluster_radius_km": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260428_124218.json b/ml_data/reports/tuning_20260428_124218.json new file mode 100644 index 0000000..87329aa --- /dev/null +++ b/ml_data/reports/tuning_20260428_124218.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-28T12:42:18.609767", + "training_rows": 1020, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7835, + "mae": 3.051, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.78, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.97, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1020 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.12, + "quality_delta_10": 25.69, + "num_orders": 12.52, + "hour": 12.17, + "day_of_week": 8.85, + "num_riders": 5.68, + "max_pickup_distance_km": 2.27, + "max_orders_per_rider": 0.98, + "max_kitchen_distance_km": 0.8, + "workload_balance_threshold": 0.56, + "is_peak": 0.5, + "ideal_load": 0.43, + "workload_penalty_weight": 0.14, + "road_factor": 0.14, + "distance_penalty_weight": 0.05, + "search_time_limit_seconds": 0.05, + "cluster_radius_km": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260428_124239.json b/ml_data/reports/tuning_20260428_124239.json new file mode 100644 index 0000000..3e94283 --- /dev/null +++ b/ml_data/reports/tuning_20260428_124239.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-28T12:42:39.034206", + "training_rows": 1021, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7867, + "mae": 3.044, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.79, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 83.97, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1021 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.94, + "quality_delta_10": 25.35, + "num_orders": 14.41, + "hour": 11.34, + "day_of_week": 8.37, + "num_riders": 5.05, + "max_pickup_distance_km": 3.5, + "max_orders_per_rider": 1.51, + "max_kitchen_distance_km": 0.96, + "workload_balance_threshold": 0.76, + "is_peak": 0.65, + "ideal_load": 0.63, + "road_factor": 0.2, + "workload_penalty_weight": 0.15, + "distance_penalty_weight": 0.06, + "cluster_radius_km": 0.06, + "search_time_limit_seconds": 0.05 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260429_020235.json b/ml_data/reports/tuning_20260429_020235.json new file mode 100644 index 0000000..885d675 --- /dev/null +++ b/ml_data/reports/tuning_20260429_020235.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-29T02:02:35.593241", + "training_rows": 1033, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7898, + "mae": 3.032, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.79, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.02, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1033 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.22, + "quality_delta_10": 25.62, + "num_orders": 12.53, + "hour": 12.26, + "day_of_week": 8.82, + "num_riders": 5.62, + "max_pickup_distance_km": 2.26, + "max_orders_per_rider": 0.97, + "max_kitchen_distance_km": 0.81, + "workload_balance_threshold": 0.55, + "is_peak": 0.5, + "ideal_load": 0.42, + "workload_penalty_weight": 0.14, + "road_factor": 0.14, + "distance_penalty_weight": 0.05, + "search_time_limit_seconds": 0.05, + "cluster_radius_km": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260429_060839.json b/ml_data/reports/tuning_20260429_060839.json new file mode 100644 index 0000000..27b0b9f --- /dev/null +++ b/ml_data/reports/tuning_20260429_060839.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-29T06:08:39.486624", + "training_rows": 1043, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7914, + "mae": 2.97, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.79, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.04, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1043 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.2, + "quality_delta_10": 25.62, + "num_orders": 12.52, + "hour": 12.32, + "day_of_week": 8.78, + "num_riders": 5.62, + "max_pickup_distance_km": 2.26, + "max_orders_per_rider": 0.98, + "max_kitchen_distance_km": 0.81, + "workload_balance_threshold": 0.54, + "is_peak": 0.5, + "ideal_load": 0.43, + "workload_penalty_weight": 0.14, + "road_factor": 0.14, + "distance_penalty_weight": 0.05, + "search_time_limit_seconds": 0.05, + "cluster_radius_km": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260429_062926.json b/ml_data/reports/tuning_20260429_062926.json new file mode 100644 index 0000000..89e320e --- /dev/null +++ b/ml_data/reports/tuning_20260429_062926.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-29T06:29:26.761249", + "training_rows": 1053, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.789, + "mae": 3.073, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.79, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.03, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1053 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.21, + "quality_delta_10": 25.69, + "num_orders": 12.51, + "hour": 12.31, + "day_of_week": 8.76, + "num_riders": 5.61, + "max_pickup_distance_km": 2.24, + "max_orders_per_rider": 0.97, + "max_kitchen_distance_km": 0.81, + "workload_balance_threshold": 0.54, + "is_peak": 0.5, + "ideal_load": 0.42, + "workload_penalty_weight": 0.14, + "road_factor": 0.14, + "distance_penalty_weight": 0.05, + "search_time_limit_seconds": 0.05, + "cluster_radius_km": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260429_120545.json b/ml_data/reports/tuning_20260429_120545.json new file mode 100644 index 0000000..13e014e --- /dev/null +++ b/ml_data/reports/tuning_20260429_120545.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-29T12:05:45.926650", + "training_rows": 1064, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7912, + "mae": 3.035, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.79, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.08, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1064 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.21, + "quality_delta_10": 25.69, + "num_orders": 12.52, + "hour": 12.31, + "day_of_week": 8.73, + "num_riders": 5.65, + "max_pickup_distance_km": 2.24, + "max_orders_per_rider": 0.96, + "max_kitchen_distance_km": 0.82, + "workload_balance_threshold": 0.53, + "is_peak": 0.51, + "ideal_load": 0.42, + "workload_penalty_weight": 0.14, + "road_factor": 0.14, + "distance_penalty_weight": 0.05, + "search_time_limit_seconds": 0.05, + "cluster_radius_km": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260429_122743.json b/ml_data/reports/tuning_20260429_122743.json new file mode 100644 index 0000000..9c6fb47 --- /dev/null +++ b/ml_data/reports/tuning_20260429_122743.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-29T12:27:43.665737", + "training_rows": 1079, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7954, + "mae": 2.994, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.80, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.11, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1079 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.25, + "quality_delta_10": 25.68, + "num_orders": 12.52, + "hour": 12.3, + "day_of_week": 8.73, + "num_riders": 5.66, + "max_pickup_distance_km": 2.24, + "max_orders_per_rider": 0.95, + "max_kitchen_distance_km": 0.82, + "workload_balance_threshold": 0.52, + "is_peak": 0.51, + "ideal_load": 0.41, + "workload_penalty_weight": 0.14, + "road_factor": 0.14, + "distance_penalty_weight": 0.05, + "search_time_limit_seconds": 0.05, + "cluster_radius_km": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260430_015218.json b/ml_data/reports/tuning_20260430_015218.json new file mode 100644 index 0000000..e6a6314 --- /dev/null +++ b/ml_data/reports/tuning_20260430_015218.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-30T01:52:18.475529", + "training_rows": 1083, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7891, + "mae": 3.009, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.79, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.11, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1083 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.0, + "quality_delta_10": 25.6, + "num_orders": 14.1, + "hour": 11.45, + "day_of_week": 8.35, + "num_riders": 5.25, + "max_pickup_distance_km": 3.24, + "max_orders_per_rider": 1.44, + "max_kitchen_distance_km": 0.95, + "workload_balance_threshold": 0.79, + "is_peak": 0.65, + "ideal_load": 0.64, + "road_factor": 0.23, + "workload_penalty_weight": 0.14, + "search_time_limit_seconds": 0.08, + "distance_penalty_weight": 0.05, + "cluster_radius_km": 0.05 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260430_060219.json b/ml_data/reports/tuning_20260430_060219.json new file mode 100644 index 0000000..912cd78 --- /dev/null +++ b/ml_data/reports/tuning_20260430_060219.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-30T06:02:19.341514", + "training_rows": 1091, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7834, + "mae": 3.028, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.78, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.13, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1091 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.29, + "quality_delta_10": 25.69, + "num_orders": 12.48, + "hour": 12.32, + "day_of_week": 8.73, + "num_riders": 5.65, + "max_pickup_distance_km": 2.23, + "max_orders_per_rider": 0.95, + "max_kitchen_distance_km": 0.83, + "workload_balance_threshold": 0.52, + "is_peak": 0.51, + "ideal_load": 0.41, + "road_factor": 0.14, + "workload_penalty_weight": 0.13, + "distance_penalty_weight": 0.05, + "search_time_limit_seconds": 0.05, + "cluster_radius_km": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260430_061313.json b/ml_data/reports/tuning_20260430_061313.json new file mode 100644 index 0000000..6cdc66b --- /dev/null +++ b/ml_data/reports/tuning_20260430_061313.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-30T06:13:13.301725", + "training_rows": 1101, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7744, + "mae": 3.076, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.1, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1101 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.27, + "quality_delta_10": 25.67, + "num_orders": 12.48, + "hour": 12.33, + "day_of_week": 8.77, + "num_riders": 5.63, + "max_pickup_distance_km": 2.23, + "max_orders_per_rider": 0.96, + "max_kitchen_distance_km": 0.83, + "is_peak": 0.51, + "workload_balance_threshold": 0.51, + "ideal_load": 0.41, + "workload_penalty_weight": 0.13, + "road_factor": 0.13, + "distance_penalty_weight": 0.05, + "search_time_limit_seconds": 0.05, + "cluster_radius_km": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260430_113753.json b/ml_data/reports/tuning_20260430_113753.json new file mode 100644 index 0000000..8dda371 --- /dev/null +++ b/ml_data/reports/tuning_20260430_113753.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-04-30T11:37:53.363691", + "training_rows": 1112, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7778, + "mae": 3.032, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.78, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.1, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1112 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.32, + "quality_delta_10": 25.65, + "num_orders": 12.47, + "hour": 12.31, + "day_of_week": 8.8, + "num_riders": 5.57, + "max_pickup_distance_km": 2.26, + "max_orders_per_rider": 0.96, + "max_kitchen_distance_km": 0.83, + "is_peak": 0.51, + "workload_balance_threshold": 0.5, + "ideal_load": 0.42, + "workload_penalty_weight": 0.13, + "road_factor": 0.13, + "distance_penalty_weight": 0.05, + "search_time_limit_seconds": 0.05, + "cluster_radius_km": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260501_015255.json b/ml_data/reports/tuning_20260501_015255.json new file mode 100644 index 0000000..72a33ab --- /dev/null +++ b/ml_data/reports/tuning_20260501_015255.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-01T01:52:55.537588", + "training_rows": 1123, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.789, + "mae": 3.035, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.79, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.09, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1123 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.33, + "quality_delta_10": 25.71, + "num_orders": 12.46, + "hour": 12.25, + "day_of_week": 8.81, + "num_riders": 5.55, + "max_pickup_distance_km": 2.27, + "max_orders_per_rider": 0.97, + "max_kitchen_distance_km": 0.83, + "is_peak": 0.5, + "workload_balance_threshold": 0.5, + "ideal_load": 0.42, + "road_factor": 0.13, + "workload_penalty_weight": 0.12, + "distance_penalty_weight": 0.05, + "cluster_radius_km": 0.04, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260501_020643.json b/ml_data/reports/tuning_20260501_020643.json new file mode 100644 index 0000000..6d0d787 --- /dev/null +++ b/ml_data/reports/tuning_20260501_020643.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-01T02:06:43.007914", + "training_rows": 1134, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7851, + "mae": 3.008, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.79, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.09, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1134 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.25, + "quality_delta_10": 25.75, + "num_orders": 12.47, + "hour": 12.26, + "day_of_week": 8.84, + "num_riders": 5.53, + "max_pickup_distance_km": 2.27, + "max_orders_per_rider": 0.99, + "max_kitchen_distance_km": 0.84, + "is_peak": 0.5, + "workload_balance_threshold": 0.5, + "ideal_load": 0.42, + "workload_penalty_weight": 0.13, + "road_factor": 0.13, + "distance_penalty_weight": 0.05, + "cluster_radius_km": 0.04, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260501_061241.json b/ml_data/reports/tuning_20260501_061241.json new file mode 100644 index 0000000..51c40a8 --- /dev/null +++ b/ml_data/reports/tuning_20260501_061241.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-01T06:12:41.593758", + "training_rows": 1144, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7663, + "mae": 3.084, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.09, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1144 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.14, + "quality_delta_10": 25.79, + "num_orders": 12.47, + "hour": 12.25, + "day_of_week": 8.9, + "num_riders": 5.55, + "max_pickup_distance_km": 2.26, + "max_orders_per_rider": 0.99, + "max_kitchen_distance_km": 0.85, + "is_peak": 0.5, + "workload_balance_threshold": 0.49, + "ideal_load": 0.42, + "workload_penalty_weight": 0.13, + "road_factor": 0.13, + "distance_penalty_weight": 0.05, + "cluster_radius_km": 0.04, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260501_123243.json b/ml_data/reports/tuning_20260501_123243.json new file mode 100644 index 0000000..fe2c8c9 --- /dev/null +++ b/ml_data/reports/tuning_20260501_123243.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-01T12:32:43.196529", + "training_rows": 1159, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7506, + "mae": 3.082, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.11, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1159 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.1, + "quality_delta_10": 25.83, + "num_orders": 12.45, + "hour": 12.21, + "day_of_week": 8.94, + "num_riders": 5.56, + "max_pickup_distance_km": 2.27, + "max_orders_per_rider": 1.0, + "max_kitchen_distance_km": 0.85, + "is_peak": 0.5, + "workload_balance_threshold": 0.49, + "ideal_load": 0.43, + "workload_penalty_weight": 0.13, + "road_factor": 0.13, + "distance_penalty_weight": 0.05, + "search_time_limit_seconds": 0.04, + "cluster_radius_km": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260501_125338.json b/ml_data/reports/tuning_20260501_125338.json new file mode 100644 index 0000000..fab8f6d --- /dev/null +++ b/ml_data/reports/tuning_20260501_125338.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-01T12:53:38.306603", + "training_rows": 1169, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7561, + "mae": 3.047, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.11, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1169 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.11, + "quality_delta_10": 25.86, + "num_orders": 12.4, + "hour": 12.21, + "day_of_week": 8.95, + "num_riders": 5.55, + "max_pickup_distance_km": 2.25, + "max_orders_per_rider": 1.0, + "max_kitchen_distance_km": 0.85, + "is_peak": 0.51, + "workload_balance_threshold": 0.49, + "ideal_load": 0.43, + "road_factor": 0.13, + "workload_penalty_weight": 0.12, + "distance_penalty_weight": 0.05, + "search_time_limit_seconds": 0.04, + "cluster_radius_km": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260502_014659.json b/ml_data/reports/tuning_20260502_014659.json new file mode 100644 index 0000000..c147d97 --- /dev/null +++ b/ml_data/reports/tuning_20260502_014659.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-02T01:46:59.299419", + "training_rows": 1179, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.756, + "mae": 3.089, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.14, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1179 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.12, + "quality_delta_10": 25.86, + "num_orders": 12.38, + "hour": 12.2, + "day_of_week": 8.98, + "num_riders": 5.53, + "max_pickup_distance_km": 2.25, + "max_orders_per_rider": 1.0, + "max_kitchen_distance_km": 0.86, + "is_peak": 0.53, + "workload_balance_threshold": 0.48, + "ideal_load": 0.44, + "road_factor": 0.13, + "workload_penalty_weight": 0.12, + "distance_penalty_weight": 0.04, + "search_time_limit_seconds": 0.04, + "cluster_radius_km": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260502_020521.json b/ml_data/reports/tuning_20260502_020521.json new file mode 100644 index 0000000..b3f6890 --- /dev/null +++ b/ml_data/reports/tuning_20260502_020521.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-02T02:05:21.234708", + "training_rows": 1190, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7723, + "mae": 2.988, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.14, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1190 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.12, + "quality_delta_10": 25.88, + "num_orders": 12.34, + "hour": 12.24, + "day_of_week": 8.99, + "num_riders": 5.49, + "max_pickup_distance_km": 2.25, + "max_orders_per_rider": 1.0, + "max_kitchen_distance_km": 0.86, + "is_peak": 0.53, + "workload_balance_threshold": 0.48, + "ideal_load": 0.44, + "road_factor": 0.14, + "workload_penalty_weight": 0.12, + "distance_penalty_weight": 0.04, + "search_time_limit_seconds": 0.04, + "cluster_radius_km": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260502_061353.json b/ml_data/reports/tuning_20260502_061353.json new file mode 100644 index 0000000..0481d29 --- /dev/null +++ b/ml_data/reports/tuning_20260502_061353.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-02T06:13:53.336809", + "training_rows": 1200, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7635, + "mae": 3.044, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.1, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1200 + }, + "feature_importance": { + "rolling_avg_quality_5": 29.16, + "quality_delta_10": 25.87, + "num_orders": 12.38, + "hour": 12.2, + "day_of_week": 8.95, + "num_riders": 5.44, + "max_pickup_distance_km": 2.3, + "max_orders_per_rider": 1.0, + "max_kitchen_distance_km": 0.88, + "is_peak": 0.52, + "workload_balance_threshold": 0.47, + "ideal_load": 0.44, + "road_factor": 0.14, + "workload_penalty_weight": 0.12, + "distance_penalty_weight": 0.04, + "search_time_limit_seconds": 0.04, + "cluster_radius_km": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260502_061427.json b/ml_data/reports/tuning_20260502_061427.json new file mode 100644 index 0000000..232407a --- /dev/null +++ b/ml_data/reports/tuning_20260502_061427.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-02T06:14:27.155675", + "training_rows": 1201, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7656, + "mae": 3.063, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.1, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1201 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.27, + "quality_delta_10": 23.38, + "num_orders": 15.55, + "hour": 11.56, + "day_of_week": 8.05, + "num_riders": 6.12, + "max_pickup_distance_km": 4.05, + "max_kitchen_distance_km": 1.2, + "max_orders_per_rider": 1.03, + "is_peak": 0.9, + "workload_balance_threshold": 0.72, + "ideal_load": 0.57, + "workload_penalty_weight": 0.19, + "road_factor": 0.17, + "distance_penalty_weight": 0.11, + "cluster_radius_km": 0.09, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260502_111142.json b/ml_data/reports/tuning_20260502_111142.json new file mode 100644 index 0000000..43d984a --- /dev/null +++ b/ml_data/reports/tuning_20260502_111142.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-02T11:11:42.758456", + "training_rows": 1213, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7225, + "mae": 3.118, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.72, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.09, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1213 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.24, + "quality_delta_10": 23.79, + "num_orders": 15.44, + "hour": 11.83, + "day_of_week": 8.11, + "num_riders": 6.02, + "max_pickup_distance_km": 3.77, + "max_kitchen_distance_km": 1.16, + "max_orders_per_rider": 1.0, + "is_peak": 0.87, + "workload_balance_threshold": 0.67, + "ideal_load": 0.51, + "road_factor": 0.19, + "workload_penalty_weight": 0.17, + "distance_penalty_weight": 0.11, + "cluster_radius_km": 0.08, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260504_060157.json b/ml_data/reports/tuning_20260504_060157.json new file mode 100644 index 0000000..5b28a07 --- /dev/null +++ b/ml_data/reports/tuning_20260504_060157.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-04T06:01:57.331243", + "training_rows": 1224, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7435, + "mae": 3.062, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.09, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1224 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.02, + "quality_delta_10": 24.13, + "num_orders": 15.41, + "hour": 11.04, + "day_of_week": 8.42, + "num_riders": 5.99, + "max_pickup_distance_km": 4.21, + "max_orders_per_rider": 1.28, + "is_peak": 0.93, + "max_kitchen_distance_km": 0.78, + "workload_balance_threshold": 0.65, + "ideal_load": 0.52, + "road_factor": 0.22, + "cluster_radius_km": 0.16, + "workload_penalty_weight": 0.14, + "search_time_limit_seconds": 0.09, + "distance_penalty_weight": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260504_061944.json b/ml_data/reports/tuning_20260504_061944.json new file mode 100644 index 0000000..6b12542 --- /dev/null +++ b/ml_data/reports/tuning_20260504_061944.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-04T06:19:44.874126", + "training_rows": 1235, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7297, + "mae": 3.132, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.73, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.08, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1235 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.29, + "quality_delta_10": 24.51, + "num_orders": 14.86, + "hour": 11.45, + "day_of_week": 8.44, + "num_riders": 5.88, + "max_pickup_distance_km": 3.93, + "max_orders_per_rider": 1.18, + "is_peak": 0.92, + "max_kitchen_distance_km": 0.84, + "workload_balance_threshold": 0.6, + "ideal_load": 0.48, + "road_factor": 0.22, + "cluster_radius_km": 0.14, + "workload_penalty_weight": 0.12, + "search_time_limit_seconds": 0.1, + "distance_penalty_weight": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260504_064121.json b/ml_data/reports/tuning_20260504_064121.json new file mode 100644 index 0000000..9f9223b --- /dev/null +++ b/ml_data/reports/tuning_20260504_064121.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-04T06:41:21.426170", + "training_rows": 1248, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7469, + "mae": 3.048, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.75, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.1, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1248 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.52, + "quality_delta_10": 24.75, + "num_orders": 14.53, + "hour": 11.83, + "day_of_week": 8.44, + "num_riders": 5.75, + "max_pickup_distance_km": 3.63, + "max_orders_per_rider": 1.09, + "max_kitchen_distance_km": 0.88, + "is_peak": 0.87, + "workload_balance_threshold": 0.55, + "ideal_load": 0.52, + "road_factor": 0.25, + "workload_penalty_weight": 0.14, + "cluster_radius_km": 0.12, + "search_time_limit_seconds": 0.09, + "distance_penalty_weight": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260504_102846.json b/ml_data/reports/tuning_20260504_102846.json new file mode 100644 index 0000000..a60084a --- /dev/null +++ b/ml_data/reports/tuning_20260504_102846.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-04T10:28:46.901141", + "training_rows": 1258, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.755, + "mae": 3.031, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.1, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1258 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.73, + "quality_delta_10": 24.81, + "num_orders": 14.18, + "hour": 11.97, + "day_of_week": 8.59, + "num_riders": 5.79, + "max_pickup_distance_km": 3.49, + "max_orders_per_rider": 1.02, + "max_kitchen_distance_km": 0.9, + "is_peak": 0.85, + "workload_balance_threshold": 0.52, + "ideal_load": 0.49, + "road_factor": 0.27, + "workload_penalty_weight": 0.13, + "cluster_radius_km": 0.1, + "distance_penalty_weight": 0.08, + "search_time_limit_seconds": 0.08 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260504_123148.json b/ml_data/reports/tuning_20260504_123148.json new file mode 100644 index 0000000..ed7c4eb --- /dev/null +++ b/ml_data/reports/tuning_20260504_123148.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-04T12:31:48.246335", + "training_rows": 1269, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7709, + "mae": 2.973, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.77, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.09, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1269 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.9, + "quality_delta_10": 25.0, + "num_orders": 14.04, + "hour": 12.01, + "day_of_week": 8.64, + "num_riders": 5.73, + "max_pickup_distance_km": 3.32, + "max_orders_per_rider": 1.0, + "max_kitchen_distance_km": 0.91, + "is_peak": 0.8, + "workload_balance_threshold": 0.52, + "ideal_load": 0.47, + "road_factor": 0.29, + "workload_penalty_weight": 0.13, + "cluster_radius_km": 0.1, + "distance_penalty_weight": 0.08, + "search_time_limit_seconds": 0.07 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260505_015149.json b/ml_data/reports/tuning_20260505_015149.json new file mode 100644 index 0000000..a2ecdec --- /dev/null +++ b/ml_data/reports/tuning_20260505_015149.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-05T01:51:49.009722", + "training_rows": 1280, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7633, + "mae": 3.026, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.09, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1280 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.04, + "quality_delta_10": 25.21, + "num_orders": 13.81, + "hour": 11.97, + "day_of_week": 8.7, + "num_riders": 5.83, + "max_pickup_distance_km": 3.18, + "max_orders_per_rider": 0.98, + "max_kitchen_distance_km": 0.9, + "is_peak": 0.8, + "workload_balance_threshold": 0.5, + "ideal_load": 0.44, + "road_factor": 0.28, + "workload_penalty_weight": 0.13, + "cluster_radius_km": 0.09, + "distance_penalty_weight": 0.07, + "search_time_limit_seconds": 0.06 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260505_020746.json b/ml_data/reports/tuning_20260505_020746.json new file mode 100644 index 0000000..397cd10 --- /dev/null +++ b/ml_data/reports/tuning_20260505_020746.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-05T02:07:46.994809", + "training_rows": 1290, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7581, + "mae": 3.042, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.1, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1290 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.28, + "quality_delta_10": 25.36, + "num_orders": 13.69, + "hour": 11.97, + "day_of_week": 8.62, + "num_riders": 5.74, + "max_pickup_distance_km": 3.12, + "max_orders_per_rider": 0.96, + "max_kitchen_distance_km": 0.92, + "is_peak": 0.77, + "workload_balance_threshold": 0.49, + "ideal_load": 0.44, + "road_factor": 0.27, + "workload_penalty_weight": 0.12, + "distance_penalty_weight": 0.09, + "cluster_radius_km": 0.08, + "search_time_limit_seconds": 0.07 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260505_020833.json b/ml_data/reports/tuning_20260505_020833.json new file mode 100644 index 0000000..0f91397 --- /dev/null +++ b/ml_data/reports/tuning_20260505_020833.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-05T02:08:33.173682", + "training_rows": 1292, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.744, + "mae": 3.061, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.09, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1292 + }, + "feature_importance": { + "rolling_avg_quality_5": 25.12, + "quality_delta_10": 24.39, + "num_orders": 15.28, + "hour": 11.88, + "day_of_week": 8.0, + "num_riders": 6.14, + "max_pickup_distance_km": 4.37, + "max_orders_per_rider": 1.15, + "max_kitchen_distance_km": 1.1, + "is_peak": 0.87, + "workload_balance_threshold": 0.78, + "ideal_load": 0.46, + "workload_penalty_weight": 0.14, + "road_factor": 0.13, + "distance_penalty_weight": 0.09, + "cluster_radius_km": 0.07, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260505_060524.json b/ml_data/reports/tuning_20260505_060524.json new file mode 100644 index 0000000..90c1209 --- /dev/null +++ b/ml_data/reports/tuning_20260505_060524.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-05T06:05:24.775838", + "training_rows": 1303, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7492, + "mae": 3.099, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.75, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.08, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1303 + }, + "feature_importance": { + "rolling_avg_quality_5": 25.4, + "quality_delta_10": 24.95, + "num_orders": 14.92, + "hour": 12.08, + "day_of_week": 7.95, + "num_riders": 6.1, + "max_pickup_distance_km": 4.02, + "max_orders_per_rider": 1.04, + "max_kitchen_distance_km": 1.02, + "is_peak": 0.85, + "workload_balance_threshold": 0.73, + "ideal_load": 0.45, + "road_factor": 0.17, + "workload_penalty_weight": 0.15, + "distance_penalty_weight": 0.07, + "cluster_radius_km": 0.06, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260505_061844.json b/ml_data/reports/tuning_20260505_061844.json new file mode 100644 index 0000000..005bf3b --- /dev/null +++ b/ml_data/reports/tuning_20260505_061844.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-05T06:18:44.204737", + "training_rows": 1316, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.74, + "mae": 3.032, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.08, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1316 + }, + "feature_importance": { + "rolling_avg_quality_5": 25.61, + "quality_delta_10": 25.41, + "num_orders": 14.62, + "hour": 12.28, + "day_of_week": 7.92, + "num_riders": 6.02, + "max_pickup_distance_km": 3.71, + "max_kitchen_distance_km": 1.01, + "max_orders_per_rider": 1.0, + "is_peak": 0.81, + "workload_balance_threshold": 0.66, + "ideal_load": 0.45, + "road_factor": 0.17, + "workload_penalty_weight": 0.14, + "distance_penalty_weight": 0.11, + "cluster_radius_km": 0.05, + "search_time_limit_seconds": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260505_121730.json b/ml_data/reports/tuning_20260505_121730.json new file mode 100644 index 0000000..aab3486 --- /dev/null +++ b/ml_data/reports/tuning_20260505_121730.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-05T12:17:30.284064", + "training_rows": 1327, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7431, + "mae": 3.052, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.09, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1327 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.04, + "quality_delta_10": 25.71, + "num_orders": 14.38, + "hour": 12.31, + "day_of_week": 7.93, + "num_riders": 5.89, + "max_pickup_distance_km": 3.49, + "max_kitchen_distance_km": 0.99, + "max_orders_per_rider": 0.96, + "is_peak": 0.79, + "workload_balance_threshold": 0.61, + "ideal_load": 0.41, + "road_factor": 0.16, + "workload_penalty_weight": 0.13, + "distance_penalty_weight": 0.11, + "cluster_radius_km": 0.07, + "search_time_limit_seconds": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260505_122823.json b/ml_data/reports/tuning_20260505_122823.json new file mode 100644 index 0000000..57af45a --- /dev/null +++ b/ml_data/reports/tuning_20260505_122823.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-05T12:28:23.201432", + "training_rows": 1338, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7361, + "mae": 3.067, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.11, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1338 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.42, + "quality_delta_10": 25.55, + "num_orders": 13.54, + "hour": 11.99, + "day_of_week": 8.66, + "num_riders": 5.63, + "max_pickup_distance_km": 3.07, + "max_orders_per_rider": 0.98, + "max_kitchen_distance_km": 0.89, + "is_peak": 0.76, + "workload_balance_threshold": 0.47, + "ideal_load": 0.44, + "road_factor": 0.26, + "workload_penalty_weight": 0.11, + "distance_penalty_weight": 0.09, + "cluster_radius_km": 0.07, + "search_time_limit_seconds": 0.07 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260505_124700.json b/ml_data/reports/tuning_20260505_124700.json new file mode 100644 index 0000000..2f27b18 --- /dev/null +++ b/ml_data/reports/tuning_20260505_124700.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-05T12:47:00.952263", + "training_rows": 1341, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7403, + "mae": 3.069, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.11, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1341 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.25, + "quality_delta_10": 25.82, + "num_orders": 14.13, + "hour": 12.44, + "day_of_week": 8.02, + "num_riders": 5.88, + "max_pickup_distance_km": 3.37, + "max_kitchen_distance_km": 0.99, + "max_orders_per_rider": 0.9, + "is_peak": 0.78, + "workload_balance_threshold": 0.56, + "ideal_load": 0.4, + "road_factor": 0.15, + "workload_penalty_weight": 0.13, + "distance_penalty_weight": 0.11, + "cluster_radius_km": 0.06, + "search_time_limit_seconds": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260506_020049.json b/ml_data/reports/tuning_20260506_020049.json new file mode 100644 index 0000000..1e513e8 --- /dev/null +++ b/ml_data/reports/tuning_20260506_020049.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-06T02:00:49.045438", + "training_rows": 1352, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7282, + "mae": 3.055, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.73, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.12, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1352 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.48, + "quality_delta_10": 26.03, + "num_orders": 13.88, + "hour": 12.36, + "day_of_week": 8.07, + "num_riders": 5.85, + "max_pickup_distance_km": 3.26, + "max_kitchen_distance_km": 0.99, + "max_orders_per_rider": 0.87, + "is_peak": 0.79, + "workload_balance_threshold": 0.54, + "ideal_load": 0.4, + "road_factor": 0.15, + "workload_penalty_weight": 0.12, + "distance_penalty_weight": 0.12, + "cluster_radius_km": 0.05, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260506_061027.json b/ml_data/reports/tuning_20260506_061027.json new file mode 100644 index 0000000..621f09d --- /dev/null +++ b/ml_data/reports/tuning_20260506_061027.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-06T06:10:27.612765", + "training_rows": 1362, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7369, + "mae": 3.06, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.12, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1362 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.8, + "quality_delta_10": 26.2, + "num_orders": 13.54, + "hour": 12.27, + "day_of_week": 8.17, + "num_riders": 5.86, + "max_pickup_distance_km": 3.19, + "max_kitchen_distance_km": 0.94, + "max_orders_per_rider": 0.84, + "is_peak": 0.77, + "workload_balance_threshold": 0.52, + "ideal_load": 0.39, + "road_factor": 0.15, + "distance_penalty_weight": 0.14, + "workload_penalty_weight": 0.12, + "cluster_radius_km": 0.05, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260506_065000.json b/ml_data/reports/tuning_20260506_065000.json new file mode 100644 index 0000000..aa84363 --- /dev/null +++ b/ml_data/reports/tuning_20260506_065000.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-06T06:50:00.881509", + "training_rows": 1376, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7532, + "mae": 3.056, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.12, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1376 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.81, + "quality_delta_10": 26.2, + "num_orders": 13.57, + "hour": 12.36, + "day_of_week": 8.26, + "num_riders": 5.75, + "max_pickup_distance_km": 3.12, + "max_kitchen_distance_km": 0.95, + "max_orders_per_rider": 0.81, + "is_peak": 0.74, + "workload_balance_threshold": 0.51, + "ideal_load": 0.38, + "distance_penalty_weight": 0.18, + "road_factor": 0.15, + "workload_penalty_weight": 0.12, + "cluster_radius_km": 0.04, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260506_121452.json b/ml_data/reports/tuning_20260506_121452.json new file mode 100644 index 0000000..bfbe9d2 --- /dev/null +++ b/ml_data/reports/tuning_20260506_121452.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-06T12:14:52.347036", + "training_rows": 1388, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7282, + "mae": 3.088, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.73, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.13, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1388 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.01, + "quality_delta_10": 26.09, + "num_orders": 13.58, + "hour": 12.35, + "day_of_week": 8.34, + "num_riders": 5.66, + "max_pickup_distance_km": 3.06, + "max_kitchen_distance_km": 0.94, + "max_orders_per_rider": 0.8, + "is_peak": 0.73, + "workload_balance_threshold": 0.5, + "ideal_load": 0.4, + "distance_penalty_weight": 0.19, + "road_factor": 0.15, + "workload_penalty_weight": 0.12, + "cluster_radius_km": 0.04, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260506_123440.json b/ml_data/reports/tuning_20260506_123440.json new file mode 100644 index 0000000..759389c --- /dev/null +++ b/ml_data/reports/tuning_20260506_123440.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-06T12:34:40.265128", + "training_rows": 1398, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7318, + "mae": 3.075, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.73, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.15, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1398 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.16, + "quality_delta_10": 26.14, + "num_orders": 13.57, + "hour": 12.36, + "day_of_week": 8.36, + "num_riders": 5.65, + "max_pickup_distance_km": 2.98, + "max_kitchen_distance_km": 0.91, + "max_orders_per_rider": 0.77, + "is_peak": 0.72, + "workload_balance_threshold": 0.47, + "ideal_load": 0.4, + "distance_penalty_weight": 0.18, + "road_factor": 0.15, + "workload_penalty_weight": 0.12, + "cluster_radius_km": 0.04, + "search_time_limit_seconds": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260506_123656.json b/ml_data/reports/tuning_20260506_123656.json new file mode 100644 index 0000000..a693af2 --- /dev/null +++ b/ml_data/reports/tuning_20260506_123656.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-06T12:36:56.512438", + "training_rows": 1402, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7416, + "mae": 3.042, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.15, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1402 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.63, + "quality_delta_10": 25.59, + "num_orders": 13.42, + "hour": 12.09, + "day_of_week": 8.57, + "num_riders": 5.6, + "max_pickup_distance_km": 2.98, + "max_orders_per_rider": 0.96, + "max_kitchen_distance_km": 0.86, + "is_peak": 0.78, + "ideal_load": 0.46, + "workload_balance_threshold": 0.46, + "road_factor": 0.24, + "workload_penalty_weight": 0.13, + "distance_penalty_weight": 0.1, + "cluster_radius_km": 0.07, + "search_time_limit_seconds": 0.07 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260507_015342.json b/ml_data/reports/tuning_20260507_015342.json new file mode 100644 index 0000000..4597b7c --- /dev/null +++ b/ml_data/reports/tuning_20260507_015342.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-07T01:53:42.465122", + "training_rows": 1411, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7381, + "mae": 3.047, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.16, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1411 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.12, + "quality_delta_10": 26.24, + "num_orders": 13.51, + "hour": 12.4, + "day_of_week": 8.47, + "num_riders": 5.55, + "max_pickup_distance_km": 2.94, + "max_kitchen_distance_km": 0.89, + "max_orders_per_rider": 0.76, + "is_peak": 0.7, + "workload_balance_threshold": 0.49, + "ideal_load": 0.39, + "distance_penalty_weight": 0.17, + "road_factor": 0.16, + "workload_penalty_weight": 0.12, + "cluster_radius_km": 0.05, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260507_020412.json b/ml_data/reports/tuning_20260507_020412.json new file mode 100644 index 0000000..53133a9 --- /dev/null +++ b/ml_data/reports/tuning_20260507_020412.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-07T02:04:12.841958", + "training_rows": 1422, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7281, + "mae": 3.082, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.73, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.18, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1422 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.37, + "quality_delta_10": 26.22, + "num_orders": 13.43, + "hour": 12.39, + "day_of_week": 8.47, + "num_riders": 5.51, + "max_pickup_distance_km": 2.91, + "max_kitchen_distance_km": 0.88, + "max_orders_per_rider": 0.76, + "is_peak": 0.7, + "workload_balance_threshold": 0.47, + "ideal_load": 0.37, + "distance_penalty_weight": 0.17, + "road_factor": 0.15, + "workload_penalty_weight": 0.11, + "cluster_radius_km": 0.04, + "search_time_limit_seconds": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260507_062336.json b/ml_data/reports/tuning_20260507_062336.json new file mode 100644 index 0000000..4501a1f --- /dev/null +++ b/ml_data/reports/tuning_20260507_062336.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-07T06:23:36.936575", + "training_rows": 1435, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7643, + "mae": 2.972, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.2, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1435 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.48, + "quality_delta_10": 26.17, + "num_orders": 13.38, + "hour": 12.46, + "day_of_week": 8.55, + "num_riders": 5.54, + "max_pickup_distance_km": 2.8, + "max_kitchen_distance_km": 0.88, + "max_orders_per_rider": 0.75, + "is_peak": 0.67, + "workload_balance_threshold": 0.44, + "ideal_load": 0.39, + "distance_penalty_weight": 0.16, + "road_factor": 0.14, + "workload_penalty_weight": 0.12, + "cluster_radius_km": 0.04, + "search_time_limit_seconds": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260507_101442.json b/ml_data/reports/tuning_20260507_101442.json new file mode 100644 index 0000000..30fb7dc --- /dev/null +++ b/ml_data/reports/tuning_20260507_101442.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-07T10:14:42.139443", + "training_rows": 1446, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7513, + "mae": 3.024, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.19, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1446 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.6, + "quality_delta_10": 26.19, + "num_orders": 13.3, + "hour": 12.46, + "day_of_week": 8.61, + "num_riders": 5.52, + "max_pickup_distance_km": 2.74, + "max_kitchen_distance_km": 0.86, + "max_orders_per_rider": 0.76, + "is_peak": 0.67, + "workload_balance_threshold": 0.41, + "ideal_load": 0.39, + "distance_penalty_weight": 0.16, + "road_factor": 0.14, + "workload_penalty_weight": 0.12, + "cluster_radius_km": 0.04, + "search_time_limit_seconds": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260507_130833.json b/ml_data/reports/tuning_20260507_130833.json new file mode 100644 index 0000000..45ee8ff --- /dev/null +++ b/ml_data/reports/tuning_20260507_130833.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-07T13:08:33.024309", + "training_rows": 1460, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.761, + "mae": 2.998, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.23, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1460 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.69, + "quality_delta_10": 25.35, + "num_orders": 13.58, + "hour": 12.19, + "day_of_week": 8.55, + "num_riders": 5.59, + "max_pickup_distance_km": 2.93, + "max_orders_per_rider": 0.93, + "max_kitchen_distance_km": 0.92, + "is_peak": 0.78, + "ideal_load": 0.47, + "workload_balance_threshold": 0.44, + "road_factor": 0.23, + "workload_penalty_weight": 0.13, + "distance_penalty_weight": 0.09, + "cluster_radius_km": 0.07, + "search_time_limit_seconds": 0.06 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260507_130854.json b/ml_data/reports/tuning_20260507_130854.json new file mode 100644 index 0000000..7db3afa --- /dev/null +++ b/ml_data/reports/tuning_20260507_130854.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-07T13:08:54.110132", + "training_rows": 1461, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7639, + "mae": 2.992, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.23, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1461 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.58, + "quality_delta_10": 26.09, + "num_orders": 13.34, + "hour": 12.48, + "day_of_week": 8.63, + "num_riders": 5.5, + "max_pickup_distance_km": 2.72, + "max_kitchen_distance_km": 0.92, + "max_orders_per_rider": 0.76, + "is_peak": 0.67, + "workload_balance_threshold": 0.41, + "ideal_load": 0.4, + "distance_penalty_weight": 0.15, + "road_factor": 0.14, + "workload_penalty_weight": 0.13, + "cluster_radius_km": 0.04, + "search_time_limit_seconds": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260508_020112.json b/ml_data/reports/tuning_20260508_020112.json new file mode 100644 index 0000000..3d7826f --- /dev/null +++ b/ml_data/reports/tuning_20260508_020112.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-08T02:01:12.019513", + "training_rows": 1472, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7619, + "mae": 2.96, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.25, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1472 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.6, + "quality_delta_10": 26.23, + "num_orders": 13.24, + "hour": 12.51, + "day_of_week": 8.6, + "num_riders": 5.52, + "max_pickup_distance_km": 2.64, + "max_kitchen_distance_km": 0.96, + "max_orders_per_rider": 0.75, + "is_peak": 0.66, + "ideal_load": 0.4, + "workload_balance_threshold": 0.4, + "distance_penalty_weight": 0.16, + "road_factor": 0.13, + "workload_penalty_weight": 0.12, + "cluster_radius_km": 0.04, + "search_time_limit_seconds": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260508_021012.json b/ml_data/reports/tuning_20260508_021012.json new file mode 100644 index 0000000..9d146a8 --- /dev/null +++ b/ml_data/reports/tuning_20260508_021012.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-08T02:10:12.541822", + "training_rows": 1482, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7639, + "mae": 2.973, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.26, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1482 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.66, + "quality_delta_10": 26.21, + "num_orders": 13.19, + "hour": 12.51, + "day_of_week": 8.57, + "num_riders": 5.57, + "max_pickup_distance_km": 2.65, + "max_kitchen_distance_km": 0.96, + "max_orders_per_rider": 0.76, + "is_peak": 0.65, + "ideal_load": 0.41, + "workload_balance_threshold": 0.39, + "distance_penalty_weight": 0.16, + "road_factor": 0.13, + "workload_penalty_weight": 0.11, + "cluster_radius_km": 0.04, + "search_time_limit_seconds": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260508_104641.json b/ml_data/reports/tuning_20260508_104641.json new file mode 100644 index 0000000..4174434 --- /dev/null +++ b/ml_data/reports/tuning_20260508_104641.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-08T10:46:41.377123", + "training_rows": 1495, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7536, + "mae": 3.006, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.28, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1495 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.54, + "quality_delta_10": 26.2, + "num_orders": 13.17, + "hour": 12.63, + "day_of_week": 8.66, + "num_riders": 5.55, + "max_pickup_distance_km": 2.6, + "max_kitchen_distance_km": 0.94, + "max_orders_per_rider": 0.76, + "is_peak": 0.67, + "ideal_load": 0.41, + "workload_balance_threshold": 0.38, + "distance_penalty_weight": 0.16, + "road_factor": 0.13, + "workload_penalty_weight": 0.12, + "cluster_radius_km": 0.04, + "search_time_limit_seconds": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260508_122824.json b/ml_data/reports/tuning_20260508_122824.json new file mode 100644 index 0000000..e564254 --- /dev/null +++ b/ml_data/reports/tuning_20260508_122824.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-08T12:28:24.803121", + "training_rows": 1507, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7489, + "mae": 3.025, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.75, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.38, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1507 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.47, + "quality_delta_10": 26.31, + "num_orders": 13.08, + "hour": 12.7, + "day_of_week": 8.71, + "num_riders": 5.53, + "max_pickup_distance_km": 2.56, + "max_kitchen_distance_km": 0.94, + "max_orders_per_rider": 0.75, + "is_peak": 0.68, + "ideal_load": 0.4, + "workload_balance_threshold": 0.4, + "distance_penalty_weight": 0.16, + "road_factor": 0.13, + "workload_penalty_weight": 0.12, + "cluster_radius_km": 0.04, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260508_124741.json b/ml_data/reports/tuning_20260508_124741.json new file mode 100644 index 0000000..42f5f1f --- /dev/null +++ b/ml_data/reports/tuning_20260508_124741.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-08T12:47:41.030958", + "training_rows": 1517, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7519, + "mae": 3.002, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.38, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1517 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.46, + "quality_delta_10": 26.3, + "num_orders": 13.03, + "hour": 12.76, + "day_of_week": 8.81, + "num_riders": 5.53, + "max_pickup_distance_km": 2.5, + "max_kitchen_distance_km": 0.94, + "max_orders_per_rider": 0.73, + "is_peak": 0.69, + "ideal_load": 0.4, + "workload_balance_threshold": 0.38, + "distance_penalty_weight": 0.15, + "road_factor": 0.14, + "workload_penalty_weight": 0.11, + "cluster_radius_km": 0.04, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260508_124912.json b/ml_data/reports/tuning_20260508_124912.json new file mode 100644 index 0000000..5873e63 --- /dev/null +++ b/ml_data/reports/tuning_20260508_124912.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-08T12:49:12.104726", + "training_rows": 1521, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7502, + "mae": 3.044, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.38, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1521 + }, + "feature_importance": { + "rolling_avg_quality_5": 24.8, + "quality_delta_10": 24.31, + "num_orders": 15.12, + "hour": 12.72, + "day_of_week": 7.67, + "num_riders": 6.33, + "max_pickup_distance_km": 3.99, + "max_orders_per_rider": 1.3, + "max_kitchen_distance_km": 1.0, + "workload_balance_threshold": 0.8, + "is_peak": 0.71, + "ideal_load": 0.5, + "road_factor": 0.24, + "distance_penalty_weight": 0.17, + "workload_penalty_weight": 0.14, + "cluster_radius_km": 0.1, + "search_time_limit_seconds": 0.09 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260508_170607.json b/ml_data/reports/tuning_20260508_170607.json new file mode 100644 index 0000000..ea9cae9 --- /dev/null +++ b/ml_data/reports/tuning_20260508_170607.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-08T17:06:07.157296", + "training_rows": 1523, + "n_trials": 150, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7529, + "mae": 3.043, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.37, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1523 + }, + "feature_importance": { + "rolling_avg_quality_5": 25.17, + "quality_delta_10": 24.82, + "num_orders": 14.46, + "hour": 12.88, + "day_of_week": 7.7, + "num_riders": 6.29, + "max_pickup_distance_km": 3.73, + "max_orders_per_rider": 1.22, + "max_kitchen_distance_km": 0.99, + "is_peak": 0.8, + "workload_balance_threshold": 0.74, + "ideal_load": 0.47, + "road_factor": 0.22, + "distance_penalty_weight": 0.21, + "workload_penalty_weight": 0.13, + "cluster_radius_km": 0.1, + "search_time_limit_seconds": 0.07 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260509_020744.json b/ml_data/reports/tuning_20260509_020744.json new file mode 100644 index 0000000..9220bf0 --- /dev/null +++ b/ml_data/reports/tuning_20260509_020744.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-09T02:07:44.578747", + "training_rows": 1534, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7476, + "mae": 3.019, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.75, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.38, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1534 + }, + "feature_importance": { + "rolling_avg_quality_5": 25.38, + "quality_delta_10": 25.19, + "num_orders": 14.1, + "hour": 12.86, + "day_of_week": 8.06, + "num_riders": 6.18, + "max_pickup_distance_km": 3.48, + "max_orders_per_rider": 1.14, + "max_kitchen_distance_km": 0.97, + "is_peak": 0.84, + "workload_balance_threshold": 0.7, + "ideal_load": 0.43, + "distance_penalty_weight": 0.2, + "road_factor": 0.2, + "workload_penalty_weight": 0.12, + "cluster_radius_km": 0.09, + "search_time_limit_seconds": 0.06 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260509_061651.json b/ml_data/reports/tuning_20260509_061651.json new file mode 100644 index 0000000..960e699 --- /dev/null +++ b/ml_data/reports/tuning_20260509_061651.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-09T06:16:51.181245", + "training_rows": 1545, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7466, + "mae": 3.036, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.75, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.41, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1545 + }, + "feature_importance": { + "rolling_avg_quality_5": 25.49, + "quality_delta_10": 25.35, + "num_orders": 14.07, + "hour": 13.11, + "day_of_week": 7.97, + "num_riders": 6.1, + "max_pickup_distance_km": 3.31, + "max_orders_per_rider": 1.06, + "max_kitchen_distance_km": 0.93, + "is_peak": 0.85, + "workload_balance_threshold": 0.68, + "ideal_load": 0.43, + "road_factor": 0.2, + "distance_penalty_weight": 0.18, + "workload_penalty_weight": 0.12, + "cluster_radius_km": 0.08, + "search_time_limit_seconds": 0.07 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260509_061932.json b/ml_data/reports/tuning_20260509_061932.json new file mode 100644 index 0000000..bd4aedb --- /dev/null +++ b/ml_data/reports/tuning_20260509_061932.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-09T06:19:32.774626", + "training_rows": 1550, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.751, + "mae": 3.037, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.4, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1550 + }, + "feature_importance": { + "rolling_avg_quality_5": 27.45, + "quality_delta_10": 26.19, + "num_orders": 13.01, + "hour": 12.83, + "day_of_week": 8.86, + "num_riders": 5.54, + "max_pickup_distance_km": 2.49, + "max_kitchen_distance_km": 0.94, + "max_orders_per_rider": 0.73, + "is_peak": 0.68, + "ideal_load": 0.42, + "workload_balance_threshold": 0.37, + "distance_penalty_weight": 0.14, + "road_factor": 0.14, + "workload_penalty_weight": 0.11, + "cluster_radius_km": 0.04, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260509_115516.json b/ml_data/reports/tuning_20260509_115516.json new file mode 100644 index 0000000..d15edc1 --- /dev/null +++ b/ml_data/reports/tuning_20260509_115516.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-09T11:55:16.983857", + "training_rows": 1560, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7438, + "mae": 3.052, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.74, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.42, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1560 + }, + "feature_importance": { + "rolling_avg_quality_5": 25.83, + "quality_delta_10": 25.47, + "num_orders": 13.88, + "hour": 13.08, + "day_of_week": 8.02, + "num_riders": 6.05, + "max_pickup_distance_km": 3.24, + "max_orders_per_rider": 1.03, + "max_kitchen_distance_km": 0.92, + "is_peak": 0.84, + "workload_balance_threshold": 0.63, + "ideal_load": 0.42, + "distance_penalty_weight": 0.18, + "road_factor": 0.18, + "workload_penalty_weight": 0.11, + "cluster_radius_km": 0.08, + "search_time_limit_seconds": 0.07 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260509_120950.json b/ml_data/reports/tuning_20260509_120950.json new file mode 100644 index 0000000..c40d442 --- /dev/null +++ b/ml_data/reports/tuning_20260509_120950.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-09T12:09:50.573837", + "training_rows": 1571, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7468, + "mae": 3.055, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.75, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.42, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1571 + }, + "feature_importance": { + "rolling_avg_quality_5": 25.97, + "quality_delta_10": 25.5, + "num_orders": 13.74, + "hour": 13.15, + "day_of_week": 8.1, + "num_riders": 5.99, + "max_pickup_distance_km": 3.16, + "max_orders_per_rider": 1.0, + "max_kitchen_distance_km": 0.92, + "is_peak": 0.83, + "workload_balance_threshold": 0.6, + "ideal_load": 0.42, + "road_factor": 0.18, + "distance_penalty_weight": 0.17, + "workload_penalty_weight": 0.11, + "cluster_radius_km": 0.08, + "search_time_limit_seconds": 0.08 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260511_020234.json b/ml_data/reports/tuning_20260511_020234.json new file mode 100644 index 0000000..33f1718 --- /dev/null +++ b/ml_data/reports/tuning_20260511_020234.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-11T02:02:34.496214", + "training_rows": 1585, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7295, + "mae": 3.07, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.1 pts (R2=0.73, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.42, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1585 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.1, + "quality_delta_10": 25.56, + "num_orders": 13.63, + "hour": 13.31, + "day_of_week": 8.16, + "num_riders": 5.86, + "max_pickup_distance_km": 3.04, + "max_orders_per_rider": 0.96, + "max_kitchen_distance_km": 0.91, + "is_peak": 0.85, + "workload_balance_threshold": 0.58, + "ideal_load": 0.41, + "distance_penalty_weight": 0.2, + "road_factor": 0.19, + "workload_penalty_weight": 0.12, + "cluster_radius_km": 0.08, + "search_time_limit_seconds": 0.07 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260511_061351.json b/ml_data/reports/tuning_20260511_061351.json new file mode 100644 index 0000000..5730d7c --- /dev/null +++ b/ml_data/reports/tuning_20260511_061351.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-11T06:13:51.722913", + "training_rows": 1596, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7493, + "mae": 2.995, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.75, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.43, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1596 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.11, + "quality_delta_10": 25.79, + "num_orders": 13.62, + "hour": 13.12, + "day_of_week": 8.3, + "num_riders": 5.81, + "max_pickup_distance_km": 2.96, + "max_orders_per_rider": 0.94, + "max_kitchen_distance_km": 0.88, + "is_peak": 0.87, + "workload_balance_threshold": 0.55, + "ideal_load": 0.42, + "distance_penalty_weight": 0.2, + "road_factor": 0.18, + "workload_penalty_weight": 0.11, + "cluster_radius_km": 0.08, + "search_time_limit_seconds": 0.06 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260511_064021.json b/ml_data/reports/tuning_20260511_064021.json new file mode 100644 index 0000000..357f60b --- /dev/null +++ b/ml_data/reports/tuning_20260511_064021.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-11T06:40:21.531072", + "training_rows": 1606, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.753, + "mae": 2.959, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.44, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1606 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.23, + "quality_delta_10": 25.81, + "num_orders": 13.63, + "hour": 12.99, + "day_of_week": 8.46, + "num_riders": 5.81, + "max_pickup_distance_km": 2.87, + "max_orders_per_rider": 0.89, + "max_kitchen_distance_km": 0.88, + "is_peak": 0.85, + "workload_balance_threshold": 0.52, + "ideal_load": 0.43, + "distance_penalty_weight": 0.19, + "road_factor": 0.19, + "workload_penalty_weight": 0.1, + "cluster_radius_km": 0.08, + "search_time_limit_seconds": 0.06 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260511_114513.json b/ml_data/reports/tuning_20260511_114513.json new file mode 100644 index 0000000..bd46bb1 --- /dev/null +++ b/ml_data/reports/tuning_20260511_114513.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-11T11:45:13.297361", + "training_rows": 1616, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7456, + "mae": 3.019, + "folds": 5, + "trust_level": "good", + "trust_score": 3, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.75, trust=good)" + }, + "baseline_stats": { + "avg_quality": 84.46, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1616 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.43, + "quality_delta_10": 25.87, + "num_orders": 13.49, + "hour": 12.89, + "day_of_week": 8.57, + "num_riders": 5.84, + "max_pickup_distance_km": 2.79, + "max_kitchen_distance_km": 0.88, + "max_orders_per_rider": 0.88, + "is_peak": 0.83, + "workload_balance_threshold": 0.51, + "ideal_load": 0.41, + "road_factor": 0.2, + "distance_penalty_weight": 0.19, + "workload_penalty_weight": 0.09, + "cluster_radius_km": 0.08, + "search_time_limit_seconds": 0.06 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260511_120422.json b/ml_data/reports/tuning_20260511_120422.json new file mode 100644 index 0000000..857b165 --- /dev/null +++ b/ml_data/reports/tuning_20260511_120422.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-11T12:04:22.967857", + "training_rows": 1626, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.756, + "mae": 2.95, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.46, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1626 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.59, + "quality_delta_10": 26.02, + "num_orders": 13.33, + "hour": 12.84, + "day_of_week": 8.61, + "num_riders": 5.78, + "max_pickup_distance_km": 2.75, + "max_kitchen_distance_km": 0.87, + "max_orders_per_rider": 0.87, + "is_peak": 0.82, + "workload_balance_threshold": 0.5, + "ideal_load": 0.42, + "road_factor": 0.21, + "distance_penalty_weight": 0.18, + "workload_penalty_weight": 0.09, + "cluster_radius_km": 0.08, + "search_time_limit_seconds": 0.06 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260512_014943.json b/ml_data/reports/tuning_20260512_014943.json new file mode 100644 index 0000000..4adf17c --- /dev/null +++ b/ml_data/reports/tuning_20260512_014943.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-12T01:49:43.385581", + "training_rows": 1631, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7643, + "mae": 2.893, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-2.9 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.46, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1631 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.08, + "quality_delta_10": 24.43, + "num_orders": 15.07, + "hour": 12.27, + "day_of_week": 7.74, + "num_riders": 5.6, + "max_pickup_distance_km": 4.28, + "max_orders_per_rider": 1.07, + "max_kitchen_distance_km": 0.83, + "workload_balance_threshold": 0.79, + "is_peak": 0.66, + "ideal_load": 0.41, + "road_factor": 0.28, + "distance_penalty_weight": 0.2, + "cluster_radius_km": 0.15, + "workload_penalty_weight": 0.1, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260512_020744.json b/ml_data/reports/tuning_20260512_020744.json new file mode 100644 index 0000000..b330f38 --- /dev/null +++ b/ml_data/reports/tuning_20260512_020744.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-12T02:07:44.784246", + "training_rows": 1644, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.754, + "mae": 2.979, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.47, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1644 + }, + "feature_importance": { + "rolling_avg_quality_5": 25.95, + "quality_delta_10": 24.75, + "num_orders": 14.83, + "hour": 12.53, + "day_of_week": 7.9, + "num_riders": 5.64, + "max_pickup_distance_km": 3.97, + "max_orders_per_rider": 1.03, + "max_kitchen_distance_km": 0.83, + "workload_balance_threshold": 0.76, + "is_peak": 0.7, + "ideal_load": 0.41, + "road_factor": 0.24, + "distance_penalty_weight": 0.22, + "cluster_radius_km": 0.14, + "workload_penalty_weight": 0.08, + "search_time_limit_seconds": 0.04 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260512_062235.json b/ml_data/reports/tuning_20260512_062235.json new file mode 100644 index 0000000..3dea8c8 --- /dev/null +++ b/ml_data/reports/tuning_20260512_062235.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-12T06:22:35.184802", + "training_rows": 1654, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7513, + "mae": 2.976, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.46, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1654 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.21, + "quality_delta_10": 24.89, + "num_orders": 14.55, + "hour": 12.64, + "day_of_week": 8.1, + "num_riders": 5.51, + "max_pickup_distance_km": 3.78, + "max_orders_per_rider": 0.95, + "max_kitchen_distance_km": 0.86, + "is_peak": 0.72, + "workload_balance_threshold": 0.72, + "ideal_load": 0.4, + "road_factor": 0.23, + "distance_penalty_weight": 0.21, + "cluster_radius_km": 0.13, + "workload_penalty_weight": 0.08, + "search_time_limit_seconds": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260512_063843.json b/ml_data/reports/tuning_20260512_063843.json new file mode 100644 index 0000000..07e39da --- /dev/null +++ b/ml_data/reports/tuning_20260512_063843.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-12T06:38:43.895271", + "training_rows": 1664, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7578, + "mae": 2.945, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-2.9 pts (R2=0.76, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.48, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1664 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.31, + "quality_delta_10": 25.33, + "num_orders": 14.22, + "hour": 12.62, + "day_of_week": 8.11, + "num_riders": 5.64, + "max_pickup_distance_km": 3.62, + "max_orders_per_rider": 0.92, + "max_kitchen_distance_km": 0.82, + "is_peak": 0.72, + "workload_balance_threshold": 0.68, + "ideal_load": 0.36, + "road_factor": 0.22, + "distance_penalty_weight": 0.2, + "cluster_radius_km": 0.11, + "workload_penalty_weight": 0.09, + "search_time_limit_seconds": 0.03 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/reports/tuning_20260512_130542.json b/ml_data/reports/tuning_20260512_130542.json new file mode 100644 index 0000000..94a0f13 --- /dev/null +++ b/ml_data/reports/tuning_20260512_130542.json @@ -0,0 +1,204 @@ +{ + "timestamp": "2026-05-12T13:05:42.234987", + "training_rows": 1677, + "n_trials": 100, + "best_predicted_quality": 95.67, + "best_params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "validation": { + "r2_score": 0.7502, + "mae": 2.951, + "folds": 5, + "trust_level": "strong", + "trust_score": 4, + "interpretation": "Predictions off by +/-3.0 pts (R2=0.75, trust=strong)" + }, + "baseline_stats": { + "avg_quality": 84.47, + "best_quality": 100.0, + "worst_quality": 30.0, + "sample_size": 1677 + }, + "feature_importance": { + "rolling_avg_quality_5": 26.45, + "quality_delta_10": 25.61, + "num_orders": 13.92, + "hour": 12.69, + "day_of_week": 8.18, + "num_riders": 5.57, + "max_pickup_distance_km": 3.44, + "max_orders_per_rider": 0.87, + "max_kitchen_distance_km": 0.86, + "is_peak": 0.76, + "workload_balance_threshold": 0.63, + "ideal_load": 0.37, + "distance_penalty_weight": 0.21, + "road_factor": 0.21, + "workload_penalty_weight": 0.1, + "cluster_radius_km": 0.1, + "search_time_limit_seconds": 0.02 + }, + "top_trials": [ + { + "params": { + "max_pickup_distance_km": 8.059607113687592, + "max_kitchen_distance_km": 3.557541351566059, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9477826833914522, + "workload_penalty_weight": 76.82444554427441, + "distance_penalty_weight": 3.1729184243565047, + "cluster_radius_km": 3.1900618324706227, + "search_time_limit_seconds": 13, + "road_factor": 1.456682787912438 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.922163642403831, + "max_kitchen_distance_km": 3.560648853560723, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9496626205810123, + "workload_penalty_weight": 75.42186153753029, + "distance_penalty_weight": 3.2508390582807714, + "cluster_radius_km": 3.139706478950993, + "search_time_limit_seconds": 13, + "road_factor": 1.4512573832284252 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.909351329233809, + "max_kitchen_distance_km": 3.5730562042946805, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9461193785353987, + "workload_penalty_weight": 75.58774451546567, + "distance_penalty_weight": 3.023081767323725, + "cluster_radius_km": 2.9359493072618243, + "search_time_limit_seconds": 13, + "road_factor": 1.4523616577581806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.899921037006148, + "max_kitchen_distance_km": 3.596149879389368, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9486010699634219, + "workload_penalty_weight": 76.40722202337206, + "distance_penalty_weight": 3.056702696738658, + "cluster_radius_km": 2.9703866947191733, + "search_time_limit_seconds": 13, + "road_factor": 1.464829881116208 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.8699343570819424, + "max_kitchen_distance_km": 3.5925575890865504, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9490495565477699, + "workload_penalty_weight": 80.15149397601218, + "distance_penalty_weight": 3.0716641537068874, + "cluster_radius_km": 2.9214053883777416, + "search_time_limit_seconds": 13, + "road_factor": 1.4643685958637496 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.837799681658111, + "max_kitchen_distance_km": 3.6432511947304795, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9418215533677297, + "workload_penalty_weight": 81.41780280727099, + "distance_penalty_weight": 2.969582531222015, + "cluster_radius_km": 2.8628487555487707, + "search_time_limit_seconds": 13, + "road_factor": 1.4671924571987078 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.879074471706855, + "max_kitchen_distance_km": 3.6557019240116966, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9493119929922423, + "workload_penalty_weight": 85.22949214929176, + "distance_penalty_weight": 2.9833341504230377, + "cluster_radius_km": 2.859226254037536, + "search_time_limit_seconds": 13, + "road_factor": 1.4686814250911806 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.823191742797717, + "max_kitchen_distance_km": 3.6432473098256875, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9498125411623218, + "workload_penalty_weight": 85.45456841118795, + "distance_penalty_weight": 2.9688230845094177, + "cluster_radius_km": 2.842435439385513, + "search_time_limit_seconds": 13, + "road_factor": 1.4670753169304525 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.852371726123224, + "max_kitchen_distance_km": 3.6398102622452124, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9428641510356341, + "workload_penalty_weight": 84.99438481502906, + "distance_penalty_weight": 2.939503242717154, + "cluster_radius_km": 2.9253430536035037, + "search_time_limit_seconds": 13, + "road_factor": 1.4674115327453523 + }, + "score": 95.66841888427734 + }, + { + "params": { + "max_pickup_distance_km": 7.924961584799045, + "max_kitchen_distance_km": 3.6506307086450454, + "max_orders_per_rider": 20, + "ideal_load": 4, + "workload_balance_threshold": 0.9427326784575867, + "workload_penalty_weight": 86.74116147010929, + "distance_penalty_weight": 2.9741884394575506, + "cluster_radius_km": 2.92845676158564, + "search_time_limit_seconds": 13, + "road_factor": 1.4668680923724249 + }, + "score": 95.66841888427734 + } + ], + "pareto_frontier": [] +} \ No newline at end of file diff --git a/ml_data/strategy_bandit.json b/ml_data/strategy_bandit.json new file mode 100644 index 0000000..51fda10 --- /dev/null +++ b/ml_data/strategy_bandit.json @@ -0,0 +1,260 @@ +{ + "posteriors": { + "LATE_MORNING|MODERATE": { + "balanced": [ + 25.638300000000005, + 5.3617 + ], + "aggressive_speed": [ + 64.9546, + 10.045399999999999 + ], + "zone_strict": [ + 25.135299999999994, + 6.864700000000001 + ] + }, + "LATE_MORNING|HEAVY": { + "balanced": [ + 7.5477, + 2.4523 + ], + "aggressive_speed": [ + 30.7476, + 5.252400000000001 + ], + "zone_strict": [ + 16.731199999999998, + 4.268799999999999 + ] + }, + "LATE_NIGHT|LIGHT": { + "fuel_saver": [ + 11.650099999999998, + 8.3499 + ], + "zone_strict": [ + 30.093800000000016, + 6.906200000000004 + ], + "balanced": [ + 44.03130000000001, + 6.9687 + ], + "aggressive_speed": [ + 57.47499999999996, + 7.5249999999999995 + ] + }, + "LATE_NIGHT|MODERATE": { + "fuel_saver": [ + 5.904199999999999, + 7.095800000000001 + ], + "zone_strict": [ + 45.605999999999995, + 12.394000000000007 + ], + "aggressive_speed": [ + 67.48440000000001, + 10.515600000000003 + ], + "balanced": [ + 63.86140000000001, + 11.1386 + ] + }, + "LATE_NIGHT|HEAVY": { + "fuel_saver": [ + 5.499, + 4.5009999999999994 + ], + "zone_strict": [ + 29.7368, + 9.2632 + ], + "aggressive_speed": [ + 35.6323, + 6.3677 + ], + "balanced": [ + 20.5191, + 5.480900000000002 + ] + }, + "MORNING_RUSH|MODERATE": { + "fuel_saver": [ + 3.9324999999999997, + 4.0675 + ], + "aggressive_speed": [ + 45.216899999999974, + 9.7831 + ], + "zone_strict": [ + 10.4061, + 3.5939000000000005 + ], + "balanced": [ + 27.109, + 7.891000000000002 + ] + }, + "MORNING_RUSH|HEAVY": { + "fuel_saver": [ + 4.6063, + 4.3937 + ], + "aggressive_speed": [ + 62.22419999999999, + 11.7758 + ], + "zone_strict": [ + 20.429899999999996, + 6.570099999999999 + ], + "balanced": [ + 52.682900000000004, + 11.317099999999996 + ] + }, + "LATE_MORNING|LIGHT": { + "aggressive_speed": [ + 69.57499999999996, + 8.424999999999997 + ], + "zone_strict": [ + 30.943900000000014, + 7.056100000000001 + ], + "balanced": [ + 23.547000000000004, + 3.4530000000000003 + ], + "fuel_saver": [ + 2.0, + 1.0 + ] + }, + "LUNCH_RUSH|LIGHT": { + "zone_strict": [ + 14.0687, + 2.9313 + ], + "aggressive_speed": [ + 47.66250000000001, + 5.337499999999997 + ], + "balanced": [ + 48.1875, + 6.8125 + ], + "fuel_saver": [ + 2.7375, + 1.2625 + ] + }, + "LATE_NIGHT|OVERLOADED": { + "fuel_saver": [ + 1.9500000000000002, + 2.05 + ], + "aggressive_speed": [ + 4.3610999999999995, + 1.6389000000000005 + ], + "balanced": [ + 4.9392000000000005, + 2.0608000000000004 + ] + }, + "MORNING_RUSH|OVERLOADED": { + "fuel_saver": [ + 1.475, + 1.525 + ], + "aggressive_speed": [ + 55.19499999999998, + 8.804999999999998 + ], + "zone_strict": [ + 19.885500000000008, + 5.1145 + ], + "balanced": [ + 43.78639999999999, + 9.213599999999998 + ] + }, + "LUNCH_RUSH|MODERATE": { + "zone_strict": [ + 12.928799999999999, + 4.0712 + ], + "aggressive_speed": [ + 35.222800000000014, + 5.7772 + ], + "balanced": [ + 74.30290000000002, + 14.697099999999995 + ] + }, + "LUNCH_RUSH|HEAVY": { + "zone_strict": [ + 5.044700000000001, + 1.9552999999999998 + ], + "aggressive_speed": [ + 26.030199999999997, + 4.969799999999999 + ], + "balanced": [ + 27.040100000000006, + 5.959899999999999 + ] + }, + "EVENING_RUSH|HEAVY": { + "zone_strict": [ + 1.8875, + 1.1125 + ] + }, + "MORNING_RUSH|LIGHT": { + "zone_strict": [ + 13.1812, + 2.8187999999999995 + ], + "aggressive_speed": [ + 41.10000000000001, + 5.899999999999998 + ], + "balanced": [ + 33.9999, + 5.0001 + ] + }, + "LATE_MORNING|OVERLOADED": { + "aggressive_speed": [ + 9.725599999999998, + 2.2744 + ], + "balanced": [ + 3.976, + 2.024 + ] + }, + "LUNCH_RUSH|OVERLOADED": { + "aggressive_speed": [ + 3.625, + 1.375 + ], + "balanced": [ + 3.4326, + 1.5674000000000001 + ] + } + }, + "update_count": 1683, + "total_pulls": 0 +} \ No newline at end of file diff --git a/output b/output new file mode 100644 index 0000000..094efd8 --- /dev/null +++ b/output @@ -0,0 +1,7762 @@ +{ + "code": 200, + "zone_summary": [ + { + "zone_name": "Central", + "total_orders": 4, + "assigned_orders": 4, + "unassigned_orders_count": 0, + "active_riders_count": 1, + "total_delivery_kms": 19.0, + "total_profit": -47.5 + }, + { + "zone_name": "East", + "total_orders": 12, + "assigned_orders": 12, + "unassigned_orders_count": 0, + "active_riders_count": 4, + "total_delivery_kms": 50.0, + "total_profit": -125.0 + }, + { + "zone_name": "North East", + "total_orders": 10, + "assigned_orders": 10, + "unassigned_orders_count": 0, + "active_riders_count": 4, + "total_delivery_kms": 98.0, + "total_profit": -65.0 + }, + { + "zone_name": "North West", + "total_orders": 1, + "assigned_orders": 1, + "unassigned_orders_count": 0, + "active_riders_count": 1, + "total_delivery_kms": 9.0, + "total_profit": -16.5 + }, + { + "zone_name": "South", + "total_orders": 3, + "assigned_orders": 3, + "unassigned_orders_count": 0, + "active_riders_count": 1, + "total_delivery_kms": 13.0, + "total_profit": -32.5 + }, + { + "zone_name": "South East", + "total_orders": 5, + "assigned_orders": 5, + "unassigned_orders_count": 0, + "active_riders_count": 3, + "total_delivery_kms": 40.0, + "total_profit": -82.0 + } + ], + "zones": [ + { + "zone_name": "Central", + "total_orders": 4, + "active_riders_count": 1, + "assigned_orders": 4, + "unassigned_orders_count": 0, + "total_delivery_kms": 19.0, + "total_profit": -47.5, + "riders": [ + { + "rider_id": "1062", + "rider_name": "Nagalakshmi M", + "orders_count": 4, + "orders": [ + { + "orderheaderid": 138251, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107316", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "VIGNESH", + "deliverycontactno": "6384868679", + "deliverylocationid": 0, + "deliveryaddress": "SECOND FLOOR, BUILDING NO 39, ALAGESAN ROAD,SAIBABA COLONY KAAPPI READY BUILDING SECOND FLOOR", + "deliverysuburb": "", + "droplat": "11.02296785", + "droplon": "76.94656475", + "deliverylat": "11.02296785", + "deliverylong": "76.94656475", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Nagalakshmi M", + "ridercontactno": "8778484594", + "riderkms": "9.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 29, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 1, + "previouskms": 4, + "cumulativekms": 4, + "actualkms": "4.0", + "ordertype": "Economy", + "eta": "21", + "cumulative_eta": "21", + "userid": 1062, + "username": "Nagalakshmi M", + "expectedDeliveryTime": "2026-05-26 07:21 PM", + "transitMinutes": 21, + "calculationDistanceKm": 4.0, + "zone_name": "Central", + "rider_charge": 40.0, + "profit": -10.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138255, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107320", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Sivasubramanian", + "deliverycontactno": "9994425347", + "deliverylocationid": 0, + "deliveryaddress": "72-1 Cowley Brown Road, RS Puram, CBE-2 Come inside gate east of Champion Physiotherapy then 1st house to the right", + "deliverysuburb": "", + "droplat": "11.0147203", + "droplon": "76.9464989", + "deliverylat": "11.0147203", + "deliverylong": "76.9464989", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Nagalakshmi M", + "ridercontactno": "8778484594", + "riderkms": "9.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 25, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 2, + "previouskms": 1, + "cumulativekms": 5, + "actualkms": "4.0", + "ordertype": "Economy", + "eta": "10", + "cumulative_eta": "31", + "userid": 1062, + "username": "Nagalakshmi M", + "expectedDeliveryTime": "2026-05-26 07:31 PM", + "transitMinutes": 31, + "calculationDistanceKm": 5.0, + "zone_name": "Central", + "rider_charge": 40.0, + "profit": -10.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138254, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107319", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "5", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Indirani", + "deliverycontactno": "9566644154", + "deliverylocationid": 0, + "deliveryaddress": "152,A.Ramalingam colony, mettupalayam road Opp .Meenakshi gov hospital, avanashilingam college 3 rd gate opp road ", + "deliverysuburb": "", + "droplat": "11.0213553", + "droplon": "76.9506268", + "deliverylat": "11.0213553", + "deliverylong": "76.9506268", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Nagalakshmi M", + "ridercontactno": "8778484594", + "riderkms": "9.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 26, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 3, + "previouskms": 1, + "cumulativekms": 6, + "actualkms": "5.0", + "ordertype": "Economy", + "eta": "10", + "cumulative_eta": "41", + "userid": 1062, + "username": "Nagalakshmi M", + "expectedDeliveryTime": "2026-05-26 07:41 PM", + "transitMinutes": 41, + "calculationDistanceKm": 6.0, + "zone_name": "Central", + "rider_charge": 42.5, + "profit": -12.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138257, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107322", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "6", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "P M PRADEEP", + "deliverycontactno": "9786698944", + "deliverylocationid": 0, + "deliveryaddress": "Old No 98, New No 111, Raju Naidu Road, Tatabad, Coimbatore 641012. In Between South Indian Coffee and Amutham Pharmacy", + "deliverysuburb": "", + "droplat": "11.02174992", + "droplon": "76.95937411", + "deliverylat": "11.02174992", + "deliverylong": "76.95937411", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Nagalakshmi M", + "ridercontactno": "8778484594", + "riderkms": "9.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 23, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 4, + "previouskms": 1, + "cumulativekms": 8, + "actualkms": "6.0", + "ordertype": "Premium", + "eta": "10", + "cumulative_eta": "51", + "userid": 1062, + "username": "Nagalakshmi M", + "expectedDeliveryTime": "2026-05-26 07:51 PM", + "transitMinutes": 51, + "calculationDistanceKm": 8.0, + "zone_name": "Central", + "rider_charge": 45.0, + "profit": -15.0, + "profit_class": "Loss" + } + ] + } + ], + "unassigned_orders": [] + }, + { + "zone_name": "East", + "total_orders": 12, + "active_riders_count": 4, + "assigned_orders": 12, + "unassigned_orders_count": 0, + "total_delivery_kms": 50.0, + "total_profit": -125.0, + "riders": [ + { + "rider_id": "753", + "rider_name": "Manikandan P", + "orders_count": 4, + "orders": [ + { + "orderheaderid": 138271, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107336", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Varsha", + "deliverycontactno": "9944397248", + "deliverylocationid": 0, + "deliveryaddress": "Masakalipalayam road,No.12,kalyana Sundara street New Iyengar bakery cut", + "deliverysuburb": "", + "droplat": "11.0241383", + "droplon": "77.0184563", + "deliverylat": "11.0241383", + "deliverylong": "77.0184563", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Manikandan P", + "ridercontactno": "9677687759", + "riderkms": "11.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 9, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 2, + "previouskms": 2, + "cumulativekms": 5, + "actualkms": "3.0", + "ordertype": "Economy", + "eta": "12", + "cumulative_eta": "29", + "userid": 753, + "username": "Manikandan P", + "expectedDeliveryTime": "2026-05-26 07:29 PM", + "transitMinutes": 29, + "calculationDistanceKm": 5.0, + "zone_name": "East", + "rider_charge": 37.5, + "profit": -7.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138270, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107335", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Vasu dharani", + "deliverycontactno": "9042730736", + "deliverylocationid": 0, + "deliveryaddress": "Royal stitch, no.26 , Srinagar, hope college Royal stitch ", + "deliverysuburb": "", + "droplat": "11.0251802", + "droplon": "77.0198024", + "deliverylat": "11.0251802", + "deliverylong": "77.0198024", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Manikandan P", + "ridercontactno": "9677687759", + "riderkms": "11.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 2, + "collectionamt": 1613, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 10, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 3, + "previouskms": 0, + "cumulativekms": 5, + "actualkms": "3.0", + "ordertype": "Economy", + "eta": "6", + "cumulative_eta": "35", + "userid": 753, + "username": "Manikandan P", + "expectedDeliveryTime": "2026-05-26 07:35 PM", + "transitMinutes": 35, + "calculationDistanceKm": 5.0, + "zone_name": "East", + "rider_charge": 37.5, + "profit": -7.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138272, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107337", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "1", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "M.S.JAVID", + "deliverycontactno": "7558120192", + "deliverylocationid": 0, + "deliveryaddress": "ROOM No-21, J.K COMPLEX, 386/A3, KAMARAJAR ROAD, PEELAMEDU, COIMBATORE-641004, NEAR BY SPAZEONE, NNRC ELDER CARE & RHR HOTEL", + "deliverysuburb": "", + "droplat": "11.0207363", + "droplon": "77.0220709", + "deliverylat": "11.0207363", + "deliverylong": "77.0220709", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Manikandan P", + "ridercontactno": "9677687759", + "riderkms": "11.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 8, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 4, + "previouskms": 1, + "cumulativekms": 6, + "actualkms": "1.0", + "ordertype": "Economy", + "eta": "8", + "cumulative_eta": "43", + "userid": 753, + "username": "Manikandan P", + "expectedDeliveryTime": "2026-05-26 07:43 PM", + "transitMinutes": 43, + "calculationDistanceKm": 6.0, + "zone_name": "East", + "rider_charge": 32.5, + "profit": -2.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138279, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107344", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "2", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Pooja", + "deliverycontactno": "9080859196", + "deliverylocationid": 0, + "deliveryaddress": "C1 castle park apartment, Ramanujam Nagar, Uppilipalayam C1- 3rd floor", + "deliverysuburb": "", + "droplat": "11.01933791", + "droplon": "77.02415225", + "deliverylat": "11.01933791", + "deliverylong": "77.02415225", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Manikandan P", + "ridercontactno": "9677687759", + "riderkms": "11.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 1, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 5, + "previouskms": 0, + "cumulativekms": 6, + "actualkms": "2.0", + "ordertype": "Economy", + "eta": "6", + "cumulative_eta": "49", + "userid": 753, + "username": "Manikandan P", + "expectedDeliveryTime": "2026-05-26 07:49 PM", + "transitMinutes": 49, + "calculationDistanceKm": 6.0, + "zone_name": "East", + "rider_charge": 35.0, + "profit": -5.0, + "profit_class": "Loss" + } + ] + }, + { + "rider_id": "883", + "rider_name": "Rajan A", + "orders_count": 6, + "orders": [ + { + "orderheaderid": 138273, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107338", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Athira Sooraj", + "deliverycontactno": "9847568898", + "deliverylocationid": 0, + "deliveryaddress": "80, Murugan Kovil street, Avarampalayam Road, Peelamedu Next to Akashmalli apartments", + "deliverysuburb": "", + "droplat": "11.02609076", + "droplon": "76.99829646", + "deliverylat": "11.02609076", + "deliverylong": "76.99829646", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Rajan A", + "ridercontactno": "9787698259", + "riderkms": "10.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 7, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 2, + "previouskms": 1, + "cumulativekms": 4, + "actualkms": "3.0", + "ordertype": "Economy", + "eta": "9", + "cumulative_eta": "29", + "userid": 883, + "username": "Rajan A", + "expectedDeliveryTime": "2026-05-26 07:29 PM", + "transitMinutes": 29, + "calculationDistanceKm": 4.0, + "zone_name": "East", + "rider_charge": 37.5, + "profit": -7.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138276, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107341", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Santosh kumar", + "deliverycontactno": "9500088928", + "deliverylocationid": 0, + "deliveryaddress": "alanita travel pvt ltd,5th floor,valencia building,336/1, Avinashi Road,Coimbatore", + "deliverysuburb": "", + "droplat": "11.01912568", + "droplon": "76.99127706", + "deliverylat": "11.01912568", + "deliverylong": "76.99127706", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Rajan A", + "ridercontactno": "9787698259", + "riderkms": "10.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 4, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 3, + "previouskms": 2, + "cumulativekms": 6, + "actualkms": "4.0", + "ordertype": "Economy", + "eta": "11", + "cumulative_eta": "40", + "userid": 883, + "username": "Rajan A", + "expectedDeliveryTime": "2026-05-26 07:40 PM", + "transitMinutes": 40, + "calculationDistanceKm": 6.0, + "zone_name": "East", + "rider_charge": 40.0, + "profit": -10.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138269, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107334", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "5", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Manikumar", + "deliverycontactno": "9025625195", + "deliverylocationid": 0, + "deliveryaddress": "Tristar towers 4th floor 407 room no Near angannan briyani", + "deliverysuburb": "", + "droplat": "11.01136931", + "droplon": "76.98546701", + "deliverylat": "11.01136931", + "deliverylong": "76.98546701", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Rajan A", + "ridercontactno": "9787698259", + "riderkms": "10.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 11, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 4, + "previouskms": 2, + "cumulativekms": 7, + "actualkms": "5.0", + "ordertype": "Economy", + "eta": "11", + "cumulative_eta": "51", + "userid": 883, + "username": "Rajan A", + "expectedDeliveryTime": "2026-05-26 07:51 PM", + "transitMinutes": 51, + "calculationDistanceKm": 7.0, + "zone_name": "East", + "rider_charge": 42.5, + "profit": -12.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138277, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107342", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "7", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Aishwarya", + "deliverycontactno": "7708542801", + "deliverylocationid": 0, + "deliveryaddress": "1c A block Pioneer apartment Avinashi road Near Residency towers", + "deliverysuburb": "", + "droplat": "11.0105", + "droplon": "76.98", + "deliverylat": "11.0105", + "deliverylong": "76.98", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Rajan A", + "ridercontactno": "9787698259", + "riderkms": "10.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 3, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 5, + "previouskms": 1, + "cumulativekms": 8, + "actualkms": "7.0", + "ordertype": "Premium", + "eta": "8", + "cumulative_eta": "59", + "userid": 883, + "username": "Rajan A", + "expectedDeliveryTime": "2026-05-26 07:59 PM", + "transitMinutes": 59, + "calculationDistanceKm": 8.0, + "zone_name": "East", + "rider_charge": 47.5, + "profit": -17.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138265, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107330", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "7", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Yaswanth Sai Jami", + "deliverycontactno": "9618838341", + "deliverylocationid": 0, + "deliveryaddress": "Flat 4b, B block, Pioneer Apartments, Pappanaickenpalayam Beside residency towers hotel ", + "deliverysuburb": "", + "droplat": "11.01067171", + "droplon": "76.97995486", + "deliverylat": "11.01067171", + "deliverylong": "76.97995486", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Rajan A", + "ridercontactno": "9787698259", + "riderkms": "10.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 2, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 15, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 6, + "previouskms": 0, + "cumulativekms": 8, + "actualkms": "7.0", + "ordertype": "Premium", + "eta": "5", + "cumulative_eta": "64", + "userid": 883, + "username": "Rajan A", + "expectedDeliveryTime": "2026-05-26 08:04 PM", + "transitMinutes": 64, + "calculationDistanceKm": 8.0, + "zone_name": "East", + "rider_charge": 47.5, + "profit": -17.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138266, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107331", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "7", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Kannammal", + "deliverycontactno": "8884366950", + "deliverylocationid": 0, + "deliveryaddress": "47 Ambika Layout, New Siddhapudur Opp to Kaleeswari Broiler", + "deliverysuburb": "", + "droplat": "11.01962586", + "droplon": "76.97291096", + "deliverylat": "11.01962586", + "deliverylong": "76.97291096", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Rajan A", + "ridercontactno": "9787698259", + "riderkms": "10.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 14, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 7, + "previouskms": 2, + "cumulativekms": 10, + "actualkms": "7.0", + "ordertype": "Premium", + "eta": "12", + "cumulative_eta": "76", + "userid": 883, + "username": "Rajan A", + "expectedDeliveryTime": "2026-05-26 08:16 PM", + "transitMinutes": 76, + "calculationDistanceKm": 10.0, + "zone_name": "East", + "rider_charge": 47.5, + "profit": -17.5, + "profit_class": "Loss" + } + ] + }, + { + "rider_id": "1111", + "rider_name": "Murali P", + "orders_count": 1, + "orders": [ + { + "orderheaderid": 138267, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107332", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "2", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "backiaraj k", + "deliverycontactno": "8807424447", + "deliverylocationid": 0, + "deliveryaddress": "1/112, Annai Velankanni Nagar, Sowripalayam, Coimbatore -641028 JJ Stores", + "deliverysuburb": "", + "droplat": "11.00715552", + "droplon": "77.00965818", + "deliverylat": "11.00715552", + "deliverylong": "77.00965818", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Murali P", + "ridercontactno": "7825996002", + "riderkms": "13.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 13, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 1, + "previouskms": 2, + "cumulativekms": 2, + "actualkms": "2.0", + "ordertype": "Economy", + "eta": "15", + "cumulative_eta": "15", + "userid": 1111, + "username": "Murali P", + "expectedDeliveryTime": "2026-05-26 07:15 PM", + "transitMinutes": 15, + "calculationDistanceKm": 2.0, + "zone_name": "East", + "rider_charge": 35.0, + "profit": -5.0, + "profit_class": "Loss" + } + ] + }, + { + "rider_id": "1062", + "rider_name": "Nagalakshmi M", + "orders_count": 1, + "orders": [ + { + "orderheaderid": 138249, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107314", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "6", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Kiran Divagar", + "deliverycontactno": "9944473099", + "deliverylocationid": 0, + "deliveryaddress": "Mukilan Maghizagam , 7/4 , 2nd Cross Street , PM Samy colony, Rathinapuri , Coimbatore Near Yoga Center", + "deliverysuburb": "", + "droplat": "11.02603373", + "droplon": "76.96712952", + "deliverylat": "11.02603373", + "deliverylong": "76.96712952", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Nagalakshmi M", + "ridercontactno": "8778484594", + "riderkms": "9.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 31, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 5, + "previouskms": 1, + "cumulativekms": 9, + "actualkms": "6.0", + "ordertype": "Premium", + "eta": "10", + "cumulative_eta": "61", + "userid": 1062, + "username": "Nagalakshmi M", + "expectedDeliveryTime": "2026-05-26 08:01 PM", + "transitMinutes": 61, + "calculationDistanceKm": 9.0, + "zone_name": "East", + "rider_charge": 45.0, + "profit": -15.0, + "profit_class": "Loss" + } + ] + } + ], + "unassigned_orders": [] + }, + { + "zone_name": "North East", + "total_orders": 10, + "active_riders_count": 4, + "assigned_orders": 10, + "unassigned_orders_count": 0, + "total_delivery_kms": 98.0, + "total_profit": -65.0, + "riders": [ + { + "rider_id": "753", + "rider_name": "Manikandan P", + "orders_count": 1, + "orders": [ + { + "orderheaderid": 138278, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107343", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Kandavelu", + "deliverycontactno": "9443913591", + "deliverylocationid": 0, + "deliveryaddress": "35 Jai Nagar 2nd street, Peelamedu Call 9443913591", + "deliverysuburb": "", + "droplat": "11.03240253", + "droplon": "77.01003422", + "deliverylat": "11.03240253", + "deliverylong": "77.01003422", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Manikandan P", + "ridercontactno": "9677687759", + "riderkms": "11.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 2, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 2, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 1, + "previouskms": 3, + "cumulativekms": 3, + "actualkms": "4.0", + "ordertype": "Economy", + "eta": "17", + "cumulative_eta": "17", + "userid": 753, + "username": "Manikandan P", + "expectedDeliveryTime": "2026-05-26 07:17 PM", + "transitMinutes": 17, + "calculationDistanceKm": 3.0, + "zone_name": "North East", + "rider_charge": 40.0, + "profit": -10.0, + "profit_class": "Loss" + } + ] + }, + { + "rider_id": "883", + "rider_name": "Rajan A", + "orders_count": 1, + "orders": [ + { + "orderheaderid": 138268, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107333", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Devikarani", + "deliverycontactno": "9940666706", + "deliverylocationid": 0, + "deliveryaddress": "229 Giriamman kovil street Peelamedu - near Peelamedu railway station call 9940666706", + "deliverysuburb": "", + "droplat": "11.0315832", + "droplon": "77.0005771", + "deliverylat": "11.0315832", + "deliverylong": "77.0005771", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Rajan A", + "ridercontactno": "9787698259", + "riderkms": "10.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 12, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 1, + "previouskms": 3, + "cumulativekms": 3, + "actualkms": "3.0", + "ordertype": "Economy", + "eta": "20", + "cumulative_eta": "20", + "userid": 883, + "username": "Rajan A", + "expectedDeliveryTime": "2026-05-26 07:20 PM", + "transitMinutes": 20, + "calculationDistanceKm": 3.0, + "zone_name": "North East", + "rider_charge": 37.5, + "profit": -7.5, + "profit_class": "Loss" + } + ] + }, + { + "rider_id": "1114", + "rider_name": "Tamilazhagan K", + "orders_count": 1, + "orders": [ + { + "orderheaderid": 138274, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107339", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "7", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Manoj", + "deliverycontactno": "9944192192", + "deliverylocationid": 0, + "deliveryaddress": "D-424, 4th Floor, Icon City Apartment, Unity Road, Vishweshwara Nagar, Near Cheran Ma Nagar, Villankurichi, Coimbatore - 641035 Villankurichi Road, Konku Bakery Road", + "deliverysuburb": "", + "droplat": "11.05688855", + "droplon": "77.01173596", + "deliverylat": "11.05688855", + "deliverylong": "77.01173596", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Tamilazhagan K", + "ridercontactno": "9788633337", + "riderkms": "7.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 6, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 1, + "previouskms": 7, + "cumulativekms": 7, + "actualkms": "7.0", + "ordertype": "Premium", + "eta": "31", + "cumulative_eta": "31", + "userid": 1114, + "username": "Tamilazhagan K", + "expectedDeliveryTime": "2026-05-26 07:31 PM", + "transitMinutes": 31, + "calculationDistanceKm": 7.0, + "zone_name": "North East", + "rider_charge": 47.5, + "profit": -17.5, + "profit_class": "Loss" + } + ] + }, + { + "rider_id": "950", + "rider_name": "Jayasabesh Kumar S", + "orders_count": 7, + "orders": [ + { + "orderheaderid": 138253, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107318", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "6", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Sreedevi", + "deliverycontactno": "7639720883", + "deliverylocationid": 0, + "deliveryaddress": "124/b5 Thirumagal nagar Maniakarampalayam near ganapathy medical centre", + "deliverysuburb": "", + "droplat": "11.04665266", + "droplon": "76.97522061", + "deliverylat": "11.04665266", + "deliverylong": "76.97522061", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Jayasabesh Kumar S", + "ridercontactno": "8940295001", + "riderkms": "30.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 27, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 1, + "previouskms": 7, + "cumulativekms": 7, + "actualkms": "6.0", + "ordertype": "Premium", + "eta": "33", + "cumulative_eta": "33", + "userid": 950, + "username": "Jayasabesh Kumar S", + "expectedDeliveryTime": "2026-05-26 07:33 PM", + "transitMinutes": 33, + "calculationDistanceKm": 7.0, + "zone_name": "North East", + "rider_charge": 45.0, + "profit": -15.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138260, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107325", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "9", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 36, + "orderamount": 36, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Archanaa", + "deliverycontactno": "7899051088", + "deliverylocationid": 0, + "deliveryaddress": "No 2, Annai Garden, Sakthi Nagar, Chinnavedampatti Backside of Dhivyam Apartment", + "deliverysuburb": "", + "droplat": "11.0583375", + "droplon": "76.9869531", + "deliverylat": "11.0583375", + "deliverylong": "76.9869531", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Jayasabesh Kumar S", + "ridercontactno": "8940295001", + "riderkms": "30.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 20, + "pickuplon": "76.9300797", + "deliverycharges": 36, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 2, + "previouskms": 3, + "cumulativekms": 10, + "actualkms": "9.0", + "ordertype": "Premium", + "eta": "13", + "cumulative_eta": "46", + "userid": 950, + "username": "Jayasabesh Kumar S", + "expectedDeliveryTime": "2026-05-26 07:46 PM", + "transitMinutes": 46, + "calculationDistanceKm": 10.0, + "zone_name": "North East", + "rider_charge": 52.5, + "profit": -16.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138250, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107315", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "12", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 54, + "orderamount": 54, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Swetha", + "deliverycontactno": "9360052122", + "deliverylocationid": 0, + "deliveryaddress": "RoomNo:202, SF No.252/1B, 252/1C, Cheran Nagar, Villankurichi, Coimbatore, Tamil Nadu 641035 Icon city-TNCD", + "deliverysuburb": "", + "droplat": "11.0572", + "droplon": "77.0119", + "deliverylat": "11.0572", + "deliverylong": "77.0119", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Jayasabesh Kumar S", + "ridercontactno": "8940295001", + "riderkms": "30.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 30, + "pickuplon": "76.9300797", + "deliverycharges": 54, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 3, + "previouskms": 4, + "cumulativekms": 14, + "actualkms": "12.0", + "ordertype": "Premium", + "eta": "19", + "cumulative_eta": "65", + "userid": 950, + "username": "Jayasabesh Kumar S", + "expectedDeliveryTime": "2026-05-26 08:05 PM", + "transitMinutes": 65, + "calculationDistanceKm": 14.0, + "zone_name": "North East", + "rider_charge": 60.0, + "profit": -6.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138258, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107323", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "13", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 60, + "orderamount": 60, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Srihari", + "deliverycontactno": "8883267757", + "deliverylocationid": 0, + "deliveryaddress": "Avinash enclave, 3rd floor, 11-D, L N Nagar, Balaji Nagar Phase 2 My house is in backside of KMCH Nursing College.", + "deliverysuburb": "", + "droplat": "11.06662342", + "droplon": "77.03174932", + "deliverylat": "11.06662342", + "deliverylong": "77.03174932", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Jayasabesh Kumar S", + "ridercontactno": "8940295001", + "riderkms": "30.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 22, + "pickuplon": "76.9300797", + "deliverycharges": 60, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 4, + "previouskms": 4, + "cumulativekms": 17, + "actualkms": "13.0", + "ordertype": "Risky", + "eta": "18", + "cumulative_eta": "83", + "userid": 950, + "username": "Jayasabesh Kumar S", + "expectedDeliveryTime": "2026-05-26 08:23 PM", + "transitMinutes": 83, + "calculationDistanceKm": 17.0, + "zone_name": "North East", + "rider_charge": 62.5, + "profit": -2.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138252, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107317", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "18", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 90, + "orderamount": 90, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Anirudh S Rao", + "deliverycontactno": "9840965656", + "deliverylocationid": 0, + "deliveryaddress": "Villa 68, phase 2, Casa Grande Eternia SNS Kalvi Nagar, Kurumbupalayam, SSKulam, Kalapatti road, Coimbatore, 641048 Casa Grande Eternia phase 2", + "deliverysuburb": "", + "droplat": "11.1022", + "droplon": "77.0328", + "deliverylat": "11.1022", + "deliverylong": "77.0328", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Jayasabesh Kumar S", + "ridercontactno": "8940295001", + "riderkms": "30.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 28, + "pickuplon": "76.9300797", + "deliverycharges": 90, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 5, + "previouskms": 6, + "cumulativekms": 23, + "actualkms": "18.0", + "ordertype": "Risky", + "eta": "25", + "cumulative_eta": "108", + "userid": 950, + "username": "Jayasabesh Kumar S", + "expectedDeliveryTime": "2026-05-26 08:48 PM", + "transitMinutes": 108, + "calculationDistanceKm": 23.0, + "zone_name": "North East", + "rider_charge": 75.0, + "profit": 15.0, + "profit_class": "HighMargin" + }, + { + "orderheaderid": 138256, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107321", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "13", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 60, + "orderamount": 60, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Bhaswar Tudu", + "deliverycontactno": "9179046653", + "deliverylocationid": 0, + "deliveryaddress": "7T1, Gate-1, Tower-1, KGISL Platina, Keeranatham Road, Saravanampatti Near Chil-Sez IT Park", + "deliverysuburb": "", + "droplat": "11.1020098", + "droplon": "76.9911354", + "deliverylat": "11.1020098", + "deliverylong": "76.9911354", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Jayasabesh Kumar S", + "ridercontactno": "8940295001", + "riderkms": "30.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 24, + "pickuplon": "76.9300797", + "deliverycharges": 60, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 6, + "previouskms": 7, + "cumulativekms": 30, + "actualkms": "13.0", + "ordertype": "Risky", + "eta": "28", + "cumulative_eta": "136", + "userid": 950, + "username": "Jayasabesh Kumar S", + "expectedDeliveryTime": "2026-05-26 09:16 PM", + "transitMinutes": 136, + "calculationDistanceKm": 30.0, + "zone_name": "North East", + "rider_charge": 62.5, + "profit": -2.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138259, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107324", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "13", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 60, + "orderamount": 60, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Aiswarya S Menon", + "deliverycontactno": "8547076489", + "deliverylocationid": 0, + "deliveryaddress": "CA 807, Coral A, Kgisl metropolis apartments Near CHIL SEZ IT park", + "deliverysuburb": "", + "droplat": "11.1015", + "droplon": "76.9907", + "deliverylat": "11.1015", + "deliverylong": "76.9907", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Jayasabesh Kumar S", + "ridercontactno": "8940295001", + "riderkms": "30.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 2, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 21, + "pickuplon": "76.9300797", + "deliverycharges": 60, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 7, + "previouskms": 0, + "cumulativekms": 30, + "actualkms": "13.0", + "ordertype": "Risky", + "eta": "5", + "cumulative_eta": "141", + "userid": 950, + "username": "Jayasabesh Kumar S", + "expectedDeliveryTime": "2026-05-26 09:21 PM", + "transitMinutes": 141, + "calculationDistanceKm": 30.0, + "zone_name": "North East", + "rider_charge": 62.5, + "profit": -2.5, + "profit_class": "Loss" + } + ] + } + ], + "unassigned_orders": [] + }, + { + "zone_name": "North West", + "total_orders": 1, + "active_riders_count": 1, + "assigned_orders": 1, + "unassigned_orders_count": 0, + "total_delivery_kms": 9.0, + "total_profit": -16.5, + "riders": [ + { + "rider_id": "897", + "rider_name": "Varun Edward", + "orders_count": 1, + "orders": [ + { + "orderheaderid": 138261, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107326", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "9", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 36, + "orderamount": 36, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Sri Gokul", + "deliverycontactno": "9080187878", + "deliverylocationid": 0, + "deliveryaddress": "The focus room,Mettupalayam Rd, Daniel Nagar, Thoppampatti Pirivu, K. Vadamadurai, Coimbatore, Tamil Nadu 641017 Thudiyalur Dmart ", + "deliverysuburb": "", + "droplat": "11.0982", + "droplon": "76.9388", + "deliverylat": "11.0982", + "deliverylong": "76.9388", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Varun Edward", + "ridercontactno": "8248136667", + "riderkms": "10.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 19, + "pickuplon": "76.9300797", + "deliverycharges": 36, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 1, + "previouskms": 10, + "cumulativekms": 10, + "actualkms": "9.0", + "ordertype": "Premium", + "eta": "38", + "cumulative_eta": "38", + "userid": 897, + "username": "Varun Edward", + "expectedDeliveryTime": "2026-05-26 07:38 PM", + "transitMinutes": 38, + "calculationDistanceKm": 10.0, + "zone_name": "North West", + "rider_charge": 52.5, + "profit": -16.5, + "profit_class": "Loss" + } + ] + } + ], + "unassigned_orders": [] + }, + { + "zone_name": "South", + "total_orders": 3, + "active_riders_count": 1, + "assigned_orders": 3, + "unassigned_orders_count": 0, + "total_delivery_kms": 13.0, + "total_profit": -32.5, + "riders": [ + { + "rider_id": "1036", + "rider_name": "Vignesh S", + "orders_count": 3, + "orders": [ + { + "orderheaderid": 138247, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 1076, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107312", + "orderdate": "2026-05-26T18:29:57+05:30", + "deliverydate": "2026-05-26 12:59:57", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "2", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Bhuvaneshwari kitchen ", + "pickupcontactno": "9597843220", + "pickuplocationid": 1076, + "pickupaddress": "Coimbatore, Light House Road, Kollupuram, Sukrawar Pettai, R.S. Puram, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "R.S. Puram", + "pickupcity": "Coimbatore", + "pickuplat": "11.0035176", + "pickuplong": "76.95454649999999", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Bharathi M", + "deliverycontactno": "9626274199", + "deliverylocationid": 0, + "deliveryaddress": "No. 56-59, Samy Iyer new Street, Opp.to Sri anantha theertha mandhir, coimbatore -641001. 1 St floor.. near to jayasurya sanna kambi kadai", + "deliverysuburb": "", + "droplat": "10.99494658", + "droplon": "76.94954136", + "deliverylat": "10.99494658", + "deliverylong": "76.94954136", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Bhuvaneshwari kitchen ", + "locationsuburb": "R.S. Puram", + "locationcity": "Coimbatore", + "locationcontactno": "9597843220", + "locationaddress": "", + "rider": "Vignesh S", + "ridercontactno": "8072675538", + "riderkms": "12.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 33, + "pickuplon": "76.95454649999999", + "deliverycharges": 30, + "pickuplocation": "R.S. Puram", + "deliverylocation": "", + "step": 1, + "previouskms": 2, + "cumulativekms": 2, + "actualkms": "2.0", + "ordertype": "Economy", + "eta": "14", + "cumulative_eta": "14", + "userid": 1036, + "username": "Vignesh S", + "expectedDeliveryTime": "2026-05-26 07:14 PM", + "transitMinutes": 14, + "calculationDistanceKm": 2.0, + "zone_name": "South", + "rider_charge": 35.0, + "profit": -5.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138248, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 1076, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107313", + "orderdate": "2026-05-26T18:29:57+05:30", + "deliverydate": "2026-05-26 12:59:57", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Bhuvaneshwari kitchen ", + "pickupcontactno": "9597843220", + "pickuplocationid": 1076, + "pickupaddress": "Coimbatore, Light House Road, Kollupuram, Sukrawar Pettai, R.S. Puram, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "R.S. Puram", + "pickupcity": "Coimbatore", + "pickuplat": "11.0035176", + "pickuplong": "76.95454649999999", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "R. VIJAYAKUMAR", + "deliverycontactno": "9894145933", + "deliverylocationid": 0, + "deliveryaddress": "1st block G3 ( ground floor) Vishwa apartment Prabhu Nagar sandaka Muthoot bypass road Coimbatore Opp Selvapuram Government Higher Secondary School", + "deliverysuburb": "", + "droplat": "10.9887125", + "droplon": "76.9470469", + "deliverylat": "10.9887125", + "deliverylong": "76.9470469", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Bhuvaneshwari kitchen ", + "locationsuburb": "R.S. Puram", + "locationcity": "Coimbatore", + "locationcontactno": "9597843220", + "locationaddress": "", + "rider": "Vignesh S", + "ridercontactno": "8072675538", + "riderkms": "12.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 32, + "pickuplon": "76.95454649999999", + "deliverycharges": 30, + "pickuplocation": "R.S. Puram", + "deliverylocation": "", + "step": 2, + "previouskms": 1, + "cumulativekms": 3, + "actualkms": "3.0", + "ordertype": "Economy", + "eta": "9", + "cumulative_eta": "23", + "userid": 1036, + "username": "Vignesh S", + "expectedDeliveryTime": "2026-05-26 07:23 PM", + "transitMinutes": 23, + "calculationDistanceKm": 3.0, + "zone_name": "South", + "rider_charge": 37.5, + "profit": -7.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138245, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 1076, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107310", + "orderdate": "2026-05-26T18:29:57+05:30", + "deliverydate": "2026-05-26 12:59:57", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "8", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Bhuvaneshwari kitchen ", + "pickupcontactno": "9597843220", + "pickuplocationid": 1076, + "pickupaddress": "Coimbatore, Light House Road, Kollupuram, Sukrawar Pettai, R.S. Puram, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "R.S. Puram", + "pickupcity": "Coimbatore", + "pickuplat": "11.0035176", + "pickuplong": "76.95454649999999", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Lakshmanan Visalakshi", + "deliverycontactno": "8886443455", + "deliverylocationid": 0, + "deliveryaddress": "New No.6, Old No. 88/51A, Sindhu Nagar, Kuniyamuthur, COIMBATORE எஸ் எஸ் கார்னர் ... 1km ", + "deliverysuburb": "", + "droplat": "10.94669601", + "droplon": "76.95759796", + "deliverylat": "10.94669601", + "deliverylong": "76.95759796", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Bhuvaneshwari kitchen ", + "locationsuburb": "R.S. Puram", + "locationcity": "Coimbatore", + "locationcontactno": "9597843220", + "locationaddress": "", + "rider": "Vignesh S", + "ridercontactno": "8072675538", + "riderkms": "12.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 35, + "pickuplon": "76.95454649999999", + "deliverycharges": 30, + "pickuplocation": "R.S. Puram", + "deliverylocation": "", + "step": 3, + "previouskms": 7, + "cumulativekms": 10, + "actualkms": "8.0", + "ordertype": "Premium", + "eta": "29", + "cumulative_eta": "52", + "userid": 1036, + "username": "Vignesh S", + "expectedDeliveryTime": "2026-05-26 07:52 PM", + "transitMinutes": 52, + "calculationDistanceKm": 10.0, + "zone_name": "South", + "rider_charge": 50.0, + "profit": -20.0, + "profit_class": "Loss" + } + ] + } + ], + "unassigned_orders": [] + }, + { + "zone_name": "South East", + "total_orders": 5, + "active_riders_count": 3, + "assigned_orders": 5, + "unassigned_orders_count": 0, + "total_delivery_kms": 40.0, + "total_profit": -82.0, + "riders": [ + { + "rider_id": "753", + "rider_name": "Manikandan P", + "orders_count": 1, + "orders": [ + { + "orderheaderid": 138262, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107327", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "8", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Narmada", + "deliverycontactno": "9003722257", + "deliverylocationid": 0, + "deliveryaddress": "Mothers village apartment B104 b block pattanam itteri road Ondipudur Coimbatore Road opposite to kings home", + "deliverysuburb": "", + "droplat": "10.99833125", + "droplon": "77.04464503", + "deliverylat": "10.99833125", + "deliverylong": "77.04464503", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Manikandan P", + "ridercontactno": "9677687759", + "riderkms": "11.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 18, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 6, + "previouskms": 5, + "cumulativekms": 11, + "actualkms": "8.0", + "ordertype": "Premium", + "eta": "22", + "cumulative_eta": "71", + "userid": 753, + "username": "Manikandan P", + "expectedDeliveryTime": "2026-05-26 08:11 PM", + "transitMinutes": 71, + "calculationDistanceKm": 11.0, + "zone_name": "South East", + "rider_charge": 50.0, + "profit": -20.0, + "profit_class": "Loss" + } + ] + }, + { + "rider_id": "1111", + "rider_name": "Murali P", + "orders_count": 3, + "orders": [ + { + "orderheaderid": 138264, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107329", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "6", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Shriram", + "deliverycontactno": "8870457850", + "deliverylocationid": 0, + "deliveryaddress": "4a,Near corner stay, Abdul Rahim road,Opposite to DIG office, off race course road, Redfield,Coimbatore Take adjacent left to Lakshmi apartments", + "deliverysuburb": "", + "droplat": "11.00337671", + "droplon": "76.98414912", + "deliverylat": "11.00337671", + "deliverylong": "76.98414912", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Murali P", + "ridercontactno": "7825996002", + "riderkms": "13.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 16, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 2, + "previouskms": 4, + "cumulativekms": 6, + "actualkms": "6.0", + "ordertype": "Premium", + "eta": "20", + "cumulative_eta": "35", + "userid": 1111, + "username": "Murali P", + "expectedDeliveryTime": "2026-05-26 07:35 PM", + "transitMinutes": 35, + "calculationDistanceKm": 6.0, + "zone_name": "South East", + "rider_charge": 45.0, + "profit": -15.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138275, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107340", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "7", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Rahul Baro", + "deliverycontactno": "7892928951", + "deliverylocationid": 0, + "deliveryaddress": "Trident Serenity Apartments, 4th Floor, Block C, Flat no.2 Beneath the railway bridge flyover & Beside Sowparnika Beetel Apartment", + "deliverysuburb": "", + "droplat": "10.9796458", + "droplon": "76.9984631", + "deliverylat": "10.9796458", + "deliverylong": "76.9984631", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Murali P", + "ridercontactno": "7825996002", + "riderkms": "13.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 5, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 3, + "previouskms": 4, + "cumulativekms": 10, + "actualkms": "7.0", + "ordertype": "Premium", + "eta": "21", + "cumulative_eta": "56", + "userid": 1111, + "username": "Murali P", + "expectedDeliveryTime": "2026-05-26 07:56 PM", + "transitMinutes": 56, + "calculationDistanceKm": 10.0, + "zone_name": "South East", + "rider_charge": 47.5, + "profit": -17.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138263, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107328", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "10", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 42, + "orderamount": 42, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Karthi", + "deliverycontactno": "9362625249", + "deliverylocationid": 0, + "deliveryaddress": "42, 10th cross street, Satyanarayana Nagar, Podanur Opposite to Podanur Indian Bank", + "deliverysuburb": "", + "droplat": "10.9696875", + "droplon": "76.9852969", + "deliverylat": "10.9696875", + "deliverylong": "76.9852969", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Murali P", + "ridercontactno": "7825996002", + "riderkms": "13.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 2, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 17, + "pickuplon": "77.0147763", + "deliverycharges": 42, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 4, + "previouskms": 3, + "cumulativekms": 13, + "actualkms": "10.0", + "ordertype": "Premium", + "eta": "13", + "cumulative_eta": "69", + "userid": 1111, + "username": "Murali P", + "expectedDeliveryTime": "2026-05-26 08:09 PM", + "transitMinutes": 69, + "calculationDistanceKm": 13.0, + "zone_name": "South East", + "rider_charge": 55.0, + "profit": -13.0, + "profit_class": "Loss" + } + ] + }, + { + "rider_id": "1036", + "rider_name": "Vignesh S", + "orders_count": 1, + "orders": [ + { + "orderheaderid": 138246, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 1076, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107311", + "orderdate": "2026-05-26T18:29:57+05:30", + "deliverydate": "2026-05-26 12:59:57", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "9", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 36, + "orderamount": 36, + "customerid": 0, + "pickupcustomer": "Bhuvaneshwari kitchen ", + "pickupcontactno": "9597843220", + "pickuplocationid": 1076, + "pickupaddress": "Coimbatore, Light House Road, Kollupuram, Sukrawar Pettai, R.S. Puram, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "R.S. Puram", + "pickupcity": "Coimbatore", + "pickuplat": "11.0035176", + "pickuplong": "76.95454649999999", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "SIVASANKAR", + "deliverycontactno": "9789781030", + "deliverylocationid": 0, + "deliveryaddress": "110 B MGR Nagar, Madukkarai Road, Sidco Post, Coimbatore - 641021 Near Pandit Nehru School", + "deliverysuburb": "", + "droplat": "10.9450125", + "droplon": "76.9696719", + "deliverylat": "10.9450125", + "deliverylong": "76.9696719", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Bhuvaneshwari kitchen ", + "locationsuburb": "R.S. Puram", + "locationcity": "Coimbatore", + "locationcontactno": "9597843220", + "locationaddress": "", + "rider": "Vignesh S", + "ridercontactno": "8072675538", + "riderkms": "12.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 34, + "pickuplon": "76.95454649999999", + "deliverycharges": 36, + "pickuplocation": "R.S. Puram", + "deliverylocation": "", + "step": 4, + "previouskms": 2, + "cumulativekms": 12, + "actualkms": "9.0", + "ordertype": "Premium", + "eta": "13", + "cumulative_eta": "65", + "userid": 1036, + "username": "Vignesh S", + "expectedDeliveryTime": "2026-05-26 08:05 PM", + "transitMinutes": 65, + "calculationDistanceKm": 12.0, + "zone_name": "South East", + "rider_charge": 52.5, + "profit": -16.5, + "profit_class": "Loss" + } + ] + } + ], + "unassigned_orders": [] + } + ], + "details": [ + { + "orderheaderid": 138278, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107343", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Kandavelu", + "deliverycontactno": "9443913591", + "deliverylocationid": 0, + "deliveryaddress": "35 Jai Nagar 2nd street, Peelamedu Call 9443913591", + "deliverysuburb": "", + "droplat": "11.03240253", + "droplon": "77.01003422", + "deliverylat": "11.03240253", + "deliverylong": "77.01003422", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Manikandan P", + "ridercontactno": "9677687759", + "riderkms": "11.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 2, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 2, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 1, + "previouskms": 3, + "cumulativekms": 3, + "actualkms": "4.0", + "ordertype": "Economy", + "eta": "17", + "cumulative_eta": "17", + "userid": 753, + "username": "Manikandan P", + "expectedDeliveryTime": "2026-05-26 07:17 PM", + "transitMinutes": 17, + "calculationDistanceKm": 3.0, + "zone_name": "North East", + "rider_charge": 40.0, + "profit": -10.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138271, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107336", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Varsha", + "deliverycontactno": "9944397248", + "deliverylocationid": 0, + "deliveryaddress": "Masakalipalayam road,No.12,kalyana Sundara street New Iyengar bakery cut", + "deliverysuburb": "", + "droplat": "11.0241383", + "droplon": "77.0184563", + "deliverylat": "11.0241383", + "deliverylong": "77.0184563", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Manikandan P", + "ridercontactno": "9677687759", + "riderkms": "11.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 9, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 2, + "previouskms": 2, + "cumulativekms": 5, + "actualkms": "3.0", + "ordertype": "Economy", + "eta": "12", + "cumulative_eta": "29", + "userid": 753, + "username": "Manikandan P", + "expectedDeliveryTime": "2026-05-26 07:29 PM", + "transitMinutes": 29, + "calculationDistanceKm": 5.0, + "zone_name": "East", + "rider_charge": 37.5, + "profit": -7.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138270, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107335", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Vasu dharani", + "deliverycontactno": "9042730736", + "deliverylocationid": 0, + "deliveryaddress": "Royal stitch, no.26 , Srinagar, hope college Royal stitch ", + "deliverysuburb": "", + "droplat": "11.0251802", + "droplon": "77.0198024", + "deliverylat": "11.0251802", + "deliverylong": "77.0198024", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Manikandan P", + "ridercontactno": "9677687759", + "riderkms": "11.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 2, + "collectionamt": 1613, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 10, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 3, + "previouskms": 0, + "cumulativekms": 5, + "actualkms": "3.0", + "ordertype": "Economy", + "eta": "6", + "cumulative_eta": "35", + "userid": 753, + "username": "Manikandan P", + "expectedDeliveryTime": "2026-05-26 07:35 PM", + "transitMinutes": 35, + "calculationDistanceKm": 5.0, + "zone_name": "East", + "rider_charge": 37.5, + "profit": -7.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138272, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107337", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "1", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "M.S.JAVID", + "deliverycontactno": "7558120192", + "deliverylocationid": 0, + "deliveryaddress": "ROOM No-21, J.K COMPLEX, 386/A3, KAMARAJAR ROAD, PEELAMEDU, COIMBATORE-641004, NEAR BY SPAZEONE, NNRC ELDER CARE & RHR HOTEL", + "deliverysuburb": "", + "droplat": "11.0207363", + "droplon": "77.0220709", + "deliverylat": "11.0207363", + "deliverylong": "77.0220709", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Manikandan P", + "ridercontactno": "9677687759", + "riderkms": "11.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 8, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 4, + "previouskms": 1, + "cumulativekms": 6, + "actualkms": "1.0", + "ordertype": "Economy", + "eta": "8", + "cumulative_eta": "43", + "userid": 753, + "username": "Manikandan P", + "expectedDeliveryTime": "2026-05-26 07:43 PM", + "transitMinutes": 43, + "calculationDistanceKm": 6.0, + "zone_name": "East", + "rider_charge": 32.5, + "profit": -2.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138279, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107344", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "2", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Pooja", + "deliverycontactno": "9080859196", + "deliverylocationid": 0, + "deliveryaddress": "C1 castle park apartment, Ramanujam Nagar, Uppilipalayam C1- 3rd floor", + "deliverysuburb": "", + "droplat": "11.01933791", + "droplon": "77.02415225", + "deliverylat": "11.01933791", + "deliverylong": "77.02415225", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Manikandan P", + "ridercontactno": "9677687759", + "riderkms": "11.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 1, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 5, + "previouskms": 0, + "cumulativekms": 6, + "actualkms": "2.0", + "ordertype": "Economy", + "eta": "6", + "cumulative_eta": "49", + "userid": 753, + "username": "Manikandan P", + "expectedDeliveryTime": "2026-05-26 07:49 PM", + "transitMinutes": 49, + "calculationDistanceKm": 6.0, + "zone_name": "East", + "rider_charge": 35.0, + "profit": -5.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138262, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107327", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "8", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Narmada", + "deliverycontactno": "9003722257", + "deliverylocationid": 0, + "deliveryaddress": "Mothers village apartment B104 b block pattanam itteri road Ondipudur Coimbatore Road opposite to kings home", + "deliverysuburb": "", + "droplat": "10.99833125", + "droplon": "77.04464503", + "deliverylat": "10.99833125", + "deliverylong": "77.04464503", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Manikandan P", + "ridercontactno": "9677687759", + "riderkms": "11.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 18, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 6, + "previouskms": 5, + "cumulativekms": 11, + "actualkms": "8.0", + "ordertype": "Premium", + "eta": "22", + "cumulative_eta": "71", + "userid": 753, + "username": "Manikandan P", + "expectedDeliveryTime": "2026-05-26 08:11 PM", + "transitMinutes": 71, + "calculationDistanceKm": 11.0, + "zone_name": "South East", + "rider_charge": 50.0, + "profit": -20.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138268, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107333", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Devikarani", + "deliverycontactno": "9940666706", + "deliverylocationid": 0, + "deliveryaddress": "229 Giriamman kovil street Peelamedu - near Peelamedu railway station call 9940666706", + "deliverysuburb": "", + "droplat": "11.0315832", + "droplon": "77.0005771", + "deliverylat": "11.0315832", + "deliverylong": "77.0005771", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Rajan A", + "ridercontactno": "9787698259", + "riderkms": "10.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 12, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 1, + "previouskms": 3, + "cumulativekms": 3, + "actualkms": "3.0", + "ordertype": "Economy", + "eta": "20", + "cumulative_eta": "20", + "userid": 883, + "username": "Rajan A", + "expectedDeliveryTime": "2026-05-26 07:20 PM", + "transitMinutes": 20, + "calculationDistanceKm": 3.0, + "zone_name": "North East", + "rider_charge": 37.5, + "profit": -7.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138273, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107338", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Athira Sooraj", + "deliverycontactno": "9847568898", + "deliverylocationid": 0, + "deliveryaddress": "80, Murugan Kovil street, Avarampalayam Road, Peelamedu Next to Akashmalli apartments", + "deliverysuburb": "", + "droplat": "11.02609076", + "droplon": "76.99829646", + "deliverylat": "11.02609076", + "deliverylong": "76.99829646", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Rajan A", + "ridercontactno": "9787698259", + "riderkms": "10.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 7, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 2, + "previouskms": 1, + "cumulativekms": 4, + "actualkms": "3.0", + "ordertype": "Economy", + "eta": "9", + "cumulative_eta": "29", + "userid": 883, + "username": "Rajan A", + "expectedDeliveryTime": "2026-05-26 07:29 PM", + "transitMinutes": 29, + "calculationDistanceKm": 4.0, + "zone_name": "East", + "rider_charge": 37.5, + "profit": -7.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138276, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107341", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Santosh kumar", + "deliverycontactno": "9500088928", + "deliverylocationid": 0, + "deliveryaddress": "alanita travel pvt ltd,5th floor,valencia building,336/1, Avinashi Road,Coimbatore", + "deliverysuburb": "", + "droplat": "11.01912568", + "droplon": "76.99127706", + "deliverylat": "11.01912568", + "deliverylong": "76.99127706", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Rajan A", + "ridercontactno": "9787698259", + "riderkms": "10.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 4, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 3, + "previouskms": 2, + "cumulativekms": 6, + "actualkms": "4.0", + "ordertype": "Economy", + "eta": "11", + "cumulative_eta": "40", + "userid": 883, + "username": "Rajan A", + "expectedDeliveryTime": "2026-05-26 07:40 PM", + "transitMinutes": 40, + "calculationDistanceKm": 6.0, + "zone_name": "East", + "rider_charge": 40.0, + "profit": -10.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138269, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107334", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "5", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Manikumar", + "deliverycontactno": "9025625195", + "deliverylocationid": 0, + "deliveryaddress": "Tristar towers 4th floor 407 room no Near angannan briyani", + "deliverysuburb": "", + "droplat": "11.01136931", + "droplon": "76.98546701", + "deliverylat": "11.01136931", + "deliverylong": "76.98546701", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Rajan A", + "ridercontactno": "9787698259", + "riderkms": "10.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 11, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 4, + "previouskms": 2, + "cumulativekms": 7, + "actualkms": "5.0", + "ordertype": "Economy", + "eta": "11", + "cumulative_eta": "51", + "userid": 883, + "username": "Rajan A", + "expectedDeliveryTime": "2026-05-26 07:51 PM", + "transitMinutes": 51, + "calculationDistanceKm": 7.0, + "zone_name": "East", + "rider_charge": 42.5, + "profit": -12.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138277, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107342", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "7", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Aishwarya", + "deliverycontactno": "7708542801", + "deliverylocationid": 0, + "deliveryaddress": "1c A block Pioneer apartment Avinashi road Near Residency towers", + "deliverysuburb": "", + "droplat": "11.0105", + "droplon": "76.98", + "deliverylat": "11.0105", + "deliverylong": "76.98", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Rajan A", + "ridercontactno": "9787698259", + "riderkms": "10.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 3, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 5, + "previouskms": 1, + "cumulativekms": 8, + "actualkms": "7.0", + "ordertype": "Premium", + "eta": "8", + "cumulative_eta": "59", + "userid": 883, + "username": "Rajan A", + "expectedDeliveryTime": "2026-05-26 07:59 PM", + "transitMinutes": 59, + "calculationDistanceKm": 8.0, + "zone_name": "East", + "rider_charge": 47.5, + "profit": -17.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138265, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107330", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "7", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Yaswanth Sai Jami", + "deliverycontactno": "9618838341", + "deliverylocationid": 0, + "deliveryaddress": "Flat 4b, B block, Pioneer Apartments, Pappanaickenpalayam Beside residency towers hotel ", + "deliverysuburb": "", + "droplat": "11.01067171", + "droplon": "76.97995486", + "deliverylat": "11.01067171", + "deliverylong": "76.97995486", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Rajan A", + "ridercontactno": "9787698259", + "riderkms": "10.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 2, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 15, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 6, + "previouskms": 0, + "cumulativekms": 8, + "actualkms": "7.0", + "ordertype": "Premium", + "eta": "5", + "cumulative_eta": "64", + "userid": 883, + "username": "Rajan A", + "expectedDeliveryTime": "2026-05-26 08:04 PM", + "transitMinutes": 64, + "calculationDistanceKm": 8.0, + "zone_name": "East", + "rider_charge": 47.5, + "profit": -17.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138266, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107331", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "7", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Kannammal", + "deliverycontactno": "8884366950", + "deliverylocationid": 0, + "deliveryaddress": "47 Ambika Layout, New Siddhapudur Opp to Kaleeswari Broiler", + "deliverysuburb": "", + "droplat": "11.01962586", + "droplon": "76.97291096", + "deliverylat": "11.01962586", + "deliverylong": "76.97291096", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Rajan A", + "ridercontactno": "9787698259", + "riderkms": "10.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 14, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 7, + "previouskms": 2, + "cumulativekms": 10, + "actualkms": "7.0", + "ordertype": "Premium", + "eta": "12", + "cumulative_eta": "76", + "userid": 883, + "username": "Rajan A", + "expectedDeliveryTime": "2026-05-26 08:16 PM", + "transitMinutes": 76, + "calculationDistanceKm": 10.0, + "zone_name": "East", + "rider_charge": 47.5, + "profit": -17.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138267, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107332", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "2", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "backiaraj k", + "deliverycontactno": "8807424447", + "deliverylocationid": 0, + "deliveryaddress": "1/112, Annai Velankanni Nagar, Sowripalayam, Coimbatore -641028 JJ Stores", + "deliverysuburb": "", + "droplat": "11.00715552", + "droplon": "77.00965818", + "deliverylat": "11.00715552", + "deliverylong": "77.00965818", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Murali P", + "ridercontactno": "7825996002", + "riderkms": "13.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 13, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 1, + "previouskms": 2, + "cumulativekms": 2, + "actualkms": "2.0", + "ordertype": "Economy", + "eta": "15", + "cumulative_eta": "15", + "userid": 1111, + "username": "Murali P", + "expectedDeliveryTime": "2026-05-26 07:15 PM", + "transitMinutes": 15, + "calculationDistanceKm": 2.0, + "zone_name": "East", + "rider_charge": 35.0, + "profit": -5.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138264, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107329", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "6", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Shriram", + "deliverycontactno": "8870457850", + "deliverylocationid": 0, + "deliveryaddress": "4a,Near corner stay, Abdul Rahim road,Opposite to DIG office, off race course road, Redfield,Coimbatore Take adjacent left to Lakshmi apartments", + "deliverysuburb": "", + "droplat": "11.00337671", + "droplon": "76.98414912", + "deliverylat": "11.00337671", + "deliverylong": "76.98414912", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Murali P", + "ridercontactno": "7825996002", + "riderkms": "13.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 16, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 2, + "previouskms": 4, + "cumulativekms": 6, + "actualkms": "6.0", + "ordertype": "Premium", + "eta": "20", + "cumulative_eta": "35", + "userid": 1111, + "username": "Murali P", + "expectedDeliveryTime": "2026-05-26 07:35 PM", + "transitMinutes": 35, + "calculationDistanceKm": 6.0, + "zone_name": "South East", + "rider_charge": 45.0, + "profit": -15.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138275, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107340", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "7", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Rahul Baro", + "deliverycontactno": "7892928951", + "deliverylocationid": 0, + "deliveryaddress": "Trident Serenity Apartments, 4th Floor, Block C, Flat no.2 Beneath the railway bridge flyover & Beside Sowparnika Beetel Apartment", + "deliverysuburb": "", + "droplat": "10.9796458", + "droplon": "76.9984631", + "deliverylat": "10.9796458", + "deliverylong": "76.9984631", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Murali P", + "ridercontactno": "7825996002", + "riderkms": "13.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 5, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 3, + "previouskms": 4, + "cumulativekms": 10, + "actualkms": "7.0", + "ordertype": "Premium", + "eta": "21", + "cumulative_eta": "56", + "userid": 1111, + "username": "Murali P", + "expectedDeliveryTime": "2026-05-26 07:56 PM", + "transitMinutes": 56, + "calculationDistanceKm": 10.0, + "zone_name": "South East", + "rider_charge": 47.5, + "profit": -17.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138263, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107328", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "10", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 42, + "orderamount": 42, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Karthi", + "deliverycontactno": "9362625249", + "deliverylocationid": 0, + "deliveryaddress": "42, 10th cross street, Satyanarayana Nagar, Podanur Opposite to Podanur Indian Bank", + "deliverysuburb": "", + "droplat": "10.9696875", + "droplon": "76.9852969", + "deliverylat": "10.9696875", + "deliverylong": "76.9852969", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Murali P", + "ridercontactno": "7825996002", + "riderkms": "13.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 2, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 17, + "pickuplon": "77.0147763", + "deliverycharges": 42, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 4, + "previouskms": 3, + "cumulativekms": 13, + "actualkms": "10.0", + "ordertype": "Premium", + "eta": "13", + "cumulative_eta": "69", + "userid": 1111, + "username": "Murali P", + "expectedDeliveryTime": "2026-05-26 08:09 PM", + "transitMinutes": 69, + "calculationDistanceKm": 13.0, + "zone_name": "South East", + "rider_charge": 55.0, + "profit": -13.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138274, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 979, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107339", + "orderdate": "2026-05-26T18:30:33+05:30", + "deliverydate": "2026-05-26 13:00:33", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "7", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Vidhya kitchen", + "pickupcontactno": "8148910297", + "pickuplocationid": 979, + "pickupaddress": "Ritham Tours & Travels, Peelamedu, Ram Lakshman Nagar, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "uppilipalayam ", + "pickupcity": "Coimbatore", + "pickuplat": "11.0163268", + "pickuplong": "77.0147763", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Manoj", + "deliverycontactno": "9944192192", + "deliverylocationid": 0, + "deliveryaddress": "D-424, 4th Floor, Icon City Apartment, Unity Road, Vishweshwara Nagar, Near Cheran Ma Nagar, Villankurichi, Coimbatore - 641035 Villankurichi Road, Konku Bakery Road", + "deliverysuburb": "", + "droplat": "11.05688855", + "droplon": "77.01173596", + "deliverylat": "11.05688855", + "deliverylong": "77.01173596", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Vidhya kitchen", + "locationsuburb": "uppilipalayam ", + "locationcity": "Coimbatore", + "locationcontactno": "8148910297", + "locationaddress": "", + "rider": "Tamilazhagan K", + "ridercontactno": "9788633337", + "riderkms": "7.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 6, + "pickuplon": "77.0147763", + "deliverycharges": 30, + "pickuplocation": "uppilipalayam ", + "deliverylocation": "", + "step": 1, + "previouskms": 7, + "cumulativekms": 7, + "actualkms": "7.0", + "ordertype": "Premium", + "eta": "31", + "cumulative_eta": "31", + "userid": 1114, + "username": "Tamilazhagan K", + "expectedDeliveryTime": "2026-05-26 07:31 PM", + "transitMinutes": 31, + "calculationDistanceKm": 7.0, + "zone_name": "North East", + "rider_charge": 47.5, + "profit": -17.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138261, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107326", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "9", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 36, + "orderamount": 36, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Sri Gokul", + "deliverycontactno": "9080187878", + "deliverylocationid": 0, + "deliveryaddress": "The focus room,Mettupalayam Rd, Daniel Nagar, Thoppampatti Pirivu, K. Vadamadurai, Coimbatore, Tamil Nadu 641017 Thudiyalur Dmart ", + "deliverysuburb": "", + "droplat": "11.0982", + "droplon": "76.9388", + "deliverylat": "11.0982", + "deliverylong": "76.9388", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Varun Edward", + "ridercontactno": "8248136667", + "riderkms": "10.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 19, + "pickuplon": "76.9300797", + "deliverycharges": 36, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 1, + "previouskms": 10, + "cumulativekms": 10, + "actualkms": "9.0", + "ordertype": "Premium", + "eta": "38", + "cumulative_eta": "38", + "userid": 897, + "username": "Varun Edward", + "expectedDeliveryTime": "2026-05-26 07:38 PM", + "transitMinutes": 38, + "calculationDistanceKm": 10.0, + "zone_name": "North West", + "rider_charge": 52.5, + "profit": -16.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138253, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107318", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "6", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Sreedevi", + "deliverycontactno": "7639720883", + "deliverylocationid": 0, + "deliveryaddress": "124/b5 Thirumagal nagar Maniakarampalayam near ganapathy medical centre", + "deliverysuburb": "", + "droplat": "11.04665266", + "droplon": "76.97522061", + "deliverylat": "11.04665266", + "deliverylong": "76.97522061", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Jayasabesh Kumar S", + "ridercontactno": "8940295001", + "riderkms": "30.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 27, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 1, + "previouskms": 7, + "cumulativekms": 7, + "actualkms": "6.0", + "ordertype": "Premium", + "eta": "33", + "cumulative_eta": "33", + "userid": 950, + "username": "Jayasabesh Kumar S", + "expectedDeliveryTime": "2026-05-26 07:33 PM", + "transitMinutes": 33, + "calculationDistanceKm": 7.0, + "zone_name": "North East", + "rider_charge": 45.0, + "profit": -15.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138260, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107325", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "9", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 36, + "orderamount": 36, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Archanaa", + "deliverycontactno": "7899051088", + "deliverylocationid": 0, + "deliveryaddress": "No 2, Annai Garden, Sakthi Nagar, Chinnavedampatti Backside of Dhivyam Apartment", + "deliverysuburb": "", + "droplat": "11.0583375", + "droplon": "76.9869531", + "deliverylat": "11.0583375", + "deliverylong": "76.9869531", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Jayasabesh Kumar S", + "ridercontactno": "8940295001", + "riderkms": "30.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 20, + "pickuplon": "76.9300797", + "deliverycharges": 36, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 2, + "previouskms": 3, + "cumulativekms": 10, + "actualkms": "9.0", + "ordertype": "Premium", + "eta": "13", + "cumulative_eta": "46", + "userid": 950, + "username": "Jayasabesh Kumar S", + "expectedDeliveryTime": "2026-05-26 07:46 PM", + "transitMinutes": 46, + "calculationDistanceKm": 10.0, + "zone_name": "North East", + "rider_charge": 52.5, + "profit": -16.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138250, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107315", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "12", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 54, + "orderamount": 54, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Swetha", + "deliverycontactno": "9360052122", + "deliverylocationid": 0, + "deliveryaddress": "RoomNo:202, SF No.252/1B, 252/1C, Cheran Nagar, Villankurichi, Coimbatore, Tamil Nadu 641035 Icon city-TNCD", + "deliverysuburb": "", + "droplat": "11.0572", + "droplon": "77.0119", + "deliverylat": "11.0572", + "deliverylong": "77.0119", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Jayasabesh Kumar S", + "ridercontactno": "8940295001", + "riderkms": "30.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 30, + "pickuplon": "76.9300797", + "deliverycharges": 54, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 3, + "previouskms": 4, + "cumulativekms": 14, + "actualkms": "12.0", + "ordertype": "Premium", + "eta": "19", + "cumulative_eta": "65", + "userid": 950, + "username": "Jayasabesh Kumar S", + "expectedDeliveryTime": "2026-05-26 08:05 PM", + "transitMinutes": 65, + "calculationDistanceKm": 14.0, + "zone_name": "North East", + "rider_charge": 60.0, + "profit": -6.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138258, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107323", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "13", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 60, + "orderamount": 60, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Srihari", + "deliverycontactno": "8883267757", + "deliverylocationid": 0, + "deliveryaddress": "Avinash enclave, 3rd floor, 11-D, L N Nagar, Balaji Nagar Phase 2 My house is in backside of KMCH Nursing College.", + "deliverysuburb": "", + "droplat": "11.06662342", + "droplon": "77.03174932", + "deliverylat": "11.06662342", + "deliverylong": "77.03174932", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Jayasabesh Kumar S", + "ridercontactno": "8940295001", + "riderkms": "30.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 22, + "pickuplon": "76.9300797", + "deliverycharges": 60, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 4, + "previouskms": 4, + "cumulativekms": 17, + "actualkms": "13.0", + "ordertype": "Risky", + "eta": "18", + "cumulative_eta": "83", + "userid": 950, + "username": "Jayasabesh Kumar S", + "expectedDeliveryTime": "2026-05-26 08:23 PM", + "transitMinutes": 83, + "calculationDistanceKm": 17.0, + "zone_name": "North East", + "rider_charge": 62.5, + "profit": -2.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138252, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107317", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "18", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 90, + "orderamount": 90, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Anirudh S Rao", + "deliverycontactno": "9840965656", + "deliverylocationid": 0, + "deliveryaddress": "Villa 68, phase 2, Casa Grande Eternia SNS Kalvi Nagar, Kurumbupalayam, SSKulam, Kalapatti road, Coimbatore, 641048 Casa Grande Eternia phase 2", + "deliverysuburb": "", + "droplat": "11.1022", + "droplon": "77.0328", + "deliverylat": "11.1022", + "deliverylong": "77.0328", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Jayasabesh Kumar S", + "ridercontactno": "8940295001", + "riderkms": "30.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 28, + "pickuplon": "76.9300797", + "deliverycharges": 90, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 5, + "previouskms": 6, + "cumulativekms": 23, + "actualkms": "18.0", + "ordertype": "Risky", + "eta": "25", + "cumulative_eta": "108", + "userid": 950, + "username": "Jayasabesh Kumar S", + "expectedDeliveryTime": "2026-05-26 08:48 PM", + "transitMinutes": 108, + "calculationDistanceKm": 23.0, + "zone_name": "North East", + "rider_charge": 75.0, + "profit": 15.0, + "profit_class": "HighMargin" + }, + { + "orderheaderid": 138256, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107321", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "13", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 60, + "orderamount": 60, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Bhaswar Tudu", + "deliverycontactno": "9179046653", + "deliverylocationid": 0, + "deliveryaddress": "7T1, Gate-1, Tower-1, KGISL Platina, Keeranatham Road, Saravanampatti Near Chil-Sez IT Park", + "deliverysuburb": "", + "droplat": "11.1020098", + "droplon": "76.9911354", + "deliverylat": "11.1020098", + "deliverylong": "76.9911354", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Jayasabesh Kumar S", + "ridercontactno": "8940295001", + "riderkms": "30.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 24, + "pickuplon": "76.9300797", + "deliverycharges": 60, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 6, + "previouskms": 7, + "cumulativekms": 30, + "actualkms": "13.0", + "ordertype": "Risky", + "eta": "28", + "cumulative_eta": "136", + "userid": 950, + "username": "Jayasabesh Kumar S", + "expectedDeliveryTime": "2026-05-26 09:16 PM", + "transitMinutes": 136, + "calculationDistanceKm": 30.0, + "zone_name": "North East", + "rider_charge": 62.5, + "profit": -2.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138259, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107324", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "13", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 60, + "orderamount": 60, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Aiswarya S Menon", + "deliverycontactno": "8547076489", + "deliverylocationid": 0, + "deliveryaddress": "CA 807, Coral A, Kgisl metropolis apartments Near CHIL SEZ IT park", + "deliverysuburb": "", + "droplat": "11.1015", + "droplon": "76.9907", + "deliverylat": "11.1015", + "deliverylong": "76.9907", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Jayasabesh Kumar S", + "ridercontactno": "8940295001", + "riderkms": "30.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 2, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 21, + "pickuplon": "76.9300797", + "deliverycharges": 60, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 7, + "previouskms": 0, + "cumulativekms": 30, + "actualkms": "13.0", + "ordertype": "Risky", + "eta": "5", + "cumulative_eta": "141", + "userid": 950, + "username": "Jayasabesh Kumar S", + "expectedDeliveryTime": "2026-05-26 09:21 PM", + "transitMinutes": 141, + "calculationDistanceKm": 30.0, + "zone_name": "North East", + "rider_charge": 62.5, + "profit": -2.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138251, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107316", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "VIGNESH", + "deliverycontactno": "6384868679", + "deliverylocationid": 0, + "deliveryaddress": "SECOND FLOOR, BUILDING NO 39, ALAGESAN ROAD,SAIBABA COLONY KAAPPI READY BUILDING SECOND FLOOR", + "deliverysuburb": "", + "droplat": "11.02296785", + "droplon": "76.94656475", + "deliverylat": "11.02296785", + "deliverylong": "76.94656475", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Nagalakshmi M", + "ridercontactno": "8778484594", + "riderkms": "9.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 29, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 1, + "previouskms": 4, + "cumulativekms": 4, + "actualkms": "4.0", + "ordertype": "Economy", + "eta": "21", + "cumulative_eta": "21", + "userid": 1062, + "username": "Nagalakshmi M", + "expectedDeliveryTime": "2026-05-26 07:21 PM", + "transitMinutes": 21, + "calculationDistanceKm": 4.0, + "zone_name": "Central", + "rider_charge": 40.0, + "profit": -10.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138255, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107320", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "4", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Sivasubramanian", + "deliverycontactno": "9994425347", + "deliverylocationid": 0, + "deliveryaddress": "72-1 Cowley Brown Road, RS Puram, CBE-2 Come inside gate east of Champion Physiotherapy then 1st house to the right", + "deliverysuburb": "", + "droplat": "11.0147203", + "droplon": "76.9464989", + "deliverylat": "11.0147203", + "deliverylong": "76.9464989", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Nagalakshmi M", + "ridercontactno": "8778484594", + "riderkms": "9.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 25, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 2, + "previouskms": 1, + "cumulativekms": 5, + "actualkms": "4.0", + "ordertype": "Economy", + "eta": "10", + "cumulative_eta": "31", + "userid": 1062, + "username": "Nagalakshmi M", + "expectedDeliveryTime": "2026-05-26 07:31 PM", + "transitMinutes": 31, + "calculationDistanceKm": 5.0, + "zone_name": "Central", + "rider_charge": 40.0, + "profit": -10.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138254, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107319", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "5", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Indirani", + "deliverycontactno": "9566644154", + "deliverylocationid": 0, + "deliveryaddress": "152,A.Ramalingam colony, mettupalayam road Opp .Meenakshi gov hospital, avanashilingam college 3 rd gate opp road ", + "deliverysuburb": "", + "droplat": "11.0213553", + "droplon": "76.9506268", + "deliverylat": "11.0213553", + "deliverylong": "76.9506268", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Nagalakshmi M", + "ridercontactno": "8778484594", + "riderkms": "9.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 26, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 3, + "previouskms": 1, + "cumulativekms": 6, + "actualkms": "5.0", + "ordertype": "Economy", + "eta": "10", + "cumulative_eta": "41", + "userid": 1062, + "username": "Nagalakshmi M", + "expectedDeliveryTime": "2026-05-26 07:41 PM", + "transitMinutes": 41, + "calculationDistanceKm": 6.0, + "zone_name": "Central", + "rider_charge": 42.5, + "profit": -12.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138257, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107322", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "6", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "P M PRADEEP", + "deliverycontactno": "9786698944", + "deliverylocationid": 0, + "deliveryaddress": "Old No 98, New No 111, Raju Naidu Road, Tatabad, Coimbatore 641012. In Between South Indian Coffee and Amutham Pharmacy", + "deliverysuburb": "", + "droplat": "11.02174992", + "droplon": "76.95937411", + "deliverylat": "11.02174992", + "deliverylong": "76.95937411", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Nagalakshmi M", + "ridercontactno": "8778484594", + "riderkms": "9.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 23, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 4, + "previouskms": 1, + "cumulativekms": 8, + "actualkms": "6.0", + "ordertype": "Premium", + "eta": "10", + "cumulative_eta": "51", + "userid": 1062, + "username": "Nagalakshmi M", + "expectedDeliveryTime": "2026-05-26 07:51 PM", + "transitMinutes": 51, + "calculationDistanceKm": 8.0, + "zone_name": "Central", + "rider_charge": 45.0, + "profit": -15.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138249, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 991, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107314", + "orderdate": "2026-05-26T18:30:15+05:30", + "deliverydate": "2026-05-26 13:00:15", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "6", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Daily grubs(jayanthi kitchen)", + "pickupcontactno": "7871951739", + "pickuplocationid": 991, + "pickupaddress": "GET STITCHED Boutique, Kavundampalayam West Road, Edayarpalayam, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "Kavandam", + "pickupcity": "Pappanaickenpalayam", + "pickuplat": "11.0388679", + "pickuplong": "76.9300797", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Kiran Divagar", + "deliverycontactno": "9944473099", + "deliverylocationid": 0, + "deliveryaddress": "Mukilan Maghizagam , 7/4 , 2nd Cross Street , PM Samy colony, Rathinapuri , Coimbatore Near Yoga Center", + "deliverysuburb": "", + "droplat": "11.02603373", + "droplon": "76.96712952", + "deliverylat": "11.02603373", + "deliverylong": "76.96712952", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Daily grubs(jayanthi kitchen)", + "locationsuburb": "Kavandam", + "locationcity": "Pappanaickenpalayam", + "locationcontactno": "7871951739", + "locationaddress": "", + "rider": "Nagalakshmi M", + "ridercontactno": "8778484594", + "riderkms": "9.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 31, + "pickuplon": "76.9300797", + "deliverycharges": 30, + "pickuplocation": "Kavandam", + "deliverylocation": "", + "step": 5, + "previouskms": 1, + "cumulativekms": 9, + "actualkms": "6.0", + "ordertype": "Premium", + "eta": "10", + "cumulative_eta": "61", + "userid": 1062, + "username": "Nagalakshmi M", + "expectedDeliveryTime": "2026-05-26 08:01 PM", + "transitMinutes": 61, + "calculationDistanceKm": 9.0, + "zone_name": "East", + "rider_charge": 45.0, + "profit": -15.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138247, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 1076, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107312", + "orderdate": "2026-05-26T18:29:57+05:30", + "deliverydate": "2026-05-26 12:59:57", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "2", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Bhuvaneshwari kitchen ", + "pickupcontactno": "9597843220", + "pickuplocationid": 1076, + "pickupaddress": "Coimbatore, Light House Road, Kollupuram, Sukrawar Pettai, R.S. Puram, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "R.S. Puram", + "pickupcity": "Coimbatore", + "pickuplat": "11.0035176", + "pickuplong": "76.95454649999999", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Bharathi M", + "deliverycontactno": "9626274199", + "deliverylocationid": 0, + "deliveryaddress": "No. 56-59, Samy Iyer new Street, Opp.to Sri anantha theertha mandhir, coimbatore -641001. 1 St floor.. near to jayasurya sanna kambi kadai", + "deliverysuburb": "", + "droplat": "10.99494658", + "droplon": "76.94954136", + "deliverylat": "10.99494658", + "deliverylong": "76.94954136", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Bhuvaneshwari kitchen ", + "locationsuburb": "R.S. Puram", + "locationcity": "Coimbatore", + "locationcontactno": "9597843220", + "locationaddress": "", + "rider": "Vignesh S", + "ridercontactno": "8072675538", + "riderkms": "12.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 33, + "pickuplon": "76.95454649999999", + "deliverycharges": 30, + "pickuplocation": "R.S. Puram", + "deliverylocation": "", + "step": 1, + "previouskms": 2, + "cumulativekms": 2, + "actualkms": "2.0", + "ordertype": "Economy", + "eta": "14", + "cumulative_eta": "14", + "userid": 1036, + "username": "Vignesh S", + "expectedDeliveryTime": "2026-05-26 07:14 PM", + "transitMinutes": 14, + "calculationDistanceKm": 2.0, + "zone_name": "South", + "rider_charge": 35.0, + "profit": -5.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138248, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 1076, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107313", + "orderdate": "2026-05-26T18:29:57+05:30", + "deliverydate": "2026-05-26 12:59:57", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "3", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Bhuvaneshwari kitchen ", + "pickupcontactno": "9597843220", + "pickuplocationid": 1076, + "pickupaddress": "Coimbatore, Light House Road, Kollupuram, Sukrawar Pettai, R.S. Puram, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "R.S. Puram", + "pickupcity": "Coimbatore", + "pickuplat": "11.0035176", + "pickuplong": "76.95454649999999", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "R. VIJAYAKUMAR", + "deliverycontactno": "9894145933", + "deliverylocationid": 0, + "deliveryaddress": "1st block G3 ( ground floor) Vishwa apartment Prabhu Nagar sandaka Muthoot bypass road Coimbatore Opp Selvapuram Government Higher Secondary School", + "deliverysuburb": "", + "droplat": "10.9887125", + "droplon": "76.9470469", + "deliverylat": "10.9887125", + "deliverylong": "76.9470469", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Bhuvaneshwari kitchen ", + "locationsuburb": "R.S. Puram", + "locationcity": "Coimbatore", + "locationcontactno": "9597843220", + "locationaddress": "", + "rider": "Vignesh S", + "ridercontactno": "8072675538", + "riderkms": "12.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 32, + "pickuplon": "76.95454649999999", + "deliverycharges": 30, + "pickuplocation": "R.S. Puram", + "deliverylocation": "", + "step": 2, + "previouskms": 1, + "cumulativekms": 3, + "actualkms": "3.0", + "ordertype": "Economy", + "eta": "9", + "cumulative_eta": "23", + "userid": 1036, + "username": "Vignesh S", + "expectedDeliveryTime": "2026-05-26 07:23 PM", + "transitMinutes": 23, + "calculationDistanceKm": 3.0, + "zone_name": "South", + "rider_charge": 37.5, + "profit": -7.5, + "profit_class": "Loss" + }, + { + "orderheaderid": 138245, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 1076, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107310", + "orderdate": "2026-05-26T18:29:57+05:30", + "deliverydate": "2026-05-26 12:59:57", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "8", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 30, + "orderamount": 30, + "customerid": 0, + "pickupcustomer": "Bhuvaneshwari kitchen ", + "pickupcontactno": "9597843220", + "pickuplocationid": 1076, + "pickupaddress": "Coimbatore, Light House Road, Kollupuram, Sukrawar Pettai, R.S. Puram, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "R.S. Puram", + "pickupcity": "Coimbatore", + "pickuplat": "11.0035176", + "pickuplong": "76.95454649999999", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "Lakshmanan Visalakshi", + "deliverycontactno": "8886443455", + "deliverylocationid": 0, + "deliveryaddress": "New No.6, Old No. 88/51A, Sindhu Nagar, Kuniyamuthur, COIMBATORE எஸ் எஸ் கார்னர் ... 1km ", + "deliverysuburb": "", + "droplat": "10.94669601", + "droplon": "76.95759796", + "deliverylat": "10.94669601", + "deliverylong": "76.95759796", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Bhuvaneshwari kitchen ", + "locationsuburb": "R.S. Puram", + "locationcity": "Coimbatore", + "locationcontactno": "9597843220", + "locationaddress": "", + "rider": "Vignesh S", + "ridercontactno": "8072675538", + "riderkms": "12.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 35, + "pickuplon": "76.95454649999999", + "deliverycharges": 30, + "pickuplocation": "R.S. Puram", + "deliverylocation": "", + "step": 3, + "previouskms": 7, + "cumulativekms": 10, + "actualkms": "8.0", + "ordertype": "Premium", + "eta": "29", + "cumulative_eta": "52", + "userid": 1036, + "username": "Vignesh S", + "expectedDeliveryTime": "2026-05-26 07:52 PM", + "transitMinutes": 52, + "calculationDistanceKm": 10.0, + "zone_name": "South", + "rider_charge": 50.0, + "profit": -20.0, + "profit_class": "Loss" + }, + { + "orderheaderid": 138246, + "applocationid": 1, + "applocation": "Coimbatore", + "tenantid": 916, + "partnerid": 44, + "locationid": 1076, + "categoryid": 0, + "subcategoryid": 0, + "moduleid": 6, + "configid": 9, + "orderid": "916-2024107311", + "orderdate": "2026-05-26T18:29:57+05:30", + "deliverydate": "2026-05-26 12:59:57", + "orderstatus": "pending", + "deliverystatus": "", + "deliveryamt": 0, + "itemcount": 1, + "ordernotes": "", + "kms": "9", + "Pending": "", + "processing": "", + "ready": "", + "cancelled": "", + "delivered": "", + "assigntime": "2026-05-26 22:06:24", + "starttime": "", + "arrivaltime": "", + "pickuptime": "", + "deliverytime": "", + "canceltime": "", + "deliverycharge": 36, + "orderamount": 36, + "customerid": 0, + "pickupcustomer": "Bhuvaneshwari kitchen ", + "pickupcontactno": "9597843220", + "pickuplocationid": 1076, + "pickupaddress": "Coimbatore, Light House Road, Kollupuram, Sukrawar Pettai, R.S. Puram, Coimbatore, Tamil Nadu, India", + "pickupsuburb": "R.S. Puram", + "pickupcity": "Coimbatore", + "pickuplat": "11.0035176", + "pickuplong": "76.95454649999999", + "pickupslot": "2026-05-26 07:00 PM", + "deliveryid": 0, + "deliverycustomerid": 0, + "deliverycustomer": "SIVASANKAR", + "deliverycontactno": "9789781030", + "deliverylocationid": 0, + "deliveryaddress": "110 B MGR Nagar, Madukkarai Road, Sidco Post, Coimbatore - 641021 Near Pandit Nehru School", + "deliverysuburb": "", + "droplat": "10.9450125", + "droplon": "76.9696719", + "deliverylat": "10.9450125", + "deliverylong": "76.9696719", + "deliverytype": "B", + "paymenttype": 42, + "tenantname": "Daily grubs", + "tenanttoken": "ew4JKQ4ATViuVJlqYdPS70:APA91bGfxzTpkxeC7lgqjCzrcuEVYbKtMvLcKGX2WFK3jPEAgaDMH2wkQX9EFePMtcBA6gO70a8ldKbvA2q2cQ8l1eGSKImfZOozCSzpesUVrXzyzGofYsxj2ZZp_iaPckI0xYKXQh6E", + "tenantsuburb": "Krishna Colony Extension", + "tenantcity": "Sowri Palayam", + "tenantcontactno": "8008984800", + "tenantpostcode": "641015", + "tenantaddress": "", + "locationname": "Bhuvaneshwari kitchen ", + "locationsuburb": "R.S. Puram", + "locationcity": "Coimbatore", + "locationcontactno": "9597843220", + "locationaddress": "", + "rider": "Vignesh S", + "ridercontactno": "8072675538", + "riderkms": "12.0", + "smsdelivery": 0, + "customertoken": "", + "ridertoken": "", + "quantity": 1, + "collectionamt": 0, + "slab": "Special", + "pricingdate": "2024-03-28T00:00:00Z", + "baseprice": 30, + "minkm": 8, + "priceperkm": 6, + "maxkm": 8, + "orders": 150, + "othercharges": 12, + "surgecharges": 2, + "sno": 34, + "pickuplon": "76.95454649999999", + "deliverycharges": 36, + "pickuplocation": "R.S. Puram", + "deliverylocation": "", + "step": 4, + "previouskms": 2, + "cumulativekms": 12, + "actualkms": "9.0", + "ordertype": "Premium", + "eta": "13", + "cumulative_eta": "65", + "userid": 1036, + "username": "Vignesh S", + "expectedDeliveryTime": "2026-05-26 08:05 PM", + "transitMinutes": 65, + "calculationDistanceKm": 12.0, + "zone_name": "South East", + "rider_charge": 52.5, + "profit": -16.5, + "profit_class": "Loss" + } + ], + "message": "Success", + "status": true, + "meta": { + "total_orders": 35, + "utilized_riders": 8, + "active_riders_pool": 8, + "assigned_orders": 35, + "unassigned_orders": 0, + "total_profit": -368.5, + "fuel_charge_base": 2.5, + "unassigned_details": [], + "distribution_summary": { + "753": 6, + "883": 7, + "1111": 4, + "1114": 1, + "897": 1, + "950": 7, + "1062": 5, + "1036": 4 + }, + "reshuffle_mode": false, + "solver_mode": "2phase_heuristic", + "hypertuning_params": "null", + "faiss_coord_corrections": 0, + "faiss_customer_records": 0, + "faiss_history_preassigned": 34, + "risk_assessment": { + "label": "SUCCESS", + "confidence": 1.0, + "features_used": { + "distance_band": "VERY_LONG", + "time_band": "AFTERNOON", + "load_band": "MODERATE", + "order_density_band": "NORMAL" + }, + "model_trained": true + } + } +} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d1ede40 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,14 @@ +fastapi +uvicorn +python-dotenv +requests +numpy +pandas +openpyxl +xlsxwriter +httpx +ortools +pyarrow +python-dateutil +faiss-cpu +psycopg2-binary diff --git a/rider_active_state.pkl b/rider_active_state.pkl new file mode 100644 index 0000000..8ff41e5 Binary files /dev/null and b/rider_active_state.pkl differ diff --git a/rider_history.pkl b/rider_history.pkl new file mode 100644 index 0000000..5c3edde Binary files /dev/null and b/rider_history.pkl differ diff --git a/start.py b/start.py new file mode 100644 index 0000000..6ea31f2 --- /dev/null +++ b/start.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +"""Mobile-optimized startup script for the Delivery Route Optimization API.""" + +import uvicorn + +def main(): + """Start the mobile-optimized API server.""" + print("📱 Starting Mobile Delivery Route Optimization API...") + print("⚡ Optimized for real-time mobile apps") + print("🎯 Default algorithm: GREEDY (ultra-fast)") + print("📚 Documentation: http://localhost:8002/docs") + print("=" * 60) + + uvicorn.run( + "app.main:app", + host="0.0.0.0", + port=8002, + reload=True, + access_log=True, + log_level="info" + ) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/test/Bhuvaneshwari_Kitchen_Route.xls b/test/Bhuvaneshwari_Kitchen_Route.xls new file mode 100644 index 0000000..a6aec9e Binary files /dev/null and b/test/Bhuvaneshwari_Kitchen_Route.xls differ diff --git a/test/Jayanthi_Kitchen_Route.xls b/test/Jayanthi_Kitchen_Route.xls new file mode 100644 index 0000000..a0d3ed4 Binary files /dev/null and b/test/Jayanthi_Kitchen_Route.xls differ diff --git a/test/Selvarani_To_Vidhya.xls b/test/Selvarani_To_Vidhya.xls new file mode 100644 index 0000000..c0660a6 Binary files /dev/null and b/test/Selvarani_To_Vidhya.xls differ diff --git a/test/Vidhya_Kitchen_Route.xls b/test/Vidhya_Kitchen_Route.xls new file mode 100644 index 0000000..5108152 Binary files /dev/null and b/test/Vidhya_Kitchen_Route.xls differ