--- a/buses.py Mon Aug 13 22:56:30 2018 +0300 +++ b/buses.py Fri Sep 07 00:23:42 2018 +0300 @@ -98,7 +98,7 @@ date += timedelta(1) # Typistä lopputulos haluttuun tulosmäärään. return result[:max_amount] - def schedule_for_day(self, date, *, arrivals = False): + def schedule_for_day(self, date, *, arrivals = False, allow_gone = False): ''' Hakee pysäkin aikataulut tiettynä päivänä. ''' @@ -117,7 +117,7 @@ if stop and (arrivals or not stop.is_arrival) and stop is not trip.schedule[-1]: # ja jos tämä halt on tulevaisuudessa, stop_time = datetime.combine(date, time()) + stop.departure_time - if stop_time + timedelta(minutes = 1) >= now(): + if allow_gone or (stop_time + timedelta(minutes = 1) >= now()): # lisää halt listaan. result.append({ 'date': date, @@ -181,6 +181,57 @@ long = long, ) +class BusStopCluster: + def __init__(self): + self.stops = set() + self.cached_center = None + self.name = None + @property + def url_name(self): + return self.name.lower().replace('(', '').replace(')', '').replace(' ', '-') + def add_stop(self, stop): + assert not stop.cluster + stop.cluster = self + self.stops.add(stop) + self.cached_center = None + @property + def center(self): + if not self.cached_center: + if self.stops: + from statistics import median + pointtype = type(next(iter(self.stops)).location) + self.cached_center = pointtype( + median(stop.location.x for stop in self.stops), + median(stop.location.y for stop in self.stops), + ) + else: + raise ValueError('an empty cluster has no center point') + return self.cached_center + def merge(self, other): + for bus_stop in other.stops: + bus_stop.cluster = self + self.stops |= other.stops + other.stops = set() + other.cached_center = None + def schedule(self, *, max_amount = 50): + result = [] + for stop in self.stops: + result += stop.schedule(max_amount = max_amount) + result.sort(key = lambda schedule_entry: schedule_entry['time']) + return result[:max_amount] + +class CustomBusStopCluster(BusStopCluster): + def __init__(self, *, name, stops): + super().__init__() + self.name = name + self.stops = stops + def add_stop(self, stop): + return NotImplemented + @property + def url_name(self): + from urllib.request import quote + return 'custom?stops=' + ';'.join(stop.code for stop in self.stops) + '&name=' + quote(self.name) + routes = {} routes_per_id = {} all_trips = {} @@ -320,45 +371,6 @@ bus_stop.region = None print('%d stops' % len(bus_stops), file = stderr) - class BusStopCluster: - def __init__(self): - self.stops = set() - self.cached_center = None - self.name = None - @property - def url_name(self): - return self.name.lower().replace('(', '').replace(')', '').replace(' ', '-') - def add_stop(self, stop): - assert not stop.cluster - stop.cluster = self - self.stops.add(stop) - self.cached_center = None - @property - def center(self): - if not self.cached_center: - if self.stops: - from statistics import median - pointtype = type(next(iter(self.stops)).location) - self.cached_center = pointtype( - median(stop.location.x for stop in self.stops), - median(stop.location.y for stop in self.stops), - ) - else: - raise ValueError('an empty cluster has no center point') - return self.cached_center - def merge(self, other): - for bus_stop in other.stops: - bus_stop.cluster = self - self.stops |= other.stops - other.stops = set() - other.cached_center = None - def schedule(self, *, max_amount = 50): - result = [] - for stop in self.stops: - result += stop.schedule(max_amount = max_amount) - result.sort(key = lambda schedule_entry: schedule_entry['time']) - return result[:max_amount] - from collections import defaultdict bus_stops_by_name = defaultdict(set) for bus_stop in bus_stops.values():