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 个事件等待处理
'''
上一篇 下一篇

猜你喜欢

热点阅读