03-yield小应用:出租车运营模拟
2019-01-25 本文已影响0人
依依东望_220b
#事件对象
class Event:
def __init__(self,time,taxi_ident,action):
'''
:param time:发生这个事件的时间
:param taxi_ident:触发这个事件的出租车对象id
:param action:这个事件所代表的行为
'''
self.time=time
self.taxi_ident=taxi_ident
self.action=action
def __str__(self):
return 'Time:{},Taxi_Ident:{},Action:{}'.format(self.time,self.taxi_ident,self.action)
def values(self):
return [self.time,self.taxi_ident,self.action]
#用于给外部排序比较的接口
def __eq__(self,other):
return self.time==other.time
def __lt__(self,other):
return self.time<other.time
#事件列表
class Event_List:
def __init__(self):
'''
我们利用一个普通列表来实现
'''
self._list=[]
def put(self,event):
self._list.append(event)
def get(self):
self._list.sort()
result=self._list[0]
del self._list[0]
return result
def list_size(self):
return len(self._list)
def is_empty(self):
return self._list==[]
#模拟出租车的协程
def taxi_coroutine(ident,trips,start_time):
"""
每次状态改变便会yield一个事件
:param ident:出租车的id
:param trips:出租车接多少趟客
:param start_time:出租车从车库出发时间
"""
time=yield Event(start_time,ident,'司机佩琪:离开车库')
for i in range(trips):
time=yield Event(time,ident,'司机佩琪:客人上车')
time=yield Event(time,ident,'司机佩琪:客人下车')
yield Event(time,ident,'司机佩琪:返回车库')
import random
#通过传入事件类型给定到从传入事件到下个事件之间的事件
def compuate_duration(event):
'''
:param event: 当前发生过的事件(根据这个事件计算到下个事件发生之间的耗时)
'''
if event.action in ['司机佩琪:客人上车','司机佩琪:离开车库']:
return random.randint(1,10)
elif event.action in ['司机佩琪:客人下车']:
return random.randint(1,5)
elif event.action in ['司机佩琪:返回车库']:
return 1
else:
raise ValueError('传入参数的事件有误')
#出租车运营模拟
class Simulator:
def __init__(self,taxi_corouting_dict):
self.events=Event_List() #所有事件
self.couroutines=taxi_corouting_dict #所有出租车协程
def run(self,end_time):
"""
模拟器从事件列表中获取事件并处理
:param end_time: 事件模拟器的结束时间
"""
for ident,taxi_corouting in self.couroutines.items(): #启动每一个出租车协程
first_event=taxi_corouting.send(None) #也可以替换为:next(taxi_corouting) 意为预激协程
self.events.put(first_event)
#运营模拟仿真主循环
current_time=0 #主循环当前时间
while current_time<end_time:
if self.events.is_empty():
print('模拟器:所有事件处理完毕')
break
current_event=self.events.get() #获取发生最早的事件(time最小)
event_time,coroutine_ident,action=current_event.values() #解析事件
current_time=event_time #更新模拟器时间
print('模拟器:处理 出租车-{}{}{}'.format(coroutine_ident,coroutine_ident*' ',current_event)) #模拟器处理事件
current_taxi_coroutine=self.couroutines[coroutine_ident] #获取触发该事件的出租车协程
taxi_next_event_time=event_time+compuate_duration(current_event) #计算当前出租车协程的下个事件发生时间
try:
taxi_next_event=current_taxi_coroutine.send(taxi_next_event_time) #把计算得出的下一个事件发生的时间发送给协程,协程会返回下一个事件或者抛出StopInteration表示执行结束
except StopIteration:
del self.couroutines[coroutine_ident] #删除执行完毕的出租车协程
else:
self.events.put(taxi_next_event) #将下一个事件放入事件容器
else: #如果所有事件没执行完毕就超时,则执行else判断下的代码
print('模拟器:超时结束,还有 {} 个事件等待处理'.format(self.events.list_size()))
def main_01():
taxis={
i:taxi_coroutine(i,(i+1)*2,(i+2)*3)
for i in range(3)
}
taxi_simulate=Simulator(taxis)
taxi_simulate.run(100)
'''
执行:
main_01() #end_time=100
输出为:
模拟器:处理 出租车-0Time:6,Taxi_Ident:0,Action:司机佩琪:离开车库
模拟器:处理 出租车-0Time:8,Taxi_Ident:0,Action:司机佩琪:客人上车
模拟器:处理 出租车-1 Time:9,Taxi_Ident:1,Action:司机佩琪:离开车库
模拟器:处理 出租车-0Time:10,Taxi_Ident:0,Action:司机佩琪:客人下车
模拟器:处理 出租车-2 Time:12,Taxi_Ident:2,Action:司机佩琪:离开车库
模拟器:处理 出租车-0Time:14,Taxi_Ident:0,Action:司机佩琪:客人上车
模拟器:处理 出租车-0Time:16,Taxi_Ident:0,Action:司机佩琪:客人下车
模拟器:处理 出租车-2 Time:18,Taxi_Ident:2,Action:司机佩琪:客人上车
模拟器:处理 出租车-0Time:18,Taxi_Ident:0,Action:司机佩琪:返回车库
模拟器:处理 出租车-1 Time:19,Taxi_Ident:1,Action:司机佩琪:客人上车
模拟器:处理 出租车-2 Time:23,Taxi_Ident:2,Action:司机佩琪:客人下车
模拟器:处理 出租车-2 Time:27,Taxi_Ident:2,Action:司机佩琪:客人上车
模拟器:处理 出租车-1 Time:29,Taxi_Ident:1,Action:司机佩琪:客人下车
模拟器:处理 出租车-1 Time:30,Taxi_Ident:1,Action:司机佩琪:客人上车
模拟器:处理 出租车-1 Time:32,Taxi_Ident:1,Action:司机佩琪:客人下车
模拟器:处理 出租车-1 Time:35,Taxi_Ident:1,Action:司机佩琪:客人上车
模拟器:处理 出租车-2 Time:36,Taxi_Ident:2,Action:司机佩琪:客人下车
模拟器:处理 出租车-2 Time:40,Taxi_Ident:2,Action:司机佩琪:客人上车
模拟器:处理 出租车-1 Time:42,Taxi_Ident:1,Action:司机佩琪:客人下车
模拟器:处理 出租车-2 Time:44,Taxi_Ident:2,Action:司机佩琪:客人下车
模拟器:处理 出租车-1 Time:47,Taxi_Ident:1,Action:司机佩琪:客人上车
模拟器:处理 出租车-2 Time:48,Taxi_Ident:2,Action:司机佩琪:客人上车
模拟器:处理 出租车-1 Time:49,Taxi_Ident:1,Action:司机佩琪:客人下车
模拟器:处理 出租车-2 Time:51,Taxi_Ident:2,Action:司机佩琪:客人下车
模拟器:处理 出租车-1 Time:53,Taxi_Ident:1,Action:司机佩琪:返回车库
模拟器:处理 出租车-2 Time:55,Taxi_Ident:2,Action:司机佩琪:客人上车
模拟器:处理 出租车-2 Time:65,Taxi_Ident:2,Action:司机佩琪:客人下车
模拟器:处理 出租车-2 Time:70,Taxi_Ident:2,Action:司机佩琪:客人上车
模拟器:处理 出租车-2 Time:80,Taxi_Ident:2,Action:司机佩琪:客人下车
模拟器:处理 出租车-2 Time:84,Taxi_Ident:2,Action:司机佩琪:返回车库
模拟器:所有事件处理完毕
'''
def main_02():
taxis={
i:taxi_coroutine(i,(i+1)*2,(i+2)*3)
for i in range(3)
}
taxi_simulate=Simulator(taxis)
taxi_simulate.run(20)
'''
执行:
main_02() #end_time=20
输出为:
模拟器:处理 出租车-0Time:6,Taxi_Ident:0,Action:司机佩琪:离开车库
模拟器:处理 出租车-1 Time:9,Taxi_Ident:1,Action:司机佩琪:离开车库
模拟器:处理 出租车-2 Time:12,Taxi_Ident:2,Action:司机佩琪:离开车库
模拟器:处理 出租车-0Time:13,Taxi_Ident:0,Action:司机佩琪:客人上车
模拟器:处理 出租车-0Time:16,Taxi_Ident:0,Action:司机佩琪:客人下车
模拟器:处理 出租车-2 Time:17,Taxi_Ident:2,Action:司机佩琪:客人上车
模拟器:处理 出租车-1 Time:19,Taxi_Ident:1,Action:司机佩琪:客人上车
模拟器:处理 出租车-0Time:19,Taxi_Ident:0,Action:司机佩琪:客人上车
模拟器:处理 出租车-2 Time:24,Taxi_Ident:2,Action:司机佩琪:客人下车
模拟器:超时结束,还有 3 个事件等待处理
'''