busroute.py

Wed, 28 Jun 2017 13:11:37 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Wed, 28 Jun 2017 13:11:37 +0300
changeset 32
ca1a0ea81cf6
parent 31
60045b362d71
child 43
1c9102fea431
permissions
-rw-r--r--

Yhdistetty pysäkki.png ja iso-pysäkki.png

#!/usr/bin/env python3

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',
	'Kemiö': 'Kemiönsaari',
	'Kasnäs': 'Kemiönsaari',
}

# nimiä joista voidaan joustaa tarvittaessa
abbreviations = {
	'Raision keskusta': 'Raisio',
	'Ruskon keskusta': 'Rusko',
	'Naantalin keskusta': 'Naantali',
	'Kaarinan keskusta': 'Kaarina',
	'Kauppakeskus Mylly': 'Mylly',
}

def simplify_name(name):
	name = replacements.get(name, name)
	name = abbreviations.get(name, name)
	return name

def reduce_schedule(reitti, trip_length, whole = False):
	length = ((trip_length / 600) + len(reitti)) / 2
	if not reitti:
		return ''
	eksoalueet = {
		'Turku', 'Naantali', 'Lieto', 'Aura', 'Kaarina', 'Pargas', 'Marttila', 'Somero', 'Koski Tl', 'Tarvasjoki',
		'Kaivopuisto',
	}
	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
	priorities = {
		'Ihala': 150,
		'Kauppakeskus Mylly': 200,
		'Kuninkoja': 80,
		'Moikoinen': 35,
		'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': 200,
		'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,
		'Lieto as': 200,
		'Ilmarinen': 50,
		'Vahto': 50,
		'Ruskon keskusta': 200,
		'Oriketo': 50,
		'Harittu': 40,
		'Jäkärlä': 50,
		'Paattinen': 100,
		'Kaarinan keskusta': 200,
		'Naantalin keskusta': 200,
		'Uittamo': 50,
		'Piikkiö': 100,
		'Paimio': 100,
		'Pargas': 100,
		'Nagu': 100,
		'Yli-Maaria': 70,
		'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': 50,
		'Rymättylä': 50,
		"Sauvo": 500,
		"Kemiönsaari": 500,
	}

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

	from_place = reitti[0]
	destination = reitti[-1]
	reitti_arvot = {}
	f = lambda i: i**-0.3
	factor = 1 / max(f(i + 1) for i in range(len(reitti)))
	for i, stop in enumerate(reitti):
		# muunna indeksi siten että myöhemmät alueet korostuvat
		i = f(i + 1) * factor
		# ota prioriteetti huomioon, jotkin alueet ovat tärkeämpiä kyltissä kuin toiset
		i *= priorities.get(stop, 1)
		reitti_arvot[stop] = i
	# nollaa lähtöpaikan arvo ettei se mitenkään tule kylttiin
	if from_place in reitti_arvot:
		reitti_arvot[from_place] = 0
	# varmista että destination tulee kylttiin
	reitti_arvot[destination] = 1e10
	# muodosta sign-tiedot järjestettynä reittiarvon mukaan
	weights = sorted([
		(stop, reitti_arvot[stop], i) \
		for i, stop in enumerate(reitti) \
		if reitti_arvot[stop] >= 1
		], key = lambda stop: -stop[1])
	# enintään neljä tulee kylttiin
	weights = weights[:3]
	# jos kolmas kylttiarvo ei ole tarpeeksi merkittävä suhteessa reitin pituuteen niin otetaan se pois
	try:
		if weights[2][0] != destination and weights[2][1] < (1200 / length ** 0.9):
			del weights[2]
	except IndexError:
		pass
	try:
		if weights[1][0] != destination and weights[1][1] < (500 / length ** 1.15):
			del weights[1]
	except IndexError:
		pass
	# lajitellaan painoarvot uudestaan reittijärjestykseen jotta sign tulee oikeinpäin
	weights = sorted(weights, key = lambda paino: paino[2])
	# muodostetaan sign..
	sign = [paino[0] for paino in weights]
	# supista nimet jos mahdollista
	def finalise(sign, abbreviation_level = 0):
		if abbreviation_level > 0:
			sign = [abbreviations.get(paikka, paikka) for paikka in sign]
		return sign
	result = finalise(sign)
	for i in range(len(sign) - 1):
		if sign[i + 1].startswith(sign[i]):
			del sign[i]
	if len(' - '.join(sign)) > 20:
		result = finalise(sign, abbreviation_level = 1)
	if whole:
		result = [from_place] + result
	short_from_place = replacements.get(from_place, from_place)
	if (
		short_from_place != result[-1]
		and abbreviations.get(short_from_place, short_from_place) in eksoalueet | {'Kauppatori'}
		and result[-1] in eksoalueet | {'Kauppatori'}
	):
		result = ['Turku' if k == 'Kauppatori' else k for k in result]
	return result

mercurial