Mon, 25 Sep 2017 10:46:23 +0300
Asioita
busroute.py | file | annotate | diff | comparison | revisions | |
service.py | file | annotate | diff | comparison | revisions | |
static/style.css | file | annotate | diff | comparison | revisions | |
templates/stop_display.html | file | annotate | diff | comparison | revisions |
--- a/busroute.py Sat Sep 23 01:23:55 2017 +0300 +++ b/busroute.py Mon Sep 25 10:46:23 2017 +0300 @@ -45,7 +45,7 @@ name = abbreviations.get(name, name) return name -def reduce_schedule(reitti, trip_length, whole = False): +def reduce_schedule(reitti, trip_length, whole = False, long = False): length = ((trip_length / 600) * 3 + len(reitti) * 2) / 5 if not reitti: return '' @@ -62,12 +62,12 @@ priorities = { 'ihala': 150, 'kauppakeskus mylly': 200, - 'kuninkoja': 80, + 'kuninkoja': 150, 'moikoinen': 80, 'raision keskusta': 150, 'kukola': 50, 'kaistarniemi': 50, - 'papinsaari': 50, + 'papinsaari': 80, 'oriniemi': 50, 'pikisaari': 50, 'häppilä': 20, @@ -76,8 +76,8 @@ 'halinen': 70, 'kakskerta': 200, 'pansio': 50, - 'räntämäki': 10, - 'verkahovi': 20, + 'räntämäki': 25, + 'verkahovi': 25, 'skanssi': 200, 'vaala': 20, 'varissuo': 60, @@ -110,7 +110,7 @@ 'marttila': 100, 'koski tl': 100, 'katariina': 50, - 'länsikeskus': 50, + 'länsikeskus': 30, 'kaanaa': 100, 'satava': 50, 'suikkila': 50, @@ -118,7 +118,6 @@ 'räntämäki': 50, 'moisio': 25, 'pääskyvuori': 100, - #'rautatieasema': 50, 'logomo': 100, 'rymättylä': 50, "sauvo": 500, @@ -132,8 +131,35 @@ 'merimasku': 50, 'turkuhalli': 100, 'messukeskus': 100, - 'naantalin pikatie': 150, - 'helsingin valtatie': 500, + 'naantalin pikatie': 25, + 'helsingin valtatie': 25, + 'lauste': 25, + 'pompo': 25, + 'loukinainen': 25, + 'tuorla': 25, + 'satakunnantie': 25, + 'hepokulta': 25, + 'nättinummi': 25, + 'nummenmäki': 25, + 'kurala': 25, + 'itäharju': 25, + 'vasaramäki': 25, + 'pohjola': 25, + 'iso-heikkilä': 25, + 'patterinhaka': 25, + 'illoinen': 50, + 'luolavuori': 25, + 'mäntymäki': 25, + 'kurjenmäki': 25, + 'kuusisto': 25, + 'rautatieasema': 25, + 'majakkaranta': 25, + 'itäranta': 25, + 'martti': 25, + 'vähä-heikkilä': 25, + 'särkilahti': 25, + 'urusvuori': 25, + 'port arthur': 25, } if 'kauppatori' not in reitti: @@ -164,19 +190,22 @@ for i, stop in enumerate(reitti) \ if reitti_arvot[stop] >= 1 ], key = lambda stop: -stop[1]) - # enintään neljä tulee kylttiin - weights = weights[:3] - # jos kolmas kylttiarvo ei ole tarpeeksi merkittävä suhteessa reitin pituuteen niin otetaan se pois - try: - if weights[2][0] != destination and weights[2][1] < (725 / length ** 0.8): - del weights[2] - except IndexError: - pass - try: - if weights[1][0] != destination and weights[1][1] < (500 / length ** 1.15): - del weights[1] - except IndexError: - pass + if long: + weights = weights[:4] + else: + # enintään neljä tulee kylttiin + weights = weights[:3] + # jos kolmas kylttiarvo ei ole tarpeeksi merkittävä suhteessa reitin pituuteen niin otetaan se pois + try: + if weights[2][0] != destination and weights[2][1] < (725 / length ** 0.8): + del weights[2] + except IndexError: + pass + try: + if weights[1][0] != destination and weights[1][1] < (500 / length ** 1.15): + del weights[1] + except IndexError: + pass # lajitellaan painoarvot uudestaan reittijärjestykseen jotta sign tulee oikeinpäin weights = sorted(weights, key = lambda weight_data: weight_data[2]) # muodostetaan sign..
--- a/service.py Sat Sep 23 01:23:55 2017 +0300 +++ b/service.py Mon Sep 25 10:46:23 2017 +0300 @@ -61,23 +61,37 @@ else: return request.accept_languages.best_match(tr.languages) -def sign(schedule_entry): +def sign(schedule_entry, long = False): 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) + sign = reduce_schedule(schedule_entry['trip'].concise_schedule(schedule_entry['stop']), trip_length = trip_length, long = long) if sign: sign_representation = ' - '.join(tr(place, 'paikat') for place in sign if place not in suffix_regions) sign_representation += ''.join(' ' + tr(place, 'suffix-places') for place in sign if place in suffix_regions) - #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 +def long_form_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, long = True) + if sign: + return { + 'destination': tr(sign[-1], 'paikat'), + 'via': [tr(place, 'paikat') for place in sign[:-1]], + } + else: + return { + 'destination': schedule_entry['trip'].schedule[-1].stop.name, + 'via': [], + } + + def imminent(schedule_entry): return (schedule_entry['time'] - now()) <= timedelta(minutes = 3) + @app.route('/stop/<reference>') def bus_stop_schedule(reference): from buses import bus_stops @@ -106,6 +120,104 @@ tr = tr, ) +@app.route('/stop_display/<reference>') +def stop_display(reference): + from buses import bus_stops + schedule = [] + try: + bus_stop = bus_stops[reference] + except KeyError: + abort(404) + for i, schedule_entry in enumerate(bus_stop.schedule(max_amount = 6, arrivals = False)): + schedule.append({ + 'time_data': schedule_entry['time'], + 'time': time_representation(schedule_entry['time']), + 'route': schedule_entry['trip'].route.reference, + 'sign': long_form_sign(schedule_entry), + 'trip': schedule_entry['stop'].trip.name, + 'night': is_night_time(schedule_entry['time']), + 'imminent': imminent(schedule_entry), + 'index': i, + }) + from pprint import pprint + pprint(schedule) + if schedule: + num_imminent_leaves = max(1, len([schedule_entry for schedule_entry in schedule if schedule_entry['time_data'] - schedule[0]['time_data'] < timedelta(minutes = 3)])) + else: + num_imminent_leaves = 1 + return render_template( + 'stop_display.html', + schedule = schedule, + ref = bus_stop.code, + name = 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, + num_imminent_leaves = num_imminent_leaves, + tr = tr, + ) + +@app.route('/test') +def test(): + from buses import bus_stops + bus_stop = bus_stops['16'] + schedule = [{'imminent': True, + 'index': 0, + 'night': False, + 'route': '2A', + 'sign': {'destination': 'Kohmo', 'via': ['Nummenmäki', 'Kurala']}, + 'time': '1m', + 'trip': '00012501__3798generatedBlock'}, + {'imminent': True, + 'index': 1, + 'night': False, + 'route': '54', + 'sign': {'destination': 'Ylioppilaskylä', 'via': []}, + 'time': '2m', + 'trip': '00014359__5656generatedBlock'}, + {'imminent': True, + 'index': 2, + 'night': False, + 'route': '1', + 'sign': {'destination': 'Lentoasema ✈', 'via': ['Urusvuori']}, + 'time': '3m', + 'trip': '00010281__1281generatedBlock'}, + {'imminent': False, + 'index': 3, + 'night': False, + 'route': '56', + 'sign': {'destination': 'Räntämäki', 'via': ['Nummenmäki', 'Halinen']}, + 'time': '8m', + 'trip': '00014686__5983generatedBlock'}, + {'imminent': False, + 'index': 4, + 'night': False, + 'route': '42', + 'sign': {'destination': 'Varissuo', 'via': ['Kupittaa as', 'Itäharju']}, + 'time': '18:30', + 'trip': '00014010__5307generatedBlock'}, + {'imminent': False, + 'index': 5, + 'night': False, + 'route': '2B', + 'sign': {'destination': 'Littoinen', + 'via': ['Nummenmäki', 'Kurala', 'Kohmo']}, + 'time': '18:35', + 'trip': '00012629__3926generatedBlock'}] + return render_template( + 'stop_display.html', + schedule = schedule, + ref = bus_stop.code, + name = 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, + num_imminent_leaves = max(1, sum(schedule_entry['imminent'] for schedule_entry in schedule)), + tr = tr, + ) + def time_representation(time, relative = True): time_difference = time - now() if relative and timedelta(minutes = -1) < time_difference < timedelta(minutes = 1):
--- a/static/style.css Sat Sep 23 01:23:55 2017 +0300 +++ b/static/style.css Mon Sep 25 10:46:23 2017 +0300 @@ -159,7 +159,6 @@ { color: #C0660B; vertical-align: middle; - animation: blinker steps(1) 500ms infinite alternate; opacity: 0; animation: blinking 2s linear infinite; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/stop_display.html Mon Sep 25 10:46:23 2017 +0300 @@ -0,0 +1,265 @@ +<html> +<head> + <link rel="icon" type="image/png" href="../static/favicon.png" /> + <link rel="stylesheet" type="text/css" href="../static/style.css" /> + <meta charset='UTF-8' /> + <title>{{name}}</title> + <meta http-equiv='refresh' content='30'> + <style> + .sarake-määränpää + { + text-align: left; + } + + .next-leave + { + margin-left: 1vw; + margin-right: 1vw; + } + + .next-leave td + { + height: 30vh; + vertical-align: middle; + } + + .next-leave-table + { + width: 100%; + } + + .next-leave-time, .next-leave-destination, .next-leave-route + { + font-weight: bold; + font-size: 10vmin; + } + + .next-leave-time + { + width: 25%; + text-align: left + } + + .next-leave-route + { + width: 25%; + } + + .next-leave-destination + { + width: 50%; + } + + .via + { + list-style: none; + font-size: 6vmin; + padding-top: 1vw; + font-weight: normal; + } + + .next-leave-table + { + text-align: center; + } + + #other-leaves + { + width: 100%; + position: absolute; + bottom: 0; + background: #ccc; + box-shadow: 0 0 1vw rgba(0, 0, 0, 0.5), inset 0 0 2vw rgba(0, 0, 0, 0.5); + } + + #other-leaves table + { + width: 80%; + margin: auto; + margin-bottom: 10pt; + margin-top: 10pt; + } + + #other-leaves table td + { + font-size: 4vh; + height: 5vh; + text-align: center; + } + + .other-leave-time + { + width: 30%; + } + + .other-leave-route + { + width: 30%; + } + + .other-leave-destination + { + width: 40%; + } + + #stop-name + { + width: 100%; + text-align: center; + } + + h1 + { + background-color: #ffd90f; + margin: 0; + padding-top: 10pt; + background: #dc9e00; + background: linear-gradient(to bottom, #ffd90f 0%, #ffd90f 95%, #AA7700 100%); + color: black; + vertical-align: middle; + box-shadow: 0px 0px 1vw rgba(0, 0, 0, 0.5); + } + + h1, h1 span + { + font-size: 5vw; + text-align: center; + font-weight: bold; + } + + h1 span, h1 img + { + vertical-align: middle; + } + + @media screen and (orientation:landscape) + { + h1 + { + height: 12vh; + } + + h1 img + { + height: 10vh; + float: left; + margin-left: 1%; + } + + #stop-name + { + margin-top: 5pt; + font-size: 8vh; + } + } + + @media screen and (orientation:portrait) + { + h1 img + { + height: 10vh; + display: block; + margin-left: auto; + margin-right: auto; + } + + #stop-name + { + font-size: 6vw; + } + } + </style> + + <script> + num_visible_leaves = 3; + num_imminent_leaves = {{num_imminent_leaves}}; + var imminent_leave_cycle = []; + var other_leave_cycle = []; + var max_leaves; + var current_imminent_leave = 0; + var current_other_leave = 0; + var initialized = false; + function cycle_leaves() + { + if (initialized == false) + { + for (max_leaves = 0;; max_leaves += 1) + { + var i = max_leaves; + var tr = document.getElementById('leave-' + i); + if (tr) + { + if (i == 0 || i == num_imminent_leaves) + tr.style.display = 'table-row-group'; + else if (i < num_imminent_leaves) + imminent_leave_cycle.push(tr); + else if (i >= num_imminent_leaves + 1) + other_leave_cycle.push(tr); + } + else + break; + } + initialized = true; + current_imminent_leave = imminent_leave_cycle.length - 1; + current_other_leave = other_leave_cycle.length - 1; + } + if (imminent_leave_cycle) + { + current_imminent_leave = (current_imminent_leave + 1) % imminent_leave_cycle.length; + for (var i = 0; i < imminent_leave_cycle.length; i += 1) + imminent_leave_cycle[i].style.display = (i == current_imminent_leave) ? 'table-row-group' : 'none'; + } + if (other_leave_cycle) + { + current_other_leave = (current_other_leave + 1) % other_leave_cycle.length; + for (var i = 0; i < other_leave_cycle.length; i += 1) + other_leave_cycle[i].style.display = (i == current_other_leave) ? 'table-row-group' : 'none'; + } + setTimeout(cycle_leaves, 6000); + } + </script> +</head> +<body onload='cycle_leaves()'> + <h1><img src="../static/pysäkki.png" height="128" /><span id='stop-name'>{{ref}} {{name}}</span></h1> + <div class='next-leave'> + <table class='next-leave-table'> + {% for schedule_entry in schedule[:num_imminent_leaves] %} + <tbody id="leave-{{schedule_entry['index']}}"> + <tr> + <td class='next-leave-time'> + {% if schedule_entry['imminent'] %} + <span class='imminent-leave'>{{schedule_entry['time']}}</span>​ + {% else %} + {{schedule_entry['time']}}​ + {% endif %} + </td> + <td class='next-leave-route'>{{schedule_entry['route']}}</td> + <td class='next-leave-destination'>{{schedule_entry['sign']['destination']}} + <span class='via'><br /> + {% if num_imminent_leaves > 1 and schedule_entry['sign']['via'][0] and schedule_entry['sign']['via'][1] %} + {{schedule_entry['sign']['via'][0]}} - {{schedule_entry['sign']['via'][1]}} + {% for entry in schedule_entry['sign']['via'][2:] %}<br />{{entry}}{% endfor %}</span> + {% else %} + {% for entry in schedule_entry['sign']['via'] %}{{entry}}<br />{% endfor %}</span> + {% endif %} + </th> + </tr> + </tbody> + {% endfor %} + </table> + </div> + {% if schedule[num_imminent_leaves] %} + <div id='other-leaves'> + <table cellspacing="0"> + {% for halt in schedule[num_imminent_leaves:] %} + <tr id="leave-{{halt['index']}}" style='display: none'> + <td class='other-leave-time'>{{halt['time']}}</td> + <td class='other-leave-route'>{{halt['route']}}</td> + <td class='other-leave-destination'>{{halt['sign']['destination']}}</td> + </tr> + {% endfor %} + </table> + </div> + {% endif %} +</body> +</html>