running-tools

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

BatchCalculator.vue (7190B)


      1 <template>
      2   <div class="calculator">
      3     <h2>Batch Input</h2>
      4     <div class="input">
      5       <pace-input v-model="batchOptions.input" aria-label="Input"/>
      6     </div>
      7 
      8     <h2>Batch Options</h2>
      9     <div class="input">
     10       <div>
     11         Increment:
     12         <time-input v-model="batchOptions.increment" label="Duration increment" :show-hours="false"/>
     13         &times;
     14         <integer-input v-model="batchOptions.rows" min="1" aria-label="Number of rows"/>
     15       </div>
     16       <div>
     17         Calculator:
     18         <select aria-label="Calculator" v-model="batchOptions.calculator">
     19           <option :value="calculators.Calculators.Pace">Pace Calculator</option>
     20           <option :value="calculators.Calculators.Race">Race Calculator</option>
     21           <option :value="calculators.Calculators.Workout">Workout Calculator</option>
     22         </select>
     23       </div>
     24     </div>
     25 
     26     <details>
     27       <summary>
     28         <h2>Advanced Options</h2>
     29       </summary>
     30       <advanced-options-input v-model:batch-options="batchOptions"
     31         v-model:globalOptions="globalOptions" v-model:options="calcOptions"
     32         v-model:targetSets="targetSets" :type="batchOptions.calculator"/>
     33     </details>
     34 
     35     <h2>Batch Results</h2>
     36     <double-output-table class="output" :calculate-result="calculateResult"
     37       :input-distance="inputDistance" :input-times="inputTimes" :label="batchColumnLabel"
     38       :targets="targetSets[calcOptions.selectedTargetSet] ?
     39       targetSets[calcOptions.selectedTargetSet].targets : []"/>
     40   </div>
     41 </template>
     42 
     43 <script setup lang="ts">
     44 import { computed } from 'vue';
     45 
     46 import * as calculators from '@/core/calculators';
     47 import type { BatchOptions, GlobalOptions, PaceOptions, RaceOptions, TargetResult,
     48   WorkoutOptions } from '@/core/calculators';
     49 import * as targetUtils from '@/core/targets';
     50 import { formatDistance } from '@/core/units';
     51 import type { Distance, DistanceTime } from '@/core/units';
     52 
     53 import AdvancedOptionsInput from '@/components/AdvancedOptionsInput.vue';
     54 import DoubleOutputTable from '@/components/DoubleOutputTable.vue';
     55 import IntegerInput from '@/components/IntegerInput.vue';
     56 import PaceInput from '@/components/PaceInput.vue';
     57 import TimeInput from '@/components/TimeInput.vue';
     58 
     59 import useStorage from '@/composables/useStorage';
     60 
     61 /*
     62  * The global options
     63  */
     64 const globalOptions = useStorage<GlobalOptions>('global-options', calculators.defaultGlobalOptions);
     65 
     66 /*
     67  * The batch calculator options
     68  */
     69 const batchOptions = useStorage<BatchOptions>('batch-calculator-options',
     70   calculators.defaultBatchOptions);
     71 
     72 /*
     73  * The options for each calculator
     74  */
     75 const paceOptions = useStorage<PaceOptions>('pace-calculator-options',
     76   calculators.defaultPaceOptions);
     77 const raceOptions = useStorage<RaceOptions>('race-calculator-options',
     78   calculators.defaultRaceOptions);
     79 const workoutOptions = useStorage<WorkoutOptions>('workout-calculator-options',
     80   calculators.defaultWorkoutOptions);
     81 
     82 /*
     83  * The target sets for each calculator
     84  */
     85 const paceTargetSets = useStorage<targetUtils.StandardTargetSets>('pace-calculator-target-sets',
     86   targetUtils.defaultPaceTargetSets);
     87 const raceTargetSets = useStorage<targetUtils.StandardTargetSets>('race-calculator-target-sets',
     88   targetUtils.defaultRaceTargetSets);
     89 const workoutTargetSets = useStorage<targetUtils.WorkoutTargetSets>(
     90   'workout-calculator-target-sets', targetUtils.defaultWorkoutTargetSets);
     91 
     92 /*
     93  * The input distance
     94  */
     95 const inputDistance = computed<Distance>(() => ({
     96   distanceValue: batchOptions.value.input.distanceValue,
     97   distanceUnit: batchOptions.value.input.distanceUnit,
     98 }));
     99 
    100 /*
    101  * The set of input times
    102  */
    103 const inputTimes = computed<Array<number>>(() => {
    104   const results = [];
    105   for (let i = 0; i < batchOptions.value.rows; i++) {
    106     results.push(batchOptions.value.input.time + batchOptions.value.increment * i);
    107   }
    108   return results;
    109 });
    110 
    111 /*
    112  * The target sets for the current calculator
    113  */
    114 const targetSets = computed<targetUtils.TargetSets>({
    115   get: () => {
    116     switch (batchOptions.value.calculator) {
    117       case (calculators.Calculators.Pace): {
    118         return paceTargetSets.value;
    119       }
    120       case (calculators.Calculators.Race): {
    121         return raceTargetSets.value;
    122       }
    123       default:
    124       case (calculators.Calculators.Workout): {
    125         return workoutTargetSets.value;
    126       }
    127     }
    128   },
    129   set: (newValue: targetUtils.TargetSets) => {
    130     switch (batchOptions.value.calculator) {
    131       case (calculators.Calculators.Pace): {
    132         paceTargetSets.value = newValue as targetUtils.StandardTargetSets;
    133         break;
    134       }
    135       case (calculators.Calculators.Race): {
    136         raceTargetSets.value = newValue as targetUtils.StandardTargetSets;
    137         break;
    138       }
    139       default:
    140       case (calculators.Calculators.Workout): {
    141         workoutTargetSets.value = newValue as targetUtils.WorkoutTargetSets;
    142         break;
    143       }
    144     }
    145   },
    146 });
    147 
    148 /*
    149  * The options for the current calculator
    150  */
    151 const calcOptions = computed<PaceOptions | RaceOptions | WorkoutOptions>({
    152   get: () => {
    153     switch (batchOptions.value.calculator) {
    154       case (calculators.Calculators.Pace): {
    155         return paceOptions.value;
    156       }
    157       case (calculators.Calculators.Race): {
    158         return raceOptions.value;
    159       }
    160       default:
    161       case (calculators.Calculators.Workout): {
    162         return workoutOptions.value;
    163       }
    164     }
    165   },
    166   set: (newValue: PaceOptions | RaceOptions | WorkoutOptions) => {
    167     switch(batchOptions.value.calculator) {
    168       case (calculators.Calculators.Pace): {
    169         paceOptions.value = newValue as PaceOptions;
    170         break;
    171       }
    172       case (calculators.Calculators.Race): {
    173         raceOptions.value = newValue as RaceOptions;
    174         break;
    175       }
    176       default:
    177       case (calculators.Calculators.Workout): {
    178         workoutOptions.value = newValue as WorkoutOptions;
    179         break;
    180       }
    181     }
    182   },
    183 });
    184 
    185 /*
    186  * The appropriate calculate_results function for the current calculator
    187  */
    188 const calculateResult = computed<(x: DistanceTime, y: targetUtils.Target) => TargetResult>(() => {
    189   switch(batchOptions.value.calculator) {
    190     case (calculators.Calculators.Pace): {
    191       return (x,y) => calculators.calculatePaceResults(x, y, globalOptions.value.defaultUnitSystem,
    192         false);
    193     }
    194     case (calculators.Calculators.Race): {
    195       return (x,y) => calculators.calculateRaceResults(x, y,
    196         globalOptions.value.racePredictionOptions, globalOptions.value.defaultUnitSystem, false);
    197     }
    198     default:
    199     case (calculators.Calculators.Workout): {
    200       return (x,y) => calculators.calculateWorkoutResults(x, y as targetUtils.WorkoutTarget,
    201         globalOptions.value.racePredictionOptions, workoutOptions.value.customTargetNames, false);
    202     }
    203   }
    204 });
    205 
    206 /*
    207  * The label to render for the batch column
    208  */
    209 const batchColumnLabel = computed<string>(() => {
    210   if (batchOptions.value.calculator == calculators.Calculators.Workout &&
    211     (calcOptions.value as WorkoutOptions).customTargetNames && batchOptions.value.label) {
    212     return batchOptions.value.label;
    213   } else {
    214     return formatDistance(batchOptions.value.input, false);
    215   }
    216 });
    217 </script>
    218 
    219 <style scoped>
    220 @import '@/assets/target-calculator.css';
    221 </style>