|
@@ -17,111 +17,124 @@ max_distance = 3000 # m
|
|
|
|
|
|
class TripConverter:
|
|
|
trips: list[Trip]
|
|
|
+ markers: list[Marker]
|
|
|
+ created: int
|
|
|
+ updated: int
|
|
|
+ skipped: int
|
|
|
|
|
|
def __init__(self, markers: list[Marker]):
|
|
|
+ self.markers = markers
|
|
|
self.trips = []
|
|
|
+ self.created = 0
|
|
|
+ self.updated = 0
|
|
|
+ self.skipped = 0
|
|
|
+
|
|
|
+ def run(self):
|
|
|
first_index = 0
|
|
|
- for i, point in enumerate(markers[1:]):
|
|
|
- prev_point = markers[i-1]
|
|
|
+ for i, point in enumerate(self.markers[1:]):
|
|
|
+ prev_point = self.markers[i-1]
|
|
|
if point.timestamp - prev_point.timestamp > max_time_diff or \
|
|
|
Distance(point.location, prev_point.location) > max_distance:
|
|
|
if i - first_index > 2:
|
|
|
- self.trips.append(create_trip(markers[first_index:i]))
|
|
|
+ self.trips.append(self.create_trip(self.markers[first_index:i]))
|
|
|
first_index = i
|
|
|
|
|
|
- if first_index < len(markers) - 2:
|
|
|
- self.trips.append(create_trip(markers[first_index:]))
|
|
|
-
|
|
|
- def save(self):
|
|
|
- for trip in self.trips:
|
|
|
- trip.save()
|
|
|
-
|
|
|
-def create_trip(markers: list[Marker]) -> Trip:
|
|
|
- print(len(markers), markers[0].timestamp, markers[-1].timestamp)
|
|
|
- trip = Trip.objects.filter(startTime__lte=markers[-1].timestamp, endTime__gte=markers[0].timestamp).first()
|
|
|
- center = markers[len(markers)//2].location
|
|
|
- if not trip:
|
|
|
- trip = Trip.objects.create(
|
|
|
- startTime = markers[0].timestamp,
|
|
|
- endTime = markers[-1].timestamp,
|
|
|
- name = f"Trip {markers[0].timestamp}",
|
|
|
- color = get_path_color(markers[0].timestamp),
|
|
|
- center = Point(center.x, center.y)
|
|
|
- )
|
|
|
- elif trip.startTime == markers[0].timestamp and trip.endTime == markers[-1].timestamp:
|
|
|
- print("Trip already exists")
|
|
|
- return trip
|
|
|
-
|
|
|
- if not trip.name or "None" in trip.name or trip.name.startswith("Trip "):
|
|
|
- start = get_location_name(markers[0].location)
|
|
|
- end = get_location_name(markers[-1].location)
|
|
|
- if start != end:
|
|
|
- trip.name = f"{start} - {end}"
|
|
|
- else:
|
|
|
- trip.name = start
|
|
|
- trip.startTime = markers[0].timestamp
|
|
|
- trip.endTime = markers[-1].timestamp
|
|
|
- trip.totalTime = trip.endTime - trip.startTime
|
|
|
- trip.center = Point(center.x, center.y)
|
|
|
-
|
|
|
- total_distance = 0 # m
|
|
|
- topSpeed = 0 # km/h
|
|
|
- ascendHeight = 0 # m
|
|
|
- descendHeight = 0 # m
|
|
|
- movementTime = timedelta(0)
|
|
|
-
|
|
|
- minLat = minLon = maxLat = maxLon = None
|
|
|
-
|
|
|
- lastSpeed = 0
|
|
|
- i = 1
|
|
|
-
|
|
|
- while i < len(markers):
|
|
|
- point = markers[i]
|
|
|
- prev_point = markers[i-1]
|
|
|
- dist = Distance(point.location, prev_point.location)
|
|
|
- if point.speed is not None and point.speed > 0:
|
|
|
- speed = point.speed
|
|
|
- else:
|
|
|
- speed = dist / abs(point.timestamp - prev_point.timestamp).seconds * 3.6
|
|
|
-
|
|
|
- if abs(speed - lastSpeed) / abs(point.timestamp - prev_point.timestamp).seconds > 10: # m/s²
|
|
|
- markers.remove(point)
|
|
|
- continue
|
|
|
-
|
|
|
- if abs(speed - lastSpeed) > 50: # m/s
|
|
|
- markers.remove(point)
|
|
|
- continue
|
|
|
-
|
|
|
- total_distance += dist
|
|
|
- topSpeed = max(topSpeed, speed)
|
|
|
-
|
|
|
- minLat = min(minLat, point.location.y) if minLat is not None else point.location.y
|
|
|
- minLon = min(minLon, point.location.x) if minLon is not None else point.location.x
|
|
|
- maxLat = max(maxLat, point.location.y) if maxLat is not None else point.location.y
|
|
|
- maxLon = max(maxLon, point.location.x) if maxLon is not None else point.location.x
|
|
|
-
|
|
|
- if speed > 2.0: # km/h
|
|
|
- movementTime += abs(point.timestamp - prev_point.timestamp)
|
|
|
+ if first_index < len(self.markers) - 2:
|
|
|
+ self.trips.append(self.create_trip(self.markers[first_index:]))
|
|
|
+
|
|
|
+ def create_trip(self, markers: list[Marker]) -> Trip:
|
|
|
+ print(len(markers), markers[0].timestamp, markers[-1].timestamp)
|
|
|
+ trip = Trip.objects.filter(startTime__lte=markers[-1].timestamp, endTime__gte=markers[0].timestamp).first()
|
|
|
+ center = markers[len(markers)//2].location
|
|
|
+ if not trip:
|
|
|
+ trip = Trip.objects.create(
|
|
|
+ startTime = markers[0].timestamp,
|
|
|
+ endTime = markers[-1].timestamp,
|
|
|
+ name = f"Trip {markers[0].timestamp}",
|
|
|
+ color = get_path_color(markers[0].timestamp),
|
|
|
+ center = Point(center.x, center.y)
|
|
|
+ )
|
|
|
+ self.created += 1
|
|
|
+ self.updated -= 1
|
|
|
+ elif trip.startTime == markers[0].timestamp and \
|
|
|
+ trip.endTime == markers[-1].timestamp and \
|
|
|
+ trip.totalTime == markers[-1].timestamp - markers[0].timestamp:
|
|
|
+ print("Trip already exists")
|
|
|
+ self.skipped += 1
|
|
|
+ return trip
|
|
|
+
|
|
|
+ if not trip.name or "None" in trip.name or trip.name.startswith("Trip "):
|
|
|
+ start = get_location_name(markers[0].location)
|
|
|
+ end = get_location_name(markers[-1].location)
|
|
|
+ if start != end:
|
|
|
+ trip.name = f"{start} - {end}"
|
|
|
+ else:
|
|
|
+ trip.name = start
|
|
|
+ trip.startTime = markers[0].timestamp
|
|
|
+ trip.endTime = markers[-1].timestamp
|
|
|
+ trip.totalTime = trip.endTime - trip.startTime
|
|
|
+ trip.center = Point(center.x, center.y)
|
|
|
+
|
|
|
+ total_distance = 0 # m
|
|
|
+ topSpeed = 0 # km/h
|
|
|
+ ascendHeight = 0 # m
|
|
|
+ descendHeight = 0 # m
|
|
|
+ movementTime = timedelta(0)
|
|
|
+
|
|
|
+ minLat = minLon = maxLat = maxLon = None
|
|
|
+
|
|
|
+ lastSpeed = 0
|
|
|
+ i = 1
|
|
|
|
|
|
- if point.alt is not None and prev_point.alt is not None:
|
|
|
- if point.alt > prev_point.alt:
|
|
|
- ascendHeight += point.alt - prev_point.alt
|
|
|
+ while i < len(markers):
|
|
|
+ point = markers[i]
|
|
|
+ prev_point = markers[i-1]
|
|
|
+ dist = Distance(point.location, prev_point.location)
|
|
|
+ if point.speed is not None and point.speed > 0:
|
|
|
+ speed = point.speed
|
|
|
else:
|
|
|
- descendHeight += prev_point.alt - point.alt
|
|
|
- i += 1
|
|
|
+ speed = dist / abs(point.timestamp - prev_point.timestamp).seconds * 3.6
|
|
|
+
|
|
|
+ if abs(speed - lastSpeed) / abs(point.timestamp - prev_point.timestamp).seconds > 10: # m/s²
|
|
|
+ markers.remove(point)
|
|
|
+ continue
|
|
|
+
|
|
|
+ if abs(speed - lastSpeed) > 50: # m/s
|
|
|
+ markers.remove(point)
|
|
|
+ continue
|
|
|
|
|
|
- trip.distance = round(total_distance, 1) # m
|
|
|
- trip.topSpeed = round(topSpeed, 1) # km/h
|
|
|
- trip.avgSpeed = round(total_distance / (movementTime or trip.endTime - trip.startTime).total_seconds() * 3.6, 1) # km/h
|
|
|
- trip.ascendHeight = round(ascendHeight, 1) # m
|
|
|
- trip.descendHeight = round(descendHeight, 1) # m
|
|
|
- trip.movementTime = movementTime
|
|
|
+ total_distance += dist
|
|
|
+ topSpeed = max(topSpeed, speed)
|
|
|
+
|
|
|
+ minLat = min(minLat, point.location.y) if minLat is not None else point.location.y
|
|
|
+ minLon = min(minLon, point.location.x) if minLon is not None else point.location.x
|
|
|
+ maxLat = max(maxLat, point.location.y) if maxLat is not None else point.location.y
|
|
|
+ maxLon = max(maxLon, point.location.x) if maxLon is not None else point.location.x
|
|
|
+
|
|
|
+ if speed > 2.0: # km/h
|
|
|
+ movementTime += abs(point.timestamp - prev_point.timestamp)
|
|
|
|
|
|
- trip.line = LineString((markers[0].location.x, markers[0].location.y), (markers[-1].location.x, markers[-1].location.y))
|
|
|
+ if point.alt is not None and prev_point.alt is not None:
|
|
|
+ if point.alt > prev_point.alt:
|
|
|
+ ascendHeight += point.alt - prev_point.alt
|
|
|
+ else:
|
|
|
+ descendHeight += prev_point.alt - point.alt
|
|
|
+ i += 1
|
|
|
|
|
|
- trip.path = points_to_blob(markers)
|
|
|
+ trip.distance = round(total_distance, 1) # m
|
|
|
+ trip.topSpeed = round(topSpeed, 1) # km/h
|
|
|
+ trip.avgSpeed = round(total_distance / (movementTime or trip.endTime - trip.startTime).total_seconds() * 3.6, 1) # km/h
|
|
|
+ trip.ascendHeight = round(ascendHeight, 1) # m
|
|
|
+ trip.descendHeight = round(descendHeight, 1) # m
|
|
|
+ trip.movementTime = movementTime
|
|
|
|
|
|
- return trip
|
|
|
+ trip.line = LineString((minLon, minLat), (maxLon, maxLat))
|
|
|
+
|
|
|
+ trip.path = points_to_blob(markers)
|
|
|
+ trip.save()
|
|
|
+ self.updated += 1
|
|
|
+
|
|
|
+ return trip
|
|
|
|
|
|
def Distance(point1: Point, point2: Point) -> float:
|
|
|
lon1 = radians(point1.x)
|
|
@@ -162,11 +175,6 @@ def get_path_color(time: datetime) -> str:
|
|
|
rgb = colorsys.hsv_to_rgb(hue, saturation, value)
|
|
|
return f"#{int(rgb[0]*255):02x}{int(rgb[1]*255):02x}{int(rgb[2]*255):02x}"
|
|
|
|
|
|
-def convert_points_to_trips():
|
|
|
- points = list(Marker.objects.all())
|
|
|
- converter = TripConverter(points)
|
|
|
- converter.save()
|
|
|
-
|
|
|
def points_to_blob(markers) -> bytes:
|
|
|
arr = []
|
|
|
|