1
0
Fork 0
mirror of https://github.com/betagouv/mon-entreprise synced 2025-02-09 04:05:01 +00:00
mon-entreprise/source/engine/units.ts
Maxime Quandalle 7e2a4085a7 Poursuite de la migration TypeScript
* Utilisation de la version stable de TypeScript 3.7

* Début de migration du State Redux. Plutôt que de redéfinir les types
  en doublon par rapport aux actions et reducers, on utilise les valeurs
  retournées par ces fonctions comme source pour les types globaux.

* Modification de tsconfig pour meilleur typage dans VS Code

* Meilleur typage de l'environnement : suppression de @types/node qui
  était trop large (contient tout l'environnement serveur), et
  remplacement par @types/webpack-env. Par ailleurs typage des variables
  d'environnement utilisées.

* Début de migration de l'économie collaborative

* Migration de nombreux composants UI

* Mise à jour de dépendances pour récupérer un meilleur typage

* Ajout d'un hook pour configurer les simulateurs

* Suppression du higher-order component "withSitePaths", on utilise
  systématiquement le hook useContext.

L'essentiel de l'application est maintenant migré, reste le moteur !
2019-11-11 11:33:38 +01:00

116 lines
2.9 KiB
TypeScript

import { isEmpty, remove, unnest } from 'ramda'
import i18n from '../i18n'
type BaseUnit = string
export type Unit = {
numerators: Array<BaseUnit>
denominators: Array<BaseUnit>
}
//TODO this function does not handle complex units like passenger-kilometer/flight
export let parseUnit = (string: string): Unit => {
let [a, b = ''] = string.split('/'),
result = {
numerators: a !== '' ? [getUnitKey(a)] : [],
denominators: b !== '' ? [getUnitKey(b)] : []
}
return result
}
const translations = Object.entries(
i18n.getResourceBundle(i18n.language, 'units')
)
function getUnitKey(unit: string): string {
const key = translations
.find(([, trans]) => trans === unit)?.[0]
.replace(/_plural$/, '')
return key || unit
}
let printUnits = (units: Array<string>, count: number): string =>
units
.filter(unit => unit !== '%')
.map(unit => i18n.t(`units:${unit}`, { count }))
.join('-')
const plural = 2
export let serialiseUnit = (
rawUnit: Unit | null | string,
count: number = plural,
lng?: string
) => {
if (rawUnit === null || typeof rawUnit !== 'object') {
return typeof rawUnit === 'string'
? i18n.t(`units:${rawUnit}`, { count, lng })
: rawUnit
}
let unit = simplify(rawUnit),
{ numerators = [], denominators = [] } = unit
// the unit '%' is only displayed when it is the only unit
let merge = [...numerators, ...denominators]
if (merge.length === 1 && merge[0] === '%') return '%'
let n = !isEmpty(numerators)
let d = !isEmpty(denominators)
let string =
!n && !d
? ''
: n && !d
? printUnits(numerators, count)
: !n && d
? `/${printUnits(denominators, 1)}`
: `${printUnits(numerators, plural)} / ${printUnits(denominators, 1)}`
return string
}
type SupportedOperators = '*' | '/' | '+' | '-'
let noUnit = { numerators: [], denominators: [] }
export let inferUnit = (
operator: SupportedOperators,
rawUnits: Array<Unit>
): Unit => {
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
}
])
}
if (operator === '-' || operator === '+') {
return rawUnits.find(u => u)
}
return null
}
export let removeOnce = <T>(element: T) => (list: Array<T>): Array<T> => {
let index = list.indexOf(element)
if (index > -1) return remove<T>(index, 1)(list)
else return list
}
let simplify = (unit: Unit): 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
)