Sat, 24 Jun 2017 19:38:05 +0300
Lisää päivityksiä
#!/usr/bin/env python3 from flask import Flask, render_template, abort, send_from_directory from datetime import datetime, date, time, timedelta from os import path, listdir from configparser import ConfigParser import locale from misc import * from busroute import reduce_schedule import buses app = Flask(__name__) # Varmista ettei järjestelmän kieliasetukset sotke muotoiluja def reset_locale(): locale.setlocale(locale.LC_ALL, locale.getdefaultlocale()) def activate_locale(language = None): language = language or language_for_page() class result: def __enter__(self): locale.setlocale(locale.LC_ALL, tr('locale', 'other', language = language)) def __exit__(self, *args): reset_locale() return result() reset_locale() # Lataa käännökset class Translator: def __init__(self): self.languages = {} def load_language(self, file_path): language_name = path.splitext(path.basename(file_path))[0] ini = ConfigParser() ini.read(path.join(file_path)) self.languages[language_name] = ini def __call__(self, name, section, language = None): language = language or language_for_page() try: return self.languages[language][section][name] except KeyError: return name tr = Translator() for file in listdir('tr'): tr.load_language(path.join('tr', file)) def language_for_page(): from flask import request if request.args.get('kääntämätön') is not None: return None else: for language_name in tr.languages: if request.args.get(language_name) is not None: return language_name else: return 'fi' def sign(schedule_entry): from math import ceil trip_length = schedule_entry['trip'].length - schedule_entry['stop'].traveled_distance sign = reduce_schedule(schedule_entry['trip'].concise_schedule(schedule_entry['stop']), trip_length = trip_length) if sign: sign = [tr(place, 'paikat') for place in sign] sign_representation = ' - '.join(sign) #if len(sign_representation) > 25: # k = ceil(len(sign) / 2) # sign_representation = ' - '.join(sign[:k]) + '\n' + ' - '.join(sign[k:]) return sign_representation else: return schedule_entry['trip'].schedule[-1].stop.name @app.route('/pysäkki/<reference>') def bus_stop_schedule(reference): from buses import bus_stops schedule = [] try: bus_stop = bus_stops[reference] except KeyError: abort(404) for schedule_entry in bus_stop.schedule(100): schedule.append({ 'time': time_representation(schedule_entry['time']), 'route': schedule_entry['trip'].route.reference, 'sign': sign(schedule_entry), 'trip': schedule_entry['stop'].trip.name, 'night': is_night_time(schedule_entry['time']), }) return render_template( 'stop.html', schedule = schedule, name = bus_stop.code + ' ' + tr(bus_stop.name, 'bus_stops'), link_to_map = bus_stop.location.link_to_map, region = bus_stop.region, location = bus_stop.location, cluster = bus_stop.cluster.url_name if len(bus_stop.cluster.stops) > 1 else None, tr = tr, ) def time_representation(time, relative = True): time_difference = time - now() if relative and time_difference > timedelta(0) and time_difference < timedelta(minutes = 1): return tr('right-now', 'misc-text') elif relative and time_difference > timedelta(0) and time_difference < timedelta(minutes = 10): return '%dm' % round(time_difference.seconds / 60) elif time.date() == today(): return '%d:%02d' % (time.hour, time.minute) elif time_difference < timedelta(7): with activate_locale(): return time.strftime('%-a %H:%M') else: with activate_locale(): return time.strftime('%-d.%-m. %H:%M') @app.route('/pysäkkiryhmä/<cluster_name>') def cluster_schedule(cluster_name): from buses import bus_stops, clusters_by_name schedule = [] try: cluster = clusters_by_name[cluster_name] except KeyError: abort(404) for schedule_entry in cluster.schedule(100): schedule.append({ 'time': time_representation(schedule_entry['time']), 'route': schedule_entry['trip'].route.reference, 'sign': sign(schedule_entry), 'trip': schedule_entry['stop'].trip.name, 'night': is_night_time(schedule_entry['time']), 'stop_id': schedule_entry['stop'].stop.reference, 'stop_code': schedule_entry['stop'].stop.code, 'stop_name': tr(schedule_entry['stop'].stop.name, 'bus_stops'), }) stops_in_cluster = sorted( ({ 'id': stop.reference, 'code': stop.code, 'name': tr(stop.name, 'bus_stops'), } for stop in cluster.stops), key = lambda stop: (len(stop['id']), stop['id']) ) return render_template( 'cluster.html', schedule = schedule, name = cluster.name, link_to_map = cluster.center.link_to_map, location = cluster.center, stops_in_cluster = stops_in_cluster, amount_of_stops_in_cluster = len(stops_in_cluster), tr = tr, ) @app.route('/ajovuoro/<trip_reference>') def trip(trip_reference): from flask import request from buses import all_trips try: trip = all_trips[trip_reference] except KeyError: abort(404) schedule = [] concise_schedule = [] used_areas = set() for halt in trip.schedule: stop_time = datetime.combine(today(), time()) + halt.arrival_time formatted_time = time_representation(stop_time) schedule.append({ 'time': formatted_time, 'id': halt.stop.reference, 'code': halt.stop.code, 'region': tr(halt.stop.region or '', 'paikat'), 'name': tr(halt.stop.name, 'bus_stops'), }) region = halt.stop.region if region: if region not in used_areas: concise_schedule.append({ 'time': formatted_time, 'region': region or '', }) used_areas.add(region) sign = reduce_schedule([k['region'] for k in concise_schedule], whole = True, trip_length = trip.length) try: sign = [sign[0], sign[-1]] except IndexError: sign = [trip.schedule[0].stop.name, trip.schedule[-1].stop.name] for entry in concise_schedule: entry['region'] = tr(entry['region'], 'paikat') return render_template('trip.html', schedule = schedule, concise_schedule = concise_schedule, trip_reference = trip_reference, route = trip.route.reference, description = ' - '.join(tr(place, 'paikat') for place in sign), night = is_night_time(datetime.combine(today(), time()) + trip.schedule[-1].arrival_time), tr = tr, length = trip.length / 1000, ) @app.route('/linja/<name>') def route_page(name): from buses import routes route = routes[name.upper()] schedule = [] for trip in route.trips: if trip.is_served_at(today()) and datetime.combine(today(), time()) + trip.schedule[-1].arrival_time < now(): schedule.append({ 'name': trip.reference, 'from': trip.from_place, 'to': trip.to_place, 'time': time_representation(datetime.combine(today(), time()) + trip.schedule[0].departure_time), }) return render_template('route.html', name = route.reference + ' ' + route.description, tr = tr, schedule = schedule, ) @app.route('/static/<path:path>') def static_file(path): return send_from_directory(path.join('static', path)) from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('gtfs_zip_path') parser.add_argument('profile_path') if __name__ == '__main__': parser.add_argument('-p', '--port', type = int, default = 5000) parser.add_argument('-d', '--debug', action = 'store_true') args = parser.parse_args() profile = ConfigParser() profile.read(args.profile_path) buses.load_buses(args.gtfs_zip_path, profile = profile) if __name__ == '__main__': app.run(debug = args.debug, port = args.port)