-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsegment.py
128 lines (97 loc) · 4.87 KB
/
segment.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from area import Area
import csv
import random
import geo_util
import util
MAX_LOCATION_DISTANCE = 30000 # feet
MAX_TIME_DISTANCE = 900 # seconds
"""
### TODO add cache for way points with predicted arrival times:
- key: hash of min_file_offset, max_file_offset, start_time and end_time
- value: grid index, list of way points with predicted arrival times
- add class method set_current_grid_index(), which will flush all
cache entries with non-matching grid index
- in get_score(), either get way points from cache or create and
put into cache
"""
class Segment:
id_base = 0
def __init__(self, segment_index, trip_id, trip_name, trip_start_seconds, stop_id, bounding_box, start_time, end_time, min_file_offset, max_file_offset):
self.id = Segment.id_base
Segment.id_base += 1
util.debug(f'segment: id={self.id} trip_id={trip_id} top_left={bounding_box.top_left} bottom_right={bounding_box.bottom_right} start_time={util.seconds_to_hhmmss(start_time)} end_time={util.seconds_to_hhmmss(end_time)}')
self.segment_index = segment_index
self.trip_id = trip_id
self.trip_name = trip_name
self.trip_start_seconds = trip_start_seconds
self.stop_id = stop_id
#print(f'- trip_start_seconds: {trip_start_seconds}')
self.bounding_box = bounding_box
self.start_time = start_time
self.end_time = end_time
self.min_file_offset = min_file_offset
self.max_file_offset = max_file_offset
self.waypoint_list = None
def set_segments_per_trip(self, count):
self.segments_per_trip = count
def get_trip_fraction(self):
return float(self.segment_index) / self.segments_per_trip
def get_score(self, lat, lon, seconds, path):
if not self.bounding_box.contains(lat, lon):
return {'score': -1, 'time_offset': 0}
### REMOVE ME: for testing only
#if random.random() < .5:
# util.debug(f'segment update: id={self.id} trip-name={util.to_b64(self.trip_name)} score={0.0000001}')
if seconds < self.trip_start_seconds or seconds < self.start_time - MAX_TIME_DISTANCE or seconds > self.end_time + MAX_TIME_DISTANCE:
return {'score': -1, 'time_offset': 0}
if self.waypoint_list is None:
self.waypoint_list = []
with open(path + '/shapes.txt', 'r') as f:
names = f.readline().strip()
csvline = csv.CSVLine(names)
f.seek(self.min_file_offset)
while True:
line = f.readline().strip()
r = csvline.parse(line)
llat = float(r['shape_pt_lat'])
llon = float(r['shape_pt_lon'])
self.waypoint_list.append({'lat': llat, 'lon': llon})
if f.tell() > self.max_file_offset:
break
delta_time = self.end_time - self.start_time
for i in range(len(self.waypoint_list)):
fraction = i / len(self.waypoint_list)
time = int(self.start_time + fraction * delta_time)
self.waypoint_list[i]['time'] = time
min_distance = 1000000000
min_index = -1
closestLat = 0
closestLon = 0
for i in range(len(self.waypoint_list) - 1):
sp1 = self.waypoint_list[i]
sp2 = self.waypoint_list[i + 1]
distance = geo_util.get_min_distance(sp1, sp2, lat, lon, seconds)
if distance < min_distance:
min_distance = distance
min_index = i
closestLat = self.waypoint_list[i]['lat']
closestLon = self.waypoint_list[i]['lon']
print(f'- min_distance: {min_distance}')
if min_distance > MAX_LOCATION_DISTANCE:
return {'score': -1, 'time_offset': 0}
print(f'+ update time : {util.seconds_to_hhmm(seconds)}')
print(f'+ segment time: {util.seconds_to_hhmm(self.waypoint_list[min_index]["time"])}')
time_distance = abs(seconds - self.waypoint_list[min_index]['time'])
print(f'- time_distance: {time_distance}')
if time_distance > MAX_TIME_DISTANCE:
return {'score': -1, 'time_offset': 0}
location_score = .5 * (MAX_LOCATION_DISTANCE - min_distance) / MAX_LOCATION_DISTANCE
time_score = .5 * (MAX_TIME_DISTANCE - time_distance) / MAX_TIME_DISTANCE
util.debug(f'segment update: id={self.id} trip-name={util.to_b64(self.trip_name)} score={location_score + time_score} trip_pos=({self.segment_index}/{self.segments_per_trip}) closest-lat={closestLat} closest-lon={closestLon}')
util.debug(f'+ trip_name: {self.trip_name}')
return {
'score': location_score + time_score,
'time_offset': seconds - self.waypoint_list[min_index]['time']
}
def get_trip_id(self):
return self.trip_id