1 #!/usr/bin/env python3 |
1 #!/usr/bin/env python3 |
2 import enum |
2 import enum, json |
|
3 from sys import stderr |
3 from datetime import date, time, datetime, timedelta |
4 from datetime import date, time, datetime, timedelta |
|
5 from misc import * |
4 Suunta = enum.Enum('Suunta', [('Taaksepäin', 0), ('Eteenpäin', 1)]) |
6 Suunta = enum.Enum('Suunta', [('Taaksepäin', 0), ('Eteenpäin', 1)]) |
5 |
|
6 def lue_csv(tiedosto, muunnokset = None): |
|
7 import csv |
|
8 lukija = csv.reader(tiedosto) |
|
9 otsakkeet = next(lukija) |
|
10 for rivi in lukija: |
|
11 tietue = dict(zip(otsakkeet, rivi)) |
|
12 if muunnokset: |
|
13 for avain, muunnos in muunnokset.items(): |
|
14 tietue[avain] = muunnos(tietue[avain]) |
|
15 yield tietue |
|
16 |
7 |
17 def muunna_ajovuoro_tunniste(tunniste): |
8 def muunna_ajovuoro_tunniste(tunniste): |
18 return int(tunniste.split('_')[0]) |
9 return int(tunniste.split('_')[0]) |
19 |
10 |
20 class Ajovuoro: |
11 class Ajovuoro: |
51 self.päivät = set() |
42 self.päivät = set() |
52 def __repr__(self): |
43 def __repr__(self): |
53 return 'palvelut[%r]' % self.tunniste |
44 return 'palvelut[%r]' % self.tunniste |
54 |
45 |
55 class Pysäkki: |
46 class Pysäkki: |
56 def __init__(self, tunniste, nimi): |
47 def __init__(self, tunniste, nimi, sijainti): |
57 self.tunniste, self.nimi = tunniste, nimi |
48 self.tunniste, self.nimi, self.sijainti = tunniste, nimi, sijainti |
58 def __repr__(self): |
49 def __repr__(self): |
59 return 'pysäkit[%r]' % self.tunniste |
50 return 'pysäkit[%r]' % self.tunniste |
60 def aikataulu(self, määrä = 50): |
51 def aikataulu(self, määrä = 50): |
61 ''' |
52 ''' |
62 Hakee tämän pysäkin seuraavat `määrä` lähtöä. Päätepysäkille saapuvia busseja ei |
53 Hakee tämän pysäkin seuraavat `määrä` lähtöä. Päätepysäkille saapuvia busseja ei |
120 ajot = {} |
111 ajot = {} |
121 ajot_per_numero = {} |
112 ajot_per_numero = {} |
122 palvelut = {} |
113 palvelut = {} |
123 pysäkit = {} |
114 pysäkit = {} |
124 |
115 |
125 print('Ladataan linjat... ', end = '', flush = True) |
116 print('Ladataan linjat... ', file = stderr, end = '', flush = True) |
126 with open('gtfs/routes.txt') as tiedosto: |
117 with open('gtfs/routes.txt') as tiedosto: |
127 for rivi in lue_csv(tiedosto): |
118 for rivi in lue_csv(tiedosto): |
128 linja = Linja(rivi) |
119 linja = Linja(rivi) |
129 linja.tunniste = linja.tunniste |
120 linja.tunniste = linja.tunniste |
130 linjat[linja.viite] = linja |
121 linjat[linja.viite] = linja |
131 linjat_per_tunniste[linja.tunniste] = linja |
122 linjat_per_tunniste[linja.tunniste] = linja |
132 print('%d linjaa' % len(linjat)) |
123 print('%d linjaa' % len(linjat), file = stderr) |
133 |
124 |
134 print('Ladataan ajot... ', end = '', flush = True) |
125 print('Ladataan ajot... ', file = stderr, end = '', flush = True) |
135 with open('gtfs/trips.txt') as tiedosto: |
126 with open('gtfs/trips.txt') as tiedosto: |
136 for rivi in lue_csv(tiedosto, muunnokset = {'direction_id': lambda k: Suunta(int(k))}): |
127 for rivi in lue_csv(tiedosto, muunnokset = {'direction_id': lambda k: Suunta(int(k))}): |
137 if rivi['service_id'] not in palvelut: |
128 if rivi['service_id'] not in palvelut: |
138 palvelut[rivi['service_id']] = Palvelu(rivi['service_id']) |
129 palvelut[rivi['service_id']] = Palvelu(rivi['service_id']) |
139 linja = linjat_per_tunniste[rivi['route_id']] |
130 linja = linjat_per_tunniste[rivi['route_id']] |
142 palvelu = palvelut[rivi['service_id']], |
133 palvelu = palvelut[rivi['service_id']], |
143 kyltti = rivi['trip_headsign'], |
134 kyltti = rivi['trip_headsign'], |
144 suunta = rivi['direction_id']) |
135 suunta = rivi['direction_id']) |
145 assert ajo.nimi not in ajot |
136 assert ajo.nimi not in ajot |
146 ajot[ajo.nimi] = ajo |
137 ajot[ajo.nimi] = ajo |
147 print('%d ajoa' % len(ajot)) |
138 print('%d ajoa' % len(ajot), file = stderr) |
148 |
139 |
149 def lue_päiväys(teksti): |
140 def lue_päiväys(teksti): |
150 return date(int(teksti[:4]), int(teksti[4:6]), int(teksti[6:])) |
141 return date(int(teksti[:4]), int(teksti[4:6]), int(teksti[6:])) |
151 |
142 |
152 def lue_aika(teksti): |
143 def lue_aika(teksti): |
153 tunti, minuutti, sekunti = map(int, teksti.split(':')) |
144 tunti, minuutti, sekunti = map(int, teksti.split(':')) |
154 return timedelta(hours = tunti, minutes = minuutti, seconds = sekunti) |
145 return timedelta(hours = tunti, minutes = minuutti, seconds = sekunti) |
155 |
146 |
156 print('Ladataan päiväykset... ', flush = True) |
147 print('Ladataan päiväykset... ', file = stderr, flush = True) |
157 |
148 |
158 viimeinen_käyttöpäivä = date.today() |
149 viimeinen_käyttöpäivä = date.today() |
159 palvelut_per_päivä = {} |
150 palvelut_per_päivä = {} |
160 |
151 |
161 with open('gtfs/calendar_dates.txt') as tiedosto: |
152 with open('gtfs/calendar_dates.txt') as tiedosto: |
171 def palvelut_käytössä(päivä): |
162 def palvelut_käytössä(päivä): |
172 for palvelu in palvelut.values(): |
163 for palvelu in palvelut.values(): |
173 if päivä in palvelu.päivät: |
164 if päivä in palvelu.päivät: |
174 yield palvelu |
165 yield palvelu |
175 |
166 |
176 print('Ladataan pysäkit... ', end = '', flush = True) |
167 print('Ladataan pysäkit... ', file = stderr, end = '', flush = True) |
177 with open('gtfs/stops.txt') as file: |
168 with open('gtfs/stops.txt') as file: |
178 for rivi in lue_csv(file): |
169 for rivi in lue_csv(file): |
179 pysäkki = Pysäkki(rivi['stop_id'], rivi['stop_name']) |
170 sijainti = (float(rivi['stop_lat']), float(rivi['stop_lon'])) |
|
171 pysäkki = Pysäkki(rivi['stop_id'], rivi['stop_name'], sijainti) |
180 pysäkit[pysäkki.tunniste] = pysäkki |
172 pysäkit[pysäkki.tunniste] = pysäkki |
181 print('%d pysäkkiä' % len(pysäkit)) |
173 with open('pysäkkialueet.json') as file: |
|
174 for pysäkkitunniste, alue in json.load(file).items(): |
|
175 pysäkit[pysäkkitunniste].alue = alue |
|
176 print('%d pysäkkiä' % len(pysäkit), file = stderr) |
182 |
177 |
183 print('Ladataan aikataulut... ', end = '', flush = True) |
178 print('Ladataan aikataulut... ', end = '', flush = True, file = stderr) |
184 with open('gtfs/stop_times.txt') as file: |
179 with open('gtfs/stop_times.txt') as file: |
185 rivimäärä = sum(line.count('\n') for line in file) |
180 rivimäärä = sum(line.count('\n') for line in file) |
186 laskettu = 0 |
181 laskettu = 0 |
187 file.seek(0) |
182 file.seek(0) |
188 for rivi in lue_csv(file): |
183 for rivi in lue_csv(file): |
191 lähtöaika = lue_aika(rivi['departure_time']) |
186 lähtöaika = lue_aika(rivi['departure_time']) |
192 pysäkki = pysäkit[rivi['stop_id']] |
187 pysäkki = pysäkit[rivi['stop_id']] |
193 ajo.reitti.append(Pysähdys(saapumisaika, lähtöaika, pysäkki, ajo)) |
188 ajo.reitti.append(Pysähdys(saapumisaika, lähtöaika, pysäkki, ajo)) |
194 laskettu += 1 |
189 laskettu += 1 |
195 if laskettu % 1000 == 0: |
190 if laskettu % 1000 == 0: |
196 print('\rLadataan aikataulut... %.1f%%' % (laskettu * 100 / rivimäärä), end = ' ') |
191 print('\rLadataan aikataulut... %.1f%%' % (laskettu * 100 / rivimäärä), end = ' ', file = stderr) |
197 print('\rLadataan aikataulut... ladattu') |
192 print('\rLadataan aikataulut... ladattu', file = stderr) |