Created
May 28, 2023 23:39
-
-
Save well1791/bcfc94972575ac9a175acc45be7abf6b to your computer and use it in GitHub Desktop.
measures
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type * as t from './types.d' | |
const ONE_IN_TO_CM = 2.54 | |
const metricMap: t.UnitMap<t.MetricUnit> = { | |
mapList: ['km', 'hm', 'dam', 'm', 'dm', 'cm', 'mm'], | |
updater: { | |
inc: (a) => a * 10, | |
dec: (a) => a / 10, | |
} | |
} | |
const imperialMap: t.UnitMap<t.ImperialUnit> = { | |
mapList: ['mi', 1760, 'yd', 3, 'ft', 12, 'in'], | |
updater: { | |
inc: (a, b) => isNaN(Number(b)) ? a : a * Number(b), | |
dec: (a, b) => isNaN(Number(b)) ? a : a / Number(b), | |
} | |
} | |
const isMetric = (a: t.LengthUnit): a is t.MetricUnit => | |
metricMap.mapList.includes(a as t.MetricUnit) | |
const isImperial = (a: t.LengthUnit): a is t.MetricUnit => | |
imperialMap.mapList.includes(a as t.ImperialUnit) | |
const getUnitDist = <T extends t.LengthUnit> ( | |
unitMap: t.UnitMap<T>, | |
fromUnit: T, | |
toUnit: T, | |
): number => { | |
if (fromUnit === toUnit) | |
return 1 | |
const [fIndex, tIndex] = [fromUnit, toUnit].map((a) => unitMap.mapList.indexOf(a)) | |
const [start, end] = [Math.min, Math.max].map((fn) => fn(fIndex, tIndex) + 1) | |
const op = fIndex > tIndex ? unitMap.updater.dec : unitMap.updater.inc | |
return unitMap.mapList.slice(start, end).reduce<number>(op, 1) | |
} | |
const dunno = ( | |
[value, measure]: t.Length, | |
toMeasure: t.LengthUnit, | |
): t.Length => { | |
const conds: [() => number, () => boolean][] = [ | |
[ | |
() => value * getUnitDist<t.MetricUnit>( | |
metricMap, | |
measure as t.MetricUnit, | |
toMeasure as t.MetricUnit, | |
), | |
() => isMetric(measure) && isMetric(toMeasure), | |
], | |
[ | |
() => value * getUnitDist<t.ImperialUnit>( | |
imperialMap, | |
measure as t.ImperialUnit, | |
toMeasure as t.ImperialUnit, | |
), | |
() => isImperial(measure) && isImperial(toMeasure), | |
], | |
[ | |
() => value | |
* getUnitDist<t.ImperialUnit>(imperialMap, measure as t.ImperialUnit, 'in') | |
* getUnitDist<t.MetricUnit>(metricMap, 'cm', toMeasure as t.MetricUnit) | |
* ONE_IN_TO_CM, | |
() => isMetric(toMeasure) | |
], | |
[ | |
() => ( | |
value | |
* getUnitDist<t.MetricUnit>(metricMap, measure as t.MetricUnit, 'cm') | |
* getUnitDist<t.ImperialUnit>(imperialMap, 'in', toMeasure as t.ImperialUnit) | |
) / ONE_IN_TO_CM, | |
() => isImperial(toMeasure) | |
], | |
] | |
const [getResult] = conds.find(([, test]) => test()) || [() => value] | |
return [getResult(), toMeasure] | |
} | |
const test = (result: t.Length, expect: string) => { | |
const r = result.join('') | |
console.log(r === expect, ` -> received(${r}) === expected(${expect})`) | |
console.log('------------------------------') | |
} | |
test(dunno([2, 'km'], 'm'), '2000m') | |
test(dunno([2, 'mm'], 'm'), '0.002m') | |
test(dunno([1, 'yd'], 'in'), '36in') | |
test(dunno([3, 'in'], 'ft'), '0.25ft') | |
test(dunno([1, 'yd'], 'm'), '0.9144m') | |
test(dunno([2.54, 'cm'], 'in'), '1in') | |
test(dunno([91.44, 'mm'], 'in'), '3.6in') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export type MetricUnits = ['km', 'hm', 'dam', 'm', 'dm', 'cm', 'mm'] | |
export type ImperialUnits = ['mi', 'yd', 'ft', 'in'] | |
export type LengthUnits = MetricUnits | ImperialUnits | |
export type MetricUnit = MetricUnits[number] | |
export type ImperialUnit = ImperialUnits[number] | |
export type LengthUnit = ImperialUnit | MetricUnit | |
export type Length = [number, LengthUnit] | |
export type Operation<T> = (value: number, measureUnit: T) => number | |
export type UnitMap<T extends LengthUnit, P extends T | number = T | number> = { | |
mapList: P[] | |
updater: { inc: Operation<P>, dec: Operation<P>} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment