Create generic zone-index detection helper
This commit is contained in:
parent
14930e748e
commit
423012024b
|
|
@ -2,33 +2,44 @@ import { Interval } from "../ast";
|
||||||
import { Duration } from "../Duration";
|
import { Duration } from "../Duration";
|
||||||
import { intervalsToIntensityNumbers } from "./intervalsToIntensityNumbers";
|
import { intervalsToIntensityNumbers } from "./intervalsToIntensityNumbers";
|
||||||
|
|
||||||
type Zone = {
|
type NumericZoneDuration = { name: string; duration: number };
|
||||||
from: number;
|
type ZoneDuration = { name: string; duration: Duration };
|
||||||
to: number;
|
type ZoneIndex = 0 | 1 | 2 | 3 | 4 | 5;
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type NumericZoneDuration = Zone & { duration: number };
|
const emptyZones = (): NumericZoneDuration[] => [
|
||||||
type ZoneDuration = Zone & { duration: Duration };
|
{ name: "Z1: Recovery", duration: 0 },
|
||||||
|
{ name: "Z2: Endurance", duration: 0 },
|
||||||
|
{ name: "Z3: Tempo", duration: 0 },
|
||||||
|
{ name: "Z4: Threshold", duration: 0 },
|
||||||
|
{ name: "Z5: VO2 Max", duration: 0 },
|
||||||
|
{ name: "Z6: Anaerobic", duration: 0 },
|
||||||
|
];
|
||||||
|
|
||||||
// Intensity ranges based on https://zwiftinsider.com/power-zone-colors/
|
// Intensity ranges based on https://zwiftinsider.com/power-zone-colors/
|
||||||
const emptyZones = (): NumericZoneDuration[] => [
|
const zoneIndex = (intensity: number): ZoneIndex => {
|
||||||
{ from: 0.0, to: 0.6, name: "Z1: Recovery", duration: 0 },
|
if (intensity >= 1.18) {
|
||||||
{ from: 0.6, to: 0.75, name: "Z2: Endurance", duration: 0 },
|
return 5;
|
||||||
{ from: 0.75, to: 0.9, name: "Z3: Tempo", duration: 0 },
|
}
|
||||||
{ from: 0.9, to: 1.05, name: "Z4: Threshold", duration: 0 },
|
if (intensity >= 1.05) {
|
||||||
{ from: 1.05, to: 1.18, name: "Z5: VO2 Max", duration: 0 },
|
return 4;
|
||||||
{ from: 1.18, to: Infinity, name: "Z6: Anaerobic", duration: 0 },
|
}
|
||||||
];
|
if (intensity >= 0.9) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if (intensity >= 0.75) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (intensity >= 0.6) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
export const zoneDistribution = (intervals: Interval[]): ZoneDuration[] => {
|
export const zoneDistribution = (intervals: Interval[]): ZoneDuration[] => {
|
||||||
const zones = emptyZones();
|
const zones = emptyZones();
|
||||||
|
|
||||||
intervalsToIntensityNumbers(intervals).forEach((intensity) => {
|
intervalsToIntensityNumbers(intervals).forEach((intensity) => {
|
||||||
const zone = zones.find((zone) => intensity >= zone.from && intensity < zone.to);
|
zones[zoneIndex(intensity)].duration++;
|
||||||
if (zone) {
|
|
||||||
zone.duration++;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return zones.map(({ duration, ...rest }) => ({ duration: new Duration(duration), ...rest }));
|
return zones.map(({ duration, ...rest }) => ({ duration: new Duration(duration), ...rest }));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue