03-yield小应用:出租车运营模拟


#事件对象
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 个事件等待处理
'''
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容