03-yield小應用:出租車運營模擬


#事件對象
class Event:
    def __init__(self,time,taxi_ident,action):
        '''
        :param time:發(fā)生這個事件的時間
        :param taxi_ident:觸發(fā)這個事件的出租車對象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):
        '''
        我們利用一個普通列表來實現(xiàn)
        '''
        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==[]


#模擬出租車的協(xié)程
def taxi_coroutine(ident,trips,start_time):
    """
    每次狀態(tài)改變便會yield一個事件
    :param ident:出租車的id
    :param trips:出租車接多少趟客
    :param start_time:出租車從車庫出發(fā)時間
    """
    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: 當前發(fā)生過的事件(根據(jù)這個事件計算到下個事件發(fā)生之間的耗時)
    '''
    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('傳入參數(shù)的事件有誤')

#出租車運營模擬
class Simulator:
    def __init__(self,taxi_corouting_dict):
        self.events=Event_List() #所有事件
        self.couroutines=taxi_corouting_dict #所有出租車協(xié)程

    def run(self,end_time):
        """
        模擬器從事件列表中獲取事件并處理
        :param end_time: 事件模擬器的結束時間
        """
        for ident,taxi_corouting in self.couroutines.items(): #啟動每一個出租車協(xié)程
            first_event=taxi_corouting.send(None) #也可以替換為:next(taxi_corouting) 意為預激協(xié)程
            self.events.put(first_event)

        #運營模擬仿真主循環(huán)
        current_time=0  #主循環(huán)當前時間
        while current_time<end_time:
            if self.events.is_empty():
                print('模擬器:所有事件處理完畢')
                break
            current_event=self.events.get() #獲取發(fā)生最早的事件(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] #獲取觸發(fā)該事件的出租車協(xié)程
            taxi_next_event_time=event_time+compuate_duration(current_event)  #計算當前出租車協(xié)程的下個事件發(fā)生時間
            try:
                taxi_next_event=current_taxi_coroutine.send(taxi_next_event_time) #把計算得出的下一個事件發(fā)生的時間發(fā)送給協(xié)程,協(xié)程會返回下一個事件或者拋出StopInteration表示執(zhí)行結束
            except StopIteration:
                del self.couroutines[coroutine_ident] #刪除執(zhí)行完畢的出租車協(xié)程
            else:
                self.events.put(taxi_next_event) #將下一個事件放入事件容器
        else: #如果所有事件沒執(zhí)行完畢就超時,則執(zhí)行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)
'''
執(zhí)行:
    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)
'''
執(zhí)行:
    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 個事件等待處理
'''
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末强衡,一起剝皮案震驚了整個濱河市常侣,隨后出現(xiàn)的幾起案子铃慷,更是在濱河造成了極大的恐慌雏搂,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宋渔,死亡現(xiàn)場離奇詭異弹灭,居然都是意外死亡督暂,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進店門穷吮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逻翁,“玉大人,你說我怎么就攤上這事捡鱼“嘶兀” “怎么了?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵驾诈,是天一觀的道長缠诅。 經常有香客問我,道長乍迄,這世上最難降的妖魔是什么管引? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮闯两,結果婚禮上汉匙,老公的妹妹穿的比我還像新娘。我一直安慰自己生蚁,他們只是感情好,可當我...
    茶點故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布戏自。 她就那樣靜靜地躺著邦投,像睡著了一般。 火紅的嫁衣襯著肌膚如雪擅笔。 梳的紋絲不亂的頭發(fā)上志衣,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天,我揣著相機與錄音猛们,去河邊找鬼念脯。 笑死,一個胖子當著我的面吹牛弯淘,可吹牛的內容都是我干的绿店。 我是一名探鬼主播,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼假勿!你這毒婦竟也來了借嗽?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤转培,失蹤者是張志新(化名)和其女友劉穎恶导,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浸须,經...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡惨寿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了删窒。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片裂垦。...
    茶點故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖易稠,靈堂內的尸體忽然破棺而出缸废,到底是詐尸還是另有隱情,我是刑警寧澤驶社,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布企量,位于F島的核電站,受9級特大地震影響亡电,放射性物質發(fā)生泄漏届巩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一份乒、第九天 我趴在偏房一處隱蔽的房頂上張望恕汇。 院中可真熱鬧,春花似錦或辖、人聲如沸瘾英。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缺谴。三九已至,卻和暖如春耳鸯,著一層夾襖步出監(jiān)牢的瞬間湿蛔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工县爬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留阳啥,地道東北人。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓财喳,卻偏偏與公主長得像察迟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,566評論 2 349

推薦閱讀更多精彩內容