2019-07-11 14:29:05 +00:00
|
|
|
import { remove, isEmpty, unnest } from 'ramda'
|
2019-06-05 15:54:52 +00:00
|
|
|
|
|
|
|
export let parseUnit = string => {
|
2019-06-11 10:03:45 +00:00
|
|
|
let [a, b = ''] = string.split('/'),
|
|
|
|
result = {
|
|
|
|
numerators: a !== '' ? [a] : [],
|
|
|
|
denominators: b !== '' ? [b] : []
|
|
|
|
}
|
|
|
|
return result
|
2019-06-05 15:54:52 +00:00
|
|
|
}
|
|
|
|
|
2019-07-11 14:29:05 +00:00
|
|
|
export let serialiseUnit = ({ numerators = [], denominators = [] }) => {
|
2019-06-05 15:54:52 +00:00
|
|
|
let n = !isEmpty(numerators)
|
|
|
|
let d = !isEmpty(denominators)
|
2019-07-09 14:50:35 +00:00
|
|
|
return !n && !d
|
|
|
|
? ''
|
|
|
|
: n && !d
|
2019-07-04 16:13:40 +00:00
|
|
|
? numerators.join('')
|
2019-06-05 15:54:52 +00:00
|
|
|
: !n && d
|
2019-07-04 16:13:40 +00:00
|
|
|
? `/${denominators.join('')}`
|
|
|
|
: `${numerators.join('')} / ${denominators.join('')}`
|
2019-06-05 15:54:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let noUnit = { numerators: [], denominators: [] }
|
2019-07-11 14:29:05 +00:00
|
|
|
export let inferUnit = (operator, rawUnits) => {
|
|
|
|
let units = rawUnits.map(u => u || noUnit)
|
|
|
|
if (operator === '*')
|
|
|
|
return simplify({
|
|
|
|
numerators: unnest(units.map(u => u.numerators)),
|
|
|
|
denominators: unnest(units.map(u => u.denominators))
|
|
|
|
})
|
|
|
|
if (operator === '/') {
|
|
|
|
if (units.length !== 2)
|
|
|
|
throw new Error('Infer units of a division with units.length !== 2)')
|
|
|
|
return inferUnit('*', [
|
|
|
|
units[0],
|
|
|
|
{
|
|
|
|
numerators: units[1].denominators,
|
|
|
|
denominators: units[1].numerators
|
|
|
|
}
|
|
|
|
])
|
|
|
|
}
|
2019-06-05 15:54:52 +00:00
|
|
|
|
2019-07-11 14:29:05 +00:00
|
|
|
if (operator === '-' || operator === '+') {
|
|
|
|
return rawUnits.find(u => u)
|
|
|
|
}
|
|
|
|
|
|
|
|
return null
|
|
|
|
}
|
2019-06-05 15:54:52 +00:00
|
|
|
export let removeOnce = element => list => {
|
|
|
|
let index = list.indexOf(element)
|
|
|
|
if (index > -1) return remove(index, 1)(list)
|
|
|
|
else return list
|
|
|
|
}
|
|
|
|
|
|
|
|
let simplify = unit =>
|
|
|
|
[...unit.numerators, ...unit.denominators].reduce(
|
|
|
|
({ numerators, denominators }, next) =>
|
|
|
|
numerators.includes(next) && denominators.includes(next)
|
|
|
|
? {
|
|
|
|
numerators: removeOnce(next)(numerators),
|
|
|
|
denominators: removeOnce(next)(denominators)
|
|
|
|
}
|
|
|
|
: { numerators, denominators },
|
|
|
|
unit
|
|
|
|
)
|