updated from Atlas
This commit is contained in:
1 parent
f4cdee2447
commit
f86aee2785
78 files changed
+587
-333
No files matched your search
@@ -15,6 +15,8 @@ While active, the context manager reverses text output to
|
||||
YKCOWREBBAJ
|
||||
>>> what # <4>
|
||||
'JABBERWOCKY'
|
||||
>>> print('Back to normal.') # <5>
|
||||
Back to normal.
|
||||
|
||||
# END MIRROR_DEMO_1
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,7 +1,7 @@
|
||||
# BEGIN CORO_AVERAGER
|
||||
"""
|
||||
A coroutine to compute a running average
|
||||
|
||||
# BEGIN CORO_AVERAGER_TEST
|
||||
>>> coro_avg = averager() # <1>
|
||||
>>> next(coro_avg) # <2>
|
||||
>>> coro_avg.send(10) # <3>
|
||||
@@ -11,14 +11,17 @@ A coroutine to compute a running average
|
||||
>>> coro_avg.send(5)
|
||||
15.0
|
||||
|
||||
# END CORO_AVERAGER_TEST
|
||||
|
||||
"""
|
||||
|
||||
# BEGIN CORO_AVERAGER
|
||||
def averager():
|
||||
total = 0.0
|
||||
count = 0
|
||||
average = None
|
||||
while True:
|
||||
term = yield average # <4>
|
||||
while True: # <1>
|
||||
term = yield average # <2>
|
||||
total += term
|
||||
count += 1
|
||||
average = total/count
|
||||
File renamed without changes.
@@ -6,8 +6,8 @@ Testing ``averager`` by itself::
|
||||
# BEGIN RETURNING_AVERAGER_DEMO1
|
||||
|
||||
>>> coro_avg = averager()
|
||||
>>> next(coro_avg) # <1>
|
||||
>>> coro_avg.send(10)
|
||||
>>> next(coro_avg)
|
||||
>>> coro_avg.send(10) # <1>
|
||||
>>> coro_avg.send(30)
|
||||
>>> coro_avg.send(6.5)
|
||||
>>> coro_avg.send(None) # <2>
|
||||
@@ -58,4 +58,4 @@ def averager():
|
||||
count += 1
|
||||
average = total/count
|
||||
return Result(count, average) # <2>
|
||||
# END RETURNING_AVERAGER
|
||||
# END RETURNING_AVERAGER
|
||||
@@ -75,7 +75,7 @@ def main(data): # <8>
|
||||
next(group) # <10>
|
||||
for value in values:
|
||||
group.send(value) # <11>
|
||||
group.send(None) # <12>
|
||||
group.send(None) # important! <12>
|
||||
|
||||
# print(results) # uncomment to debug
|
||||
report(results)
|
||||
File renamed without changes.
@@ -0,0 +1,203 @@
|
||||
|
||||
"""
|
||||
Taxi simulator
|
||||
==============
|
||||
|
||||
Driving a taxi from the console::
|
||||
|
||||
>>> from taxi_sim import taxi_process
|
||||
>>> taxi = taxi_process(ident=13, trips=2, start_time=0)
|
||||
>>> next(taxi)
|
||||
Event(time=0, proc=13, action='leave garage')
|
||||
>>> taxi.send(_.time + 7)
|
||||
Event(time=7, proc=13, action='pick up passenger')
|
||||
>>> taxi.send(_.time + 23)
|
||||
Event(time=30, proc=13, action='drop off passenger')
|
||||
>>> taxi.send(_.time + 5)
|
||||
Event(time=35, proc=13, action='pick up passenger')
|
||||
>>> taxi.send(_.time + 48)
|
||||
Event(time=83, proc=13, action='drop off passenger')
|
||||
>>> taxi.send(_.time + 1)
|
||||
Event(time=84, proc=13, action='going home')
|
||||
>>> taxi.send(_.time + 10)
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
StopIteration
|
||||
|
||||
Sample run with two cars, random seed 10. This is a valid doctest::
|
||||
|
||||
>>> main(num_taxis=2, seed=10)
|
||||
taxi: 0 Event(time=0, proc=0, action='leave garage')
|
||||
taxi: 0 Event(time=5, proc=0, action='pick up passenger')
|
||||
taxi: 1 Event(time=5, proc=1, action='leave garage')
|
||||
taxi: 1 Event(time=10, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=15, proc=1, action='drop off passenger')
|
||||
taxi: 0 Event(time=17, proc=0, action='drop off passenger')
|
||||
taxi: 1 Event(time=24, proc=1, action='pick up passenger')
|
||||
taxi: 0 Event(time=26, proc=0, action='pick up passenger')
|
||||
taxi: 0 Event(time=30, proc=0, action='drop off passenger')
|
||||
taxi: 0 Event(time=34, proc=0, action='going home')
|
||||
taxi: 1 Event(time=46, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=48, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=110, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=139, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=140, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=150, proc=1, action='going home')
|
||||
*** end of events ***
|
||||
|
||||
See longer sample run at the end of this module.
|
||||
|
||||
"""
|
||||
|
||||
import random
|
||||
import collections
|
||||
import queue
|
||||
import argparse
|
||||
import time
|
||||
|
||||
DEFAULT_NUMBER_OF_TAXIS = 3
|
||||
DEFAULT_END_TIME = 180
|
||||
SEARCH_DURATION = 5
|
||||
TRIP_DURATION = 20
|
||||
DEPARTURE_INTERVAL = 5
|
||||
|
||||
Event = collections.namedtuple('Event', 'time proc action')
|
||||
|
||||
|
||||
# BEGIN TAXI_PROCESS
|
||||
def taxi_process(ident, trips, start_time=0): # <1>
|
||||
"""Yield to simulator issuing event at each state change"""
|
||||
time = yield Event(start_time, ident, 'leave garage') # <2>
|
||||
for i in range(trips): # <3>
|
||||
time = yield Event(time, ident, 'pick up passenger') # <4>
|
||||
time = yield Event(time, ident, 'drop off passenger') # <5>
|
||||
|
||||
yield Event(time, ident, 'going home') # <6>
|
||||
# end of taxi process # <7>
|
||||
# END TAXI_PROCESS
|
||||
|
||||
|
||||
# BEGIN TAXI_SIMULATOR
|
||||
class Simulator:
|
||||
|
||||
def __init__(self, procs_map):
|
||||
self.events = queue.PriorityQueue()
|
||||
self.procs = dict(procs_map)
|
||||
|
||||
def run(self, end_time): # <1>
|
||||
"""Schedule and display events until time is up"""
|
||||
# schedule the first event for each cab
|
||||
for _, proc in sorted(self.procs.items()): # <2>
|
||||
first_event = next(proc) # <3>
|
||||
self.events.put(first_event) # <4>
|
||||
|
||||
# main loop of the simulation
|
||||
sim_time = 0 # <5>
|
||||
while sim_time < end_time: # <6>
|
||||
if self.events.empty(): # <7>
|
||||
print('*** end of events ***')
|
||||
break
|
||||
|
||||
current_event = self.events.get() # <8>
|
||||
sim_time, proc_id, previous_action = current_event # <9>
|
||||
print('taxi:', proc_id, proc_id * ' ', current_event) # <10>
|
||||
active_proc = self.procs[proc_id] # <11>
|
||||
next_time = sim_time + compute_duration(previous_action) # <12>
|
||||
try:
|
||||
next_event = active_proc.send(next_time) # <13>
|
||||
except StopIteration:
|
||||
del self.procs[proc_id] # <14>
|
||||
else:
|
||||
self.events.put(next_event) # <15>
|
||||
else: # <16>
|
||||
msg = '*** end of simulation time: {} events pending ***'
|
||||
print(msg.format(self.events.qsize()))
|
||||
# END TAXI_SIMULATOR
|
||||
|
||||
|
||||
def compute_duration(previous_action):
|
||||
"""Compute action duration using exponential distribution"""
|
||||
if previous_action in ['leave garage', 'drop off passenger']:
|
||||
# new state is prowling
|
||||
interval = SEARCH_DURATION
|
||||
elif previous_action == 'pick up passenger':
|
||||
# new state is trip
|
||||
interval = TRIP_DURATION
|
||||
elif previous_action == 'going home':
|
||||
interval = 1
|
||||
else:
|
||||
raise ValueError('Unknown previous_action: %s' % previous_action)
|
||||
return int(random.expovariate(1/interval)) + 1
|
||||
|
||||
|
||||
def main(end_time=DEFAULT_END_TIME, num_taxis=DEFAULT_NUMBER_OF_TAXIS,
|
||||
seed=None):
|
||||
"""Initialize random generator, build procs and run simulation"""
|
||||
if seed is not None:
|
||||
random.seed(seed) # get reproducible results
|
||||
|
||||
taxis = {i: taxi_process(i, (i+1)*2, i*DEPARTURE_INTERVAL)
|
||||
for i in range(num_taxis)}
|
||||
sim = Simulator(taxis)
|
||||
sim.run(end_time)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Taxi fleet simulator.')
|
||||
parser.add_argument('-e', '--end-time', type=int,
|
||||
default=DEFAULT_END_TIME,
|
||||
help='simulation end time; default = %s'
|
||||
% DEFAULT_END_TIME)
|
||||
parser.add_argument('-t', '--taxis', type=int,
|
||||
default=DEFAULT_NUMBER_OF_TAXIS,
|
||||
help='number of taxis running; default = %s'
|
||||
% DEFAULT_NUMBER_OF_TAXIS)
|
||||
parser.add_argument('-s', '--seed', type=int, default=None,
|
||||
help='random generator seed (for testing)')
|
||||
|
||||
args = parser.parse_args()
|
||||
main(args.end_time, args.taxis, args.seed)
|
||||
|
||||
|
||||
"""
|
||||
|
||||
Sample run from the command line, seed=3, maximum elapsed time=120::
|
||||
|
||||
# BEGIN TAXI_SAMPLE_RUN
|
||||
$ python3 taxi_sim.py -s 3 -e 120
|
||||
taxi: 0 Event(time=0, proc=0, action='leave garage')
|
||||
taxi: 0 Event(time=2, proc=0, action='pick up passenger')
|
||||
taxi: 1 Event(time=5, proc=1, action='leave garage')
|
||||
taxi: 1 Event(time=8, proc=1, action='pick up passenger')
|
||||
taxi: 2 Event(time=10, proc=2, action='leave garage')
|
||||
taxi: 2 Event(time=15, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=17, proc=2, action='drop off passenger')
|
||||
taxi: 0 Event(time=18, proc=0, action='drop off passenger')
|
||||
taxi: 2 Event(time=18, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=25, proc=2, action='drop off passenger')
|
||||
taxi: 1 Event(time=27, proc=1, action='drop off passenger')
|
||||
taxi: 2 Event(time=27, proc=2, action='pick up passenger')
|
||||
taxi: 0 Event(time=28, proc=0, action='pick up passenger')
|
||||
taxi: 2 Event(time=40, proc=2, action='drop off passenger')
|
||||
taxi: 2 Event(time=44, proc=2, action='pick up passenger')
|
||||
taxi: 1 Event(time=55, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=59, proc=1, action='drop off passenger')
|
||||
taxi: 0 Event(time=65, proc=0, action='drop off passenger')
|
||||
taxi: 1 Event(time=65, proc=1, action='pick up passenger')
|
||||
taxi: 2 Event(time=65, proc=2, action='drop off passenger')
|
||||
taxi: 2 Event(time=72, proc=2, action='pick up passenger')
|
||||
taxi: 0 Event(time=76, proc=0, action='going home')
|
||||
taxi: 1 Event(time=80, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=88, proc=1, action='pick up passenger')
|
||||
taxi: 2 Event(time=95, proc=2, action='drop off passenger')
|
||||
taxi: 2 Event(time=97, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=98, proc=2, action='drop off passenger')
|
||||
taxi: 1 Event(time=106, proc=1, action='drop off passenger')
|
||||
taxi: 2 Event(time=109, proc=2, action='going home')
|
||||
taxi: 1 Event(time=110, proc=1, action='going home')
|
||||
*** end of events ***
|
||||
# END TAXI_SAMPLE_RUN
|
||||
|
||||
"""
|
||||
File renamed without changes.
@@ -0,0 +1,215 @@
|
||||
|
||||
"""
|
||||
Taxi simulator with delay on output
|
||||
===================================
|
||||
|
||||
This is a variation of ``taxi_sim.py`` which adds a ``-d`` comand-line
|
||||
option. When given, that option adds a delay in the main loop, pausing
|
||||
the simulation for .5s for each "minute" of simulation time.
|
||||
|
||||
|
||||
Driving a taxi from the console::
|
||||
|
||||
>>> from taxi_sim import taxi_process
|
||||
>>> taxi = taxi_process(ident=13, trips=2, start_time=0)
|
||||
>>> next(taxi)
|
||||
Event(time=0, proc=13, action='leave garage')
|
||||
>>> taxi.send(_.time + 7)
|
||||
Event(time=7, proc=13, action='pick up passenger')
|
||||
>>> taxi.send(_.time + 23)
|
||||
Event(time=30, proc=13, action='drop off passenger')
|
||||
>>> taxi.send(_.time + 5)
|
||||
Event(time=35, proc=13, action='pick up passenger')
|
||||
>>> taxi.send(_.time + 48)
|
||||
Event(time=83, proc=13, action='drop off passenger')
|
||||
>>> taxi.send(_.time + 1)
|
||||
Event(time=84, proc=13, action='going home')
|
||||
>>> taxi.send(_.time + 10)
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
StopIteration
|
||||
|
||||
Sample run with two cars, random seed 10. This is a valid doctest::
|
||||
|
||||
>>> main(num_taxis=2, seed=10)
|
||||
taxi: 0 Event(time=0, proc=0, action='leave garage')
|
||||
taxi: 0 Event(time=5, proc=0, action='pick up passenger')
|
||||
taxi: 1 Event(time=5, proc=1, action='leave garage')
|
||||
taxi: 1 Event(time=10, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=15, proc=1, action='drop off passenger')
|
||||
taxi: 0 Event(time=17, proc=0, action='drop off passenger')
|
||||
taxi: 1 Event(time=24, proc=1, action='pick up passenger')
|
||||
taxi: 0 Event(time=26, proc=0, action='pick up passenger')
|
||||
taxi: 0 Event(time=30, proc=0, action='drop off passenger')
|
||||
taxi: 0 Event(time=34, proc=0, action='going home')
|
||||
taxi: 1 Event(time=46, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=48, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=110, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=139, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=140, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=150, proc=1, action='going home')
|
||||
*** end of events ***
|
||||
|
||||
See longer sample run at the end of this module.
|
||||
|
||||
"""
|
||||
|
||||
import random
|
||||
import collections
|
||||
import queue
|
||||
import argparse
|
||||
import time
|
||||
|
||||
DEFAULT_NUMBER_OF_TAXIS = 3
|
||||
DEFAULT_END_TIME = 180
|
||||
SEARCH_DURATION = 5
|
||||
TRIP_DURATION = 20
|
||||
DEPARTURE_INTERVAL = 5
|
||||
|
||||
Event = collections.namedtuple('Event', 'time proc action')
|
||||
|
||||
|
||||
# BEGIN TAXI_PROCESS
|
||||
def taxi_process(ident, trips, start_time=0): # <1>
|
||||
"""Yield to simulator issuing event at each state change"""
|
||||
time = yield Event(start_time, ident, 'leave garage') # <2>
|
||||
for i in range(trips): # <3>
|
||||
time = yield Event(time, ident, 'pick up passenger') # <4>
|
||||
time = yield Event(time, ident, 'drop off passenger') # <5>
|
||||
|
||||
yield Event(time, ident, 'going home') # <6>
|
||||
# end of taxi process # <7>
|
||||
# END TAXI_PROCESS
|
||||
|
||||
|
||||
# BEGIN TAXI_SIMULATOR
|
||||
class Simulator:
|
||||
|
||||
def __init__(self, procs_map):
|
||||
self.events = queue.PriorityQueue()
|
||||
self.procs = dict(procs_map)
|
||||
|
||||
def run(self, end_time, delay=False): # <1>
|
||||
"""Schedule and display events until time is up"""
|
||||
# schedule the first event for each cab
|
||||
for _, proc in sorted(self.procs.items()): # <2>
|
||||
first_event = next(proc) # <3>
|
||||
self.events.put(first_event) # <4>
|
||||
|
||||
# main loop of the simulation
|
||||
sim_time = 0 # <5>
|
||||
while sim_time < end_time: # <6>
|
||||
if self.events.empty(): # <7>
|
||||
print('*** end of events ***')
|
||||
break
|
||||
|
||||
# get and display current event
|
||||
current_event = self.events.get() # <8>
|
||||
if delay:
|
||||
time.sleep((current_event.time - sim_time) / 2)
|
||||
# update the simulation time
|
||||
sim_time, proc_id, previous_action = current_event
|
||||
print('taxi:', proc_id, proc_id * ' ', current_event)
|
||||
active_proc = self.procs[proc_id]
|
||||
# schedule next action for current proc
|
||||
next_time = sim_time + compute_duration(previous_action)
|
||||
try:
|
||||
next_event = active_proc.send(next_time) # <12>
|
||||
except StopIteration:
|
||||
del self.procs[proc_id] # <13>
|
||||
else:
|
||||
self.events.put(next_event) # <14>
|
||||
else: # <15>
|
||||
msg = '*** end of simulation time: {} events pending ***'
|
||||
print(msg.format(self.events.qsize()))
|
||||
# END TAXI_SIMULATOR
|
||||
|
||||
|
||||
def compute_duration(previous_action):
|
||||
"""Compute action duration using exponential distribution"""
|
||||
if previous_action in ['leave garage', 'drop off passenger']:
|
||||
# new state is prowling
|
||||
interval = SEARCH_DURATION
|
||||
elif previous_action == 'pick up passenger':
|
||||
# new state is trip
|
||||
interval = TRIP_DURATION
|
||||
elif previous_action == 'going home':
|
||||
interval = 1
|
||||
else:
|
||||
raise ValueError('Unknown previous_action: %s' % previous_action)
|
||||
return int(random.expovariate(1/interval)) + 1
|
||||
|
||||
|
||||
def main(end_time=DEFAULT_END_TIME, num_taxis=DEFAULT_NUMBER_OF_TAXIS,
|
||||
seed=None, delay=False):
|
||||
"""Initialize random generator, build procs and run simulation"""
|
||||
if seed is not None:
|
||||
random.seed(seed) # get reproducible results
|
||||
|
||||
taxis = {i: taxi_process(i, (i+1)*2, i*DEPARTURE_INTERVAL)
|
||||
for i in range(num_taxis)}
|
||||
sim = Simulator(taxis)
|
||||
sim.run(end_time, delay)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Taxi fleet simulator.')
|
||||
parser.add_argument('-e', '--end-time', type=int,
|
||||
default=DEFAULT_END_TIME,
|
||||
help='simulation end time; default = %s'
|
||||
% DEFAULT_END_TIME)
|
||||
parser.add_argument('-t', '--taxis', type=int,
|
||||
default=DEFAULT_NUMBER_OF_TAXIS,
|
||||
help='number of taxis running; default = %s'
|
||||
% DEFAULT_NUMBER_OF_TAXIS)
|
||||
parser.add_argument('-s', '--seed', type=int, default=None,
|
||||
help='random generator seed (for testing)')
|
||||
parser.add_argument('-d', '--delay', action='store_true',
|
||||
help='introduce delay proportional to simulation time')
|
||||
|
||||
args = parser.parse_args()
|
||||
main(args.end_time, args.taxis, args.seed, args.delay)
|
||||
|
||||
|
||||
"""
|
||||
|
||||
Sample run from the command line, seed=3, maximum elapsed time=120::
|
||||
|
||||
# BEGIN TAXI_SAMPLE_RUN
|
||||
$ python3 taxi_sim.py -s 3 -e 120
|
||||
taxi: 0 Event(time=0, proc=0, action='leave garage')
|
||||
taxi: 0 Event(time=2, proc=0, action='pick up passenger')
|
||||
taxi: 1 Event(time=5, proc=1, action='leave garage')
|
||||
taxi: 1 Event(time=8, proc=1, action='pick up passenger')
|
||||
taxi: 2 Event(time=10, proc=2, action='leave garage')
|
||||
taxi: 2 Event(time=15, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=17, proc=2, action='drop off passenger')
|
||||
taxi: 0 Event(time=18, proc=0, action='drop off passenger')
|
||||
taxi: 2 Event(time=18, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=25, proc=2, action='drop off passenger')
|
||||
taxi: 1 Event(time=27, proc=1, action='drop off passenger')
|
||||
taxi: 2 Event(time=27, proc=2, action='pick up passenger')
|
||||
taxi: 0 Event(time=28, proc=0, action='pick up passenger')
|
||||
taxi: 2 Event(time=40, proc=2, action='drop off passenger')
|
||||
taxi: 2 Event(time=44, proc=2, action='pick up passenger')
|
||||
taxi: 1 Event(time=55, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=59, proc=1, action='drop off passenger')
|
||||
taxi: 0 Event(time=65, proc=0, action='drop off passenger')
|
||||
taxi: 1 Event(time=65, proc=1, action='pick up passenger')
|
||||
taxi: 2 Event(time=65, proc=2, action='drop off passenger')
|
||||
taxi: 2 Event(time=72, proc=2, action='pick up passenger')
|
||||
taxi: 0 Event(time=76, proc=0, action='going home')
|
||||
taxi: 1 Event(time=80, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=88, proc=1, action='pick up passenger')
|
||||
taxi: 2 Event(time=95, proc=2, action='drop off passenger')
|
||||
taxi: 2 Event(time=97, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=98, proc=2, action='drop off passenger')
|
||||
taxi: 1 Event(time=106, proc=1, action='drop off passenger')
|
||||
taxi: 2 Event(time=109, proc=2, action='going home')
|
||||
taxi: 1 Event(time=110, proc=1, action='going home')
|
||||
*** end of events ***
|
||||
# END TAXI_SAMPLE_RUN
|
||||
|
||||
"""
|
||||
File renamed without changes.
@@ -0,0 +1,32 @@
|
||||
# Code below is a very simplified expansion of the statement:
|
||||
#
|
||||
# RESULT = yield from EXPR
|
||||
#
|
||||
# This code assumes that the subgenerator will run to completion,
|
||||
# without the client ever calling ``.throw()`` or ``.close()``.
|
||||
# Also, this code makes no distinction between the client
|
||||
# calling ``next(subgen)`` or ``subgen.send(...)``
|
||||
#
|
||||
# The full expansion is in:
|
||||
# PEP 380 -- Syntax for Delegating to a Subgenerator
|
||||
#
|
||||
# https://www.python.org/dev/peps/pep-0380/#formal-semantics
|
||||
|
||||
|
||||
# BEGIN YIELD_FROM_EXPANSION_SIMPLIFIED
|
||||
_i = iter(EXPR) # <1>
|
||||
try:
|
||||
_y = next(_i) # <2>
|
||||
except StopIteration as _e:
|
||||
_r = _e.value # <3>
|
||||
else:
|
||||
while 1: # <4>
|
||||
_s = yield _y # <5>
|
||||
try:
|
||||
_y = _i.send(_s) # <6>
|
||||
except StopIteration as _e: # <7>
|
||||
_r = _e.value
|
||||
break
|
||||
|
||||
RESULT = _r # <8>
|
||||
# END YIELD_FROM_EXPANSION_SIMPLIFIED
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -92,25 +92,23 @@ def downloader_coro(cc_list, base_url, verbose, concur_req): # <1>
|
||||
error_msg = exc.__cause__.args[0] # <10>
|
||||
except IndexError:
|
||||
error_msg = exc.__cause__.__class__.__name__ # <11>
|
||||
if verbose and error_msg:
|
||||
msg = '*** Error for {}: {}'
|
||||
print(msg.format(country_code, error_msg))
|
||||
status = HTTPStatus.error
|
||||
else:
|
||||
error_msg = ''
|
||||
status = res.status
|
||||
|
||||
if error_msg: # <12>
|
||||
status = HTTPStatus.error
|
||||
counter[status] += 1
|
||||
if verbose and error_msg:
|
||||
msg = '*** Error for {}: {}'
|
||||
print(msg.format(country_code, error_msg))
|
||||
counter[status] += 1 # <12>
|
||||
|
||||
return counter
|
||||
return counter # <13>
|
||||
|
||||
|
||||
def download_many(cc_list, base_url, verbose, concur_req):
|
||||
loop = asyncio.get_event_loop()
|
||||
coro = downloader_coro(cc_list, base_url, verbose, concur_req)
|
||||
counts = loop.run_until_complete(coro) # <13>
|
||||
loop.close() # <14>
|
||||
counts = loop.run_until_complete(coro) # <14>
|
||||
loop.close() # <15>
|
||||
|
||||
return counts
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -38,10 +38,10 @@ def download_many(cc_list, base_url, verbose, concur_req):
|
||||
future = executor.submit(download_one,
|
||||
cc, base_url, verbose) # <9>
|
||||
to_do_map[future] = cc # <10>
|
||||
to_do_iter = futures.as_completed(to_do_map) # <11>
|
||||
done_iter = futures.as_completed(to_do_map) # <11>
|
||||
if not verbose:
|
||||
to_do_iter = tqdm.tqdm(to_do_iter, total=len(cc_list)) # <12>
|
||||
for future in to_do_iter: # <13>
|
||||
done_iter = tqdm.tqdm(done_iter, total=len(cc_list)) # <12>
|
||||
for future in done_iter: # <13>
|
||||
try:
|
||||
res = future.result() # <14>
|
||||
except requests.exceptions.HTTPError as exc: # <15>
|
||||
@@ -105,16 +105,14 @@ def downloader_coro(cc_list, base_url, verbose, concur_req):
|
||||
error_msg = exc.__cause__.args[0]
|
||||
except IndexError:
|
||||
error_msg = exc.__cause__.__class__.__name__
|
||||
if verbose and error_msg:
|
||||
msg = '*** Error for {}: {}'
|
||||
print(msg.format(country_code, error_msg))
|
||||
status = HTTPStatus.error
|
||||
else:
|
||||
error_msg = ''
|
||||
status = res.status
|
||||
|
||||
if error_msg:
|
||||
status = HTTPStatus.error
|
||||
counter[status] += 1
|
||||
if verbose and error_msg:
|
||||
msg = '*** Error for {}: {}'
|
||||
print(msg.format(country_code, error_msg))
|
||||
|
||||
return counter
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -10,8 +10,8 @@ import itertools
|
||||
import sys
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def spin(msg): # <1>
|
||||
@asyncio.coroutine # <1>
|
||||
def spin(msg): # <2>
|
||||
write, flush = sys.stdout.write, sys.stdout.flush
|
||||
for char in itertools.cycle('|/-\\'):
|
||||
status = char + ' ' + msg
|
||||
@@ -19,31 +19,31 @@ def spin(msg): # <1>
|
||||
flush()
|
||||
write('\x08' * len(status))
|
||||
try:
|
||||
yield from asyncio.sleep(.1) # <2>
|
||||
except asyncio.CancelledError: # <3>
|
||||
yield from asyncio.sleep(.1) # <3>
|
||||
except asyncio.CancelledError: # <4>
|
||||
break
|
||||
write(' ' * len(status) + '\x08' * len(status))
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def slow_computation(): # <4>
|
||||
# fake computation waiting a long time for I/O
|
||||
yield from asyncio.sleep(3) # <5>
|
||||
def slow_function(): # <5>
|
||||
# pretend waiting a long time for I/O
|
||||
yield from asyncio.sleep(3) # <6>
|
||||
return 42
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def supervisor(): # <6>
|
||||
spinner = asyncio.async(spin('thinking!')) # <7>
|
||||
print('spinner object:', spinner) # <8>
|
||||
result = yield from slow_computation() # <9>
|
||||
spinner.cancel() # <10>
|
||||
def supervisor(): # <7>
|
||||
spinner = asyncio.async(spin('thinking!')) # <8>
|
||||
print('spinner object:', spinner) # <9>
|
||||
result = yield from slow_function() # <10>
|
||||
spinner.cancel() # <11>
|
||||
return result
|
||||
|
||||
|
||||
def main():
|
||||
loop = asyncio.get_event_loop() # <11>
|
||||
result = loop.run_until_complete(supervisor()) # <12>
|
||||
loop = asyncio.get_event_loop() # <12>
|
||||
result = loop.run_until_complete(supervisor()) # <13>
|
||||
loop.close()
|
||||
print('Answer:', result)
|
||||
|
||||
|
||||
@@ -28,19 +28,19 @@ def spin(msg, signal): # <2>
|
||||
write(' ' * len(status) + '\x08' * len(status)) # <6>
|
||||
|
||||
|
||||
def slow_computation(): # <7>
|
||||
# fake computation waiting a long time for I/O
|
||||
def slow_function(): # <7>
|
||||
# pretend waiting a long time for I/O
|
||||
time.sleep(3) # <8>
|
||||
return 42
|
||||
|
||||
|
||||
def supervisor(): # <9>
|
||||
signal = Signal()
|
||||
spinner = threading.Thread(None, spin,
|
||||
spinner = threading.Thread(target=spin,
|
||||
args=('thinking!', signal))
|
||||
print('spinner object:', spinner) # <10>
|
||||
spinner.start() # <11>
|
||||
result = slow_computation() # <12>
|
||||
result = slow_function() # <12>
|
||||
signal.go = False # <13>
|
||||
spinner.join() # <14>
|
||||
return result
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
explore1.py: Script to explore the OSCON schedule feed
|
||||
explore0.py: Script to explore the OSCON schedule feed
|
||||
|
||||
# BEGIN EXPLORE1_DEMO
|
||||
# BEGIN EXPLORE0_DEMO
|
||||
>>> from osconfeed import load
|
||||
>>> raw_feed = load()
|
||||
>>> feed = FrozenJSON(raw_feed) # <1>
|
||||
@@ -18,7 +18,9 @@ explore1.py: Script to explore the OSCON schedule feed
|
||||
53 venues
|
||||
>>> feed.Schedule.speakers[-1].name # <5>
|
||||
'Carina C. Zona'
|
||||
>>> talk = feed.Schedule.events[40] # <6>
|
||||
>>> talk = feed.Schedule.events[40]
|
||||
>>> type(talk) # <6>
|
||||
<class 'explore0.FrozenJSON'>
|
||||
>>> talk.name
|
||||
'There *Will* Be Bugs'
|
||||
>>> talk.speakers # <7>
|
||||
@@ -28,10 +30,11 @@ explore1.py: Script to explore the OSCON schedule feed
|
||||
...
|
||||
KeyError: 'flavor'
|
||||
|
||||
# END EXPLORE1_DEMO
|
||||
# END EXPLORE0_DEMO
|
||||
|
||||
"""
|
||||
|
||||
# BEGIN EXPLORE1
|
||||
# BEGIN EXPLORE0
|
||||
from collections import abc
|
||||
|
||||
|
||||
@@ -57,4 +60,4 @@ class FrozenJSON:
|
||||
return [cls.build(item) for item in obj]
|
||||
else: # <8>
|
||||
return obj
|
||||
# END EXPLORE1
|
||||
# END EXPLORE0
|
||||
@@ -0,0 +1,78 @@
|
||||
"""
|
||||
explore1.py: Script to explore the OSCON schedule feed
|
||||
|
||||
>>> from osconfeed import load
|
||||
>>> raw_feed = load()
|
||||
>>> feed = FrozenJSON(raw_feed)
|
||||
>>> len(feed.Schedule.speakers)
|
||||
357
|
||||
>>> sorted(feed.Schedule.keys())
|
||||
['conferences', 'events', 'speakers', 'venues']
|
||||
>>> for key, value in sorted(feed.Schedule.items()):
|
||||
... print('{:3} {}'.format(len(value), key))
|
||||
...
|
||||
1 conferences
|
||||
484 events
|
||||
357 speakers
|
||||
53 venues
|
||||
>>> feed.Schedule.speakers[-1].name
|
||||
'Carina C. Zona'
|
||||
>>> talk = feed.Schedule.events[40]
|
||||
>>> type(talk)
|
||||
<class 'explore1.FrozenJSON'>
|
||||
>>> talk.name
|
||||
'There *Will* Be Bugs'
|
||||
>>> talk.speakers
|
||||
[3471, 5199]
|
||||
>>> talk.flavor
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
KeyError: 'flavor'
|
||||
|
||||
Handle keywords by appending a `_`.
|
||||
|
||||
# BEGIN EXPLORE1_DEMO
|
||||
|
||||
>>> grad = FrozenJSON({'name': 'Jim Bo', 'class': 1982})
|
||||
>>> grad.name
|
||||
'Jim Bo'
|
||||
>>> grad.class_
|
||||
1991
|
||||
|
||||
# END EXPLORE1_DEMO
|
||||
|
||||
"""
|
||||
|
||||
from collections import abc
|
||||
import keyword
|
||||
|
||||
|
||||
class FrozenJSON:
|
||||
"""A read-only façade for navigating a JSON-like object
|
||||
using attribute notation
|
||||
"""
|
||||
|
||||
# BEGIN EXPLORE1
|
||||
def __init__(self, mapping):
|
||||
self.__data = {}
|
||||
for key, value in mapping.items():
|
||||
if keyword.iskeyword(key): # <1>
|
||||
key += '_'
|
||||
self.__data[key] = value
|
||||
# END EXPLORE1
|
||||
|
||||
def __getattr__(self, name):
|
||||
if hasattr(self.__data, name):
|
||||
return getattr(self.__data, name)
|
||||
else:
|
||||
return FrozenJSON.build(self.__data[name])
|
||||
|
||||
@classmethod
|
||||
def build(cls, obj):
|
||||
if isinstance(obj, abc.Mapping):
|
||||
return cls(obj)
|
||||
elif isinstance(obj, abc.MutableSequence):
|
||||
return [cls.build(item) for item in obj]
|
||||
else: # <8>
|
||||
return obj
|
||||
|
||||
@@ -40,7 +40,11 @@ class FrozenJSON:
|
||||
return arg
|
||||
|
||||
def __init__(self, mapping):
|
||||
self.__data = dict(mapping)
|
||||
self.__data = {}
|
||||
for key, value in mapping.items():
|
||||
if iskeyword(key):
|
||||
key += '_'
|
||||
self.__data[key] = value
|
||||
|
||||
def __getattr__(self, name):
|
||||
if hasattr(self.__data, name):
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,12 +0,0 @@
|
||||
What's New in Python 2.5 - PEP 342: New Generator Features
|
||||
http://docs.python.org/release/2.5/whatsnew/pep-342.html
|
||||
|
||||
PEP 342 -- Coroutines via Enhanced Generators
|
||||
http://www.python.org/dev/peps/pep-0342/
|
||||
|
||||
PEP 380 -- Syntax for Delegating to a Subgenerator
|
||||
http://www.python.org/dev/peps/pep-0380/
|
||||
|
||||
Coroutines For the Working Python Developer
|
||||
http://sdiehl.github.io/coroutine-tutorial/
|
||||
|
||||
@@ -1,270 +0,0 @@
|
||||
|
||||
"""
|
||||
Taxi simulator
|
||||
|
||||
Sample run with two cars, random seed 10. This is a valid doctest.
|
||||
|
||||
>>> main(num_taxis=2, seed=10)
|
||||
taxi: 0 Event(time=0, proc=0, action='leave garage')
|
||||
taxi: 0 Event(time=4, proc=0, action='pick up passenger')
|
||||
taxi: 1 Event(time=5, proc=1, action='leave garage')
|
||||
taxi: 1 Event(time=9, proc=1, action='pick up passenger')
|
||||
taxi: 0 Event(time=10, proc=0, action='drop off passenger')
|
||||
taxi: 1 Event(time=12, proc=1, action='drop off passenger')
|
||||
taxi: 0 Event(time=17, proc=0, action='pick up passenger')
|
||||
taxi: 1 Event(time=19, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=21, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=24, proc=1, action='pick up passenger')
|
||||
taxi: 0 Event(time=28, proc=0, action='drop off passenger')
|
||||
taxi: 1 Event(time=28, proc=1, action='drop off passenger')
|
||||
taxi: 0 Event(time=29, proc=0, action='going home')
|
||||
taxi: 1 Event(time=30, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=61, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=62, proc=1, action='going home')
|
||||
*** end of events ***
|
||||
|
||||
See explanation and longer sample run at the end of this module.
|
||||
|
||||
"""
|
||||
|
||||
import random
|
||||
import collections
|
||||
import queue
|
||||
import argparse
|
||||
import time
|
||||
|
||||
DEFAULT_NUMBER_OF_TAXIS = 3
|
||||
DEFAULT_END_TIME = 180
|
||||
SEARCH_DURATION = 5
|
||||
TRIP_DURATION = 20
|
||||
DEPARTURE_INTERVAL = 5
|
||||
|
||||
Event = collections.namedtuple('Event', 'time proc action')
|
||||
|
||||
|
||||
# BEGIN TAXI_PROCESS
|
||||
def taxi_process(ident, trips, start_time=0): # <1>
|
||||
"""Yield to simulator issuing event at each state change"""
|
||||
time = yield Event(start_time, ident, 'leave garage') # <2>
|
||||
for i in range(trips): # <3>
|
||||
time = yield Event(time, ident, 'pick up passenger') # <4>
|
||||
time = yield Event(time, ident, 'drop off passenger') # <5>
|
||||
|
||||
yield Event(time, ident, 'going home') # <6>
|
||||
# end of taxi process # <7>
|
||||
# END TAXI_PROCESS
|
||||
|
||||
|
||||
# BEGIN TAXI_SIMULATOR
|
||||
class Simulator:
|
||||
|
||||
def __init__(self, procs_map):
|
||||
self.events = queue.PriorityQueue()
|
||||
self.procs = dict(procs_map)
|
||||
|
||||
def run(self, end_time, delay=False): # <1>
|
||||
"""Schedule and display events until time is up"""
|
||||
# schedule the first event for each cab
|
||||
for _, proc in sorted(self.procs.items()): # <2>
|
||||
first_event = next(proc) # <3>
|
||||
self.events.put(first_event) # <4>
|
||||
|
||||
# main loop of the simulation
|
||||
sim_time = 0 # <5>
|
||||
while sim_time < end_time: # <6>
|
||||
if self.events.empty(): # <7>
|
||||
print('*** end of events ***')
|
||||
break
|
||||
|
||||
# get and display current event
|
||||
current_event = self.events.get() # <8>
|
||||
if delay:
|
||||
time.sleep((current_event.time - sim_time) / 2)
|
||||
# update the simulation time
|
||||
sim_time, proc_id, previous_action = current_event
|
||||
print('taxi:', proc_id, proc_id * ' ', current_event)
|
||||
active_proc = self.procs[proc_id]
|
||||
# schedule next action for current proc
|
||||
next_time = sim_time + compute_duration(previous_action)
|
||||
try:
|
||||
next_event = active_proc.send(next_time) # <12>
|
||||
except StopIteration:
|
||||
del self.procs[proc_id] # <13>
|
||||
else:
|
||||
self.events.put(next_event) # <14>
|
||||
else: # <15>
|
||||
msg = '*** end of simulation time: {} events pending ***'
|
||||
print(msg.format(self.events.qsize()))
|
||||
# END TAXI_SIMULATOR
|
||||
|
||||
|
||||
def compute_duration(previous_action):
|
||||
"""Compute action duration using exponential distribution"""
|
||||
if previous_action in ['leave garage', 'drop off passenger']:
|
||||
# state is prowling
|
||||
interval = SEARCH_DURATION
|
||||
elif previous_action == 'pick up passenger':
|
||||
# state is trip
|
||||
interval = TRIP_DURATION
|
||||
elif previous_action == 'going home':
|
||||
interval = 1
|
||||
else:
|
||||
assert False
|
||||
return int(random.expovariate(1/interval)) + 1
|
||||
|
||||
|
||||
def main(end_time=DEFAULT_END_TIME, num_taxis=DEFAULT_NUMBER_OF_TAXIS,
|
||||
seed=None, delay=False):
|
||||
"""Initialize random generator, build procs and run simulation"""
|
||||
if seed is not None:
|
||||
random.seed(seed) # get reproducible results
|
||||
|
||||
taxis = {i: taxi_process(i, (i+1)*2, i*DEPARTURE_INTERVAL)
|
||||
for i in range(num_taxis)}
|
||||
sim = Simulator(taxis)
|
||||
sim.run(end_time, delay)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Taxi fleet simulator.')
|
||||
parser.add_argument('-e', '--end-time', type=int,
|
||||
default=DEFAULT_END_TIME,
|
||||
help='simulation end time; default = %s'
|
||||
% DEFAULT_END_TIME)
|
||||
parser.add_argument('-t', '--taxis', type=int,
|
||||
default=DEFAULT_NUMBER_OF_TAXIS,
|
||||
help='number of taxis running; default = %s'
|
||||
% DEFAULT_NUMBER_OF_TAXIS)
|
||||
parser.add_argument('-s', '--seed', type=int, default=None,
|
||||
help='random generator seed (for testing)')
|
||||
parser.add_argument('-d', '--delay', action='store_true',
|
||||
help='introduce delay proportional to simulation time')
|
||||
|
||||
args = parser.parse_args()
|
||||
main(args.end_time, args.taxis, args.seed, args.delay)
|
||||
|
||||
|
||||
"""
|
||||
Notes for the ``taxi_process`` coroutine::
|
||||
|
||||
<1> `taxi_process` will be called once per taxi, creating a generator
|
||||
object to represent its operations. `ident` is the number of the taxi
|
||||
(eg. 0, 1, 2 in the sample run); `trips` is the number of trips this
|
||||
taxi will make before going home; `start_time` is when the taxi
|
||||
leaves the garage.
|
||||
|
||||
<2> The first `Event` yielded is `'leave garage'`. This suspends the
|
||||
coroutine, and lets the simulation main loop proceed to the next
|
||||
scheduled event. When it's time to reactivate this process, the main
|
||||
loop will `send` the current simulation time, which is assigned to
|
||||
`time`.
|
||||
|
||||
<3> This block will be repeated once for each trip.
|
||||
|
||||
<4> The ending time of the search for a passenger is computed.
|
||||
|
||||
<5> An `Event` signaling passenger pick up is yielded. The coroutine
|
||||
pauses here. When the time comes to reactivate this coroutine,
|
||||
the main loop will again `send` the current time.
|
||||
|
||||
<6> The ending time of the trip is computed, taking into account the
|
||||
current `time`.
|
||||
|
||||
<7> An `Event` signaling passenger drop off is yielded. Coroutine
|
||||
suspended again, waiting for the main loop to send the time of when
|
||||
it's time to continue.
|
||||
|
||||
<8> The `for` loop ends after the given number of trips, and a final
|
||||
`'going home'` event is yielded, to happen 1 minute after the current
|
||||
time. The coroutine will suspend for the last time. When reactivated,
|
||||
it will be sent the time from the simulation main loop, but here I
|
||||
don't assign it to any variable because it will not be useful.
|
||||
|
||||
<9> When the coroutine falls off the end, the coroutine object raises
|
||||
`StopIteration`.
|
||||
|
||||
|
||||
Notes for the ``Simulator.run`` method::
|
||||
|
||||
<1> The simulation `end_time` is the only required argument for `run`.
|
||||
|
||||
<2> Use `sorted` to retrieve the `self.procs` items ordered by the
|
||||
integer key; we don't care about the key, so assign it to `_`.
|
||||
|
||||
<3> `next(proc)` primes each coroutine by advancing it to the first
|
||||
yield, so it's ready to be sent data. An `Event` is yielded.
|
||||
|
||||
<4> Add each event to the `self.events` `PriorityQueue`. The first
|
||||
event for each taxi is `'leave garage'`, as seen in the sample run
|
||||
(ex_taxi_process>>).
|
||||
|
||||
<5> Main loop of the simulation: run until the current `time` equals
|
||||
or exceeds the `end_time`.
|
||||
|
||||
<6> The main loop may also exit if there are no pending events in the
|
||||
queue.
|
||||
|
||||
<7> Get `Event` with the smallest `time` in the queue; this is the
|
||||
`current_event`.
|
||||
|
||||
<8> Display the `Event`, identifying the taxi and adding indentation
|
||||
according to the taxi id.
|
||||
|
||||
<9> Update the simulation time with the time of the `current_event`.
|
||||
|
||||
<10> Retrieve the coroutine for this taxi from the `self.procs`
|
||||
dictionary.
|
||||
|
||||
<11> Send the `time` to the coroutine. The coroutine will yield the
|
||||
`next_event` or raise `StopIteration` it's finished.
|
||||
|
||||
<12> If `StopIteration` was raised, delete the coroutine from the
|
||||
`self.procs` dictionary.
|
||||
|
||||
<13> Otherwise, put the `next_event` in the queue.
|
||||
|
||||
<14> If the loop exits because the simulation time passed, display the
|
||||
number of events pending (which may be zero by coincidence,
|
||||
sometimes).
|
||||
|
||||
|
||||
Sample run from the command line, seed=24, total elapsed time=160::
|
||||
|
||||
# BEGIN TAXI_SAMPLE_RUN
|
||||
$ python3 taxi_sim.py -s 24 -e 160
|
||||
taxi: 0 Event(time=0, proc=0, action='leave garage')
|
||||
taxi: 0 Event(time=5, proc=0, action='pick up passenger')
|
||||
taxi: 1 Event(time=5, proc=1, action='leave garage')
|
||||
taxi: 1 Event(time=6, proc=1, action='pick up passenger')
|
||||
taxi: 2 Event(time=10, proc=2, action='leave garage')
|
||||
taxi: 2 Event(time=11, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=23, proc=2, action='drop off passenger')
|
||||
taxi: 0 Event(time=24, proc=0, action='drop off passenger')
|
||||
taxi: 2 Event(time=24, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=26, proc=2, action='drop off passenger')
|
||||
taxi: 0 Event(time=30, proc=0, action='pick up passenger')
|
||||
taxi: 2 Event(time=31, proc=2, action='pick up passenger')
|
||||
taxi: 0 Event(time=43, proc=0, action='drop off passenger')
|
||||
taxi: 0 Event(time=44, proc=0, action='going home')
|
||||
taxi: 2 Event(time=46, proc=2, action='drop off passenger')
|
||||
taxi: 2 Event(time=49, proc=2, action='pick up passenger')
|
||||
taxi: 1 Event(time=70, proc=1, action='drop off passenger')
|
||||
taxi: 2 Event(time=70, proc=2, action='drop off passenger')
|
||||
taxi: 2 Event(time=71, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=79, proc=2, action='drop off passenger')
|
||||
taxi: 1 Event(time=88, proc=1, action='pick up passenger')
|
||||
taxi: 2 Event(time=92, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=98, proc=2, action='drop off passenger')
|
||||
taxi: 2 Event(time=99, proc=2, action='going home')
|
||||
taxi: 1 Event(time=102, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=104, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=135, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=136, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=151, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=152, proc=1, action='going home')
|
||||
*** end of events ***
|
||||
# END TAXI_SAMPLE_RUN
|
||||
|
||||
"""
|
||||
Reference in new issue
Block a user