Add freeride to zone types
This commit is contained in:
parent
dcf851294d
commit
2be2c9254c
|
|
@ -6,4 +6,3 @@
|
|||
- Unsupported params: message duration & y-position
|
||||
- More restricted syntax for text (with quotes)
|
||||
- Support for tags
|
||||
- Include free-ride to zone types
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import { intensityValueToZoneType, ZoneType } from "./ZoneType";
|
||||
|
||||
export interface Intensity {
|
||||
readonly value: number;
|
||||
readonly start: number;
|
||||
readonly end: number;
|
||||
readonly zone: ZoneType;
|
||||
}
|
||||
|
||||
export class ConstantIntensity implements Intensity {
|
||||
|
|
@ -18,6 +21,10 @@ export class ConstantIntensity implements Intensity {
|
|||
get end() {
|
||||
return this._value;
|
||||
}
|
||||
|
||||
get zone() {
|
||||
return intensityValueToZoneType(this._value);
|
||||
}
|
||||
}
|
||||
|
||||
export class RangeIntensity implements Intensity {
|
||||
|
|
@ -34,6 +41,10 @@ export class RangeIntensity implements Intensity {
|
|||
get end() {
|
||||
return this._end;
|
||||
}
|
||||
|
||||
get zone() {
|
||||
return intensityValueToZoneType(this.value);
|
||||
}
|
||||
}
|
||||
|
||||
export class FreeIntensity implements Intensity {
|
||||
|
|
@ -48,4 +59,8 @@ export class FreeIntensity implements Intensity {
|
|||
get end() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
get zone() {
|
||||
return "free" as ZoneType;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
export type ZoneType = "Z1" | "Z2" | "Z3" | "Z4" | "Z5" | "Z6" | "free";
|
||||
|
||||
// Intensity ranges based on https://zwiftinsider.com/power-zone-colors/
|
||||
export const intensityValueToZoneType = (intensity: number): ZoneType => {
|
||||
if (intensity >= 1.18) {
|
||||
return "Z6";
|
||||
}
|
||||
if (intensity >= 1.05) {
|
||||
return "Z5";
|
||||
}
|
||||
if (intensity >= 0.9) {
|
||||
return "Z4";
|
||||
}
|
||||
if (intensity >= 0.75) {
|
||||
return "Z3";
|
||||
}
|
||||
if (intensity >= 0.6) {
|
||||
return "Z2";
|
||||
}
|
||||
return "Z1";
|
||||
};
|
||||
|
|
@ -7,9 +7,9 @@ export { parseCliOptions } from "./parseCliOptions";
|
|||
export { Workout, Interval, Comment } from "./ast";
|
||||
export { Duration } from "./Duration";
|
||||
export { Intensity, ConstantIntensity, RangeIntensity, FreeIntensity } from "./Intensity";
|
||||
export { ZoneType } from "./ZoneType";
|
||||
|
||||
// utils
|
||||
export { totalDuration } from "./stats/totalDuration";
|
||||
export { intensityToZoneIndex, ZoneIndex } from "./stats/zoneDistribution";
|
||||
export { maximumIntensity } from "./stats/maximumIntensity";
|
||||
export { chunkRangeIntervals } from "./utils/chunkRangeIntervals";
|
||||
|
|
|
|||
|
|
@ -1,50 +1,27 @@
|
|||
import { Interval } from "../ast";
|
||||
import { Duration } from "../Duration";
|
||||
import { Intensity } from "../Intensity";
|
||||
import { intensityValueToZoneType, ZoneType } from "../ZoneType";
|
||||
import { intervalsToIntensityNumbers } from "./intervalsToIntensityNumbers";
|
||||
|
||||
type NumericZoneDuration = { name: string; duration: number };
|
||||
type ZoneDuration = { name: string; duration: Duration };
|
||||
export type ZoneIndex = 0 | 1 | 2 | 3 | 4 | 5;
|
||||
|
||||
const emptyZones = (): NumericZoneDuration[] => [
|
||||
{ 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/
|
||||
const zoneIndex = (intensity: number): ZoneIndex => {
|
||||
if (intensity >= 1.18) {
|
||||
return 5;
|
||||
}
|
||||
if (intensity >= 1.05) {
|
||||
return 4;
|
||||
}
|
||||
if (intensity >= 0.9) {
|
||||
return 3;
|
||||
}
|
||||
if (intensity >= 0.75) {
|
||||
return 2;
|
||||
}
|
||||
if (intensity >= 0.6) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
// For external use (consumes Intensity interface instead of plain number)
|
||||
export const intensityToZoneIndex = (intensity: Intensity): ZoneIndex => zoneIndex(intensity.value);
|
||||
const emptyZones = (): Record<ZoneType, NumericZoneDuration> => ({
|
||||
Z1: { name: "Z1: Recovery", duration: 0 },
|
||||
Z2: { name: "Z2: Endurance", duration: 0 },
|
||||
Z3: { name: "Z3: Tempo", duration: 0 },
|
||||
Z4: { name: "Z4: Threshold", duration: 0 },
|
||||
Z5: { name: "Z5: VO2 Max", duration: 0 },
|
||||
Z6: { name: "Z6: Anaerobic", duration: 0 },
|
||||
free: { name: "Freeride", duration: 0 },
|
||||
});
|
||||
|
||||
export const zoneDistribution = (intervals: Interval[]): ZoneDuration[] => {
|
||||
const zones = emptyZones();
|
||||
|
||||
intervalsToIntensityNumbers(intervals).forEach((intensity) => {
|
||||
zones[zoneIndex(intensity)].duration++;
|
||||
zones[intensityValueToZoneType(intensity)].duration++;
|
||||
});
|
||||
|
||||
return zones.map(({ duration, ...rest }) => ({ duration: new Duration(duration), ...rest }));
|
||||
return Object.values(zones).map(({ duration, ...rest }) => ({ duration: new Duration(duration), ...rest }));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -254,6 +254,7 @@ Zone Distribution:
|
|||
1 min - Z4: Threshold
|
||||
3 min - Z5: VO2 Max
|
||||
0 min - Z6: Anaerobic
|
||||
0 min - Freeride
|
||||
"
|
||||
`;
|
||||
|
||||
|
|
@ -273,6 +274,7 @@ Zone Distribution:
|
|||
0 min - Z4: Threshold
|
||||
0 min - Z5: VO2 Max
|
||||
3 min - Z6: Anaerobic
|
||||
0 min - Freeride
|
||||
"
|
||||
`;
|
||||
|
||||
|
|
@ -292,6 +294,7 @@ Zone Distribution:
|
|||
0 min - Z4: Threshold
|
||||
3 min - Z5: VO2 Max
|
||||
2 min - Z6: Anaerobic
|
||||
0 min - Freeride
|
||||
"
|
||||
`;
|
||||
|
||||
|
|
@ -311,6 +314,7 @@ Zone Distribution:
|
|||
37 min - Z4: Threshold
|
||||
1 min - Z5: VO2 Max
|
||||
0 min - Z6: Anaerobic
|
||||
0 min - Freeride
|
||||
"
|
||||
`;
|
||||
|
||||
|
|
@ -330,5 +334,6 @@ Zone Distribution:
|
|||
24 min - Z4: Threshold
|
||||
0 min - Z5: VO2 Max
|
||||
0 min - Z6: Anaerobic
|
||||
0 min - Freeride
|
||||
"
|
||||
`;
|
||||
|
|
|
|||
Loading…
Reference in New Issue