From 09e38cd615b5aec0223488a1def610550376e3ce Mon Sep 17 00:00:00 2001 From: Rene Saarsoo Date: Sun, 20 Sep 2020 13:56:55 +0300 Subject: [PATCH] Replace power% field with intensity fraction --- src/ast.ts | 2 +- src/parser.ts | 16 +++++++++------- src/tokenizer.ts | 16 +++++++++------- src/tss.ts | 16 +++++++--------- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/ast.ts b/src/ast.ts index 2288481..3df5a02 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -10,6 +10,6 @@ export type Workout = { export type Interval = { type: IntervalLabelTokenValue; duration: number; - power: { from: number; to: number }; + intensity: { from: number; to: number }; cadence?: number; }; diff --git a/src/parser.ts b/src/parser.ts index c51c720..63af0c0 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -58,11 +58,11 @@ const parseIntervalParams = (tokens: Token[]): [IntervalData, Token[]] => { } else if (token.type === "cadence") { data.cadence = token.value; tokens.shift(); - } else if (token.type === "power") { - data.power = { from: token.value, to: token.value }; + } else if (token.type === "intensity") { + data.intensity = { from: token.value, to: token.value }; tokens.shift(); - } else if (token.type === "power-range") { - data.power = { from: token.value[0], to: token.value[1] }; + } else if (token.type === "intensity-range") { + data.intensity = { from: token.value[0], to: token.value[1] }; tokens.shift(); } else { break; @@ -72,7 +72,7 @@ const parseIntervalParams = (tokens: Token[]): [IntervalData, Token[]] => { if (!("duration" in data)) { throw new Error("Duration not specified"); } - if (!("power" in data)) { + if (!("intensity" in data)) { throw new Error("Power not specified"); } @@ -85,11 +85,13 @@ const parseIntervals = (tokens: Token[]): Interval[] => { while (tokens[0]) { const token = tokens.shift() as Token; if (token.type === "label" && isIntervalLabelTokenValue(token.value)) { - const [{ duration, power, cadence }, rest] = parseIntervalParams(tokens); + const [{ duration, intensity, cadence }, rest] = parseIntervalParams( + tokens + ); intervals.push({ type: token.value, duration, - power, + intensity, cadence, }); tokens = rest; diff --git a/src/tokenizer.ts b/src/tokenizer.ts index 628fc65..d09828d 100644 --- a/src/tokenizer.ts +++ b/src/tokenizer.ts @@ -29,14 +29,14 @@ export type TextToken = { value: string; }; export type NumberToken = { - type: "power" | "cadence" | "duration"; + type: "intensity" | "cadence" | "duration"; value: number; }; -export type PowerRangeToken = { - type: "power-range"; +export type IntensityRangeToken = { + type: "intensity-range"; value: [number, number]; }; -export type Token = LabelToken | TextToken | NumberToken | PowerRangeToken; +export type Token = LabelToken | TextToken | NumberToken | IntensityRangeToken; const toInteger = (str: string): number => { return parseInt(str.replace(/[^0-9]/, ""), 10); @@ -47,6 +47,8 @@ const toSeconds = (str: string): number => { return seconds + minutes * 60 + (hours || 0) * 60 * 60; }; +const toFraction = (percentage: number): number => percentage / 100; + const tokenizeValueParam = (text: string): Token => { if (/^[0-9:]+$/.test(text)) { return { type: "duration", value: toSeconds(text) }; @@ -55,11 +57,11 @@ const tokenizeValueParam = (text: string): Token => { return { type: "cadence", value: toInteger(text) }; } if (/^[0-9]+%..[0-9]+%$/.test(text)) { - const [from, to] = text.split("..").map(toInteger); - return { type: "power-range", value: [from, to] }; + const [from, to] = text.split("..").map(toInteger).map(toFraction); + return { type: "intensity-range", value: [from, to] }; } if (/^[0-9]+%$/.test(text)) { - return { type: "power", value: toInteger(text) }; + return { type: "intensity", value: toFraction(toInteger(text)) }; } throw new Error(`Unrecognized parameter "${text}"`); }; diff --git a/src/tss.ts b/src/tss.ts index 2398e66..fc741e4 100644 --- a/src/tss.ts +++ b/src/tss.ts @@ -8,9 +8,7 @@ import { Interval } from "./ast"; // W - power in watts // IF - intensity factor (power / FTP) -const steadyTss = (duration: number, power: number): number => { - const intensity = power / 100; - +const steadyTss = (duration: number, intensity: number): number => { return ((duration * intensity * intensity) / 3600) * 100; }; @@ -18,17 +16,17 @@ const rangeTss = (duration: number, from: number, to: number): number => { let score = 0; const step = 1; for (let i = 0; i < duration; i += step) { - let power = from + (to - from) * (i / duration); - score += steadyTss(step, power); + let intensity = from + (to - from) * (i / duration); + score += steadyTss(step, intensity); } return score; }; -const intervalTss = ({ duration, power }: Interval): number => { - if (power.from === power.to) { - return steadyTss(duration, power.from); +const intervalTss = ({ duration, intensity }: Interval): number => { + if (intensity.from === intensity.to) { + return steadyTss(duration, intensity.from); } else { - return rangeTss(duration, power.from, power.to); + return rangeTss(duration, intensity.from, intensity.to); } };