aboutsummaryrefslogtreecommitdiff
path: root/web/frontend/ride-detail-logic.ts
diff options
context:
space:
mode:
Diffstat (limited to 'web/frontend/ride-detail-logic.ts')
-rw-r--r--web/frontend/ride-detail-logic.ts32
1 files changed, 23 insertions, 9 deletions
diff --git a/web/frontend/ride-detail-logic.ts b/web/frontend/ride-detail-logic.ts
index b4d4dba..e7fc822 100644
--- a/web/frontend/ride-detail-logic.ts
+++ b/web/frontend/ride-detail-logic.ts
@@ -1,4 +1,4 @@
-import type { ClimbBounds, ClimbMetrics, ProfilePoint } from "./types.js";
+import type { ClimbBounds, ClimbMetrics, ClimbSample, ProfilePoint } from "./types.js";
export const clamp = (value: number, min: number, max: number): number => Math.max(min, Math.min(max, value));
@@ -71,15 +71,13 @@ export const cotacolForClimb = (points: ProfilePoint[], startIndex: number, endI
return cotacol;
};
+const boundsAreValid = (points: ProfilePoint[], bounds: ClimbBounds | undefined): bounds is ClimbBounds => {
+ if (!bounds || !Number.isInteger(bounds.startIndex) || !Number.isInteger(bounds.endIndex)) return false;
+ return bounds.startIndex >= 0 && bounds.endIndex < points.length && bounds.startIndex < bounds.endIndex;
+};
+
export const climbMetrics = (points: ProfilePoint[], bounds: ClimbBounds | undefined): ClimbMetrics | null => {
- if (
- !bounds ||
- !Number.isInteger(bounds.startIndex) ||
- !Number.isInteger(bounds.endIndex) ||
- bounds.startIndex < 0 ||
- bounds.endIndex >= points.length ||
- bounds.startIndex >= bounds.endIndex
- ) {
+ if (!boundsAreValid(points, bounds)) {
return null;
}
const start = points[bounds.startIndex];
@@ -98,3 +96,19 @@ export const climbMetrics = (points: ProfilePoint[], bounds: ClimbBounds | undef
category: categoryForCotacol(cotacol),
};
};
+
+// climbSample returns the segment's recorded length and upward-only gain, as the server computes it for an official climb sample.
+export const climbSample = (points: ProfilePoint[], bounds: ClimbBounds | undefined): ClimbSample | null => {
+ if (!boundsAreValid(points, bounds)) {
+ return null;
+ }
+ const sample: ClimbSample = {
+ distanceM: (points[bounds.endIndex].distanceKm - points[bounds.startIndex].distanceKm) * 1000,
+ elevationGainM: 0,
+ };
+ for (let index = bounds.startIndex + 1; index <= bounds.endIndex; index++) {
+ const gain = points[index].elevationM - points[index - 1].elevationM;
+ if (gain > 0) sample.elevationGainM += gain;
+ }
+ return sample;
+};