forked from OurHike/OurHike
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnaismith.ts
More file actions
38 lines (31 loc) · 1.42 KB
/
Copy pathnaismith.ts
File metadata and controls
38 lines (31 loc) · 1.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// Naismith's Rule time estimate. See WIREFRAMES.md's Load-bearing values:
// 5 km/h base pace + 1 hour per 600m of ascent, rounded to 5-minute steps,
// always prefixed ≈, never shown as an arrival clock, no descent credit (a
// known weakness of the rule - don't silently "improve" it by adding one).
//
// Deliberately no `descentFt` parameter at all - not just "ignored if
// passed" but structurally absent, so a future call site can't accidentally
// wire descent in without touching this function's signature first.
const KM_PER_HOUR = 5
const MILES_TO_KM = 1.609344
const FEET_TO_METERS = 0.3048
const MINUTES_PER_HOUR_OF_ASCENT = 60 // 1h per 600m
const METERS_PER_ASCENT_HOUR = 600
const ROUND_TO_MINUTES = 5
export interface NaismithInput {
distanceMi: number
ascentFt: number
}
export function naismithTime({ distanceMi, ascentFt }: NaismithInput): string {
const distanceKm = distanceMi * MILES_TO_KM
const ascentM = ascentFt * FEET_TO_METERS
const distanceMinutes = (distanceKm / KM_PER_HOUR) * 60
const ascentMinutes = (ascentM / METERS_PER_ASCENT_HOUR) * MINUTES_PER_HOUR_OF_ASCENT
const totalMinutes = distanceMinutes + ascentMinutes
const rounded = Math.round(totalMinutes / ROUND_TO_MINUTES) * ROUND_TO_MINUTES
const hours = Math.floor(rounded / 60)
const minutes = rounded % 60
if (hours === 0) return `≈${minutes}m`
if (minutes === 0) return `≈${hours}h`
return `≈${hours}h ${minutes}m`
}