running-tools

A collection of tools for runners and their coaches
git clone https://git.ashermorgan.net/running-tools/
Log | Files | Refs | README

commit 99d557f36550851ffb46323fbb4b26d6fff8d9a5
parent 7edfe58ae307c4120d55f40b2105d319e12e42ee
Author: ashermorgan <59518073+ashermorgan@users.noreply.github.com>
Date:   Thu,  9 Sep 2021 21:13:27 -0700

Refactor units

Diffstat:
Msrc/components/TargetTable.vue | 13++++---------
Msrc/utils/units.js | 240++++++++++++++++++++++++++++---------------------------------------------------
Msrc/views/PaceCalculator.vue | 13+++++--------
Msrc/views/RaceCalculator.vue | 13+++++--------
Msrc/views/UnitCalculator.vue | 37+++++++++++++++++--------------------
Mtests/unit/utils/units.spec.js | 60++++++++++--------------------------------------------------
6 files changed, 127 insertions(+), 249 deletions(-)

diff --git a/src/components/TargetTable.vue b/src/components/TargetTable.vue @@ -19,7 +19,7 @@ <tr v-for="(item, index) in results" :key="index"> <td :class="item.result === 'distance' ? 'result' : ''"> {{ item.distanceValue.toFixed(2) }} - {{ distanceSymbols[item.distanceUnit] }} + {{ distanceUnits[item.distanceUnit].symbol }} </td> <td>in</td> @@ -63,7 +63,7 @@ :min="0" :digits="2"/> <select v-model="item.distanceUnit" aria-label="Distance Unit"> <option v-for="(value, key) in distanceUnits" :key="key" :value="key"> - {{ value }} + {{ value.name }} </option> </select> </td> @@ -154,14 +154,9 @@ export default { data() { return { /** - * The names of the distance units + * The distance units */ - distanceUnits: unitUtils.DISTANCE_UNIT_NAMES, - - /** - * The symbols of the distance units - */ - distanceSymbols: unitUtils.DISTANCE_UNIT_SYMBOLS, + distanceUnits: unitUtils.DISTANCE_UNITS, /** * The formatDuration method diff --git a/src/utils/units.js b/src/utils/units.js @@ -2,152 +2,94 @@ * The time units */ const TIME_UNITS = { - seconds: 'seconds', - minutes: 'minutes', - hours: 'hours', -}; - -/** - * The time unit names - */ -const TIME_UNIT_NAMES = { - seconds: 'Seconds', - minutes: 'Minutes', - hours: 'Hours', -}; - -/** - * The time unit symbols - */ -const TIME_UNIT_SYMBOLS = { - seconds: 's', - minutes: 'min', - hours: 'hr', -}; - -/** - * The value of each time unit in seconds - */ -const TIME_UNIT_VALUES = { - seconds: 1, - minutes: 1 * 60, - hours: 1 * 60 * 60, + seconds: { + name: 'Seconds', + symbol: 's', + value: 1, + }, + minutes: { + name: 'Minutes', + symbol: 'min', + value: 60, + }, + hours: { + name: 'Hours', + symbol: 'hr', + value: 3600, + }, }; /** * The distance units */ const DISTANCE_UNITS = { - meters: 'meters', - kilometers: 'kilometers', - yards: 'yards', - miles: 'miles', - marathons: 'marathons', -}; - -/** - * The distance unit names - */ -const DISTANCE_UNIT_NAMES = { - meters: 'Meters', - kilometers: 'Kilometers', - yards: 'Yards', - miles: 'Miles', - marathons: 'Marathons', -}; - -/** - * The distance unit symbols - */ -const DISTANCE_UNIT_SYMBOLS = { - meters: 'm', - kilometers: 'km', - yards: 'yd', - miles: 'mi', - marathons: 'marathons', -}; - -/** - * The value of each distance unit in meters - */ -const DISTANCE_UNIT_VALUES = { - meters: 1, - kilometers: 1000, - yards: 0.9144, - miles: 1609.3499, - marathons: 42195, + meters: { + name: 'Meters', + symbol: 'm', + value: 1, + }, + yards: { + name: 'Yards', + symbol: 'yd', + value: 0.9144, + }, + kilometers: { + name: 'Kilometers', + symbol: 'km', + value: 1000, + }, + miles: { + name: 'Miles', + symbol: 'mi', + value: 1609.3499, + }, + marathons: { + name: 'Marathons', + symbol: 'marathons', + value: 42195, + }, }; /** * The speed units */ const SPEED_UNITS = { - meters_per_second: 'meters_per_second', - kilometers_per_hour: 'kilometers_per_hour', - miles_per_hour: 'miles_per_hour', -}; - -/** - * The speed unit names - */ -const SPEED_UNIT_NAMES = { - meters_per_second: 'Meters per Second', - kilometers_per_hour: 'Kilometers per Hour', - miles_per_hour: 'Miles per Hour', -}; - -/** - * The speed unit symbols - */ -const SPEED_UNIT_SYMBOLS = { - meters_per_second: 'm/s', - kilometers_per_hour: 'kph', - miles_per_hour: 'mph', -}; - -/** - * The value of each speed unit in meters per second - */ -const SPEED_UNIT_VALUES = { - meters_per_second: 1, - kilometers_per_hour: DISTANCE_UNIT_VALUES.kilometers / TIME_UNIT_VALUES.hours, - miles_per_hour: DISTANCE_UNIT_VALUES.miles / TIME_UNIT_VALUES.hours, -}; - -/** - * The pace units - */ -const PACE_UNITS = { - seconds_per_meter: 'seconds_per_meter', - seconds_per_kilometer: 'seconds_per_kilometer', - seconds_per_mile: 'seconds_per_mile', -}; - -/** - * The pace unit names - */ -const PACE_UNIT_NAMES = { - seconds_per_meter: 'Seconds per Meter', - seconds_per_kilometer: 'Time per Kilometer', - seconds_per_mile: 'Time per Mile', -}; - -/** - * The pace unit symbols - */ -const PACE_UNIT_SYMBOLS = { - seconds_per_meter: 's/m', - seconds_er_kilometer: '/km', - seconds_per_mile: '/mi', + meters_per_second: { + name: 'Meters per Second', + symbol: 'm/s', + value: 1, + }, + kilometers_per_hour: { + name: 'Kilometers per Hour', + symbol: 'kph', + value: DISTANCE_UNITS.kilometers.value / TIME_UNITS.hours.value, + }, + miles_per_hour: { + name: 'Miles per Hour', + symbol: 'mph', + value: DISTANCE_UNITS.miles.value / TIME_UNITS.hours.value, + }, }; /** * The value of each pace unit in seconds per meter */ -const PACE_UNIT_VALUES = { - seconds_per_meter: 1, - seconds_per_kilometer: TIME_UNIT_VALUES.seconds / DISTANCE_UNIT_VALUES.kilometers, - seconds_per_mile: TIME_UNIT_VALUES.seconds / DISTANCE_UNIT_VALUES.miles, +const PACE_UNITS = { + seconds_per_meter: { + name: 'Seconds per Meter', + symbol: 's/m', + value: 1, + }, + seconds_per_kilometer: { + name: 'Time per Kilometer', + symbol: '/ km', + value: TIME_UNITS.seconds.value / DISTANCE_UNITS.kilometers.value, + }, + seconds_per_mile: { + name: 'Time per Mile', + symbol: '/ mi', + value: TIME_UNITS.seconds.value / DISTANCE_UNITS.miles.value, + }, }; /** @@ -157,8 +99,8 @@ const PACE_UNIT_VALUES = { * @param {String} outputUnit The unit of the output * @returns {Number} The output */ -function convertTime(inputValue, inputUnits, outputUnits) { - return (inputValue * TIME_UNIT_VALUES[inputUnits]) / TIME_UNIT_VALUES[outputUnits]; +function convertTime(inputValue, inputUnit, outputUnit) { + return (inputValue * TIME_UNITS[inputUnit].value) / TIME_UNITS[outputUnit].value; } /** @@ -168,8 +110,8 @@ function convertTime(inputValue, inputUnits, outputUnits) { * @param {String} outputUnit The unit of the output * @returns {Number} The output */ -function convertDistance(inputValue, inputUnits, outputUnits) { - return (inputValue * DISTANCE_UNIT_VALUES[inputUnits]) / DISTANCE_UNIT_VALUES[outputUnits]; +function convertDistance(inputValue, inputUnit, outputUnit) { + return (inputValue * DISTANCE_UNITS[inputUnit].value) / DISTANCE_UNITS[outputUnit].value; } /** @@ -179,8 +121,8 @@ function convertDistance(inputValue, inputUnits, outputUnits) { * @param {String} outputUnit The unit of the output * @returns {Number} The output */ -function convertSpeed(inputValue, inputUnits, outputUnits) { - return (inputValue * SPEED_UNIT_VALUES[inputUnits]) / SPEED_UNIT_VALUES[outputUnits]; +function convertSpeed(inputValue, inputUnit, outputUnit) { + return (inputValue * SPEED_UNITS[inputUnit].value) / SPEED_UNITS[outputUnit].value; } /** @@ -190,8 +132,8 @@ function convertSpeed(inputValue, inputUnits, outputUnits) { * @param {String} outputUnit The unit of the output * @returns {Number} The output */ -function convertPace(inputValue, inputUnits, outputUnits) { - return (inputValue * PACE_UNIT_VALUES[inputUnits]) / PACE_UNIT_VALUES[outputUnits]; +function convertPace(inputValue, inputUnit, outputUnit) { + return (inputValue * PACE_UNITS[inputUnit].value) / PACE_UNITS[outputUnit].value; } /** @@ -201,20 +143,20 @@ function convertPace(inputValue, inputUnits, outputUnits) { * @param {String} outputUnit The unit of the output * @returns {Number} The output */ -function convertSpeedPace(inputValue, inputUnits, outputUnits) { +function convertSpeedPace(inputValue, inputUnit, outputUnit) { // Calculate input speed let speed; - if (inputUnits in PACE_UNIT_VALUES) { - speed = 1 / (inputValue * PACE_UNIT_VALUES[inputUnits]); + if (inputUnit in PACE_UNITS) { + speed = 1 / (inputValue * PACE_UNITS[inputUnit].value); } else { - speed = inputValue * SPEED_UNIT_VALUES[inputUnits]; + speed = inputValue * SPEED_UNITS[inputUnit].value; } // Calculate output - if (outputUnits in PACE_UNIT_VALUES) { - return (1 / speed) / PACE_UNIT_VALUES[outputUnits]; + if (outputUnit in PACE_UNITS) { + return (1 / speed) / PACE_UNITS[outputUnit].value; } - return speed / SPEED_UNIT_VALUES[outputUnits]; + return speed / SPEED_UNITS[outputUnit].value; } /** @@ -279,16 +221,6 @@ export default { SPEED_UNITS, PACE_UNITS, - TIME_UNIT_NAMES, - DISTANCE_UNIT_NAMES, - SPEED_UNIT_NAMES, - PACE_UNIT_NAMES, - - TIME_UNIT_SYMBOLS, - DISTANCE_UNIT_SYMBOLS, - SPEED_UNIT_SYMBOLS, - PACE_UNIT_SYMBOLS, - convertTime, convertDistance, convertSpeed, diff --git a/src/views/PaceCalculator.vue b/src/views/PaceCalculator.vue @@ -6,7 +6,7 @@ :min="0" :digits="2"/> <select v-model="inputUnit" aria-label="distance unit"> <option v-for="(value, key) in distanceUnits" :key="key" :value="key"> - {{ value }} + {{ value.name }} </option> </select> in @@ -57,7 +57,7 @@ export default { /** * The names of the distance units */ - distanceUnits: unitUtils.DISTANCE_UNIT_NAMES, + distanceUnits: unitUtils.DISTANCE_UNITS, /** * The default output targets @@ -107,8 +107,7 @@ export default { * The input pace (in seconds per meter) */ pace() { - const distance = unitUtils.convertDistance(this.inputDistance, - this.inputUnit, unitUtils.DISTANCE_UNITS.meters); + const distance = unitUtils.convertDistance(this.inputDistance, this.inputUnit, 'meters'); return paceUtils.getPace(distance, this.inputTime); }, }, @@ -131,8 +130,7 @@ export default { // Add missing value to result if (target.result === 'time') { // Convert target distance into meters - const d2 = unitUtils.convertDistance(target.distanceValue, target.distanceUnit, - unitUtils.DISTANCE_UNITS.meters); + const d2 = unitUtils.convertDistance(target.distanceValue, target.distanceUnit, 'meters'); // Calculate time to travel distance at input pace const time = paceUtils.getTime(this.pace, d2); @@ -144,8 +142,7 @@ export default { let distance = paceUtils.getDistance(this.pace, target.time); // Convert output distance into miles - distance = unitUtils.convertDistance(distance, unitUtils.DISTANCE_UNITS.meters, - unitUtils.DISTANCE_UNITS.miles); + distance = unitUtils.convertDistance(distance, 'meters', 'miles'); // Update result result.distanceValue = distance; diff --git a/src/views/RaceCalculator.vue b/src/views/RaceCalculator.vue @@ -5,7 +5,7 @@ <decimal-input v-model="inputDistance" aria-label="Distance value" :min="0" :digits="2"/> <select v-model="inputUnit" aria-label="Distance unit"> <option v-for="(value, key) in distanceUnits" :key="key" :value="key"> - {{ value }} + {{ value.name }} </option> </select> in @@ -56,7 +56,7 @@ export default { /** * The names of the distance units */ - distanceUnits: unitUtils.DISTANCE_UNIT_NAMES, + distanceUnits: unitUtils.DISTANCE_UNITS, /** * The default output targets @@ -99,8 +99,7 @@ export default { */ predictTime(target) { // Convert input race distance into meters - const d1 = unitUtils.convertDistance(this.inputDistance, this.inputUnit, - unitUtils.DISTANCE_UNITS.meters); + const d1 = unitUtils.convertDistance(this.inputDistance, this.inputUnit, 'meters'); // Initialize result const result = { @@ -113,8 +112,7 @@ export default { // Add missing value to result if (target.result === 'time') { // Convert target distance into meters - const d2 = unitUtils.convertDistance(target.distanceValue, target.distanceUnit, - unitUtils.DISTANCE_UNITS.meters); + const d2 = unitUtils.convertDistance(target.distanceValue, target.distanceUnit, 'meters'); // Get prediction const time = raceUtils.AverageModel.predictTime(d1, this.inputTime, d2); @@ -126,8 +124,7 @@ export default { let distance = raceUtils.AverageModel.predictDistance(this.inputTime, d1, target.time); // Convert output distance into miles - distance = unitUtils.convertDistance(distance, unitUtils.DISTANCE_UNITS.meters, - unitUtils.DISTANCE_UNITS.miles); + distance = unitUtils.convertDistance(distance, 'meters', 'miles'); // Update result result.distanceValue = distance; diff --git a/src/views/UnitCalculator.vue b/src/views/UnitCalculator.vue @@ -12,8 +12,8 @@ v-model="inputValue" :min="0" :digits="2"/> <select v-model="inputUnit" class="input-units" aria-label="input units"> - <option v-for="(value, key) in unitNames" :key="key" :value="key"> - {{ value }} + <option v-for="(value, key) in units" :key="key" :value="key"> + {{ value.name }} </option> </select> @@ -27,8 +27,8 @@ </span> <select v-model="outputUnit" class="output-units" aria-label="output units"> - <option v-for="(value, key) in unitNames" :key="key" :value="key"> - {{ value }} + <option v-for="(value, key) in units" :key="key" :value="key"> + {{ value.name }} </option> </select> </div> @@ -81,16 +81,23 @@ export default { /** * The names of the units in the current category */ - unitNames() { + units() { switch (this.category) { case 'distance': { - return unitUtils.DISTANCE_UNIT_NAMES; + return unitUtils.DISTANCE_UNITS; } case 'time': { - return { ...unitUtils.TIME_UNIT_NAMES, 'hh:mm:ss': 'hh:mm:ss' }; + return { + ...unitUtils.TIME_UNITS, + 'hh:mm:ss': { + name: 'hh:mm:ss', + symbol: '', + value: null, + }, + }; } case 'speed_and_pace': { - return { ...unitUtils.PACE_UNIT_NAMES, ...unitUtils.SPEED_UNIT_NAMES }; + return { ...unitUtils.PACE_UNITS, ...unitUtils.SPEED_UNITS }; } default: { return {}; @@ -108,18 +115,8 @@ export default { } case 'time': { // Correct input and output units for 'hh:mm:ss' unit - let realInput; - if (this.inputUnit === 'hh:mm:ss') { - realInput = unitUtils.TIME_UNITS.seconds; - } else { - realInput = this.inputUnit; - } - let realOutput; - if (this.outputUnit === 'hh:mm:ss') { - realOutput = unitUtils.TIME_UNITS.seconds; - } else { - realOutput = this.outputUnit; - } + const realInput = this.inputUnit === 'hh:mm:ss' ? 'seconds' : this.inputUnit; + const realOutput = this.outputUnit === 'hh:mm:ss' ? 'seconds' : this.outputUnit; // Calculate conversion return unitUtils.convertTime(this.inputValue, realInput, realOutput); diff --git a/tests/unit/utils/units.spec.js b/tests/unit/utils/units.spec.js @@ -4,100 +4,60 @@ import units from '@/utils/units'; describe('utils/units.js', () => { describe('convertTime method', () => { it('90 seconds should equal 1.5 minutes', () => { - const result = units.convertTime( - 90, - units.TIME_UNITS.seconds, - units.TIME_UNITS.minutes, - ); + const result = units.convertTime(90, 'seconds', 'minutes'); expect(result).to.equal(1.5); }); it('1.5 minutes should equal 95 seconds', () => { - const result = units.convertTime( - 1.5, - units.TIME_UNITS.minutes, - units.TIME_UNITS.seconds, - ); + const result = units.convertTime(1.5, 'minutes', 'seconds'); expect(result).to.equal(90); }); }); describe('convertDistance method', () => { it('100 meters should equal 0.1 kilometers', () => { - const result = units.convertDistance( - 100, - units.DISTANCE_UNITS.meters, - units.DISTANCE_UNITS.kilometers, - ); + const result = units.convertDistance(100, 'meters', 'kilometers'); expect(result).to.equal(0.1); }); it('0.1 kilometers should equal 100 meters', () => { - const result = units.convertDistance( - 0.1, - units.DISTANCE_UNITS.kilometers, - units.DISTANCE_UNITS.meters, - ); + const result = units.convertDistance(0.1, 'kilometers', 'meters'); expect(result).to.equal(100); }); }); describe('convertSpeed method', () => { it('1000 meters per seconds should equal 3600 kilometers per hour', () => { - const result = units.convertSpeed( - 1000, - units.SPEED_UNITS.meters_per_second, - units.SPEED_UNITS.kilometers_per_hour, - ); + const result = units.convertSpeed(1000, 'meters_per_second', 'kilometers_per_hour'); expect(result).to.equal(3600); }); it('3600 kilometers per hour should equal 1000 meters per second', () => { - const result = units.convertSpeed( - 3600, - units.SPEED_UNITS.kilometers_per_hour, - units.SPEED_UNITS.meters_per_second, - ); + const result = units.convertSpeed(3600, 'kilometers_per_hour', 'meters_per_second'); expect(result).to.equal(1000); }); }); describe('convertPace method', () => { it('1 second per meter should equal 1000 seconds per kilometer', () => { - const result = units.convertPace( - 1, - units.PACE_UNITS.seconds_per_meter, - units.PACE_UNITS.seconds_per_kilometer, - ); + const result = units.convertPace(1, 'seconds_per_meter', 'seconds_per_kilometer'); expect(result).to.equal(1000); }); it('1000 seconds per kilometer should equal 1 second per meter', () => { - const result = units.convertPace( - 1000, - units.PACE_UNITS.seconds_per_kilometer, - units.PACE_UNITS.seconds_per_meter, - ); + const result = units.convertPace(1000, 'seconds_per_kilometer', 'seconds_per_meter'); expect(result).to.equal(1); }); }); describe('convertSpeedPace method', () => { it('3600 kilometers per hour should equal 1 second per kilometer', () => { - const result = units.convertSpeedPace( - 3600, - units.SPEED_UNITS.kilometers_per_hour, - units.PACE_UNITS.seconds_per_kilometer, - ); + const result = units.convertSpeedPace(3600, 'kilometers_per_hour', 'seconds_per_kilometer'); expect(result).to.equal(1); }); it('1 second per kilometer should equal 3600 kilometers per hour', () => { - const result = units.convertSpeedPace( - 3600, - units.PACE_UNITS.seconds_per_kilometer, - units.SPEED_UNITS.kilometers_per_hour, - ); + const result = units.convertSpeedPace(3600, 'seconds_per_kilometer', 'kilometers_per_hour'); expect(result).to.equal(1); }); });