--- a/buses.py Wed Jun 21 18:25:09 2017 +0300 +++ b/buses.py Thu Jun 22 19:01:31 2017 +0300 @@ -59,8 +59,9 @@ return 'services[%r]' % self.reference class BusStop: - def __init__(self, reference, name, location): + def __init__(self, reference, name, location, code = None): self.reference, self.name, self.location = reference, name, location + self.code = code or reference self.cluster = None self.pairs = set() # samannimiset lähellä olevat pysäkit self.involved_trips = set() @@ -108,7 +109,7 @@ # ja jos tämä trip pysähtyy tällä pysäkillä, ei kuitenkaan saapuen # päätepysäkille, stop = trip.contains_stop(self) - if stop and not stop.isArrival: # stop is not trip.schedule[-1]: + if stop and not stop.is_arrival: # stop is not trip.schedule[-1]: # ja jos tämä halt on tulevaisuudessa, stop_time = datetime.combine(date, time()) + stop.arrival_time if stop_time >= now(): @@ -128,18 +129,21 @@ stop, trip self.traveled_distance = traveled_distance @property - def isArrival(self): + def is_arrival(self): if not hasattr(self, 'cachedIsArrival'): - iterator = iter(self.trip.schedule) - stop = next(iterator) - while stop is not self: + 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 + self.cachedIsArrival = False return self.cachedIsArrival def __repr__(self): return 'BusHalt(%r, %r, %r, %r)' % (self.arrival_time, self.departure_time, self.stop, self.trip) @@ -182,7 +186,7 @@ all_trips[trip.name] = trip print('%d ajoa' % len(all_trips), file = stderr) -def lue_päiväys(teksti): +def read_date(teksti): return date(int(teksti[:4]), int(teksti[4:6]), int(teksti[6:])) def read_time(teksti): @@ -194,16 +198,42 @@ viimeinen_käyttöpäivä = date.today() services_for_day = {} -with open('gtfs/calendar_dates.txt') as file: - for row in read_csv(file): - service = services[row['service_id']] - day = lue_päiväys(row['date']) +def date_range(start_date, end_date, *, include_end = False): + ''' Generates date from start_date to end_date. If include_end is True, then end_date will be yielded. ''' + current_date = start_date + while current_date < end_date: + yield current_date + current_date += timedelta(1) + if include_end: + yield end_date + +def add_day_to_service(service_name, day): + try: + service = services[service_name] + except KeyError: + return + else: service.dates.add(day) if day not in services_for_day: services_for_day[day] = set() services_for_day[day].add(service) + global viimeinen_käyttöpäivä viimeinen_käyttöpäivä = max(day, viimeinen_käyttöpäivä) +def filter_day(row, day): + day_names = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'] + return int(row[day_names[day.isoweekday() - 1]]) + +with open('gtfs/calendar.txt') as file: + for row in read_csv(file): + for day in date_range(read_date(row['start_date']), read_date(row['end_date']), include_end = True): + if filter_day(row, day): + add_day_to_service(service_name = row['service_id'], day = day) + +with open('gtfs/calendar_dates.txt') as file: + for row in read_csv(file): + add_day_to_service(service_name = row['service_id'], day = read_date(row['date'])) + def services_available_at(day): for service in services.values(): if day in service.dates: @@ -213,7 +243,12 @@ with open('gtfs/stops.txt') as file: for row in read_csv(file): location = Sijainti(float(row['stop_lat']), float(row['stop_lon'])) - stop = BusStop(row['stop_id'], row['stop_name'], location) + stop = BusStop( + reference = row['stop_id'], + name = row['stop_name'], + location = location, + code = row['stop_code'], + ) bus_stops[stop.reference] = stop with open('regions-per-stop.json') as file: for stop_reference, region in json.load(file).items(): @@ -276,7 +311,7 @@ # etsi pysäkin samannimiset vastaparit for pair_candidate in bus_stops_by_name[bus_stop.name]: distance = pair_candidate.location.etäisyys(bus_stop.location) - if pair_candidate is not bus_stop and distance <= 0.3: + if pair_candidate is not bus_stop and distance <= 0.4: stops_to_cluster.add(pair_candidate) for stop_to_cluster in stops_to_cluster: if stop_to_cluster.cluster: @@ -299,7 +334,7 @@ for cluster in all_clusters: if cluster is not bus_stop.cluster: distance = cluster.center.etäisyys(bus_stop.location) - if distance <= 0.3: + if distance <= 0.4: possibilities.add((distance, cluster)) if possibilities: best = min(possibilities)[1] @@ -356,8 +391,10 @@ clusters_by_name = {} for cluster in all_clusters: - assert cluster.url_name not in clusters_by_name - clusters_by_name[cluster.url_name] = cluster + if cluster.url_name in clusters_by_name: + print('Warning: Clusters %r and %r share the same URL name: %r' % (cluster.name, clusters_by_name[cluster.url_name].name, cluster.url_name)) + else: + clusters_by_name[cluster.url_name] = cluster print('Ladataan aikataulut... ', end = '', flush = True, file = stderr) with open('gtfs/stop_times.txt') as file: