busroute.py

Sat, 10 Jun 2017 22:30:55 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Sat, 10 Jun 2017 22:30:55 +0300
changeset 19
16fa9fb20b32
parent 16
d94cde20abee
child 20
3199e289ae62
permissions
-rw-r--r--

Lisätty pysäkkiryhmän aikataulunäkymä

#!/usr/bin/env python3
def supista_reitti(reitti, kokonainen = False):
	def abstract_sign(sign):
		abstractions = {
			'Moikoinen': 'Hirvensalo',
			'Maanpää': 'Hirvensalo',
			'Papinsaari': 'Hirvensalo',
			'Häppilä': 'Hirvensalo',
			'Friskala': 'Hirvensalo',
			'Kukola': 'Hirvensalo',
			'Oriniemi': 'Hirvensalo',
			'Haarla': 'Hirvensalo',
			'Lauttasaari': 'Hirvensalo',
			'Pikisaari': 'Hirvensalo',
			'Vienola': 'Pahaniemi',
			'Takakirves': 'Kärsämäki',
			'Liljalaakso': 'Länsinummi',
			'Pernon telakka': 'Perno',
		}
		try:
			start = sign.index('Kauppatori')
		except ValueError:
			return sign
		result = []
		for i, place in enumerate(sign):
			if i >= start:
				abstract_place = abstractions.get(place, place)
				if abstract_place not in result:
					result.append(abstract_place)
			else:
				result.append(place)
		return result
	if not reitti:
		return ''
	kunnat = {'Turku', 'Naantali', 'Lieto', 'Aura', 'Kaarina', 'Pargas', 'Marttila', 'Somero', 'Koski Tl', 'Tarvasjoki'}
	replacements = {
		"Ylioppilaskylä-Itä": "Ylioppilaskylä",
		"Ylioppilaskylä-Länsi": "Ylioppilaskylä",
		"Caribia": "Ylioppilaskylä",
		"Jokila": "Lieto",
		"Piispala": "Lieto",
		'Saaro': 'Ruissalo',
		'Silvola': 'Vahto',
		'Hemmola': 'Vahto',
		'Paasniittu': 'Ruskon keskusta',
		'Kahari': 'Ruskon keskusta',
	}
	have_already = set()
	i = 0
	while i < len(reitti):
		if reitti[i] in replacements:
			reitti[i] = replacements[reitti[i]]
		if reitti[i] in have_already:
			del reitti[i]
		else:
			have_already.add(reitti[i])
			i += 1
	prioriteetit = {
		'Ihala': 150,
		'Kauppakeskus Mylly': 200,
		'Kuninkoja': 80,
		'Moikoinen': 50,
		'Raision keskusta': 100,
		'Friskala': 20,
		'Kukola': 50,
		'Kaistarniemi': 50,
		'Papinsaari': 50,
		'Oriniemi': 50,
		'Pikisaari': 50,
		'Häppilä': 50,
		'Haarla': 50,
		'Ylioppilaskylä': 50,
		'Halinen': 70,
		'Kakskerta': 50,
		'Pansio': 50,
		'Räntämäki': 10,
		'Verkahovi': 20,
		'Skanssi': 200,
		'Vaala': 20,
		'Varissuo': 60,
		'Kohmo': 80,
		'Kupittaa': 70,
		'Kauppatori': 1e15,
		'Lentoasema': 50,
		'Runosmäki': 50,
		'Lieto': 100,
		'Liedon asemanseutu': 200,
		'Ilmarinen': 50,
		'Vahto': 50,
		'Ruskon keskusta': 200,
		'Oriketo': 30,
		'Harittu': 40,
		'Jäkärlä': 50,
		'Paattinen': 100,
		'Kaarinan keskusta': 200,
		'Naantalin keskusta': 200,
		'Uittamo': 50,
		'Piikkiö': 100,
		'Paimio': 100,
		'Pargas': 50,
		'Yli-Maaria': 50,
		'Saramäki': 50,
		'Tarvasjoki': 100,
		'Marttila': 100,
		'Koski Tl': 100,
		'Katariina': 50,
		'Länsikeskus': 50,
		'Kaanaa': 100,
		'Satava': 50,
		'Suikkila': 50,
		'Raunistula': 50,
		'Räntämäki': 50,
		'Moisio': 25,
		'Pääskyvuori': 100,
		'Rautatieasema': 100,
	}

	if 'Kauppatori' not in reitti:
		prioriteetit['Länsikeskus'] = prioriteetit['Skanssi'] = prioriteetit['Kauppatori']

	# nimiä joista voidaan joustaa tarvittaessa
	helpot_supistukset = {
		'Raision keskusta': 'Raisio',
		'Ruskon keskusta': 'Rusko',
		'Naantalin keskusta': 'Naantali',
		'Kaarinan keskusta': 'Kaarina',
		'Liedon asemanseutu': 'Lieto as.',
		'Kauppakeskus Mylly': 'Mylly',
	}

	# jos ei nyt millään vaan mahdu muuten...
	vakavat_supistukset = {
		'Kauppatori': 'Tori',
		'Ylioppilaskylä': 'Yo-kylä',
	}

	lähtö = reitti[0]
	määränpää = reitti[-1]
	reitti_arvot = {}
	f = lambda i: i**-0.6
	jakaja = max(f(i + 1) for i in range(len(reitti)))
	for i, pysäkki in enumerate(reitti):
		# muunna indeksi siten että myöhemmät alueet korostuvat
		i = f(i + 1) / jakaja
		# ota prioriteetti huomioon, jotkin alueet ovat tärkeämpiä kyltissä kuin toiset
		i *= prioriteetit.get(pysäkki, 1)
		reitti_arvot[pysäkki] = i
	# nollaa lähtöpaikan arvo ettei se mitenkään tule kylttiin
	if lähtö in reitti_arvot:
		reitti_arvot[lähtö] = 0
	# varmista että määränpää tulee kylttiin
	reitti_arvot[määränpää] = 1e10
	# muodosta kyltti-tiedot järjestettynä reittiarvon mukaan
	painot = sorted([
		(pysäkki, reitti_arvot[pysäkki], i) \
		for i, pysäkki in enumerate(reitti) \
		if reitti_arvot[pysäkki] >= 1
		], key = lambda pysäkki: -pysäkki[1])
	# enintään neljä tulee kylttiin
	painot = painot[:4]
	# jos neljäs kylttiarvo ei ole tarpeeksi merkittävä suhteessa reitin pituuteen niin otetaan neljäs pois
	if len(painot) == 4 and painot[3][0] != määränpää and painot[3][1] < (4000 / len(reitti) ** 1.5):
		del painot[3]
	# sama kolmannelle
	if len(painot) == 3 and painot[2][0] != määränpää and painot[2][1] < (500 / len(reitti) ** 1.5):
		del painot[2]
	if len(painot) == 2 and painot[1][0] != määränpää and painot[1][1] < (150 / len(reitti) ** 1.5):
		del painot[1]
	# lajitellaan painoarvot uudestaan reittijärjestykseen jotta kyltti tulee oikeinpäin
	painot = sorted(painot, key = lambda paino: paino[2])
	# muodostetaan kyltti..
	kyltti = [paino[0] for paino in painot]
	kyltti = abstract_sign(kyltti)
	# supista nimet jos mahdollista
	def viimeistele(kyltti, supistus_taso = 0):
		if supistus_taso > 0:
			kyltti = [helpot_supistukset.get(paikka, paikka) for paikka in kyltti]
		if supistus_taso > 1:
			kyltti = [vakavat_supistukset.get(paikka, paikka) for paikka in kyltti]
		return kyltti
	tulos = viimeistele(kyltti)
	if len(' - '.join(kyltti)) > 20:
		tulos = viimeistele(kyltti, supistus_taso = 1)
	if len(' - '.join(kyltti)) > 70:
		tulos = viimeistele(kyltti, supistus_taso = 2)
	if kokonainen:
		tulos = [lähtö] + tulos
	lyhyt_lähtö = replacements.get(lähtö, lähtö)
	if lyhyt_lähtö != tulos[-1] and helpot_supistukset.get(lyhyt_lähtö, lyhyt_lähtö) in kunnat | {'Kauppatori'} and tulos[-1] in kunnat | {'Kauppatori'}:
		tulos = ['Turku' if k == 'Kauppatori' else k for k in tulos]
	return tulos

mercurial