diff options
Diffstat (limited to 'web/frontend/official-climb-profile.ts')
| -rw-r--r-- | web/frontend/official-climb-profile.ts | 53 |
1 files changed, 35 insertions, 18 deletions
diff --git a/web/frontend/official-climb-profile.ts b/web/frontend/official-climb-profile.ts index 7e93cc7..72bc8d2 100644 --- a/web/frontend/official-climb-profile.ts +++ b/web/frontend/official-climb-profile.ts @@ -1,13 +1,18 @@ -import { officialProfileSections } from "./official-climb-profile-logic.js"; -import type { OfficialProfileSection } from "./official-climb-profile-logic.js"; -import type { OfficialProfileColors, RideProfilePoint } from "./types.js"; +import type { + OfficialProfileColors, + OfficialProfileSection, + ProfileBand, + ProfileSectionPayload, + RideProfile, + RideProfileClimb, +} from "./types.js"; export class OfficialClimbProfileController { - readonly points: RideProfilePoint[]; + readonly climbs: RideProfileClimb[]; readonly colors: OfficialProfileColors; readonly cards: HTMLDetailsElement[]; - constructor(points: RideProfilePoint[]) { - this.points = points; + constructor(profile: RideProfile) { + this.climbs = profile.climbs; this.colors = this.resolveColors(); this.cards = [...document.querySelectorAll("[data-official-climb-card]")].map((card) => card as HTMLDetailsElement); for (const card of this.cards) { @@ -24,18 +29,10 @@ export class OfficialClimbProfileController { } drawOfficialProfile(profileCanvas: HTMLCanvasElement): void { - const { points } = this; - const startIndex = Number.parseInt(profileCanvas.dataset.profileStart ?? "", 10); - const endIndex = Number.parseInt(profileCanvas.dataset.profileEnd ?? "", 10); - if ( - !Number.isInteger(startIndex) || - !Number.isInteger(endIndex) || - startIndex < 0 || - endIndex >= points.length || - startIndex >= endIndex - ) - return; - const sections = officialProfileSections(points, startIndex, endIndex); + const climbIndex = Number.parseInt(profileCanvas.dataset.profileClimbIndex ?? "", 10); + const climb = this.climbs.find((candidate) => candidate.index === climbIndex); + if (!climb?.sections) return; + const sections = officialProfileSections(climb.sections); if (sections.length === 0) return; drawOfficialSections(profileCanvas, sections, this.colors); } @@ -76,6 +73,26 @@ export function resolveOfficialProfileColors(): OfficialProfileColors { return colors; } +const profileBandForSlope = (slopePercent: number): ProfileBand => { + if (slopePercent <= 0) return "downhill"; + if (slopePercent < 3) return "0-3"; + if (slopePercent < 6) return "3-6"; + if (slopePercent < 9) return "6-9"; + return "9-plus"; +}; + +// officialProfileSections turns the sections the server cut out of the trace into the chart shape, +// tagging each step with the band its slope falls in. +export const officialProfileSections = (sections: ProfileSectionPayload[]): OfficialProfileSection[] => + sections.map((section) => ({ + startDistanceKm: section.startKm, + endDistanceKm: section.endKm, + startElevation: section.startElevationM, + endElevation: section.endElevationM, + slopePercent: section.slopePercent, + band: profileBandForSlope(section.slopePercent), + })); + export interface OfficialProfilePlot { left: number; right: number; |
