busroute.py

Sun, 03 Sep 2017 17:18:28 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Sun, 03 Sep 2017 17:18:28 +0300
changeset 56
e055b418fbf3
parent 55
0f1d046b3f78
child 57
69ee68608e56
permissions
-rw-r--r--

Takakirves

#!/usr/bin/env python3

from configparser import ConfigParser

replacements = {
	"ylioppilaskylä-itä": "ylioppilaskylä",
	"ylioppilaskylä-länsi": "ylioppilaskylä",
	"jokila": "lieto",
	"piispala": "lieto",
	'saaro': 'ruissalo',
	'silvola': 'vahto',
	'hemmola': 'vahto',
	'paasniittu': 'ruskon keskusta',
	'kahari': 'ruskon keskusta',
	'kemiö': 'kemiönsaari',
	'kasnäs': 'kemiönsaari',
	'pernon telakka': 'perno',
	'paimion sairaala': 'paimio',
	'hanhijoki': 'paimio',
}

# nimiä joista voidaan joustaa tarvittaessa
abbreviations = {
	'raision keskusta': 'raisio',
	'ruskon keskusta': 'rusko',
	'naantalin keskusta': 'naantali',
	'kaarinan keskusta': 'kaarina',
	'kauppakeskus mylly': 'mylly',
}

region_info = ConfigParser()
region_info.read('regions.ini')
municipalities = set(region_info.sections())
municipalities_per_region = {}

for municipality in municipalities:
	for region in region_info[municipality].keys():
		municipalities_per_region[region] = municipality

for place_from, place_to in replacements.items():
	municipalities_per_region[place_to] = municipalities_per_region[place_from]

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 ''
	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': 80,
		'raision keskusta': 150,
		'kukola': 50,
		'kaistarniemi': 50,
		'papinsaari': 50,
		'oriniemi': 50,
		'pikisaari': 50,
		'häppilä': 20,
		'haarla': 80,
		'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,
		'takakirves': 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,
		'logomo': 100,
		'rymättylä': 50,
		"sauvo": 500,
		"kemiönsaari": 500,
		'suovuori': 300,
		'eerikvalla': 50,
		'petäsmäki': 50,
		'tortinmäki': 50,
		'aura': 100,
		'friskala': -1,
		'merimasku': 50,
		'turkuhalli': 100,
		'messukeskus': 100,
		'naantalin pikatie': 150,
		'helsingin valtatie': 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)))
	while priorities.get(reitti[-1], 0) < 0:
		del reitti[-1]
		destination = reitti[-1]
	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] < (725 / length ** 0.8):
			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 weight_data: weight_data[2])
	# muodostetaan sign..
	sign = [paino[0] for paino in weights]
	to_place = sign[-1]
	nearby_municipalities = {'Turku', 'Raisio', 'Naantali', 'Kaarina', 'Lieto'}
	if from_place != to_place:
		municipality_from = municipalities_per_region.get(from_place)
		municipality_to = municipalities_per_region.get(to_place)
		if municipality_from and municipality_to and municipality_from not in nearby_municipalities | {municipality_to} and municipality_to not in nearby_municipalities:
			def convert_region(region):
				municipality = municipalities_per_region.get(region, region)
				if municipality != municipality_from:
					return municipality
				else:
					return region
			sign = [convert_region(region) for region in sign]
	# supista nimet tarvittaessa
	if len(' - '.join(sign)) > 20:
		sign = [abbreviations.get(place, place) for place in sign]
	old_sign = sign.copy()
	sign = []
	for place in old_sign:
		if place not in sign:
			sign.append(place)
	if whole:
		sign = [from_place] + sign
	if not sign:
		sign = [destination]
	return sign

mercurial