fix: Recalculate visit ranges using point-based gap threshold

Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
2025-08-15 18:59:26 +00:00
parent c959321c7b
commit 6d1a1e7c78

38
main.py
View File

@@ -567,44 +567,44 @@ async def search(request):
return web.json_response({'error': 'invalid area format in areas list'}, status=400) return web.json_response({'error': 'invalid area format in areas list'}, status=400)
client = sensors_client client = sensors_client
q = f'select "lat", "lon" from owntracks where "acc" < 100 and "name" = \'{name}\' order by time asc'
where_clauses = []
for area in areas:
sw = area['southWest']
ne = area['northEast']
where_clauses.append(f'("lat" >= {sw["lat"]} and "lat" <= {ne["lat"]} and "lon" >= {sw["lng"]} and "lon" <= {ne["lng"]})')
full_where_clause = ' or '.join(where_clauses)
q = f'select "lat", "lon" from owntracks where "acc" < 100 and "name" = \'{name}\' and ({full_where_clause}) order by time asc'
points = list(client.query(q).get_points()) points = list(client.query(q).get_points())
ranges = [] ranges = []
current_range = None current_range = None
last_point_dt = None outside_points_count = 0
GAP_THRESHOLD_MINUTES = 5 GAP_THRESHOLD_POINTS = 5
for point in points: for point in points:
is_inside = False
if point.get('lat') is not None and point.get('lon') is not None:
for area in areas:
sw = area['southWest']
ne = area['northEast']
if sw['lat'] <= point['lat'] <= ne['lat'] and sw['lng'] <= point['lon'] <= ne['lng']:
is_inside = True
break
point_time_str = point['time'] point_time_str = point['time']
if '.' in point_time_str: if '.' in point_time_str:
point_dt = datetime.strptime(point_time_str, '%Y-%m-%dT%H:%M:%S.%fZ') point_dt = datetime.strptime(point_time_str, '%Y-%m-%dT%H:%M:%S.%fZ')
else: else:
point_dt = datetime.strptime(point_time_str, '%Y-%m-%dT%H:%M:%SZ') point_dt = datetime.strptime(point_time_str, '%Y-%m-%dT%H:%M:%SZ')
if is_inside:
outside_points_count = 0
if current_range is None: if current_range is None:
current_range = {'start': point_dt, 'end': point_dt} current_range = {'start': point_dt, 'end': point_dt}
else: else:
time_diff_minutes = (point_dt - last_point_dt).total_seconds() / 60 current_range['end'] = point_dt
if time_diff_minutes > GAP_THRESHOLD_MINUTES: else: # outside
outside_points_count += 1
if current_range is not None and outside_points_count >= GAP_THRESHOLD_POINTS:
ranges.append({ ranges.append({
'start': int(current_range['start'].timestamp()), 'start': int(current_range['start'].timestamp()),
'end': int(current_range['end'].timestamp()) 'end': int(current_range['end'].timestamp())
}) })
current_range = {'start': point_dt, 'end': point_dt} current_range = None
else:
current_range['end'] = point_dt
last_point_dt = point_dt
if current_range is not None: if current_range is not None:
ranges.append({ ranges.append({