import asyncio
import json
from spade.behaviour import State, FSMBehaviour
from taxi_simulator.taxi import TaxiStrategyBehaviour
from taxi_simulator.helpers import PathRequestException
from taxi_simulator.protocol import REQUEST_PERFORMATIVE, ACCEPT_PERFORMATIVE, REFUSE_PERFORMATIVE
from taxi_simulator.utils import TAXI_WAITING, TAXI_WAITING_FOR_APPROVAL, TAXI_MOVING_TO_PASSENGER
[docs]class TaxiWaitingState(TaxiStrategyBehaviour, State):
[docs] async def on_start(self):
await super().on_start()
self.agent.status = TAXI_WAITING
[docs] async def run(self):
msg = await self.receive(timeout=60)
if not msg:
self.set_next_state(TAXI_WAITING)
return
self.logger.info("received: {}".format(msg.body))
content = json.loads(msg.body)
performative = msg.get_metadata("performative")
if performative == REQUEST_PERFORMATIVE:
await self.send_proposal(content["passenger_id"], {})
self.set_next_state(TAXI_WAITING_FOR_APPROVAL)
return
else:
self.set_next_state(TAXI_WAITING)
return
[docs]class TaxiWaitingForApprovalState(TaxiStrategyBehaviour, State):
[docs] async def on_start(self):
await super().on_start()
self.agent.status = TAXI_WAITING_FOR_APPROVAL
[docs] async def run(self):
msg = await self.receive(timeout=60)
if not msg:
self.logger.info("No approval msg received. Still waiting.")
self.set_next_state(TAXI_WAITING_FOR_APPROVAL)
return
content = json.loads(msg.body)
performative = msg.get_metadata("performative")
if performative == ACCEPT_PERFORMATIVE:
try:
self.logger.info("Got accept. Picking up passenger.")
await self.pick_up_passenger(content["passenger_id"], content["origin"], content["dest"])
self.set_next_state(TAXI_MOVING_TO_PASSENGER)
return
except PathRequestException:
await self.cancel_proposal(content["passenger_id"])
self.set_next_state(TAXI_WAITING)
return
except Exception as e:
await self.cancel_proposal(content["passenger_id"])
self.set_next_state(TAXI_WAITING)
return
elif performative == REFUSE_PERFORMATIVE:
self.logger.info("Got refuse :(")
self.set_next_state(TAXI_WAITING)
return
passenger_in_taxi_event = asyncio.Event()
[docs]def passenger_in_taxi_callback(old, new):
if not passenger_in_taxi_event.is_set() and new is None:
passenger_in_taxi_event.set()
[docs]class TaxiMovingState(TaxiStrategyBehaviour, State):
[docs] async def on_start(self):
await super().on_start()
self.agent.status = TAXI_MOVING_TO_PASSENGER
[docs] async def run(self):
passenger_in_taxi_event.clear()
self.agent.watch_value("passenger_in_taxi", passenger_in_taxi_callback)
await passenger_in_taxi_event.wait()
self.logger.info("Taxi is free again.")
return self.set_next_state(TAXI_WAITING)
[docs]class FSMTaxiStrategyBehaviour(FSMBehaviour):
[docs] def setup(self):
# Create states
self.add_state(TAXI_WAITING, TaxiWaitingState(), initial=True)
self.add_state(TAXI_WAITING_FOR_APPROVAL, TaxiWaitingForApprovalState())
self.add_state(TAXI_MOVING_TO_PASSENGER, TaxiMovingState())
# Create transitions
self.add_transition(TAXI_WAITING, TAXI_WAITING)
self.add_transition(TAXI_WAITING, TAXI_WAITING_FOR_APPROVAL)
self.add_transition(TAXI_WAITING_FOR_APPROVAL, TAXI_MOVING_TO_PASSENGER)
self.add_transition(TAXI_WAITING_FOR_APPROVAL, TAXI_WAITING)
self.add_transition(TAXI_WAITING_FOR_APPROVAL, TAXI_WAITING_FOR_APPROVAL)
self.add_transition(TAXI_MOVING_TO_PASSENGER, TAXI_WAITING)