218 tr = tr, |
218 tr = tr, |
219 typename = bus_stop.typename, |
219 typename = bus_stop.typename, |
220 service = min(bus_stop.services), |
220 service = min(bus_stop.services), |
221 ) |
221 ) |
222 |
222 |
223 def week_schedule(bus_stop, **kwargs): |
223 def week_schedule(bus_stop, start_date = today(), **kwargs): |
224 for i in range(-1, 7): |
224 for i in range(-1, 7): |
225 try: |
225 try: |
226 yield from bus_stop.schedule_for_day(today() + timedelta(i), **kwargs) |
226 yield from bus_stop.schedule_for_day(start_date + timedelta(i), **kwargs) |
227 except ValueError: |
227 except ValueError: |
228 # went outside bounds |
228 # went outside bounds |
229 return |
229 return |
230 |
230 |
231 def route_key(route): |
231 def route_key(route): |
624 return 'saturday' |
624 return 'saturday' |
625 else: |
625 else: |
626 assert weekday == 6 |
626 assert weekday == 6 |
627 return 'sunday' |
627 return 'sunday' |
628 |
628 |
|
629 class Week: |
|
630 def __init__(self, year, weeknumber): |
|
631 self.year, self.weeknumber = year, weeknumber |
|
632 def normalize(self): |
|
633 while self.weeknumber > 52: |
|
634 self.weeknumber -= 52 |
|
635 self.year += 1 |
|
636 while self.weeknumber < 1: |
|
637 self.weeknumber += 52 |
|
638 self.year -= 1 |
|
639 def __repr__(self): |
|
640 return str.format( |
|
641 'Week({year}, {weeknumber})', |
|
642 year = self.year, |
|
643 weeknumber = self.weeknumber |
|
644 ) |
|
645 def __add__(self, numweeks): |
|
646 newweek = Week(year = self.year, weeknumber = self.weeknumber + numweeks) |
|
647 newweek.normalize() |
|
648 return newweek |
|
649 def __sub__(self, numweeks): |
|
650 newweek = Week(year = self.year, weeknumber = self.weeknumber - numweeks) |
|
651 newweek.normalize() |
|
652 return newweek |
|
653 def monday(self): |
|
654 from datetime import datetime |
|
655 datestring = str.format( |
|
656 '{year}-W{weeknumber}-1', |
|
657 year = self.year, |
|
658 weeknumber = self.weeknumber, |
|
659 ) |
|
660 return datetime.strptime(datestring, "%Y-W%W-%w").date() |
|
661 @staticmethod |
|
662 def fromstring(string): |
|
663 try: |
|
664 year, weeknumber = string.split('W', 1) |
|
665 return Week(year = int(year), weeknumber = int(weeknumber)) |
|
666 except ValueError: |
|
667 raise ValueError('bad week string: ' + repr(string)) |
|
668 @staticmethod |
|
669 def now(): |
|
670 from datetime import date |
|
671 cal = date.today().isocalendar() |
|
672 return Week(year = cal[0], weeknumber = cal[1]) |
|
673 |
629 @app.route('/stop_week/<stop_reference>') |
674 @app.route('/stop_week/<stop_reference>') |
630 def stop_week(stop_reference): |
675 def stop_week(stop_reference): |
631 from buses import bus_stops |
676 from buses import bus_stops |
632 from flask import request |
677 from flask import request |
|
678 from datetime import date |
|
679 if 'week' in request.args: |
|
680 try: |
|
681 week = Week.fromstring(request.args['week']) |
|
682 except ValueError: |
|
683 abort(400) |
|
684 else: |
|
685 week = Week.now() |
633 if 'routes' in request.args: |
686 if 'routes' in request.args: |
634 filtered_routes = set(request.args['routes'].split(';')) |
687 filtered_routes = set(request.args['routes'].split(';')) |
635 route_filter = lambda route: route in filtered_routes |
688 route_filter = lambda route: route in filtered_routes |
636 else: |
689 else: |
637 route_filter = lambda route: True |
690 route_filter = lambda route: True |
645 try: |
698 try: |
646 bus_stop = bus_stops[stop_reference] |
699 bus_stop = bus_stops[stop_reference] |
647 except KeyError: |
700 except KeyError: |
648 abort(404) |
701 abort(404) |
649 week_model = {} |
702 week_model = {} |
650 bus_stop_schedule = list(week_schedule(bus_stop, arrivals = True)) |
703 bus_stop_schedule = list(week_schedule(bus_stop, start_date = week.monday(), arrivals = True)) |
651 description = describe(bus_stop, bus_stop_schedule) |
704 description = describe(bus_stop, bus_stop_schedule) |
652 for schedule_entry in bus_stop_schedule: |
705 for schedule_entry in bus_stop_schedule: |
653 route_ref = schedule_entry['trip'].route.reference |
706 route_ref = schedule_entry['trip'].route.reference |
654 if route_filter(route_ref) and dest_filter(schedule_entry['trip']): |
707 if route_filter(route_ref) and dest_filter(schedule_entry['trip']): |
655 time = schedule_entry['time'] |
708 time = schedule_entry['time'] |
667 'night': is_night_time(schedule_entry['time']), |
720 'night': is_night_time(schedule_entry['time']), |
668 'minute': time.minute, |
721 'minute': time.minute, |
669 }) |
722 }) |
670 for day_offset in range(7): |
723 for day_offset in range(7): |
671 from datetime import date, datetime, timedelta |
724 from datetime import date, datetime, timedelta |
672 day = date.today() + timedelta(day_offset) |
725 day = week.monday() + timedelta(day_offset) |
673 try: |
726 try: |
674 day_model = week_model[day] |
727 day_model = week_model[day] |
675 except KeyError: |
728 except KeyError: |
676 week_model[day] = {} |
729 week_model[day] = {} |
677 else: |
730 else: |
708 name = tr(bus_stop.name, 'bus-stops'), |
761 name = tr(bus_stop.name, 'bus-stops'), |
709 tr = tr, |
762 tr = tr, |
710 week = week_model, |
763 week = week_model, |
711 description = description, |
764 description = description, |
712 typename = bus_stop.typename, |
765 typename = bus_stop.typename, |
|
766 curweek = week, |
713 ) |
767 ) |
714 |
768 |
715 @app.route('/trip/<trip_reference>') |
769 @app.route('/trip/<trip_reference>') |
716 def trip(trip_reference): |
770 def trip(trip_reference): |
717 from flask import request |
771 from flask import request |