buses.py

changeset 29
2c78e68d7363
parent 28
670ffa424ded
child 30
a5bfd99bc2a3
--- 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:

mercurial