fix low level issues
This commit is contained in:
@@ -346,5 +346,6 @@ def _patch_duplicate_of(output_dir: Path, activity_id: str, canonical_id: str) -
|
||||
data = json.loads(p.read_text())
|
||||
data["duplicate_of"] = canonical_id
|
||||
p.write_text(json.dumps(data, indent=2, ensure_ascii=False))
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
import logging
|
||||
logging.getLogger(__name__).warning("_patch_duplicate_of failed for %s: %s", activity_id, e)
|
||||
|
||||
@@ -237,19 +237,29 @@ def _fastest_time_for_distance(speed_1hz: list[float], target_km: float) -> Opti
|
||||
def _best_climb(ele_1hz: list[Optional[float]]) -> Optional[float]:
|
||||
"""Maximum net elevation gain over any contiguous window (Kadane's on deltas).
|
||||
|
||||
Ignores samples where elevation is None. Returns None if fewer than two
|
||||
valid elevation samples exist.
|
||||
None samples are treated as breaks between segments — the Kadane window is
|
||||
reset to 0 at each gap so non-contiguous elevation data is never joined.
|
||||
Returns None if fewer than two non-None samples exist.
|
||||
"""
|
||||
valid = [e for e in ele_1hz if e is not None]
|
||||
if len(valid) < 2:
|
||||
non_null = sum(1 for e in ele_1hz if e is not None)
|
||||
if non_null < 2:
|
||||
return None
|
||||
|
||||
max_gain = 0.0
|
||||
current = 0.0
|
||||
for a, b in zip(valid, valid[1:]):
|
||||
current = max(0.0, current + (b - a))
|
||||
if current > max_gain:
|
||||
max_gain = current
|
||||
prev: Optional[float] = None
|
||||
|
||||
for e in ele_1hz:
|
||||
if e is None:
|
||||
# Gap — reset window so we don't bridge the discontinuity
|
||||
current = 0.0
|
||||
prev = None
|
||||
continue
|
||||
if prev is not None:
|
||||
current = max(0.0, current + (e - prev))
|
||||
if current > max_gain:
|
||||
max_gain = current
|
||||
prev = e
|
||||
|
||||
return round(max_gain, 1) if max_gain > 0 else None
|
||||
|
||||
|
||||
@@ -43,11 +43,11 @@ def preview_coords(
|
||||
mask = rdp(coords, epsilon=0.001, return_mask=True)
|
||||
reduced = [gps[i] for i, keep in enumerate(mask) if keep]
|
||||
|
||||
# Subsample if still too many
|
||||
# Subsample if still too many — always include last point without exceeding max_points
|
||||
if len(reduced) > max_points:
|
||||
step = len(reduced) / max_points
|
||||
reduced = [reduced[int(i * step)] for i in range(max_points)]
|
||||
reduced.append(gps[-1]) # always include the last point
|
||||
step = len(reduced) / (max_points - 1)
|
||||
reduced = [reduced[int(i * step)] for i in range(max_points - 1)]
|
||||
reduced.append(gps[-1])
|
||||
|
||||
return [[round(lat, 5), round(lon, 5)] for lat, lon in reduced]
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@ def build_timeseries(
|
||||
t = int((p.timestamp - started_at).total_seconds())
|
||||
if t < 0:
|
||||
continue
|
||||
if last_t is not None and t == last_t:
|
||||
continue # skip sub-second duplicates
|
||||
if last_t is not None and t <= last_t:
|
||||
continue # skip sub-second duplicates and non-monotonic points
|
||||
sampled.append(p)
|
||||
last_t = t
|
||||
|
||||
|
||||
Reference in New Issue
Block a user