commit b5ad7c6a08b2298e0e13beff4c48c0e7890ca366
parent c5af1776ef05a6ba2546f95ffac2c2628f7bb9f3
Author: Asher Morgan <59518073+ashermorgan@users.noreply.github.com>
Date: Mon, 24 Mar 2025 13:38:13 -0700
Round durations in Batch Calculator
Diffstat:
8 files changed, 48 insertions(+), 41 deletions(-)
diff --git a/src/utils/calculators.js b/src/utils/calculators.js
@@ -7,20 +7,21 @@ import { DISTANCE_UNITS, convertDistance, getDefaultDistanceUnit } from '@/utils
* Format a distance/time result as a key/value result
* @param {Object} result The distance/time result
* @param {String} defaultUnitSystem The default unit system (imperial or metric)
+ * @param {Boolean} preciseDurations Whether to return precise, unrounded, durations
* @returns {Object} The key/value result
*/
-export function formatDistTimeResult(result, defaultUnitSystem) {
+export function formatDistTimeResult(result, defaultUnitSystem, preciseDurations = true) {
// Calculate numerical pace
const pace = result.time / convertDistance(result.distanceValue, result.distanceUnit,
getDefaultDistanceUnit(defaultUnitSystem));
return {
// Convert distance to key string
- key: formatNumber(result.distanceValue, 0, 2, result.result === 'distance') + ' '
- + DISTANCE_UNITS[result.distanceUnit].symbol,
+ key: formatNumber(result.distanceValue, 0, 2, result.result === 'distance') + ' ' +
+ DISTANCE_UNITS[result.distanceUnit].symbol,
// Convert time to time string
- value: formatDuration(result.time, 3, 2, result.result === 'time'),
+ value: formatDuration(result.time, 3, preciseDurations ? 2 : 0, result.result === 'time'),
// Convert pace to pace string
pace: formatDuration(pace, 3, 0, true) + ' / '
@@ -39,9 +40,10 @@ export function formatDistTimeResult(result, defaultUnitSystem) {
* @param {Object} input The input pace
* @param {Object} target The pace target
* @param {String} defaultUnitSystem The default unit system (imperial or metric)
+ * @param {Boolean} preciseDurations Whether to return precise, unrounded, durations
* @returns {Object} The result
*/
-export function calculatePaceResults(input, target, defaultUnitSystem) {
+export function calculatePaceResults(input, target, defaultUnitSystem, preciseDurations = true) {
const result = {
distanceValue: target.distanceValue,
distanceUnit: target.distanceUnit,
@@ -69,7 +71,7 @@ export function calculatePaceResults(input, target, defaultUnitSystem) {
}
// Return result
- return formatDistTimeResult(result, defaultUnitSystem);
+ return formatDistTimeResult(result, defaultUnitSystem, preciseDurations);
}
/**
@@ -78,9 +80,12 @@ export function calculatePaceResults(input, target, defaultUnitSystem) {
* @param {Object} target The race target
* @param {Object} options The race prediction options
* @param {String} defaultUnitSystem The default unit system (imperial or metric)
+ * @param {Boolean} preciseDurations Whether to return precise, unrounded, durations
* @returns {Object} The result
*/
-export function calculateRaceResults(input, target, options, defaultUnitSystem) {
+export function calculateRaceResults(input, target, options, defaultUnitSystem,
+ preciseDurations = true) {
+
const result = {
distanceValue: target.distanceValue,
distanceUnit: target.distanceUnit,
@@ -112,7 +117,7 @@ export function calculateRaceResults(input, target, options, defaultUnitSystem)
}
// Return result
- return formatDistTimeResult(result, defaultUnitSystem);
+ return formatDistTimeResult(result, defaultUnitSystem, preciseDurations);
}
/**
@@ -136,9 +141,10 @@ export function calculateRaceStats(input) {
* @param {Object} input The input race
* @param {Object} target The workout target
* @param {Object} options The race prediction options
+ * @param {Boolean} preciseDurations Whether to return precise, unrounded, durations
* @returns {Object} The result
*/
-export function calculateWorkoutResults(input, target, options) {
+export function calculateWorkoutResults(input, target, options, preciseDurations = true) {
const d1 = convertDistance(input.distanceValue, input.distanceUnit, 'meters');
const t1 = input.time;
const d3 = convertDistance(target.splitValue, target.splitUnit, 'meters');
@@ -165,7 +171,7 @@ export function calculateWorkoutResults(input, target, options) {
// Calculate time
return {
key: key,
- value: formatDuration(t3, 3, 2, true),
+ value: formatDuration(t3, 3, preciseDurations ? 2 : 0, true),
pace: '', // Pace not used in workout calculator
result: 'value',
sort: t3,
diff --git a/src/views/BatchCalculator.vue b/src/views/BatchCalculator.vue
@@ -195,11 +195,12 @@ const advancedOptions = computed(() => {
*/
const calculateResult = computed(() => {
if (options.value.calculator === 'pace') {
- return (x,y) => calcUtils.calculatePaceResults(x, y, defaultUnitSystem.value);
+ return (x,y) => calcUtils.calculatePaceResults(x, y, defaultUnitSystem.value, false);
} else if (options.value.calculator === 'race') {
- return (x,y) => calcUtils.calculateRaceResults(x, y, raceOptions.value, defaultUnitSystem.value);
+ return (x,y) => calcUtils.calculateRaceResults(x, y, raceOptions.value, defaultUnitSystem.value,
+ false);
} else {
- return (x,y) => calcUtils.calculateWorkoutResults(x, y, workoutOptions.value);
+ return (x,y) => calcUtils.calculateWorkoutResults(x, y, workoutOptions.value, false);
}
});
</script>
diff --git a/src/views/PaceCalculator.vue b/src/views/PaceCalculator.vue
@@ -25,7 +25,7 @@
<h2>Equivalent Paces</h2>
<single-output-table class="output" :calculate-result="x =>
- calculatePaceResults(input, x, defaultUnitSystem)"
+ calculatePaceResults(input, x, defaultUnitSystem, true)"
:targets="targetSets[selectedTargetSet] ? targetSets[selectedTargetSet].targets : []"/>
</div>
</template>
diff --git a/src/views/RaceCalculator.vue b/src/views/RaceCalculator.vue
@@ -43,7 +43,7 @@
<h2>Equivalent Race Results</h2>
<single-output-table class="output" show-pace
- :calculate-result="x => calculateRaceResults(input, x, options, defaultUnitSystem)"
+ :calculate-result="x => calculateRaceResults(input, x, options, defaultUnitSystem, true)"
:targets="targetSets[selectedTargetSet] ? targetSets[selectedTargetSet].targets : []"/>
</div>
</template>
diff --git a/src/views/WorkoutCalculator.vue b/src/views/WorkoutCalculator.vue
@@ -26,7 +26,7 @@
<h2>Workout Splits</h2>
<single-output-table class="output"
- :calculate-result="x => calculateWorkoutResults(input, x, options)"
+ :calculate-result="x => calculateWorkoutResults(input, x, options, true)"
:targets="targetSets[selectedTargetSet] ? targetSets[selectedTargetSet].targets : []"/>
</div>
</template>
diff --git a/tests/e2e/batch-calculator.spec.js b/tests/e2e/batch-calculator.spec.js
@@ -33,10 +33,10 @@ test('Batch calculator', async ({ page }) => {
await expect(page.getByRole('row').nth(0).getByRole('cell').nth(2)).toHaveText('800 m @ 5 km');
await expect(page.getByRole('row').nth(0).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('10:30');
- await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:41.21');
+ await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:41');
await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50');
- await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('3:16.90');
+ await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('3:17');
await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row')).toHaveCount(16);
@@ -49,10 +49,10 @@ test('Batch calculator', async ({ page }) => {
await expect(page.getByRole('row').nth(0).getByRole('cell').nth(2)).toHaveText('800 m @ 5 km');
await expect(page.getByRole('row').nth(0).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('10:30');
- await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:40.78');
+ await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:41');
await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50');
- await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('3:16.51');
+ await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('3:17');
await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row')).toHaveCount(16);
@@ -66,11 +66,11 @@ test('Batch calculator', async ({ page }) => {
await expect(page.getByRole('row').nth(0).getByRole('cell').nth(28)).toHaveText('10:00');
await expect(page.getByRole('row').nth(0).getByRole('cell')).toHaveCount(31);
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('10:30');
- await expect(page.getByRole('row').nth(1).getByRole('cell').nth(6)).toHaveText('2:36.58');
+ await expect(page.getByRole('row').nth(1).getByRole('cell').nth(6)).toHaveText('2:37');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(28)).toHaveText('1.90 mi');
await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(31);
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50');
- await expect(page.getByRole('row').nth(15).getByRole('cell').nth(6)).toHaveText('3:11.38');
+ await expect(page.getByRole('row').nth(15).getByRole('cell').nth(6)).toHaveText('3:11');
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(28)).toHaveText('1.56 mi');
await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(31);
await expect(page.getByRole('row')).toHaveCount(16);
@@ -87,11 +87,11 @@ test('Batch calculator', async ({ page }) => {
await expect(page.getByRole('row').nth(0).getByRole('cell').nth(28)).toHaveText('10:00');
await expect(page.getByRole('row').nth(0).getByRole('cell')).toHaveCount(31);
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('10:30');
- await expect(page.getByRole('row').nth(1).getByRole('cell').nth(6)).toHaveText('2:36.58');
+ await expect(page.getByRole('row').nth(1).getByRole('cell').nth(6)).toHaveText('2:37');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(28)).toHaveText('3.07 km');
await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(31);
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50');
- await expect(page.getByRole('row').nth(15).getByRole('cell').nth(6)).toHaveText('3:11.38');
+ await expect(page.getByRole('row').nth(15).getByRole('cell').nth(6)).toHaveText('3:11');
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(28)).toHaveText('2.51 km');
await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(31);
await expect(page.getByRole('row')).toHaveCount(16);
@@ -104,10 +104,10 @@ test('Batch calculator', async ({ page }) => {
await expect(page.getByRole('row').nth(0).getByRole('cell').nth(2)).toHaveText('800 m');
await expect(page.getByRole('row').nth(0).getByRole('cell')).toHaveCount(17);
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('10:30');
- await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:14.60');
+ await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:15');
await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(17);
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50');
- await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('2:43.62');
+ await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('2:44');
await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(17);
await expect(page.getByRole('row')).toHaveCount(16);
@@ -120,10 +120,10 @@ test('Batch calculator', async ({ page }) => {
await expect(page.getByRole('row').nth(0).getByRole('cell').nth(2)).toHaveText('800 m');
await expect(page.getByRole('row').nth(0).getByRole('cell')).toHaveCount(17);
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('10:30');
- await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:11.72');
+ await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:12');
await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(17);
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50');
- await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('2:40.09');
+ await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('2:40');
await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(17);
await expect(page.getByRole('row')).toHaveCount(16);
@@ -135,10 +135,10 @@ test('Batch calculator', async ({ page }) => {
await expect(page.getByRole('row').nth(0).getByRole('cell').nth(2)).toHaveText('800 m');
await expect(page.getByRole('row').nth(0).getByRole('cell')).toHaveCount(17);
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('10:30');
- await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:11.72');
+ await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:12');
await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(17);
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50');
- await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('2:40.09');
+ await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('2:40');
await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(17);
await expect(page.getByRole('row')).toHaveCount(16);
@@ -149,11 +149,11 @@ test('Batch calculator', async ({ page }) => {
await expect(page.getByRole('row').nth(0).getByRole('cell').nth(28)).toHaveText('10:00');
await expect(page.getByRole('row').nth(0).getByRole('cell')).toHaveCount(31);
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('10:30');
- await expect(page.getByRole('row').nth(1).getByRole('cell').nth(6)).toHaveText('2:36.58');
+ await expect(page.getByRole('row').nth(1).getByRole('cell').nth(6)).toHaveText('2:37');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(28)).toHaveText('3.07 km');
await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(31);
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50');
- await expect(page.getByRole('row').nth(15).getByRole('cell').nth(6)).toHaveText('3:11.38');
+ await expect(page.getByRole('row').nth(15).getByRole('cell').nth(6)).toHaveText('3:11');
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(28)).toHaveText('2.51 km');
await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(31);
await expect(page.getByRole('row')).toHaveCount(16);
@@ -164,10 +164,10 @@ test('Batch calculator', async ({ page }) => {
await expect(page.getByRole('row').nth(0).getByRole('cell').nth(2)).toHaveText('800 m @ 5 km');
await expect(page.getByRole('row').nth(0).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('10:30');
- await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:40.78');
+ await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:41');
await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50');
- await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('3:16.51');
+ await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('3:17');
await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row')).toHaveCount(16);
});
diff --git a/tests/e2e/cross-calculator.spec.js b/tests/e2e/cross-calculator.spec.js
@@ -123,10 +123,10 @@ test('Cross-calculator', async ({ page }) => {
await expect(page.getByRole('row').nth(0).getByRole('cell').nth(2)).toHaveText('800 m');
await expect(page.getByRole('row').nth(0).getByRole('cell')).toHaveCount(17);
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('10:30');
- await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:24.04');
+ await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:24');
await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(17);
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50');
- await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('2:56.05');
+ await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('2:56');
await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(17);
await expect(page.getByRole('row')).toHaveCount(16);
@@ -136,10 +136,10 @@ test('Cross-calculator', async ({ page }) => {
await expect(page.getByRole('row').nth(0).getByRole('cell').nth(2)).toHaveText('800 m');
await expect(page.getByRole('row').nth(0).getByRole('cell')).toHaveCount(4);
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('10:30');
- await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:36.58');
+ await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:37');
await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(4);
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50');
- await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('3:11.38');
+ await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('3:11');
await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(4);
await expect(page.getByRole('row')).toHaveCount(16);
@@ -149,10 +149,10 @@ test('Cross-calculator', async ({ page }) => {
await expect(page.getByRole('row').nth(0).getByRole('cell').nth(2)).toHaveText('800 m @ 5 km');
await expect(page.getByRole('row').nth(0).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('10:30');
- await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:41.92');
+ await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:42');
await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50');
- await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('3:16.97');
+ await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('3:17');
await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row')).toHaveCount(16);
diff --git a/tests/unit/views/BatchCalculator.spec.js b/tests/unit/views/BatchCalculator.spec.js
@@ -412,7 +412,7 @@ test('should correctly calculate outputs', async () => {
const workoutTarget = { type: 'time', time: 3600, splitValue: 1, splitUnit: 'miles' };
const result = calculate(input, workoutTarget);
expect(result.key).to.equal('1 mi @ 1:00:00');
- expect(result.value).to.equal('5:53.07');
+ expect(result.value).to.equal('5:53');
expect(result.pace).to.equal('');
expect(result.sort).to.be.closeTo(353.07, 0.01);
expect(result.result).to.equal('value');