bussit.py

changeset 7
f3791dccfd03
parent 6
88cfb916c852
child 8
d12e8a560faa
--- a/bussit.py	Sat Jun 10 16:36:36 2017 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +0,0 @@
-#!/usr/bin/env python3
-import enum, json
-from sys import stderr
-from datetime import date, time, datetime, timedelta
-from copy import copy
-from misc import *
-from geometria import *
-Suunta = enum.Enum('Suunta', [('Taaksepäin', 0), ('Eteenpäin', 1)])
-
-def muunna_ajovuoro_tunniste(tunniste):
-	return tunniste
-
-class Ajovuoro:
-	def __init__(self, tunniste, linja, palvelu, kyltti, suunta):
-		self.tunniste, self.linja, self.palvelu, self.kyltti, self.suunta = tunniste, linja, \
-			palvelu, kyltti, suunta
-		self.reitti = []
-		self.nimi = muunna_ajovuoro_tunniste(tunniste)
-	def __repr__(self):
-		return 'ajot[%r]' % self.nimi
-	def pysäkkiReitillä(self, pysäkki):
-		for pysähdys in self.reitti:
-			if pysähdys.pysäkki is pysäkki:
-				return pysähdys
-		else:
-			return None
-	def ajetaan_päivänä(self, päivä):
-		try:
-			return self.palvelu in palvelut_per_päivä[päivä]
-		except KeyError:
-			return False
-	def suppea_reitti(self, pysäkistä = None):
-		if pysäkistä and pysäkistä in self.reitti:
-			reitti = copy(self.reitti)
-			reitti = reitti[reitti.index(pysäkistä):]
-		else:
-			reitti = self.reitti
-		käytetyt_alueet = set()
-		tulos = []
-		for pysähdys in reitti:
-			pysäkki = pysähdys.pysäkki
-			if pysäkki.alue and pysäkki.alue not in käytetyt_alueet:
-				käytetyt_alueet.add(pysäkki.alue)
-				tulos.append(pysäkki.alue)
-		return tulos
-
-class Linja:
-	def __init__(self, tietue):
-		self.tunniste = tietue['route_id']
-		self.viite = tietue['route_short_name']
-		self.selite = tietue['route_long_name']
-	def __repr__(self):
-		return 'linjat[%r]' % self.viite
-
-class Palvelu:
-	def __init__(self, tunniste):
-		self.tunniste = tunniste
-		self.päivät = set()
-	def __repr__(self):
-		return 'palvelut[%r]' % self.tunniste
-
-class Pysäkki:
-	def __init__(self, tunniste, nimi, sijainti):
-		self.tunniste, self.nimi, self.sijainti = tunniste, nimi, sijainti
-	def __repr__(self):
-		return 'pysäkit[%r]' % self.tunniste
-	def aikataulu(self, määrä = 50):
-		'''
-			Hakee tämän pysäkin seuraavat `määrä` lähtöä. Päätepysäkille saapuvia busseja ei
-			lasketa. Palauttaa pysähdykset listana jossa alkiot ovat muotoa (aika, pysähdys),
-			jossa:
-			- `aika` on saapumishetki muotoa datetime ja
-			- `pysähdys` on vastaava Pysähdys olio.
-			
-			Mikäli pysäkille ei ole määrätty riittävästi pysähdyksiä kalenterissa, tuloslista
-			jää alimittaiseksi, mahdollisesti jopa tyhjäksi.
-		'''
-		class PäivätLoppuError(Exception):
-			pass
-		# Hakee pysäkin aikataulut tiettynä päivänä.
-		def aikataulu_päivänä(päivä):
-			# Jos päädyttiin aikataulukalenterin ulkopuolelle, niin tuotetaan virhe. Jos vain
-			# palautettaisiin tyhjä tulos, niin algoritmi jatkaisi etsintää loputtomiin.
-			if päivä > viimeinen_käyttöpäivä:
-				raise PäivätLoppuError()
-			taulu = []
-			# Jokaiselle ajovuorolle,
-			for ajo in ajot.values():
-				# jos tämä ajovuoro ajetaan tänä päivänä
-				if ajo.ajetaan_päivänä(päivä):
-					# ja jos tämä ajo pysähtyy tällä pysäkillä, ei kuitenkaan saapuen
-					# päätepysäkille,
-					pysähdys = ajo.pysäkkiReitillä(self)
-					if pysähdys and pysähdys is not ajo.reitti[-1]:
-						# ja jos tämä pysähdys on tulevaisuudessa,
-						aika = datetime.combine(päivä, time()) + pysähdys.saapumisaika
-						if aika >= nyt():
-							# lisää pysähdys listaan.
-							taulu.append((aika, pysähdys))
-			# Lajittele lopputulos saapumisajan mukaan.
-			taulu.sort(key = lambda tietue: tietue[0])
-			return taulu
-		taulu = []
-		päivä = tänään()
-		# Niin kauan kuin aikatauluja ei ole vielä tarpeeksi,
-		while len(taulu) < määrä:
-			try:
-				# hae nykyisen päivän aikataulut ja lisää ne,
-				taulu += aikataulu_päivänä(päivä)
-			except PäivätLoppuError:
-				# paitsi jos mentiin kalenterin ulkopuolelle, jolloin lopetetaan,
-				break
-			# ja siirry seuraavaan päivään.
-			päivä += timedelta(1)
-		# Typistä lopputulos haluttuun tulosmäärään.
-		return taulu[:määrä]
-	@property
-	def linkki_karttaan(self):
-		return 'http://www.openstreetmap.org/#map=19/%f/%f' % (self.sijainti.leveys, self.sijainti.pituus)
-
-class Pysähdys:
-	def __init__(self, saapumisaika, lähtöaika, pysäkki, ajo):
-		self.saapumisaika, self.lähtöaika, self.pysäkki, self.ajo = saapumisaika, lähtöaika, \
-			pysäkki, ajo
-	def __repr__(self):
-		return 'Pysähdys(%r, %r, %r, %r)' % (self.saapumisaika, self.lähtöaika, self.pysäkki, self.ajo)
-
-linjat = {}
-linjat_per_tunniste = {}
-ajot = {}
-ajot_per_numero = {}
-palvelut = {}
-pysäkit = {}
-
-print('Ladataan linjat... ', file = stderr, end = '', flush = True)
-with open('gtfs/routes.txt') as tiedosto:
-	for rivi in lue_csv(tiedosto):
-		linja = Linja(rivi)
-		linja.tunniste = linja.tunniste
-		linjat[linja.viite] = linja
-		linjat_per_tunniste[linja.tunniste] = linja
-print('%d linjaa' % len(linjat), file = stderr)
-
-print('Ladataan ajot... ', file = stderr, end = '', flush = True)
-with open('gtfs/trips.txt') as tiedosto:
-	for rivi in lue_csv(tiedosto, muunnokset = {'direction_id': lambda k: Suunta(int(k))}):
-		if rivi['service_id'] not in palvelut:
-			palvelut[rivi['service_id']] = Palvelu(rivi['service_id'])
-		linja = linjat_per_tunniste[rivi['route_id']]
-		ajo = Ajovuoro(tunniste = rivi['trip_id'],
-			linja = linja,
-			palvelu = palvelut[rivi['service_id']],
-			kyltti = rivi['trip_headsign'],
-			suunta = rivi['direction_id'])
-		assert ajo.nimi not in ajot
-		ajot[ajo.nimi] = ajo
-print('%d ajoa' % len(ajot), file = stderr)
-
-def lue_päiväys(teksti):
-	return date(int(teksti[:4]), int(teksti[4:6]), int(teksti[6:]))
-
-def lue_aika(teksti):
-	tunti, minuutti, sekunti = map(int, teksti.split(':'))
-	return timedelta(hours = tunti, minutes = minuutti, seconds = sekunti)
-
-print('Ladataan päiväykset... ', file = stderr, flush = True)
-
-viimeinen_käyttöpäivä = date.today()
-palvelut_per_päivä = {}
-
-with open('gtfs/calendar_dates.txt') as tiedosto:
-	for rivi in lue_csv(tiedosto):
-		palvelu = palvelut[rivi['service_id']]
-		päivä = lue_päiväys(rivi['date'])
-		palvelu.päivät.add(päivä)
-		if päivä not in palvelut_per_päivä:
-			palvelut_per_päivä[päivä] = set()
-		palvelut_per_päivä[päivä].add(palvelu)
-		viimeinen_käyttöpäivä = max(päivä, viimeinen_käyttöpäivä)
-
-def palvelut_käytössä(päivä):
-	for palvelu in palvelut.values():
-		if päivä in palvelu.päivät:
-			yield palvelu
-
-print('Ladataan pysäkit... ', file = stderr, end = '', flush = True)
-with open('gtfs/stops.txt') as file:
-	for rivi in lue_csv(file):
-		sijainti = Sijainti(float(rivi['stop_lat']), float(rivi['stop_lon']))
-		pysäkki = Pysäkki(rivi['stop_id'], rivi['stop_name'], sijainti)
-		pysäkit[pysäkki.tunniste] = pysäkki
-with open('pysäkkialueet.json') as file:
-	for pysäkkitunniste, alue in json.load(file).items():
-		pysäkit[pysäkkitunniste].alue = alue
-print('%d pysäkkiä' % len(pysäkit), file = stderr)
-
-print('Ladataan aikataulut... ', end = '', flush = True, file = stderr)
-with open('gtfs/stop_times.txt') as file:
-	rivimäärä = sum(line.count('\n') for line in file)
-	laskettu = 0
-	file.seek(0)
-	for rivi in lue_csv(file):
-		ajo = ajot[muunna_ajovuoro_tunniste(rivi['trip_id'])]
-		saapumisaika = lue_aika(rivi['arrival_time'])
-		lähtöaika = lue_aika(rivi['departure_time'])
-		pysäkki = pysäkit[rivi['stop_id']]
-		ajo.reitti.append(Pysähdys(saapumisaika, lähtöaika, pysäkki, ajo))
-		laskettu += 1
-		if laskettu % 1000 == 0:
-			print('\rLadataan aikataulut... %.1f%%' % (laskettu * 100 / rivimäärä), end = ' ', file = stderr)
-print('\rLadataan aikataulut... ladattu', file = stderr)

mercurial