| 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 |