aboutsummaryrefslogtreecommitdiff
path: root/web/frontend/official-climb-profile-logic.test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'web/frontend/official-climb-profile-logic.test.ts')
-rw-r--r--web/frontend/official-climb-profile-logic.test.ts102
1 files changed, 0 insertions, 102 deletions
diff --git a/web/frontend/official-climb-profile-logic.test.ts b/web/frontend/official-climb-profile-logic.test.ts
deleted file mode 100644
index ca8dea2..0000000
--- a/web/frontend/official-climb-profile-logic.test.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-import test from "node:test";
-import assert from "node:assert/strict";
-import { officialProfileSections, profileBandForSlope } from "./official-climb-profile-logic.ts";
-import type { ProfilePoint } from "./types.js";
-
-test("assigns each slope to its color band", () => {
- assert.equal(profileBandForSlope(-0.1), "downhill");
- assert.equal(profileBandForSlope(0), "downhill");
- assert.equal(profileBandForSlope(0.1), "0-3");
- assert.equal(profileBandForSlope(2.9), "0-3");
- assert.equal(profileBandForSlope(3), "3-6");
- assert.equal(profileBandForSlope(6), "6-9");
- assert.equal(profileBandForSlope(9), "9-plus");
- assert.equal(profileBandForSlope(12), "9-plus");
-});
-
-// buildProfile lays out one recorded point every 50 m along the given [length in km, slope in %] stretches.
-const buildProfile = (stretches: [number, number][]): ProfilePoint[] => {
- const points: ProfilePoint[] = [{ distanceKm: 0, elevationM: 0 }];
- let distanceKm = 0;
- let elevationM = 0;
- for (const [lengthKm, slopePercent] of stretches) {
- const pointCount = Math.round(lengthKm * 20);
- for (let index = 1; index <= pointCount; index++) {
- const distanceStepKm = (lengthKm * index) / pointCount;
- points.push({ distanceKm: distanceKm + distanceStepKm, elevationM: elevationM + distanceStepKm * 1000 * (slopePercent / 100) });
- }
- distanceKm += lengthKm;
- elevationM += lengthKm * 1000 * (slopePercent / 100);
- }
- return points;
-};
-
-test("keeps a short steep ramp as its own section", () => {
- const points = buildProfile([
- [0.3, 4],
- [0.3, 12],
- [0.3, 4],
- ]);
- const sections = officialProfileSections(points, 0, points.length - 1);
-
- assert.equal(sections.length, 3);
- assert.ok(Math.abs(sections[1].slopePercent - 12) < 0.01);
- assert.equal(sections[1].band, "9-plus");
- assert.equal(Math.round((sections[1].endDistanceKm - sections[1].startDistanceKm) * 1000), 300);
- assert.ok(Math.abs(sections[0].slopePercent - 4) < 0.01);
- assert.ok(Math.abs(sections[2].slopePercent - 4) < 0.01);
-});
-
-test("collapses a constant slope into a single section", () => {
- const points = buildProfile([[5, 6]]);
- const sections = officialProfileSections(points, 0, points.length - 1);
-
- assert.equal(sections.length, 1);
- assert.ok(Math.abs(sections[0].slopePercent - 6) < 0.01);
- assert.equal(sections[0].startDistanceKm, 0);
- assert.equal(sections[0].endDistanceKm, 5);
-});
-
-test("reports a descending stretch as downhill", () => {
- const points = buildProfile([[2, -5]]);
- const sections = officialProfileSections(points, 0, points.length - 1);
-
- assert.equal(sections.length, 1);
- assert.equal(sections[0].band, "downhill");
-});
-
-test("keeps a noisy profile within the readable section budget", () => {
- const points: ProfilePoint[] = [];
- for (let index = 0; index <= 200; index++) {
- const distanceKm = index * 0.05;
- points.push({ distanceKm, elevationM: distanceKm * 1000 * 0.05 + Math.sin(index) * 4 });
- }
- const sections = officialProfileSections(points, 0, points.length - 1);
-
- assert.ok(sections.length > 10 && sections.length <= 24, `expected 10-24 sections, got ${sections.length}`);
- assert.equal(sections[0].startDistanceKm, 0);
- assert.equal(sections[sections.length - 1].endDistanceKm, 10);
-});
-
-test("reads a slice of a longer profile", () => {
- const points = buildProfile([
- [1, 20],
- [1, 8],
- [1, 20],
- ]);
- const startIndex = points.findIndex((point) => point.distanceKm >= 1);
- const endIndex = points.findIndex((point) => point.distanceKm >= 2);
- const sections = officialProfileSections(points, startIndex, endIndex);
-
- assert.equal(sections.length, 1);
- assert.equal(Math.round(sections[0].slopePercent), 8);
- assert.equal(sections[0].startDistanceKm, points[startIndex].distanceKm);
- assert.equal(sections[0].endDistanceKm, points[endIndex].distanceKm);
-});
-
-test("returns no section for an empty range", () => {
- const points = buildProfile([[1, 6]]);
-
- assert.deepEqual(officialProfileSections(points, 3, 3), []);
- assert.deepEqual(officialProfileSections(points, 0, points.length), []);
-});