Handle short workouts when calculating normalized intensity

This commit is contained in:
Rene Saarsoo 2020-10-04 13:13:52 +03:00
parent 77c6a721d4
commit adebc3d460
2 changed files with 84 additions and 4 deletions

View File

@ -0,0 +1,75 @@
import { Interval } from "../ast";
import { Duration } from "../Duration";
import { ConstantIntensity, RangeIntensity } from "../Intensity";
import { normalizedIntensity } from "./normalizedIntensity";
const round = (intensity: ConstantIntensity) => Math.round(intensity.value * 100) / 100;
describe("normalizedIntensity()", () => {
it("when no intervals, returns 0 for all zones", () => {
expect(round(normalizedIntensity([]))).toEqual(0);
});
it("returns plain average for < 30-seconds workout", () => {
expect(
round(
normalizedIntensity([
{
type: "Interval",
duration: new Duration(10),
intensity: new ConstantIntensity(0.5),
comments: [],
},
{
type: "Interval",
duration: new Duration(10),
intensity: new ConstantIntensity(0.7),
comments: [],
},
]),
),
).toEqual(0.6);
});
it("is the intensity of an interval for single-interval workout", () => {
const intervals: Interval[] = [
{
type: "Interval",
duration: new Duration(20 * 60),
intensity: new ConstantIntensity(0.75),
comments: [],
},
];
expect(round(normalizedIntensity(intervals))).toEqual(0.75);
});
it("leans towards higher intensity for two-interval workout", () => {
const intervals: Interval[] = [
{
type: "Interval",
duration: new Duration(10 * 60),
intensity: new ConstantIntensity(0.5),
comments: [],
},
{
type: "Interval",
duration: new Duration(10 * 60),
intensity: new ConstantIntensity(1.0),
comments: [],
},
];
expect(round(normalizedIntensity(intervals))).toEqual(0.85);
});
it("handles range-intensities", () => {
const intervals: Interval[] = [
{
type: "Warmup",
duration: new Duration(20 * 60),
intensity: new RangeIntensity(0.5, 1.0),
comments: [],
},
];
expect(round(normalizedIntensity(intervals))).toEqual(0.79);
});
});

View File

@ -7,11 +7,16 @@ import { intervalsToIntensityNumbers } from "./intervalsToIntensityNumbers";
// Starting at the beginning of the data, calculate 30-second rolling average
const windowSize = 30; // equals to nr of seconds, but also to nr of entries in intensities array
const rollingAverages = (intensities: number[]): number[] => {
if (intensities.length < windowSize) {
throw new Error(`Workout must be at least ${windowSize} seconds long`);
}
const averages: number[] = [];
let rollingSum: number = sum(intensities.slice(0, windowSize));
if (intensities.length === 0) {
return [0];
}
if (intensities.length < windowSize) {
return [rollingSum / intensities.length];
}
const averages: number[] = [];
averages.push(rollingSum / windowSize);
for (let i = 0; i < intensities.length - windowSize; i++) {
rollingSum -= intensities[i];