33from rest_framework import status
44
55from simulator .engine import simulate_trip
6+ from simulator .geocoding import reverse_geocode
67from simulator .models import TripInput
78
89from .serializers import TripPlanRequestSerializer , TripPlanResponseSerializer
910
1011
12+ def _coord_pair (data , lat_key : str , lng_key : str ):
13+ """Return (lat, lng) tuple if both keys are present and non-null, else None."""
14+ lat = data .get (lat_key )
15+ lng = data .get (lng_key )
16+ if lat is None or lng is None :
17+ return None
18+ return (float (lat ), float (lng ))
19+
20+
1121class TripPlanView (APIView ):
1222 def post (self , request ):
1323 req_serializer = TripPlanRequestSerializer (data = request .data )
@@ -18,17 +28,43 @@ def post(self, request):
1828 )
1929
2030 data = req_serializer .validated_data
31+
32+ current_coords_override = _coord_pair (data , "current_lat" , "current_lng" )
33+ pickup_coords_override = _coord_pair (data , "pickup_lat" , "pickup_lng" )
34+ dropoff_coords_override = _coord_pair (data , "dropoff_lat" , "dropoff_lng" )
35+
2136 try :
22- result = simulate_trip (TripInput (
23- current_location = data ["current_location" ],
24- pickup_location = data ["pickup_location" ],
25- dropoff_location = data ["dropoff_location" ],
26- cycle_hours_used = data ["cycle_hours_used" ],
27- ))
37+ result = simulate_trip (
38+ TripInput (
39+ current_location = data ["current_location" ],
40+ pickup_location = data ["pickup_location" ],
41+ dropoff_location = data ["dropoff_location" ],
42+ cycle_hours_used = data ["cycle_hours_used" ],
43+ ),
44+ current_coords_override = current_coords_override ,
45+ pickup_coords_override = pickup_coords_override ,
46+ dropoff_coords_override = dropoff_coords_override ,
47+ )
2848 except Exception as exc :
2949 return Response (
3050 {"error" : "Simulation failed" , "details" : str (exc )},
3151 status = status .HTTP_500_INTERNAL_SERVER_ERROR ,
3252 )
3353
3454 return Response (TripPlanResponseSerializer (result ).data , status = status .HTTP_200_OK )
55+
56+
57+ class ReverseGeocodeView (APIView ):
58+ """GET /api/geocode/reverse/?lat=...&lng=... -> {"label": "City, ST"}."""
59+
60+ def get (self , request ):
61+ try :
62+ lat = float (request .query_params .get ("lat" , 0 ))
63+ lng = float (request .query_params .get ("lng" , 0 ))
64+ except (TypeError , ValueError ):
65+ return Response (
66+ {"error" : "lat and lng must be numbers" },
67+ status = status .HTTP_400_BAD_REQUEST ,
68+ )
69+ label = reverse_geocode (lat , lng )
70+ return Response ({"label" : label })
0 commit comments