136 old_places = places |
136 old_places = places |
137 if trip.to_place not in entries: |
137 if trip.to_place not in entries: |
138 entries += [trip.to_place] |
138 entries += [trip.to_place] |
139 return trip.route.reference + ':' + '-'.join(map(place_abbreviation, entries)) |
139 return trip.route.reference + ':' + '-'.join(map(place_abbreviation, entries)) |
140 |
140 |
|
141 def split_route_ref(route_ref): |
|
142 try: |
|
143 return list(parse_route_ref(route_ref)) |
|
144 except ValueError: |
|
145 return ['', route_ref, ''] |
|
146 |
141 @app.route('/stop/<reference>') |
147 @app.route('/stop/<reference>') |
142 def bus_stop_schedule(reference): |
148 def bus_stop_schedule(reference): |
143 from buses import bus_stops |
149 from buses import bus_stops |
144 schedule = [] |
150 schedule = [] |
145 try: |
151 try: |
146 bus_stop = bus_stops[reference] |
152 bus_stop = bus_stops[reference] |
147 except KeyError: |
153 except KeyError: |
148 abort(404) |
154 abort(404) |
149 for schedule_entry in bus_stop.schedule(max_amount = 100, arrivals = True): |
155 for schedule_entry in bus_stop.schedule(max_amount = 100, arrivals = True): |
|
156 route_ref = schedule_entry['trip'].route.reference |
150 schedule.append({ |
157 schedule.append({ |
151 'time': time_representation(schedule_entry['time']), |
158 'time': time_representation(schedule_entry['time']), |
152 'route': schedule_entry['trip'].route.reference, |
159 'route': route_ref, |
|
160 'route-splice': split_route_ref(route_ref), |
153 'sign': sign(schedule_entry), |
161 'sign': sign(schedule_entry), |
154 'trip': schedule_entry['stop'].trip.name, |
162 'trip': schedule_entry['stop'].trip.name, |
155 'night': is_night_time(schedule_entry['time']), |
163 'night': is_night_time(schedule_entry['time']), |
156 'imminent': imminent(schedule_entry), |
164 'imminent': imminent(schedule_entry), |
157 }) |
165 }) |
176 groups = match.groups() |
184 groups = match.groups() |
177 return (groups[0], int(groups[1]), groups[2]) |
185 return (groups[0], int(groups[1]), groups[2]) |
178 else: |
186 else: |
179 return (route,) |
187 return (route,) |
180 |
188 |
|
189 def parse_route_ref(route_ref): |
|
190 from re import search |
|
191 match = search(r'^([^0-9]*)([0-9]+)(.*)$', route_ref) |
|
192 try: |
|
193 return match.group(1), int(match.group(2)), match.group(3) |
|
194 except AttributeError: |
|
195 raise ValueError(route_ref) |
|
196 |
181 @app.route('/stop_description/<reference>') |
197 @app.route('/stop_description/<reference>') |
182 def bus_stop_description(reference): |
198 def bus_stop_description(reference): |
183 from buses import bus_stops |
199 from buses import bus_stops |
184 schedule = [] |
200 schedule = [] |
185 try: |
201 try: |
188 abort(404) |
204 abort(404) |
189 from collections import defaultdict, Counter |
205 from collections import defaultdict, Counter |
190 from busroute import simplify_name |
206 from busroute import simplify_name |
191 destinations_per_route = defaultdict(Counter) |
207 destinations_per_route = defaultdict(Counter) |
192 def route_key(route_ref): |
208 def route_key(route_ref): |
193 from re import search |
209 try: |
194 match = search(r'^([^0-9]*)([0-9]+)(.*)$', route_ref).groups() |
210 return parse_route_ref(route_ref) |
195 if match: |
211 except ValueError: |
196 return match[0], int(match[1]), match[2] |
|
197 else: |
|
198 return () |
212 return () |
199 def filter_names(names): |
213 def filter_names(names): |
200 if len(names) == 1 and names[0] == (bus_stop.region and simplify_name(bus_stop.region)): |
214 if len(names) == 1 and names[0] == (bus_stop.region and simplify_name(bus_stop.region)): |
201 return type(names)() |
215 return type(names)() |
202 else: |
216 else: |
394 abort(404) |
408 abort(404) |
395 for schedule_entry in cluster.schedule(max_amount = 100): |
409 for schedule_entry in cluster.schedule(max_amount = 100): |
396 schedule.append({ |
410 schedule.append({ |
397 'time': time_representation(schedule_entry['time']), |
411 'time': time_representation(schedule_entry['time']), |
398 'route': schedule_entry['trip'].route.reference, |
412 'route': schedule_entry['trip'].route.reference, |
|
413 'route-splice': split_route_ref(schedule_entry['trip'].route.reference), |
399 'sign': sign(schedule_entry), |
414 'sign': sign(schedule_entry), |
400 'trip': schedule_entry['stop'].trip.name, |
415 'trip': schedule_entry['stop'].trip.name, |
401 'night': is_night_time(schedule_entry['time']), |
416 'night': is_night_time(schedule_entry['time']), |
402 'stop_id': schedule_entry['stop'].stop.reference, |
417 'stop_id': schedule_entry['stop'].stop.reference, |
403 'stop_code': schedule_entry['stop'].stop.code, |
418 'stop_code': schedule_entry['stop'].stop.code, |
419 link_to_map = cluster.center.link_to_map, |
434 link_to_map = cluster.center.link_to_map, |
420 location = cluster.center, |
435 location = cluster.center, |
421 stops_in_cluster = stops_in_cluster, |
436 stops_in_cluster = stops_in_cluster, |
422 amount_of_stops_in_cluster = len(stops_in_cluster), |
437 amount_of_stops_in_cluster = len(stops_in_cluster), |
423 tr = tr, |
438 tr = tr, |
|
439 ) |
|
440 |
|
441 |
|
442 def hour_key(hour): |
|
443 return (hour - 5) % 24 |
|
444 |
|
445 def day_class(weekday): |
|
446 if weekday < 5: |
|
447 return 'working-day' |
|
448 elif weekday == 5: |
|
449 return 'saturday' |
|
450 else: |
|
451 assert weekday == 6 |
|
452 return 'sunday' |
|
453 |
|
454 @app.route('/stop_week/<stop_reference>') |
|
455 def stop_week(stop_reference): |
|
456 from buses import bus_stops |
|
457 from flask import request |
|
458 if 'routes' in request.args: |
|
459 filtered_routes = set(request.args['routes'].split(';')) |
|
460 route_filter = lambda route: route in filtered_routes |
|
461 else: |
|
462 route_filter = lambda route: True |
|
463 if 'dest' in request.args: |
|
464 dests = {bus_stops.get(dest, None) for dest in request.args['dest'].split(';')} |
|
465 dests.discard(None) |
|
466 dest_filter = lambda trip: any(trip.contains_stop(dest) for dest in dests) |
|
467 else: |
|
468 dest_filter = lambda trip: True |
|
469 schedule = [] |
|
470 try: |
|
471 bus_stop = bus_stops[stop_reference] |
|
472 except KeyError: |
|
473 abort(404) |
|
474 week_model = {} |
|
475 for schedule_entry in week_schedule(bus_stop, arrivals = True): |
|
476 route_ref = schedule_entry['trip'].route.reference |
|
477 if route_filter(route_ref) and dest_filter(schedule_entry['trip']): |
|
478 time = schedule_entry['time'] |
|
479 date = schedule_entry['date'] |
|
480 if date not in week_model: |
|
481 week_model[date] = {} |
|
482 day_model = week_model[date] |
|
483 if time.hour not in day_model: |
|
484 day_model[time.hour] = [] |
|
485 hour_model = day_model[time.hour] |
|
486 hour_model.append({ |
|
487 'route': route_ref, |
|
488 'route-splice': split_route_ref(route_ref), |
|
489 'trip': schedule_entry['stop'].trip.name, |
|
490 'night': is_night_time(schedule_entry['time']), |
|
491 'minute': time.minute, |
|
492 }) |
|
493 week_model = [{'day': day, 'schedule': schedule, 'day-class': day_class(day.weekday())} for day, schedule in week_model.items()] |
|
494 week_model = sorted(week_model, key = lambda day: day['day']) |
|
495 from pprint import pprint |
|
496 pprint(week_model) |
|
497 return render_template( |
|
498 'stop_week.html', |
|
499 ref = bus_stop.code, |
|
500 name = tr(bus_stop.name, 'bus-stops'), |
|
501 tr = tr, |
|
502 week = week_model, |
424 ) |
503 ) |
425 |
504 |
426 @app.route('/trip/<trip_reference>') |
505 @app.route('/trip/<trip_reference>') |
427 def trip(trip_reference): |
506 def trip(trip_reference): |
428 from flask import request |
507 from flask import request |