busroute.py

Wed, 29 Jul 2020 23:45:53 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Wed, 29 Jul 2020 23:45:53 +0300
changeset 1
f9788970fa46
permissions
-rw-r--r--

begin work on bus compiler

1
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
1 #!/usr/bin/env python3
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
2 def via_factor(region_name, *, regions):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
3 # how important is it that
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
4 if region_name in regions:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
5 return float(regions[region_name]['via_factor'])
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
6 else:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
7 return 0
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
8
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
9 def simplify_name(region_name, *, regions, replace = False):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
10 # take short_name to account
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
11 region = regions.get(region_name)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
12 if region:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
13 return region.get('short_name', region_name)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
14 else:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
15 return region_name
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
16
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
17 def destinations_list(
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
18 itinerary,
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
19 *, trip_length,
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
20 regions,
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
21 whole = False,
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
22 format = 'medium',
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
23 ):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
24 '''
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
25 Produces a sign of destinations for the given itinerary.
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
26 `itinerary`: list of region names passed through
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
27 `trip_length`: length of the itinerary in meters.
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
28 `regions`: the regions table, used to decide what is important to show.
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
29 `whole`: whether or not the starting place is also included.
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
30 `format` controls what kind of sign to produce:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
31 - 'short': at most 2 destinations, with reducing
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
32 - 'medium': at most 3 destinations, with reducing
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
33 - 'long': at most 4 destinations, no reducing.
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
34 Returns a list of region names.
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
35 e.g. ['Turun keskusta', 'Ihala', 'Kauppakeskus Mylly']
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
36 for Föli bus route 220 at the student village.
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
37 '''
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
38 # prefer longer destination signs on longer routes
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
39 length = ((trip_length / 600) * 3 + len(itinerary) * 2) / 5
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
40 # collect regions along the itinerary
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
41 have_already = set()
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
42 i = 0
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
43 if not itinerary:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
44 # not going anywhere?
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
45 return ''
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
46 while i < len(itinerary):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
47 region = regions.get(itinerary[i])
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
48 if not itinerary[i] or itinerary[i] in have_already:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
49 del itinerary[i]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
50 else:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
51 have_already.add(itinerary[i])
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
52 i += 1
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
53 from_place = itinerary[0]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
54 destination = itinerary[-1]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
55 route_weights = {}
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
56 # create weights for all places along the way. Transforming by x^-0.3
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
57 # lessens weights for places further out in the itinerary.
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
58 f = lambda i: i**-0.3
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
59 # this factor scales the weights so that they become comparable against
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
60 # constant values
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
61 factor = 1 / max(f(i + 1) for i in range(len(itinerary)))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
62 while via_factor(itinerary[-1], regions = regions) < 0:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
63 del itinerary[-1]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
64 if not itinerary:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
65 return ''
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
66 destination = itinerary[-1]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
67 for i, stop in enumerate(itinerary):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
68 # transform index by:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
69 # - our gradually decreasing x^-0.3 curve,
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
70 # - our normalising factor,
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
71 # - and the via_factor of the stop
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
72 route_weights[stop] = f(i + 1) * factor * via_factor(stop, regions = regions)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
73 # ensure that the starting region does not make it into the destinations
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
74 # sign by setting its weight to 0
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
75 if from_place in route_weights:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
76 route_weights[from_place] = 0
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
77 # ensure that the destination does make it to the signpost
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
78 route_weights[destination] = 1.0e+10
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
79 # sort destinations by importance
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
80 weights = sorted(
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
81 [
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
82 (stop, route_weights[stop], i)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
83 for i, stop in enumerate(itinerary)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
84 if route_weights[stop] >= 1
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
85 ], key = lambda stop: -stop[1])
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
86 # now consider what do we want to display:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
87 if format == 'long':
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
88 # long format, just take at most four destinations
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
89 weights = weights[:4]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
90 elif format == 'short':
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
91 # short format, take at most two destinations
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
92 weights = weights[:2]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
93 # possibly drop the via-region as well
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
94 try:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
95 if weights[1][0] != destination and weights[1][1] < (500 / length ** 1.15):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
96 del weights[1]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
97 except IndexError:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
98 pass
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
99 elif format == 'medium':
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
100 # regular format, at most three destinations
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
101 weights = weights[:3]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
102 # if the third sign value is not significant enough, drop it
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
103 try:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
104 if weights[2][0] != destination and weights[2][1] < (725 / length ** 0.8):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
105 del weights[2]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
106 except IndexError:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
107 pass
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
108 # and repeat for the second sign value
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
109 try:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
110 if weights[1][0] != destination and weights[1][1] < (500 / length ** 1.15):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
111 del weights[1]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
112 except IndexError:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
113 pass
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
114 else:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
115 raise ValueError(str.format('Unknown format {format}', format = repr(format)))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
116 # restore the signpost back to itinerary order
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
117 weights.sort(key = lambda weight_data: weight_data[2])
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
118 # form the sign
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
119 sign = [paino[0] for paino in weights]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
120 old_sign = sign.copy()
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
121 sign = []
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
122 for place in old_sign:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
123 if place not in sign:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
124 sign.append(place)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
125 if whole:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
126 # whole format, also include the starting point
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
127 sign = [from_place] + sign
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
128 if not sign:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
129 sign = [destination]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
130 return sign

mercurial