Select Git revision
parameters.ts

Emmanuel Raviart authored
parameters.ts 7.91 KiB
import rootParameterUnknown from "@leximpact/socio-fiscal-openfisca-json/editable_processed_parameters.json"
import {
improveParameter,
ParameterClass,
scaleByInstantFromBrackets,
ScaleType,
Unit,
ValueType,
walkParameters,
type AmountBracketAtInstant,
type AmountUnit,
type BracketAtInstant,
type LinearAverageRateScaleParameter,
type MarginalAmountScaleParameter,
type MarginalRateScaleParameter,
type NodeParameter,
type Parameter,
type RateBracketAtInstant,
type RateUnit,
type Reference,
type ScaleAtInstant,
type ScaleParameter,
type SingleAmountScaleParameter,
type ValueAtInstant,
type ValueParameter,
} from "@openfisca/json-model"
import { metadata } from "$lib/metadata"
import { reformChangesByName } from "$lib/reforms"
export interface InstantReferencesAndScale {
instant: string
references: Reference[]
scaleAtInstant?: ScaleAtInstant
}
export interface InstantReferencesAndValue {
instant: string
references: Reference[]
valueAtInstant?: ValueAtInstant
}
improveParameter(null, rootParameterUnknown as NodeParameter)
export const rootParameter = rootParameterUnknown as NodeParameter
export const rootParameterByReformName: { [name: string]: NodeParameter } =
Object.fromEntries(
Object.entries(reformChangesByName).map(([reformName, reformChanges]) => {
const reformRootParameter = patchParameter(
rootParameter,
reformChanges.editable_processed_parameters,
)
improveParameter(null, reformRootParameter)
return [reformName, reformRootParameter]
}),
)
export const leafParametersName = new Set<string>()
for (const parameter of walkParameters(rootParameter)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
leafParametersName.add(parameter.name!)
}
export function asAmountBracketAtInstant(bracket: BracketAtInstant) {
return bracket as AmountBracketAtInstant
}
export function asAmountScaleParameter(parameter: ScaleParameter) {
return parameter as MarginalAmountScaleParameter | SingleAmountScaleParameter
}
export function asNodeParameter(parameter: Parameter): NodeParameter {
return parameter as NodeParameter
}
export function asRateBracketAtInstant(bracket: BracketAtInstant) {
return bracket as RateBracketAtInstant
}
export function asRateScaleParameter(parameter: ScaleParameter) {
return parameter as
| LinearAverageRateScaleParameter
| MarginalRateScaleParameter
}
export function asScaleParameter(
parameter: Parameter | undefined,
): ScaleParameter | undefined {
return parameter as ScaleParameter | undefined
}
export function asValueParameter(
parameter: Parameter | undefined,
): ValueParameter | undefined {
return parameter as ValueParameter | undefined
}
export function buildInstantReferencesAndScaleArray(
parameter: ScaleParameter,
): InstantReferencesAndScale[] {
const scaleByInstant = scaleByInstantFromBrackets(parameter.brackets ?? [])
const instantReferencesAndScaleByInstant: {
[instant: string]: InstantReferencesAndScale
} = Object.fromEntries(
Object.entries(scaleByInstant).map(([instant, scaleAtInstant]) => [
instant,
{ instant, references: [], scaleAtInstant },
]),
)
if (parameter.reference !== undefined) {
for (const [instant, references] of Object.entries(parameter.reference)) {
if (instantReferencesAndScaleByInstant[instant] === undefined) {
instantReferencesAndScaleByInstant[instant] = {
instant,
references,
}
} else {
instantReferencesAndScaleByInstant[instant].references = references
}
}
}
return Object.entries(instantReferencesAndScaleByInstant)
.sort(([instant1], [instant2]) => instant2.localeCompare(instant1))
.map(([, instantReferencesAndScale]) => instantReferencesAndScale)
}
export function buildInstantReferencesAndValueArray(
parameter: ValueParameter,
): InstantReferencesAndValue[] {
const instantReferencesAndValueByInstant: {
[instant: string]: InstantReferencesAndValue
} = Object.fromEntries(
Object.entries(parameter.values ?? {}).map(([instant, valueAtInstant]) => [
instant,
{ instant, references: [], valueAtInstant },
]),
)
if (parameter.reference !== undefined) {
for (const [instant, references] of Object.entries(parameter.reference)) {
if (instantReferencesAndValueByInstant[instant] === undefined) {
instantReferencesAndValueByInstant[instant] = {
instant,
references,
}
} else {
instantReferencesAndValueByInstant[instant].references = references
}
}
}
return Object.entries(instantReferencesAndValueByInstant)
.sort(([instant1], [instant2]) => instant2.localeCompare(instant1))
.map(([, instantReferencesAndValue]) => instantReferencesAndValue)
}
export function getParameter(
rootParameter: Parameter,
name: string,
): Parameter | undefined {
let parameter = rootParameter
for (const id of name.split(".")) {
const children =
parameter.class === ParameterClass.Node ? parameter.children : undefined
if (children === undefined) {
return undefined
}
parameter = children[id]
if (parameter === undefined) {
return undefined
}
}
return parameter
}
export function labelFromParameterClass(
parameterClass: ParameterClass | string,
): string {
return (
{
[ParameterClass.Node]: "Nœud",
[ParameterClass.Scale]: "Barème",
[ParameterClass.Value]: "Valeur",
}[parameterClass] ?? parameterClass
)
}
export function labelFromScaleType(type: ScaleType | string): string {
return (
{
[ScaleType.LinearAverageRate]: "à taux moyen linéaire",
[ScaleType.MarginalAmount]: "à montant marginal",
[ScaleType.MarginalRate]: "à taux marginal",
[ScaleType.SingleAmount]: "à montant unique",
}[type] ?? type
)
}
export function labelFromUnit(
unit: AmountUnit | RateUnit | Unit | string | null | undefined,
): string {
if (unit == null) {
return undefined
}
return (
{
[Unit.CodesDepartements]: "code département",
[Unit.CountryCode]: "code pays",
[Unit.Currency]: metadata.currency,
[Unit.CurrencyEUR]: "€",
[Unit.CurrencyFRF]: "FRF",
[Unit.CurrencyGBP]: "£",
[Unit.CurrencyUSD]: "$",
[Unit.Day]: "jour",
[Unit.Month]: "mois",
[Unit.Rate]: "%", // Number between 0 and 1
[Unit.Year]: "année",
}[unit] ?? unit
)
}
export function labelFromValueType(type: ValueType | string): string {
return (
{
[ValueType.Boolean]: "booléen",
[ValueType.Number]: "nombre",
[ValueType.StringArray]: "tableau de chaînes de caractères",
[ValueType.StringByString]: "dictionnaire de chaines de caractères",
}[type] ?? type
)
}
function patchParameter<ParameterType extends Parameter>(
parameter: ParameterType,
patch: { [key: string]: unknown },
): ParameterType {
if (Object.keys(patch).length === 0) {
return parameter
}
const patchedParameter = { ...parameter }
for (const [key, value] of Object.entries(patch)) {
if (value === null) {
delete patchedParameter[key]
} else if (patchedParameter[key] === undefined) {
patchedParameter[key] = value
} else if (key === "children") {
const patchedChildren = ((patchedParameter as NodeParameter).children = {
...(patchedParameter as NodeParameter).children,
})
for (const [childId, childPatch] of Object.entries(
value as { [childId: string]: unknown },
)) {
if (childPatch === null) {
delete patchedChildren[childId]
} else if (patchedChildren[childId] === undefined) {
patchedChildren[childId] = childPatch as Parameter
} else {
patchedChildren[childId] = patchParameter(
patchedChildren[childId],
childPatch as { [key: string]: unknown },
)
}
}
} else {
patchedParameter[key] = value
}
}
return patchedParameter
}