# HG changeset patch # User Teemu Piippo # Date 1509026069 -10800 # Node ID d2e19670b772ffa028299f906f67e66c48098b50 # Parent c2fc50748efd88def4178b1294d4effe2c6876ad Remove assumptions and added some api stuff diff -r c2fc50748efd -r d2e19670b772 abbreviations.ini --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/abbreviations.ini Thu Oct 26 16:54:29 2017 +0300 @@ -0,0 +1,235 @@ +[abbreviations] +aaslaluoto = Aas +ahteentaka = Aht +airismaa = Air +ajola = Ajo +artukainen = Ar +asikko = Ask +aura = Au +auvaismäki = Auv +avanti = Ava +björkhagen = Bjö +eerikvalla = Ev +friskala = Frs +haapala = Haa +haarla = Hla +hadvala = Hdv +haijainen = Hja +hakkinen = Hak +halinen = Hn +hanhijoki = Han +harittu = Har +helsingin valtatie = Hgv +hemmola = Hem +hepokulta = Hp +herttula = Hert +hyrköinen = Hyr +hämölä = Hmö +häppilä = Häp +härkämäki = Häm +ihala = Ih +illoinen = Ill +ilmarinen = Ilm +ilpoinen = Ilp +impivaara = Imv +iso-heikkilä = Ish +ispoinen = Isp +itäharju = Ith +itäranta = Itr +jokila = Jkl +jyrkkälä = Jyr +jäkärlä = Jäk +jänessaari = Jäs +kaanaa = Kaa +kaarina = Ka +kahari = Kah +kaistarniemi = Krn +kaivola = Kaiv +kaivopuisto = Kvp +kakskerta = Kk +karvetti = Kav +kasarmialue = Krm +kasnäs = Knä +kastu = Kas +katariina = Kat +mylly = My +kauppatori = Kt +kemiö = Kö +kemiönsaari = Kös +kerttuli = Ker +kesämäki = Ksä +kirjala = Kij +kirkkotien terveyskeskus = Kttk +kohmo = Km +koivula = Koi +konserttitalo = Kns +korpo = Kpo +koski tl = Ktl +kuivalahti = Kvl +kukola = Kuk +kultaranta = Klr +kuninkoja = Kni +kupittaa as = Kua +kupittaa = Ku +kupittaanpuisto = Kup +kurala = Kur +kurala (naantali) = Kurn +kurjenmäki = Kj +kuusisto = Kst +kuuvuori = Kuu +kyrkäng = Kyr +kårkulla = Kår +kähäri = Käh +käkölä = Käk +lauste = Ls +lauttaranta = Ltr +lehmusvalkama = Lmv +lemu = Lemu +lentoasema = Len +lieranta = Lie +lieto as = Lta +lieto = Lt +liedon keskusta = Lik +liljalaakso = Llj +linja-autoasema = La +linnavuori = Liv +littoinen = Lit +logomo = Lg +loukinainen = Lna +luolavuori = Llv +luostarinmäki = Lum +länsikeskus = Läk +länsinummi = Lä +maanpää = Mpä +majakkaranta = Mj +maksla = Mks +marjaniemi = Man +marttila = Mla +martti = Mar +merimasku = Mma +meripirtti = Mpi +messukeskus = Mes +metsäaro = Mta +metsämäki = Met +moikoinen = Mo +moisio = Msi +montola = Mon +muhkuri = Mhk +munittula = Mni +munkviken = Mkv +mälikkälä = Mäl +mäntymäki = Män +naantali = Na +naantalin pikatie = Nnpt +nagu = Nv +naskarla = Nsk +norrby = Nor +nummen koulu = Nuk +nummenmäki = Num +nuorikkala = Nuo +nättinummi = Nät +ojanto = Oja +okala = Oka +oriketo = Ork +oriniemi = Orn +paasniittu = Ptu +paattinen = Paa +paimion sairaala = Pms +paimio = Pm +pansio = Ps +papinsaari = Pap +pargas = Pa +patterinhaka = Pat +peijerlä = Pej +peltola = Pel +pernon telakka = Pnt +perno = Pn +petäsmäki = Pem +piikkiö = Pkö +piispala = Ppla +piispanlähde = Pplä +piispanristi = Pri +pikisaari = Pik +pläkkikaupunki = Plä +pohjola = Phj +poikko = Pko +pompo = Ppo +porhonkallio = Porh +port arthur = Par +puosta = Puo +puutori = Puu +pyöli = Pyö +pärnäs = Pnä +pääskyvuori = Päv +raadelma = Raa +raisio = Rs +rauduinen = Rau +rauhakylä = Rhk +raunistulan puistotie = Rnp +raunistula = Rni +rautatieasema = Ra +ruissalo = Rus +runko = Rnk +runosmäki = Rum +ruona = Ruo +rusko = Rko +rymättylä = Rym +räntämäki = Räm +röölä = Röö +saaro = Sro +salonkylä = Sak +salo = Sl +saramäki = Srm +satakunnantie = Sat +satama = Sm +satava = Sv +sauvo = Sg +sillilä = Sil +silvola = Siv +sipilänmäki = Spm +skanssi = Ska +somero = Sro +storäng = Str +suikkila = Ski +suovuori = Sv +suutarla = Suu +särkilahti = Säl +takakirves = Tka +tamminiemi = Tamn +tammi = Tmi +tarvasjoki = Tj +teerimäki = Tee +tennby = Ten +teräsrautela = Trä +tikanmaa = Tik +toijainen = Tja +torppala = Tor +tortinmäki = Ttm +tuomiokirkkotori = Tk +tuorla = Tla +turkuhalli = Tuh +tyks = Tyks +uittamo = Ui +urusvuori = Urv +vaala = Va +vahto = Vh +vaisaari = Vai +varissuo = Vs +vasaramäki = Vm +velkua = Ve +velusmaa = Vlu +verkahovi = Ver +vienola = Vn +vieru = Vru +viiala = Vii +vii kaupunginosa = Vii +viluluoto = Vil +vuorenpää = Vpä +vähä-heikkilä = Väh +yli-maaria = Ylm +yliopisto = Yop +ylioppilaskylä-itä = Yoi +ylioppilaskylä-länsi = Yol +ylioppilaskylä = Yok +ylttinen = Ylt +österby = Öst diff -r c2fc50748efd -r d2e19670b772 buses.py --- a/buses.py Sat Oct 07 01:52:15 2017 +0300 +++ b/buses.py Thu Oct 26 16:54:29 2017 +0300 @@ -10,8 +10,8 @@ return reference class BusTrip: - def __init__(self, reference, route, service, length): - self.reference, self.route, self.service = reference, route, service + def __init__(self, reference, route, service, length, block_id): + self.reference, self.route, self.service, self.block_id = reference, route, service, block_id self.length = length self.schedule = [] self.name = transform_trip_reference(reference) @@ -29,19 +29,22 @@ except KeyError: return False def concise_schedule(self, starting_stop = None): - if starting_stop and starting_stop in self.schedule: - schedule = copy(self.schedule) - schedule = schedule[schedule.index(starting_stop):] + if profile['regions']['use-regions']: + if starting_stop and starting_stop in self.schedule: + schedule = copy(self.schedule) + schedule = schedule[schedule.index(starting_stop):] + else: + schedule = self.schedule + used_areas = set() + result = [] + for halt in schedule: + stop = halt.stop + if stop.region and stop.region not in used_areas: + used_areas.add(stop.region) + result.append(stop.region) + return result else: - schedule = self.schedule - used_areas = set() - result = [] - for halt in schedule: - stop = halt.stop - if stop.region and stop.region not in used_areas: - used_areas.add(stop.region) - result.append(stop.region) - return result + return [halt.stop.name for halt in self.schedule] class BusRoute: def __init__(self, entry): @@ -130,23 +133,33 @@ self.traveled_distance = traveled_distance @property def is_arrival(self): - if not hasattr(self, 'cachedIsArrival'): - if self.stop.region: - iterator = iter(self.trip.schedule) - stop = next(iterator) - while stop is not self: + if profile['regions']['use-regions']: + if not hasattr(self, 'cachedIsArrival'): + if self.stop.region: + iterator = iter(self.trip.schedule) stop = next(iterator) - for stop in iterator: - if stop.stop.region != self.stop.region: - self.cachedIsArrival = False - break + while stop is not self: + stop = next(iterator) + for stop in iterator: + if stop.stop.region != self.stop.region: + self.cachedIsArrival = False + break + else: + self.cachedIsArrival = True else: - self.cachedIsArrival = True - else: - self.cachedIsArrival = False - return self.cachedIsArrival + self.cachedIsArrival = False + return self.cachedIsArrival + else: + return self == self.trip.schedule[-1] def __repr__(self): return 'BusHalt(%r, %r, %r, %r)' % (self.arrival_time, self.departure_time, self.stop, self.trip) + def sign(self, long = False): + from busroute import reduce_schedule + return reduce_schedule( + route = self.trip.concise_schedule(self), + trip_length = self.trip.length - self.traveled_distance, + long = long, + ) routes = {} routes_per_id = {} @@ -158,7 +171,7 @@ clusters_by_name = {} services_for_day = {} -def load_buses(gtfs_zip_path, profile): +def load_buses(gtfs_zip_path): global viimeinen_käyttöpäivä from zipfile import ZipFile with ZipFile(gtfs_zip_path) as gtfs_zip: @@ -173,9 +186,12 @@ print('Ladataan ajovuorot... ', file = stderr, end = '', flush = True) shape_distances = {} - with gtfs_zip.open('shapes.txt') as file: - for row in read_csv(map(bytes.decode, file)): - shape_distances[row['shape_id']] = max(shape_distances.get(row['shape_id'], 0), float(row['shape_dist_traveled'])) + try: + with gtfs_zip.open('shapes.txt') as file: + for row in read_csv(map(bytes.decode, file)): + shape_distances[row['shape_id']] = max(shape_distances.get(row['shape_id'], 0), float(row['shape_dist_traveled'])) + except KeyError: + pass with gtfs_zip.open('trips.txt') as file: for row in read_csv(map(bytes.decode, file)): @@ -186,11 +202,14 @@ reference = row['trip_id'], route = route, service = services[row['service_id']], - length = shape_distances[row['shape_id']] * float(profile['metrics']['shape-modifier']) + length = shape_distances.get(row.get('shape_id'), 1) * float(profile['metrics']['shape-modifier']), + block_id = row['block_id'], ) route.trips.add(trip) - assert trip.name not in all_trips - all_trips[trip.name] = trip + if trip.name in all_trips: + print('Trip %s already exists' % trip.name) + else: + all_trips[trip.name] = trip print('%d ajoa' % len(all_trips), file = stderr) def read_date(teksti): @@ -253,12 +272,16 @@ reference = row['stop_id'], name = row['stop_name'], location = location, - code = row['stop_code'], + code = row.get('stop_code', row['stop_id']), ) bus_stops[stop.reference] = stop - with open('regions-per-stop.json') as file: - for stop_reference, region in json.load(file).items(): - bus_stops[stop_reference].region = region + if profile['regions']['use-regions']: + with open('regions-per-stop.json') as file: + for stop_reference, region in json.load(file).items(): + try: + bus_stops[stop_reference].region = region + except KeyError: + pass print('%d pysäkkiä' % len(bus_stops), file = stderr) @@ -367,30 +390,31 @@ # Ryhmä on ainoa jolla on varaus tälle nimelle. Sen kuin vaan. next(iter(clusters)).name = name else: - # Olisiko kaikki klusterit eri alueilla? - common_regions = shared_elements_in_n_sets({stop.region for stop in cluster.stops} for cluster in clusters) - # Esitys: ryhmä -> ne alueet jotka ovat tälle ryhmälle ainutlaatuisia - proposal = { - cluster: {stop.region for stop in cluster.stops} - common_regions - {None} + if profile['regions']['use-regions']: + # Olisiko kaikki klusterit eri alueilla? + common_regions = shared_elements_in_n_sets({stop.region for stop in cluster.stops} for cluster in clusters) + # Esitys: ryhmä -> ne alueet jotka ovat tälle ryhmälle ainutlaatuisia + proposal = { + cluster: {stop.region for stop in cluster.stops} - common_regions - {None} + for cluster in clusters + } + # Jos enintään yksi klusteri tässä esityksessä on kokonaan ilman omaa aluetta, jolla se voisi eritellä, + # niin nimetään klusterit näiden alueiden mukaan. + # Se klusteri jolla ei ole omaa aluetta (jos on) jätetään ilman aluepäätettä. + if sum([1 for unique_areas in proposal.values() if not unique_areas]) <= 1: + for cluster, unique_areas in proposal.items(): + individual_cluster_name = name + if unique_areas: + individual_cluster_name += ' (' + min(unique_areas) + ')' + cluster.name = individual_cluster_name + break + # Typerä reunatapaus. Indeksoidaan numeroin... + for n, (_, cluster) in enumerate(sorted( + min((stop.reference.lower(), cluster) for stop in cluster.stops) for cluster in clusters - } - # Jos enintään yksi klusteri tässä esityksessä on kokonaan ilman omaa aluetta, jolla se voisi eritellä, - # niin nimetään klusterit näiden alueiden mukaan. - # Se klusteri jolla ei ole omaa aluetta (jos on) jätetään ilman aluepäätettä. - if sum([1 for unique_areas in proposal.values() if not unique_areas]) <= 1: - for cluster, unique_areas in proposal.items(): - individual_cluster_name = name - if unique_areas: - individual_cluster_name += ' (' + min(unique_areas) + ')' - cluster.name = individual_cluster_name - else: - # Typerä reunatapaus. Indeksoidaan numeroin... - for n, (_, cluster) in enumerate(sorted( - min((stop.reference.lower(), cluster) for stop in cluster.stops) - for cluster in clusters - ), 1): - individual_cluster_name = name + '-' + str(n) - cluster.name = individual_cluster_name + ), 1): + individual_cluster_name = name + '-' + str(n) + cluster.name = individual_cluster_name print('Ryhmitellään pysäkit...') cluster_bus_stops() @@ -408,11 +432,13 @@ with gtfs_zip.open('stop_times.txt') as file: progress = 0 for row in read_csv(map(bytes.decode, file)): + if int(row.get('pickup_type', 0)) and int(row.get('drop_off_type', 0)): + continue trip = all_trips[transform_trip_reference(row['trip_id'])] arrival_time = read_time(row['arrival_time']) departure_time = read_time(row['departure_time']) stop = bus_stops[row['stop_id']] - traveled_distance = float(row['shape_dist_traveled']) * float(profile['metrics']['shape-modifier']) + traveled_distance = float(row.get('shape_dist_traveled', 1)) * float(profile['metrics']['shape-modifier']) trip.schedule.append(BusHalt(arrival_time, departure_time, stop, trip, traveled_distance)) stop.involved_trips.add(trip) progress += 1 @@ -450,19 +476,23 @@ route.description = simplify_name(most_common_route[0]) + ' - ' + simplify_name(most_common_route[-1]) except: route.description = '' - route.trips = sorted(route.trips, key = lambda trip: trip.schedule[0].departure_time) + route.trips = sorted(route.trips, key = lambda trip: trip.schedule and trip.schedule[0].departure_time or timedelta()) # Fölin datassa on jotain tosi kummaa. Ilmeisesti ajovuoron viimeisen pysähdyksen saapumisaika on ihan täysin # väärin. Arvaan että se on seuraavan lähdön aika, mutta joka tapauksessa se on väärin. # Arvataan mikä se todellinen saapumisaika on. Se ei voi mennä kauhean paljon pahemmin vikaan kuin alkuperäinen # väärin oleva data. for trip in all_trips.values(): - bus_speed_coefficient = 750 # metriä minuutissa - last_leg_distance = trip.schedule[-1].traveled_distance - trip.schedule[-2].traveled_distance - trip.schedule[-1].arrival_time = trip.schedule[-2].departure_time + timedelta(minutes = last_leg_distance / bus_speed_coefficient) + if len(trip.schedule) >= 2: + bus_speed_coefficient = 750 # metriä minuutissa + last_leg_distance = trip.schedule[-1].traveled_distance - trip.schedule[-2].traveled_distance + trip.schedule[-1].arrival_time = trip.schedule[-2].departure_time + timedelta(minutes = last_leg_distance / bus_speed_coefficient) + + global trips_by_vehicle_info + trips_by_vehicle_info = {} + for trip in all_trips.values(): + trips_by_vehicle_info[(trip.block_id, trip.schedule[0].arrival_time)] = trip if __name__ == '__main__': - from configparser import ConfigParser - profile = ConfigParser() profile.read('profiles/föli.ini') - load_buses('gtfs.zip', profile) + load_buses('gtfs.zip') diff -r c2fc50748efd -r d2e19670b772 busroute.py --- a/busroute.py Sat Oct 07 01:52:15 2017 +0300 +++ b/busroute.py Thu Oct 26 16:54:29 2017 +0300 @@ -1,6 +1,7 @@ #!/usr/bin/env python3 from configparser import ConfigParser +from math import inf replacements = { "ylioppilaskylä-itä": "ylioppilaskylä", @@ -10,8 +11,8 @@ 'saaro': 'ruissalo', 'silvola': 'vahto', 'hemmola': 'vahto', - 'paasniittu': 'ruskon keskusta', - 'kahari': 'ruskon keskusta', + 'paasniittu': 'rusko', + 'kahari': 'rusko', 'kemiö': 'kemiönsaari', 'kasnäs': 'kemiönsaari', 'pernon telakka': 'perno', @@ -19,15 +20,6 @@ 'hanhijoki': 'paimio', } -# nimiä joista voidaan joustaa tarvittaessa -abbreviations = { - 'raision keskusta': 'raisio', - 'ruskon keskusta': 'rusko', - 'naantalin keskusta': 'naantali', - 'kaarinan keskusta': 'kaarina', - 'kauppakeskus mylly': 'mylly', -} - region_info = ConfigParser() region_info.read('regions.ini') municipalities = set(region_info.sections()) @@ -42,31 +34,30 @@ def simplify_name(name): name = replacements.get(name, name) - name = abbreviations.get(name, name) return name -def reduce_schedule(reitti, trip_length, whole = False, long = False): - length = ((trip_length / 600) * 3 + len(reitti) * 2) / 5 - if not reitti: +def reduce_schedule(route, trip_length, whole = False, long = False): + length = ((trip_length / 600) * 3 + len(route) * 2) / 5 + if not route: return '' have_already = set() i = 0 - while i < len(reitti): - if reitti[i] in replacements: - reitti[i] = replacements[reitti[i]] - if reitti[i] in have_already: - del reitti[i] + while i < len(route): + if route[i] in replacements: + route[i] = replacements[route[i]] + if route[i] in have_already: + del route[i] else: - have_already.add(reitti[i]) + have_already.add(route[i]) i += 1 priorities = { 'ihala': 150, - 'kauppakeskus mylly': 200, + 'mylly': 200, 'kuninkoja': 150, - 'moikoinen': 80, - 'raision keskusta': 150, + 'moikoinen': 100, + 'raisio': 150, 'kukola': 50, - 'kaistarniemi': 50, + 'kaistarniemi': 75, 'papinsaari': 80, 'oriniemi': 50, 'pikisaari': 50, @@ -84,21 +75,21 @@ 'kohmo': 80, 'kupittaa': 70, 'kupittaa as': 120, - 'kauppatori': 1e15, + 'kauppatori': inf, 'lentoasema': 50, 'runosmäki': 50, 'lieto': 100, 'lieto as': 200, 'ilmarinen': 50, 'vahto': 50, - 'ruskon keskusta': 200, - 'oriketo': 60, + 'rusko': 200, + 'oriketo': 50, 'harittu': 40, - 'jäkärlä': 80, - 'moisio': 100, - 'paattinen': 100, - 'kaarinan keskusta': 200, - 'naantalin keskusta': 200, + 'jäkärlä': 150, + 'moisio': 150, + 'paattinen': 25, + 'kaarina': 200, + 'naantali': 200, 'uittamo': 50, 'piikkiö': 100, 'paimio': 100, @@ -116,7 +107,6 @@ 'suikkila': 50, 'raunistula': 50, 'räntämäki': 50, - 'moisio': 25, 'pääskyvuori': 100, 'logomo': 100, 'rymättylä': 50, @@ -140,8 +130,8 @@ 'satakunnantie': 25, 'hepokulta': 25, 'nättinummi': 25, - 'nummenmäki': 25, - 'kurala': 25, + 'nummenmäki': 10, + 'kurala': 10, 'itäharju': 25, 'vasaramäki': 25, 'pohjola': 25, @@ -162,18 +152,18 @@ 'port arthur': 25, } - if 'kauppatori' not in reitti: + if 'kauppatori' not in route: priorities['länsikeskus'] = priorities['skanssi'] = priorities['kauppatori'] - from_place = reitti[0] - destination = reitti[-1] + from_place = route[0] + destination = route[-1] reitti_arvot = {} f = lambda i: i**-0.3 - factor = 1 / max(f(i + 1) for i in range(len(reitti))) - while priorities.get(reitti[-1], 0) < 0: - del reitti[-1] - destination = reitti[-1] - for i, stop in enumerate(reitti): + factor = 1 / max(f(i + 1) for i in range(len(route))) + while priorities.get(route[-1], 0) < 0: + del route[-1] + destination = route[-1] + for i, stop in enumerate(route): # muunna indeksi siten että myöhemmät alueet korostuvat i = f(i + 1) * factor # ota prioriteetti huomioon, jotkin alueet ovat tärkeämpiä kyltissä kuin toiset @@ -187,7 +177,7 @@ # muodosta sign-tiedot järjestettynä reittiarvon mukaan weights = sorted([ (stop, reitti_arvot[stop], i) \ - for i, stop in enumerate(reitti) \ + for i, stop in enumerate(route) \ if reitti_arvot[stop] >= 1 ], key = lambda stop: -stop[1]) if long: @@ -211,21 +201,18 @@ # muodostetaan sign.. sign = [paino[0] for paino in weights] to_place = sign[-1] - nearby_municipalities = {'Turku', 'Raisio', 'Naantali', 'Kaarina', 'Lieto'} - if from_place != to_place: - municipality_from = municipalities_per_region.get(from_place) - municipality_to = municipalities_per_region.get(to_place) - if municipality_from and municipality_to and municipality_from not in nearby_municipalities | {municipality_to} and municipality_to not in nearby_municipalities: - def convert_region(region): - municipality = municipalities_per_region.get(region, region) - if municipality != municipality_from: - return municipality - else: - return region - sign = [convert_region(region) for region in sign] - # supista nimet tarvittaessa - if len(' - '.join(sign)) > 20: - sign = [abbreviations.get(place, place) for place in sign] + #nearby_municipalities = {'Turku', 'Raisio', 'Naantali', 'Kaarina', 'Lieto'} + #if from_place != to_place: + # municipality_from = municipalities_per_region.get(from_place) + # municipality_to = municipalities_per_region.get(to_place) + # if municipality_from and municipality_to and municipality_from not in nearby_municipalities | {municipality_to} and municipality_to not in nearby_municipalities: + # def convert_region(region): + # municipality = municipalities_per_region.get(region, region) + # if municipality != municipality_from: + # return municipality + # else: + # return region + # sign = [convert_region(region) for region in sign] old_sign = sign.copy() sign = [] for place in old_sign: diff -r c2fc50748efd -r d2e19670b772 misc.py --- a/misc.py Sat Oct 07 01:52:15 2017 +0300 +++ b/misc.py Thu Oct 26 16:54:29 2017 +0300 @@ -23,3 +23,6 @@ def is_night_time(time): return time.hour >= 23 or time.hour < 5 + +from configparser import ConfigParser +profile = ConfigParser() diff -r c2fc50748efd -r d2e19670b772 profiles/föli.ini --- a/profiles/föli.ini Sat Oct 07 01:52:15 2017 +0300 +++ b/profiles/föli.ini Thu Oct 26 16:54:29 2017 +0300 @@ -1,2 +1,5 @@ [metrics] shape-modifier = 1 + +[regions] +use-regions = 1 diff -r c2fc50748efd -r d2e19670b772 profiles/junat.ini --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/profiles/junat.ini Thu Oct 26 16:54:29 2017 +0300 @@ -0,0 +1,5 @@ +[metrics] +shape-modifier = 1 + +[regions] +use-regions = diff -r c2fc50748efd -r d2e19670b772 regions.ini --- a/regions.ini Sat Oct 07 01:52:15 2017 +0300 +++ b/regions.ini Thu Oct 26 16:54:29 2017 +0300 @@ -1,5 +1,5 @@ [Kaarina] -Kaarinan keskusta = 6043 +Kaarina = 6043 Piikkiö = 6175 Hadvala = 6171 Puosta = 6351 @@ -65,8 +65,8 @@ Marttila = 8800 [Raisio] -Raision keskusta = 2010 -Kauppakeskus Mylly = 2117 +Raisio = 2010 +Mylly = 2117 Petäsmäki = 2063 Kaanaa = 2037 Vuorenpää = 2028 @@ -79,7 +79,7 @@ Tikanmaa = 2136 [Naantali] -Naantalin keskusta = 3016 +Naantali = 3016 Ahteentaka = 3290 Kurala (Naantali) = 3196 Haapala = 3283 @@ -121,7 +121,7 @@ Haijainen = 3231 [Rusko] -Ruskon keskusta = 4017 +Rusko = 4017 Vahto = 4069 Hemmola = 4077 Silvola = 4086 diff -r c2fc50748efd -r d2e19670b772 service.py --- a/service.py Sat Oct 07 01:52:15 2017 +0300 +++ b/service.py Thu Oct 26 16:54:29 2017 +0300 @@ -91,6 +91,43 @@ def imminent(schedule_entry): return (schedule_entry['time'] - now()) <= timedelta(minutes = 3) +def first_halt_in_trip_in_place(trip, place): + for halt in trip.schedule: + if halt.stop.region == place: + return halt + else: + return None + +place_abbreviations = ConfigParser() +place_abbreviations.read('abbreviations.ini') + +def place_abbreviation(place): + try: + return place_abbreviations['abbreviations'][place] + except KeyError: + return place + +def trip_abbreviation(trip): + entries = [trip.from_place] + old_places = None + starting_halt = None + while True: + remaining_length = trip.length + if starting_halt: + remaining_length -= starting_halt.traveled_distance + places = reduce_schedule(trip.concise_schedule(starting_stop = starting_halt), trip_length = remaining_length, long = False) + new_places = set(places) - set(entries) + if not new_places or places == old_places: + break + for place in places: + if place in new_places: + starting_halt = first_halt_in_trip_in_place(trip, place) + entries += [place] + break + old_places = places + if trip.to_place not in entries: + entries += [trip.to_place] + return trip.route.reference + ':' + '-'.join(map(place_abbreviation, entries)) @app.route('/stop/') def bus_stop_schedule(reference): @@ -120,6 +157,34 @@ tr = tr, ) +@app.route('/api/describe_destination///') +def describe_destination(trip_reference, stop_reference, index): + from buses import bus_stops, all_trips + from busroute import simplify_name + from flask import jsonify + try: + trip = all_trips[trip_reference] + bus_stop = bus_stops[stop] + schedule_entry = [schedule_entry for schedule_entry in trip.schedule if schedule_entry.stop.reference == stop_reference][index] + except KeyError: + abort(404) + except ValueError: + abort(404) + return jsonify(long_form_sign({'trip': trip, 'stop': schedule_entry})) + +@app.route('/api/trip_abbreviation//') +def api_trip_abbreviation(block_id, arrival_time_offset): + from buses import trips_by_vehicle_info + from flask import jsonify + from datetime import timedelta + try: + trip = trips_by_vehicle_info[block_id, timedelta(seconds = arrival_time_offset)] + except KeyError: + abort(404) + return jsonify({ + 'abbreviation': trip_abbreviation(trip), + }) + @app.route('/stop_display/') def stop_display(reference): from buses import bus_stops @@ -286,17 +351,25 @@ for halt in trip.schedule: stop_time = datetime.combine(today(), time()) + halt.arrival_time formatted_time = time_representation(stop_time) - if halt.stop.region != region and not (region and not halt.stop.region): - if len(schedule) and not schedule[-1]['name']: - schedule[-1]['name'] = tr(halt.stop.region or '', 'paikat') - else: - schedule.append({ - 'name': tr(halt.stop.region or '', 'paikat'), - 'time': formatted_time, - 'stops': [], - 'index': len(schedule), - }) - region = halt.stop.region + if profile['regions']['use-regions']: + if halt.stop.region != region and not (region and not halt.stop.region): + if len(schedule) and not schedule[-1]['name']: + schedule[-1]['name'] = tr(halt.stop.region or '', 'paikat') + else: + schedule.append({ + 'name': tr(halt.stop.region or '', 'paikat'), + 'time': formatted_time, + 'stops': [], + 'index': len(schedule), + }) + region = halt.stop.region + else: + schedule.append({ + 'name': tr(halt.stop.name or '', 'bus-stops'), + 'time': formatted_time, + 'stops': [], + 'index': len(schedule), + }) schedule[-1]['stops'].append({ 'time': formatted_time, 'id': halt.stop.reference, @@ -367,9 +440,8 @@ 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) +buses.load_buses(args.gtfs_zip_path) if __name__ == '__main__': app.run(debug = args.debug, port = args.port)