commit a11031a0646507e537e4b021e003bcf7b169032c
parent 68c74edb81d3493afcf0ad2b435357c682a062a6
Author: Asher Morgan <59518073+ashermorgan@users.noreply.github.com>
Date: Sun, 29 Jun 2025 18:09:30 -0700
Miscellaneous cleanup after TypeScript migration
Update README.md, update comments, and replace formatTargetResult() with
calculateStandardResult() in calculator utils.
Diffstat:
11 files changed, 232 insertions(+), 289 deletions(-)
diff --git a/README.md b/README.md
@@ -34,9 +34,10 @@ Run development server
npm run dev
```
-Run linter and tests
+Run type checker, linter, unit tests, and end-to-end tests
```
+npm run type-check
npm run lint
npm run test:unit
npm run test:e2e
diff --git a/src/utils/calculators.ts b/src/utils/calculators.ts
@@ -7,18 +7,17 @@ import { DistanceUnits, DistanceUnitData, UnitSystems, convertDistance,
getDefaultDistanceUnit } from '@/utils/units';
import type { DistanceTime } from '@/utils/units';
+/*
+ * The two possible result fields of a target result: "key" and "value"
+ */
export enum ResultType {
Key = 'key',
Value = 'value',
};
-interface PreResult {
- distanceValue: number,
- distanceUnit: DistanceUnits,
- result: TargetTypes,
- time: number,
-};
-
+/*
+ * The type for target results
+ */
export interface TargetResult {
key: string,
value: string,
@@ -27,58 +26,94 @@ export interface TargetResult {
sort: number,
};
+/*
+ * The type for the options specific to the race calculator
+ */
export interface RaceOptions {
model: raceUtils.RacePredictionModel,
riegelExponent: number,
-}
+};
+/*
+ * The type for the available race statistics
+ */
export interface RaceStats {
purdyPoints: number,
vo2Max: number,
vo2: number,
vo2MaxPercentage: number,
-}
+};
+/*
+ * The type for the options specific to the workout calculator
+ */
export interface WorkoutOptions extends RaceOptions {
customTargetNames: boolean,
-}
+};
/**
- * Format a distance/time result as a key/value result
- * @param {PreResult} result The distance/time result
+ * Calculate results for a standard target
+ * @param {DistanceTime} input The input pace
+ * @param {StandardTarget} target The standard target
+ * @param {Function} calculateTime The function for calculating time results
+ * @param {Function} calculateDistance The function for calculating distance results
* @param {UnitSystems} defaultUnitSystem The default unit system (imperial or metric)
* @param {Boolean} preciseDurations Whether to return precise, unrounded, durations
- * @returns {TargetResult} The key/value result
+ * @returns {TargetResult} The result
*/
-export function formatTargetResult(result: PreResult, defaultUnitSystem: UnitSystems,
- preciseDurations: boolean = true): TargetResult {
+function calculateStandardResult(input: DistanceTime, target: StandardTarget,
+ calculateTime: (d1: number, t1: number, d2: number) => number,
+ calculateDistance: (t1: number, d1: number, t2: number) => number, defaultUnitSystem: UnitSystems,
+ preciseDurations: boolean = true): TargetResult {
+
+ let distanceValue, distanceUnit, time;
+ const d1 = convertDistance(input.distanceValue, input.distanceUnit, DistanceUnits.Meters);
+ if (target.type === TargetTypes.Distance) {
+ // Add target distance to result
+ distanceValue = target.distanceValue;
+ distanceUnit = target.distanceUnit;
+
+ // Calculate time result
+ const d2 = convertDistance(target.distanceValue, target.distanceUnit, DistanceUnits.Meters);
+ time = calculateTime(d1, input.time, d2);
+ } else {
+ // Add target time to result
+ time = target.time;
+
+ // Calculate distance result
+ const d2 = calculateDistance(input.time, d1, target.time);
+ const units = getDefaultDistanceUnit(defaultUnitSystem);
+ distanceValue = convertDistance(d2, DistanceUnits.Meters, units);
+ distanceUnit = units;
+ }
+
// Calculate numerical pace
- const pace = result.time / convertDistance(result.distanceValue, result.distanceUnit,
+ const pace = time / convertDistance(distanceValue, distanceUnit,
getDefaultDistanceUnit(defaultUnitSystem));
return {
// Convert distance to key string
- key: formatNumber(result.distanceValue, 0, 2, result.result === 'distance') + ' ' +
- DistanceUnitData[result.distanceUnit].symbol,
+ key: formatNumber(distanceValue, 0, 2, target.type === TargetTypes.Time) + ' ' +
+ DistanceUnitData[distanceUnit].symbol,
// Convert time to time string
- value: formatDuration(result.time, 3, preciseDurations ? 2 : 0, result.result === 'time'),
+ value: formatDuration(time, 3, preciseDurations ? 2 : 0, target.type === TargetTypes.Distance),
// Convert pace to pace string
pace: formatDuration(pace, 3, 0, true) + ' / '
+ DistanceUnitData[getDefaultDistanceUnit(defaultUnitSystem)].symbol,
// Convert dist/time result to key/value
- result: result.result === TargetTypes.Time ? ResultType.Value : ResultType.Key,
+ result: target.type === TargetTypes.Distance ? ResultType.Value : ResultType.Key,
// Use time (in seconds) as sort key
- sort: result.time,
+ sort: time,
};
}
/**
* Calculate paces from a target
- * @param {DistanceTime } input The input pace
+ * @param {DistanceTime} input The input pace
* @param {StandardTarget} target The pace target
* @param {UnitSystems} defaultUnitSystem The default unit system (imperial or metric)
* @param {Boolean} preciseDurations Whether to return precise, unrounded, durations
@@ -87,41 +122,9 @@ export function formatTargetResult(result: PreResult, defaultUnitSystem: UnitSys
export function calculatePaceResults(input: DistanceTime, target: StandardTarget,
defaultUnitSystem: UnitSystems,
preciseDurations: boolean = true): TargetResult {
- const result: PreResult = {
- distanceValue: 0,
- distanceUnit: DistanceUnits.Meters,
- time: 0,
- result: target.type === TargetTypes.Distance ? TargetTypes.Time : TargetTypes.Distance,
- };
- const d1 = convertDistance(input.distanceValue, input.distanceUnit, DistanceUnits.Meters);
-
- // Add missing value to result
- if (target.type === 'distance') {
- // Add target distance to result
- result.distanceValue = target.distanceValue;
- result.distanceUnit = target.distanceUnit;
-
- // Convert target distance into meters
- const d2 = convertDistance(target.distanceValue, target.distanceUnit, DistanceUnits.Meters);
-
- // Calculate time to travel distance at input pace
- result.time = paceUtils.calculateTime(d1, input.time, d2);
- } else {
- // Add target time to result
- result.time = target.time;
-
- // Calculate distance traveled in time at input pace
- const d2 = paceUtils.calculateDistance(input.time, d1, target.time);
-
- // Convert output distance into default distance unit
- const units = getDefaultDistanceUnit(defaultUnitSystem);
- result.distanceValue = convertDistance(d2, DistanceUnits.Meters, units);
- result.distanceUnit = units;
- }
-
- // Return result
- return formatTargetResult(result, defaultUnitSystem, preciseDurations);
+ return calculateStandardResult(input, target, (d1, t1, d2) => paceUtils.calculateTime(d1, t1, d2),
+ (t1, d1, t2) => paceUtils.calculateDistance(t1, d1, t2), defaultUnitSystem, preciseDurations);
}
/**
@@ -137,42 +140,10 @@ export function calculateRaceResults(input: DistanceTime, target: StandardTarget
options: RaceOptions, defaultUnitSystem: UnitSystems,
preciseDurations: boolean = true): TargetResult {
- const result: PreResult = {
- distanceValue: 0,
- distanceUnit: DistanceUnits.Meters,
- time: 0,
- result: target.type === TargetTypes.Distance ? TargetTypes.Time : TargetTypes.Distance,
- };
-
- const d1 = convertDistance(input.distanceValue, input.distanceUnit, DistanceUnits.Meters);
-
- // Add missing value to result
- if (target.type === 'distance') {
- // Add target distance to result
- result.distanceValue = target.distanceValue;
- result.distanceUnit = target.distanceUnit;
-
- // Convert target distance into meters
- const d2 = convertDistance(target.distanceValue, target.distanceUnit, DistanceUnits.Meters);
-
- // Get prediction
- result.time = raceUtils.predictTime(d1, input.time, d2, options.model, options.riegelExponent);
- } else {
- // Add target time to result
- result.time = target.time;
-
- // Get prediction
- const distance = raceUtils.predictDistance(input.time, d1, target.time, options.model,
- options.riegelExponent);
-
- // Convert output distance into default distance unit
- const units = getDefaultDistanceUnit(defaultUnitSystem);
- result.distanceValue = convertDistance(distance, DistanceUnits.Meters, units);
- result.distanceUnit = getDefaultDistanceUnit(defaultUnitSystem);
- }
-
- // Return result
- return formatTargetResult(result, defaultUnitSystem, preciseDurations);
+ return calculateStandardResult(input, target,
+ (d1, t1, d2) => raceUtils.predictTime(d1, t1, d2, options.model, options.riegelExponent),
+ (t1, d1, t2) => raceUtils.predictDistance(t1, d1, t2, options.model, options.riegelExponent),
+ defaultUnitSystem, preciseDurations);
}
/**
diff --git a/src/utils/races.ts b/src/utils/races.ts
@@ -1,10 +1,22 @@
+/*
+ * The available race prediction models
+ */
export enum RacePredictionModel {
AverageModel = 'AverageModel',
PurdyPointsModel = 'PurdyPointsModel',
VO2MaxModel = 'VO2MaxModel',
RiegelModel = 'RiegelModel',
CameronModel = 'CameronModel',
-}
+};
+
+/*
+ * The type for internal variables used by the Purdy Points race prediction model
+ */
+interface PurdyPointsVariables {
+ twsec: number,
+ a: number,
+ b: number,
+};
/**
* Estimate the point at which a function returns a target value using Newton's Method
@@ -39,15 +51,6 @@ function NewtonsMethod(initialEstimate: number, target: number, method: (x: numb
}
/*
- * The internal variables used by the Purdy Points race prediction model
- */
-interface PurdyPointsVariables {
- twsec: number,
- a: number,
- b: number,
-}
-
-/*
* Methods that implement the Purdy Points race prediction model
* https://www.cs.uml.edu/~phoffman/xcinfo3.html
*/
diff --git a/src/utils/targets.ts b/src/utils/targets.ts
@@ -2,98 +2,66 @@ import { formatDuration, formatNumber } from '@/utils/format';
import { DistanceUnits, DistanceUnitData, convertDistance } from '@/utils/units';
/*
- * Enumeration for the two basic types of targets: those defined by distance vs time
+ * The two basic types of targets: those defined by distance and those defined by time
*/
export enum TargetTypes {
Distance = 'distance',
Time = 'time',
};
-/**
- * Type for basic distance-defined targets
+/*
+ * The types for basic standard targets and target sets
*/
interface DistanceTarget {
type: TargetTypes.Distance,
distanceValue: number,
distanceUnit: DistanceUnits,
};
-
-/**
- * Type for basic time-defined targets
- */
interface TimeTarget {
type: TargetTypes.Time,
time: number,
};
-
-/**
- * Type for pace and race calculator targets
- */
export type StandardTarget = DistanceTarget | TimeTarget;
-
-/*
- * Type for pace and race calculator target sets
- */
export interface StandardTargetSet {
name: string,
targets: Array<StandardTarget>,
-}
-
-/*
- * Type for a collection of pace and race calculator target sets
- */
+};
export interface StandardTargetSets {
[key: string]: StandardTargetSet,
-}
+};
/*
- * Type for split calculator targets
+ * The types for split calculator targets and target sets
*/
export type SplitTarget = DistanceTarget & {
splitTime?: number
};
-
-/*
- * Type for split calculator target sets
- */
export interface SplitTargetSet {
name: string,
targets: Array<SplitTarget>,
-}
-
-/*
- * Type for a collection of split calculator target sets
- */
+};
export interface SplitTargetSets {
[key: string]: SplitTargetSet,
-}
+};
/*
- * Type for workout calculator targets
+ * The types for workout calculator targets and target sets
*/
export type WorkoutTarget = StandardTarget & {
splitValue: number,
splitUnit: DistanceUnits,
customName?: string,
};
-
-/*
- * Type for workout calculator target sets
- */
export interface WorkoutTargetSet {
name: string,
targets: Array<WorkoutTarget>,
-}
-
-/*
- * Type for a collection of workout calculator target sets
- */
+};
export interface WorkoutTargetSets {
[key: string]: WorkoutTargetSet,
-}
+};
/*
- * Enumeration for the three types of targets sets: standard (pace & race), split, and workout
+ * The three types of targets sets: standard (pace & race), split, and workout
*/
export enum TargetSetTypes {
Standard = 'standard',
@@ -102,18 +70,10 @@ export enum TargetSetTypes {
};
/*
- * Type for generic targets
+ * The types for generic targets and target sets
*/
export type Target = StandardTarget | SplitTarget | WorkoutTarget;
-
-/*
- * Type for generic target sets
- */
export type TargetSet = StandardTargetSet | SplitTargetSet | WorkoutTargetSet;
-
-/*
- * Type for generic collection of target sets
- */
export type TargetSets = StandardTargetSets | SplitTargetSets | WorkoutTargetSets;
/**
@@ -135,7 +95,7 @@ export function sort(targets: Array<Target>): Array<Target> {
/**
* Generate a string description of a workout target
* @param {WorkoutTarget} target The workout target
- * @return {String} The string description
+ * @return {string} The string description
*/
export function workoutTargetToString(target: WorkoutTarget): string {
let result = formatNumber(target.splitValue, 0, 2, false) + ' ' +
@@ -149,7 +109,7 @@ export function workoutTargetToString(target: WorkoutTarget): string {
return result;
}
-/**
+/*
* A set of common pace calculator targets
*/
const common_pace_targets: StandardTargetSet = {
@@ -192,7 +152,7 @@ const common_pace_targets: StandardTargetSet = {
]),
};
-/**
+/*
* A set of common race calculator targets
*/
const common_race_targets: StandardTargetSet = {
@@ -220,7 +180,7 @@ const common_race_targets: StandardTargetSet = {
};
-/**
+/*
* A set of targets for 5K mile splits
*/
const five_k_mile_splits: SplitTargetSet = {
@@ -232,7 +192,7 @@ const five_k_mile_splits: SplitTargetSet = {
],
};
-/**
+/*
* A set of common workout calculator targets
*/
const common_workout_targets: WorkoutTargetSet = {
@@ -257,7 +217,7 @@ const common_workout_targets: WorkoutTargetSet = {
],
};
-export const defaultTargetSets: TargetSets = {
+export const defaultTargetSets: { [key: string]: TargetSet } = {
'_pace_targets': common_pace_targets,
'_race_targets': common_race_targets,
'_split_targets': five_k_mile_splits,
diff --git a/src/utils/units.ts b/src/utils/units.ts
@@ -1,5 +1,5 @@
-/**
- * The data included for each unit
+/*
+ * The type for the data available for each unit
*/
export interface UnitData {
name: string,
@@ -7,14 +7,14 @@ export interface UnitData {
value: number,
};
-/**
- * The supported time units
+/*
+ * The available time units
*/
export enum TimeUnits {
Seconds = 'seconds',
Minutes = 'minutes',
Hours = 'hours',
-}
+};
export const TimeUnitData: { [key in TimeUnits]: UnitData } = {
[TimeUnits.Seconds]: {
name: 'Seconds',
@@ -33,8 +33,8 @@ export const TimeUnitData: { [key in TimeUnits]: UnitData } = {
},
};
-/**
- * The supported distance units
+/*
+ * The available distance units
*/
export enum DistanceUnits {
Meters = 'meters',
@@ -42,7 +42,7 @@ export enum DistanceUnits {
Kilometers = 'kilometers',
Miles = 'miles',
Marathons = 'marathons',
-}
+};
export const DistanceUnitData: { [key in DistanceUnits]: UnitData } = {
[DistanceUnits.Meters]: {
name: 'Meters',
@@ -71,14 +71,14 @@ export const DistanceUnitData: { [key in DistanceUnits]: UnitData } = {
},
};
-/**
- * The supported speed units
+/*
+ * The available speed units
*/
export enum SpeedUnits {
MetersPerSecond = 'meters_per_second',
KilometersPerHour = 'kilometers_per_hour',
MilesPerHour = 'miles_per_hour',
-}
+};
export const SpeedUnitData: { [key in SpeedUnits]: UnitData } = {
[SpeedUnits.MetersPerSecond]: {
name: 'Meters per Second',
@@ -97,14 +97,14 @@ export const SpeedUnitData: { [key in SpeedUnits]: UnitData } = {
},
};
-/**
- * The supported pace units
+/*
+ * The available pace units
*/
export enum PaceUnits {
SecondsPerMeter = 'seconds_per_meter',
TimePerKilometer = 'seconds_per_kilometer',
TimePerMile = 'seconds_per_mile',
-}
+};
export const PaceUnitData: { [key in PaceUnits]: UnitData } = {
[PaceUnits.SecondsPerMeter]: {
name: 'Seconds per Meter',
@@ -123,24 +123,33 @@ export const PaceUnitData: { [key in PaceUnits]: UnitData } = {
},
};
-/**
- * The supported speed and pace units
+/*
+ * The available speed and pace units
*/
export type SpeedPaceUnits = SpeedUnits | PaceUnits;
-export enum UnitSystems {
- Metric = 'metric',
- Imperial = 'imperial',
-};
-
+/*
+ * The type for a distance input
+ */
export interface Distance {
distanceValue: number,
distanceUnit: DistanceUnits,
-}
+};
+/*
+ * The type for a distance/time input pair
+ */
export interface DistanceTime extends Distance {
time: number,
-}
+};
+
+/*
+ * The available unit systems
+ */
+export enum UnitSystems {
+ Metric = 'metric',
+ Imperial = 'imperial',
+};
/**
* Convert between time units
diff --git a/src/views/BatchCalculator.vue b/src/views/BatchCalculator.vue
@@ -38,10 +38,10 @@
Target Set:
<target-set-selector v-model:selectedTargetSet="selectedTargetSet"
:set-type="options.calculator === BatchCompatableCalculators.Workout ?
- TargetSetTypes.Workout : TargetSetTypes.Standard" v-model:targetSets="targetSets"
+ targetUtils.TargetSetTypes.Workout : targetUtils.TargetSetTypes.Standard"
+ v-model:targetSets="targetSets" :default-unit-system="defaultUnitSystem"
:customWorkoutNames="options.calculator === BatchCompatableCalculators.Workout ?
- (advancedOptions as WorkoutOptions).customTargetNames : false"
- :default-unit-system="defaultUnitSystem"/>
+ (advancedOptions as WorkoutOptions).customTargetNames : false"/>
</div>
<div v-if="options.calculator === 'workout'">
Target Name Customization:
@@ -66,11 +66,9 @@
import { computed } from 'vue';
import * as calcUtils from '@/utils/calculators';
-import type { TargetResult, RaceOptions, WorkoutOptions } from '@/utils/calculators';
+import type { RaceOptions, TargetResult, WorkoutOptions } from '@/utils/calculators';
import { RacePredictionModel } from '@/utils/races';
-import { TargetSetTypes, defaultTargetSets } from '@/utils/targets';
-import type { Target, TargetSets, StandardTargetSet, StandardTargetSets, WorkoutTarget,
- WorkoutTargetSet, WorkoutTargetSets } from '@/utils/targets';
+import * as targetUtils from '@/utils/targets';
import { DistanceUnits, UnitSystems, detectDefaultUnitSystem } from '@/utils/units';
import type { Distance, DistanceTime } from '@/utils/units';
@@ -83,25 +81,25 @@ import TimeInput from '@/components/TimeInput.vue';
import useStorage from '@/composables/useStorage';
-/**
+/*
* The calculators that may be used from within the batch calculator
*/
enum BatchCompatableCalculators {
Pace = 'pace',
Race = 'race',
Workout = 'workout',
-}
+};
-/**
- * The batch calculator settings type
+/*
+ * The type for options specific to the batch calculator
*/
interface BatchCalculatorOptions {
calculator: BatchCompatableCalculators,
increment: number,
rows: number,
-}
+};
-/**
+/*
* The input pace
*/
const input = useStorage<DistanceTime>('batch-calculator-input', {
@@ -110,7 +108,7 @@ const input = useStorage<DistanceTime>('batch-calculator-input', {
time: 1200,
});
-/**
+/*
* The batch input options
*/
const options = useStorage<BatchCalculatorOptions>('batch-calculator-options', {
@@ -119,12 +117,12 @@ const options = useStorage<BatchCalculatorOptions>('batch-calculator-options', {
rows: 20,
});
-/**
+/*
* The default unit system
*/
const defaultUnitSystem = useStorage<UnitSystems>('default-unit-system', detectDefaultUnitSystem());
-/**
+/*
* The current selected target sets for each calculator
*/
const selectedPaceTargetSet = useStorage<string>('pace-calculator-target-set', '_pace_targets');
@@ -132,20 +130,20 @@ const selectedRaceTargetSet = useStorage<string>('race-calculator-target-set', '
const selectedWorkoutTargetSet = useStorage<string>('workout-calculator-target-set',
'_workout_targets');
-/**
+/*
* The target sets for each calculator
*/
-const paceTargetSets = useStorage<StandardTargetSets>('pace-calculator-target-sets', {
- _pace_targets: defaultTargetSets._pace_targets as StandardTargetSet
+const paceTargetSets = useStorage<targetUtils.StandardTargetSets>('pace-calculator-target-sets', {
+ _pace_targets: targetUtils.defaultTargetSets._pace_targets as targetUtils.StandardTargetSet
});
-const raceTargetSets = useStorage<StandardTargetSets>('race-calculator-target-sets', {
- _race_targets: defaultTargetSets._race_targets as StandardTargetSet
+const raceTargetSets = useStorage<targetUtils.StandardTargetSets>('race-calculator-target-sets', {
+ _race_targets: targetUtils.defaultTargetSets._race_targets as targetUtils.StandardTargetSet
});
-const workoutTargetSets = useStorage<WorkoutTargetSets>('workout-calculator-target-sets', {
- _workout_targets: defaultTargetSets._workout_targets as WorkoutTargetSet
+const workoutTargetSets = useStorage<targetUtils.WorkoutTargetSets>('workout-calculator-target-sets', {
+ _workout_targets: targetUtils.defaultTargetSets._workout_targets as targetUtils.WorkoutTargetSet
});
-/**
+/*
* The advanced options for each calculator
*/
const raceOptions = useStorage<RaceOptions>('race-calculator-options', {
@@ -158,7 +156,7 @@ const workoutOptions = useStorage<WorkoutOptions>('workout-calculator-options',
riegelExponent: 1.06,
});
-/**
+/*
* The input distance
*/
const inputDistance = computed<Distance>(() => ({
@@ -166,7 +164,7 @@ const inputDistance = computed<Distance>(() => ({
distanceUnit: input.value.distanceUnit,
}));
-/**
+/*
* The set of input times
*/
const inputTimes = computed<Array<number>>(() => {
@@ -177,7 +175,7 @@ const inputTimes = computed<Array<number>>(() => {
return results;
});
-/**
+/*
* The selected target set for the current calculator
*/
const selectedTargetSet = computed<string>({
@@ -214,10 +212,10 @@ const selectedTargetSet = computed<string>({
},
});
-/**
+/*
* The target sets for the current calculator
*/
-const targetSets = computed<TargetSets>({
+const targetSets = computed<targetUtils.TargetSets>({
get: () => {
switch (options.value.calculator) {
case (BatchCompatableCalculators.Pace): {
@@ -232,26 +230,26 @@ const targetSets = computed<TargetSets>({
}
}
},
- set: (newValue: TargetSets) => {
+ set: (newValue: targetUtils.TargetSets) => {
switch (options.value.calculator) {
case (BatchCompatableCalculators.Pace): {
- paceTargetSets.value = newValue as StandardTargetSets;
+ paceTargetSets.value = newValue as targetUtils.StandardTargetSets;
break;
}
case (BatchCompatableCalculators.Race): {
- raceTargetSets.value = newValue as StandardTargetSets;
+ raceTargetSets.value = newValue as targetUtils.StandardTargetSets;
break;
}
default:
case (BatchCompatableCalculators.Workout): {
- workoutTargetSets.value = newValue as WorkoutTargetSets;
+ workoutTargetSets.value = newValue as targetUtils.WorkoutTargetSets;
break;
}
}
},
});
-/**
+/*
* The advanced options for the current calculator
*/
const advancedOptions = computed<null | RaceOptions | WorkoutOptions>({
@@ -288,10 +286,10 @@ const advancedOptions = computed<null | RaceOptions | WorkoutOptions>({
},
});
-/**
+/*
* The appropriate calculate_results function for the current calculator
*/
-const calculateResult = computed<(x: DistanceTime, y: Target) => TargetResult>(() => {
+const calculateResult = computed<(x: DistanceTime, y: targetUtils.Target) => TargetResult>(() => {
switch(options.value.calculator) {
case (BatchCompatableCalculators.Pace): {
return (x,y) => calcUtils.calculatePaceResults(x, y, defaultUnitSystem.value, false);
@@ -302,8 +300,8 @@ const calculateResult = computed<(x: DistanceTime, y: Target) => TargetResult>((
}
default:
case (BatchCompatableCalculators.Workout): {
- return (x,y) => calcUtils.calculateWorkoutResults(x, y as WorkoutTarget, workoutOptions.value,
- false);
+ return (x,y) => calcUtils.calculateWorkoutResults(x, y as targetUtils.WorkoutTarget,
+ workoutOptions.value, false);
}
}
});
diff --git a/src/views/PaceCalculator.vue b/src/views/PaceCalculator.vue
@@ -43,7 +43,7 @@ import TargetSetSelector from '@/components/TargetSetSelector.vue';
import useStorage from '@/composables/useStorage';
-/**
+/*
* The input pace
*/
const input = useStorage<DistanceTime>('pace-calculator-input', {
@@ -52,17 +52,17 @@ const input = useStorage<DistanceTime>('pace-calculator-input', {
time: 1200,
});
-/**
+/*
* The default unit system
*/
const defaultUnitSystem = useStorage<UnitSystems>('default-unit-system', detectDefaultUnitSystem());
-/**
+/*
* The current selected target set
*/
const selectedTargetSet = useStorage<string>('pace-calculator-target-set', '_pace_targets');
-/**
+/*
* The target sets
*/
const targetSets = useStorage<StandardTargetSets>('pace-calculator-target-sets', {
diff --git a/src/views/RaceCalculator.vue b/src/views/RaceCalculator.vue
@@ -52,7 +52,7 @@
import { computed } from 'vue';
import { calculateRaceResults, calculateRaceStats } from '@/utils/calculators';
-import type { RaceOptions } from '@/utils/calculators';
+import type { RaceOptions, RaceStats } from '@/utils/calculators';
import { formatNumber } from '@/utils/format';
import { RacePredictionModel } from '@/utils/races';
import { defaultTargetSets } from '@/utils/targets';
@@ -67,7 +67,7 @@ import TargetSetSelector from '@/components/TargetSetSelector.vue';
import useStorage from '@/composables/useStorage';
-/**
+/*
* The input race
*/
const input = useStorage<DistanceTime>('race-calculator-input', {
@@ -76,12 +76,12 @@ const input = useStorage<DistanceTime>('race-calculator-input', {
time: 1200,
});
-/**
+/*
* The default unit system
*/
const defaultUnitSystem = useStorage<UnitSystems>('default-unit-system', detectDefaultUnitSystem());
-/**
+/*
* The race prediction options
*/
const options = useStorage<RaceOptions>('race-calculator-options', {
@@ -89,22 +89,22 @@ const options = useStorage<RaceOptions>('race-calculator-options', {
riegelExponent: 1.06,
});
-/**
+/*
* The current selected target set
*/
const selectedTargetSet = useStorage<string>('race-calculator-target-set', '_race_targets');
-/**
+/*
* The target sets
*/
const targetSets = useStorage<StandardTargetSets>('race-calculator-target-sets', {
_race_targets: defaultTargetSets._race_targets
});
-/**
+/*
* The statistics for the current input race
*/
-const raceStats = computed(() => calculateRaceStats(input.value));
+const raceStats = computed<RaceStats>(() => calculateRaceStats(input.value));
</script>
<style scoped>
diff --git a/src/views/SplitCalculator.vue b/src/views/SplitCalculator.vue
@@ -36,24 +36,24 @@ import TargetSetSelector from '@/components/TargetSetSelector.vue';
import useStorage from '@/composables/useStorage';
-/**
+/*
* The default unit system
*/
const defaultUnitSystem = useStorage<UnitSystems>('default-unit-system', detectDefaultUnitSystem());
-/**
+/*
* The current selected target set
*/
const selectedTargetSet = useStorage<string>('split-calculator-target-set', '_split_targets');
-/**
+/*
* The default output targets
*/
const targetSets = useStorage<SplitTargetSets>('split-calculator-target-sets', {
_split_targets: defaultTargetSets._split_targets as SplitTargetSet
});
-/**
+/*
* The active target set
*/
const targetSet = computed({
diff --git a/src/views/UnitCalculator.vue b/src/views/UnitCalculator.vue
@@ -38,26 +38,14 @@
import { computed, ref } from 'vue';
import { formatDuration, formatNumber } from '@/utils/format';
-import { DistanceUnits, DistanceUnitData, TimeUnits, TimeUnitData, PaceUnits, SpeedUnits, SpeedUnitData,
- PaceUnitData, convertDistance, convertTime, convertSpeedPace } from '@/utils/units';
-import type { SpeedPaceUnits, UnitData } from '@/utils/units';
+import * as unitUtils from '@/utils/units';
import DecimalInput from '@/components/DecimalInput.vue';
import TimeInput from '@/components/TimeInput.vue';
import useStorage from '@/composables/useStorage';
-/**
- * The supported time units: Hours, Minutes, Seconds, and 'hh:mm:ss'
- */
-type ExtendedTimeUnits = TimeUnits | 'hh:mm:ss';
-
-/**
- * All supported distance, time, speed, and pace units
- */
-type AllUnits = DistanceUnits | ExtendedTimeUnits | SpeedPaceUnits;
-
-/**
+/*
* The three categories of units
*/
enum UnitTypes {
@@ -66,14 +54,24 @@ enum UnitTypes {
SpeedPace = 'speed_and_pace',
}
-/**
+/*
+ * The supported time units: Hours, Minutes, Seconds, and 'hh:mm:ss'
+ */
+type ExtendedTimeUnits = unitUtils.TimeUnits | 'hh:mm:ss';
+
+/*
+ * The support units from all categories
+ */
+type AllUnits = unitUtils.DistanceUnits | ExtendedTimeUnits | unitUtils.SpeedPaceUnits;
+
+/*
* The type of the calculator inputs
*/
interface UnitCalculatorInputs {
[UnitTypes.Distance]: {
inputValue: number,
- inputUnit: DistanceUnits,
- outputUnit: DistanceUnits,
+ inputUnit: unitUtils.DistanceUnits,
+ outputUnit: unitUtils.DistanceUnits,
},
[UnitTypes.Time]: {
inputValue: number,
@@ -82,38 +80,38 @@ interface UnitCalculatorInputs {
},
[UnitTypes.SpeedPace]: {
inputValue: number,
- inputUnit: SpeedPaceUnits,
- outputUnit: SpeedPaceUnits,
+ inputUnit: unitUtils.SpeedPaceUnits,
+ outputUnit: unitUtils.SpeedPaceUnits,
},
};
-/**
+/*
* The calculator inputs
*/
const inputs = useStorage<UnitCalculatorInputs>('unit-calculator-inputs', {
[UnitTypes.Distance]: {
inputValue: 1,
- inputUnit: DistanceUnits.Miles,
- outputUnit: DistanceUnits.Kilometers,
+ inputUnit: unitUtils.DistanceUnits.Miles,
+ outputUnit: unitUtils.DistanceUnits.Kilometers,
},
[UnitTypes.Time]: {
inputValue: 1,
- inputUnit: TimeUnits.Seconds,
+ inputUnit: unitUtils.TimeUnits.Seconds,
outputUnit: 'hh:mm:ss',
},
[UnitTypes.SpeedPace]: {
inputValue: 600,
- inputUnit: PaceUnits.TimePerMile,
- outputUnit: SpeedUnits.MilesPerHour,
+ inputUnit: unitUtils.PaceUnits.TimePerMile,
+ outputUnit: unitUtils.SpeedUnits.MilesPerHour,
},
});
-/**
+/*
* The unit category
*/
const category = ref<UnitTypes>(UnitTypes.Distance);
-/**
+/*
* The inputs for the current category
*/
const input = computed<{ inputValue: number, inputUnit: AllUnits, outputUnit: AllUnits }>({
@@ -126,8 +124,8 @@ const input = computed<{ inputValue: number, inputUnit: AllUnits, outputUnit: Al
case UnitTypes.Distance: {
inputs.value[category.value] = {
inputValue: newValue.inputValue,
- inputUnit: newValue.inputUnit as DistanceUnits,
- outputUnit: newValue.outputUnit as DistanceUnits,
+ inputUnit: newValue.inputUnit as unitUtils.DistanceUnits,
+ outputUnit: newValue.outputUnit as unitUtils.DistanceUnits,
};
break;
}
@@ -142,27 +140,27 @@ const input = computed<{ inputValue: number, inputUnit: AllUnits, outputUnit: Al
case UnitTypes.SpeedPace: {
inputs.value[category.value] = {
inputValue: newValue.inputValue,
- inputUnit: newValue.inputUnit as SpeedPaceUnits,
- outputUnit: newValue.outputUnit as SpeedPaceUnits,
+ inputUnit: newValue.inputUnit as unitUtils.SpeedPaceUnits,
+ outputUnit: newValue.outputUnit as unitUtils.SpeedPaceUnits,
};
break;
}
}
- }
+ },
});
-/**
- * The names of the units in the current category
+/*
+ * The data for the units in the current category
*/
-const units = computed<{ [key in AllUnits]?: UnitData }>(() => {
+const units = computed<{ [key in AllUnits]?: unitUtils.UnitData }>(() => {
switch (category.value) {
default:
case UnitTypes.Distance: {
- return DistanceUnitData;
+ return unitUtils.DistanceUnitData;
}
case UnitTypes.Time: {
return {
- ...TimeUnitData,
+ ...unitUtils.TimeUnitData,
'hh:mm:ss': {
name: 'hh:mm:ss',
symbol: '',
@@ -171,20 +169,21 @@ const units = computed<{ [key in AllUnits]?: UnitData }>(() => {
};
}
case UnitTypes.SpeedPace: {
- return { ...PaceUnitData, ...SpeedUnitData };
+ return { ...unitUtils.PaceUnitData, ...unitUtils.SpeedUnitData };
}
}
});
-/**
+/*
* The output value
*/
const outputValue = computed<number>(() => {
switch (category.value) {
default:
case UnitTypes.Distance: {
- return convertDistance(input.value.inputValue, input.value.inputUnit as DistanceUnits,
- input.value.outputUnit as DistanceUnits);
+ return unitUtils.convertDistance(input.value.inputValue,
+ input.value.inputUnit as unitUtils.DistanceUnits,
+ input.value.outputUnit as unitUtils.DistanceUnits);
}
case UnitTypes.Time: {
// Correct input and output units for 'hh:mm:ss' unit
@@ -192,11 +191,13 @@ const outputValue = computed<number>(() => {
const realOutput = input.value.outputUnit === 'hh:mm:ss' ? 'seconds' : input.value.outputUnit;
// Calculate conversion
- return convertTime(input.value.inputValue, realInput as TimeUnits, realOutput as TimeUnits);
+ return unitUtils.convertTime(input.value.inputValue, realInput as unitUtils.TimeUnits,
+ realOutput as unitUtils.TimeUnits);
}
case UnitTypes.SpeedPace: {
- return convertSpeedPace(input.value.inputValue, input.value.inputUnit as SpeedPaceUnits,
- input.value.outputUnit as SpeedPaceUnits);
+ return unitUtils.convertSpeedPace(input.value.inputValue,
+ input.value.inputUnit as unitUtils.SpeedPaceUnits,
+ input.value.outputUnit as unitUtils.SpeedPaceUnits);
}
}
});
@@ -207,7 +208,7 @@ const outputValue = computed<number>(() => {
* @returns {boolean} Whether the unit should be represented as a time
*/
function isTimeUnit(unit: AllUnits): boolean {
- return unit in PaceUnitData || unit === 'hh:mm:ss';
+ return unit in unitUtils.PaceUnitData || unit === 'hh:mm:ss';
}
</script>
diff --git a/src/views/WorkoutCalculator.vue b/src/views/WorkoutCalculator.vue
@@ -55,7 +55,7 @@ import TargetSetSelector from '@/components/TargetSetSelector.vue';
import useStorage from '@/composables/useStorage';
-/**
+/*
* The input race
*/
const input = useStorage<DistanceTime>('workout-calculator-input', {
@@ -64,12 +64,12 @@ const input = useStorage<DistanceTime>('workout-calculator-input', {
time: 1200,
});
-/**
+/*
* The default unit system
*/
const defaultUnitSystem = useStorage<UnitSystems>('default-unit-system', detectDefaultUnitSystem());
-/**
+/*
* The race prediction options
*/
const options = useStorage<WorkoutOptions>('workout-calculator-options', {
@@ -78,12 +78,12 @@ const options = useStorage<WorkoutOptions>('workout-calculator-options', {
riegelExponent: 1.06,
});
-/**
+/*
* The current selected target set
*/
const selectedTargetSet = useStorage<string>('workout-calculator-target-set', '_workout_targets');
-/**
+/*
* The target sets
*/
const targetSets = useStorage<WorkoutTargetSets>('workout-calculator-target-sets', {