def visualize(self, start_time=None, end_time=None): """ Visualizes the fleet for the given time frame. Args: start_time (datetime.datetime or str): The start time, either as a datetime.datetime object or an ISO string. Set to the python fleet creation time if not set. Defaults to None. end_time (datetime.datetime or str): The end time, either as a datetime.datetime object or an ISO string. Set to the latest API call time if not set. Defaults to None. Returns: IFrame: A graphic view of the fleet through time. """ if start_time is None: start_time = self.start_time if end_time is None: end_time = self.end_time if isinstance(start_time, str): start_time = isoparse(start_time) if isinstance(end_time, str): end_time = isoparse(end_time) url = self.vis_url.format(start=to_rfc3339(start_time), end=to_rfc3339(end_time), api_key=self.api_key, fleet_key=self.fleet_key) print(url) return IPython.display.IFrame(url, 800, 800)
def cancel_request(self, rid, event_time=None): """ Attempts to cancel a request. Args: rid (int): The unique request ID event_time (datetime.datetime, optional): Time of the cancellation. Set to datetime.datetime.now() if not provided. Defaults to None. Raises: StatusError: If unsuccessful. Returns: Status Response: If the request is sucessfully cancelled. """ if event_time is None: event_time = datetime.datetime.now() if event_time > self.end_time: self.end_time = event_time url = self.build_url(Endpoints.CANCEL_REQUEST) payload = { 'id': rid, 'event_time': to_rfc3339(event_time), 'user_key': self.user_key.todict() } r = requests.post(url, data = json.dumps(payload)) resp = r.json() if r.status_code == 200: return StatusResponse(resp=resp) else: raise StatusError(resp=resp)
def update_vehicle(self, vid, location, event, direction=Defaults.DEFAULT_DIRECTION, event_time=None, req_id=None): """ Attempts to update a vehicle. Args: vid (int): The unique vehicle ID location (Location): The vehicle location. direction (float): Angle in radians clockwise away from true north event (VehicleEvent): Describes the current event for the vehicle. pickup occurs when the vehicle has picked up a request. dropoff occurs when the vehicle has dropped of a request. progress should be set when the vehicle is moving to service a request, either picking up or dropping off. The vehicle should be marked as unassigned when it is is not assigned to any requests. event_time (datetime.datetime, optional): Time at which the vehicle update has occurred. Set to datetime.datetime.now() if not provided. Defaults to None. req_id (int, optional): The unique ID of request the vehicle is servicing. If the vehicle is unassigned, this may be omitted. Defaults to None. Returns: Vehicle: If successful. Raises: StatusError: If unsucessful. """ if event_time is None: event_time = datetime.datetime.now() if event_time > self.end_time: self.end_time = event_time url = self.build_url(Endpoints.UPDATE_VEHICLE) payload = { 'id': vid, 'location': location.todict(), 'direction': direction, 'event_time': to_rfc3339(event_time), 'event': event, 'user_key': self.user_key.todict() } if req_id is not None: payload['req_id'] = req_id r = requests.post(url, data=json.dumps(payload)) resp = r.json() if r.status_code == 200: return Vehicle.fromdict(self, resp) else: raise StatusError(resp=resp)
def plot_metrics(self, metrics, start_time=None, end_time=None): """ Plots time series metrics. Args: metrics (list[Metrics]): A list of metrics to plot. start_time (datetime.datetime or str): The start time, either as a datetime.datetime object or an ISO string. Set to the fleet creation time if not set. Defaults to None. end_time (datetime.datetime or str): The end time, either as a datetime.datetime object or an ISO string. Set to the latest API call time if not set. Defaults to None. Returns: Plotly.Figure: A figure that graphs the metrics over the time interval. """ if start_time is None: start_time = self.start_time if end_time is None: end_time = self.end_time if isinstance(start_time, str): start_time = isoparse(start_time) if isinstance(end_time, str): end_time = isoparse(end_time) url = self.build_url(Endpoints.GRAPHQL) query = Metrics.QUERY.format(api_key=self.api_key, fleet_key=self.fleet_key, start_time=to_rfc3339(start_time), end_time=to_rfc3339(end_time)) r = requests.post(url, json={"query": query}) resp = r.json() data = resp['data']['live_fleets'][0]['metrics'] x = [met[Metrics.TIME] for met in data] figure = go.Figure() for metric in metrics: figure.add_trace( go.Scatter(x=x, y=[met[metric] for met in data], mode='lines+markers', name=metric)) return figure
def forward_simulate(self, duration, current_time=None): """ Forward simulates the fleet for a given duration. Args: duration (string): A duration to forward simulate for, e.g. "5m." current_time (datetime.datetime or str, optional): The current time, from when the simulation will begin. Can be provided as a datetime.datetime object or ISO string. Set to datetime.datetime.now() if not provided. Defaults to None. Returns: VehicleAssignments: The final state of all vehicles and requests, after the simulation. Raises: StatusError: If unsuccessful. """ if current_time is None: current_time = datetime.datetime.now() if isinstance(current_time, str): current_time = isoparse(current_time) duration_td = datetime.timedelta(seconds=timeparse(duration)) if current_time + duration_td > self.end_time: self.end_time = current_time + duration_td url = self.build_url(Endpoints.FORWARD_SIMULATE) payload = { 'user_key': self.user_key.todict(), 'sim_duration': duration, 'current_time': to_rfc3339(current_time) } r = requests.post(url, data=json.dumps(payload)) resp = r.json() if r.status_code == 200: return VehicleAssignments( vehs=[Vehicle.fromdict(self, veh) for veh in resp.get('vehs')], requests=[Request.fromdict(self, req) for req in resp.get('reqs')], notifications=[ Notification.fromdict(notif) for notif in resp.get('notifications') ], ) else: raise StatusError(resp=resp)
def todict(self): """ Converts a Request to a python dict. Returns: dict: A dictionary representation of self. """ return { 'fleet': self.fleet.todict(), 'pickup': self.pickup.todict(), 'dropoff': self.dropoff.todict(), 'request_time': to_rfc3339(self.request_time), 'req_id': self.req_id, 'veh_id': self.veh_id, 'load': self.load, 'assigned': self.assigned }
def add_request(self, rid, pickup, dropoff, load, request_time=None): """ Attempts to add a request. Args: rid (int): The unique request ID. pickup (Location): The pickup location. dropoff (Location): The dropoff location. load (int): The load (number of passengers). request_time (datetime.datetime, optional): Time of the request. This may be in the future for scheduled pickups. Set to datetime.datetime.now() if not provided. Defaults to None. Returns: StatusResponse: If successful. Raises: StatusError: If unsuccessful. """ if request_time is None: request_time = datetime.datetime.now() if request_time > self.end_time: self.end_time = request_time url = self.build_url(Endpoints.ADD_REQUEST) payload = { 'id': rid, 'pickup': pickup.todict(), 'dropoff': dropoff.todict(), 'load': load, 'request_time': to_rfc3339(request_time), 'user_key': self.user_key.todict() } r = requests.post(url, data=json.dumps(payload)) resp = r.json() if r.status_code == 200: return StatusResponse(resp=resp) else: raise StatusError(resp=resp)
def get_assignments(self, current_time=None): """ Computes vehicle assignments for the fleet in the current state. Args: current_time (datetime.datetime, optional): Current time. Set to datetime.datetime.now() if not provided. Defaults to None. Raises: StatusError: If unsuccessful. Returns: VehicleAssignments: If assignments are successfully computed. """ if current_time is None: current_time = datetime.datetime.now() if current_time > self.end_time: self.end_time = current_time url = self.build_url(Endpoints.COMPUTE_ASSIGNMENTS) payload = { 'api_key': self.api_key, 'fleet_key': self.fleet_key, 'current_time': to_rfc3339(current_time) } r = requests.get(url, params=payload) resp = r.json() if r.status_code == 200: return VehicleAssignments( vehs=[Vehicle.fromdict(self, veh) for veh in resp.get('vehs')], requests=[Request.fromdict(self, req) for req in resp.get('reqs')], notifications=[ Notification.fromdict(notif) for notif in resp.get('notifications') ], ) else: raise StatusError(resp=resp)