Skip to content

Commit

Permalink
refactor!: redesign the package API and internal design
Browse files Browse the repository at this point in the history
  • Loading branch information
EmileRolley committed Nov 15, 2024
1 parent 50b6a36 commit 92131b3
Show file tree
Hide file tree
Showing 10 changed files with 2,177 additions and 110 deletions.
15 changes: 8 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,20 @@
"require": "./dist/publicodes-build/index.cjs",
"import": "./dist/publicodes-build/index.js"
},
"./data": {
"types": "./dist/src/data/index.d.ts",
"require": "./dist/src/data/index.cjs",
"import": "./dist/src/data/index.js"
"./personas": {
"types": "./dist/src/personas/index.d.ts",
"require": "./dist/src/personas/index.cjs",
"import": "./dist/src/personas/index.js"
}
},
"files": [
"dist",
"publicodes-build"
],
"scripts": {
"generate-alternatives": "node scripts/generate-alternatives.js",
"precompile": "node scripts/precompile.js",
"compile:rules": "publicodes compile src/rules",
"compile": "yarn run generate-alternatives && yarn compile:rules && tsup",
"compile": "yarn compile:rules && tsup",
"test": "yarn compile:rules && vitest run",
"doc": "yarn run build && cd online-doc && yarn run dev",
"doc:build": "yarn run build && cd online-doc && yarn run build"
Expand All @@ -53,7 +53,8 @@
"terser": "^5.36.0",
"tsup": "^8.3.5",
"typescript": "^5.6.3",
"vitest": "^2.1.1"
"vitest": "^2.1.1",
"yaml": "^2.6.0"
},
"publishConfig": {
"access": "public"
Expand Down
73 changes: 0 additions & 73 deletions scripts/compile-ui.js

This file was deleted.

57 changes: 32 additions & 25 deletions scripts/generate-alternatives.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,18 @@ export default function generateAlternatives(rules) {
return []
})

const alternatives = {}

for (const motorisation of motorisations) {
rules[`empreinte . ${motorisation}`] = {
alternatives[`empreinte . ${motorisation}`] = {
titre: `Ensemble des véhicules ${motorisation}`,
}
rules[`coûts . ${motorisation}`] = {
alternatives[`coûts . ${motorisation}`] = {
titre: `Ensemble des véhicules ${motorisation}`,
}
for (const gabarit of gabarits) {
const gabaritTitle =
rules[`voiture . gabarit . ${gabarit}`]?.titre ?? gabarit
alternatives[`voiture . gabarit . ${gabarit}`]?.titre ?? gabarit
const baseContexte = {
"voiture . gabarit": `'${gabarit}'`,
"voiture . motorisation": `'${motorisation}'`,
Expand All @@ -62,31 +64,33 @@ export default function generateAlternatives(rules) {
}

if (motorisation === "électrique") {
rules[`empreinte . ${motorisation} . ${gabarit}`] = {
alternatives[`empreinte . ${motorisation} . ${gabarit}`] = {
titre: `${gabaritTitle} ${motorisation}`,
unité: "kgCO2eq/an",
valeur: "empreinte . voiture",
contexte: baseContexte,
}
rules[`coûts . ${motorisation} . ${gabarit}`] = {
alternatives[`coûts . ${motorisation} . ${gabarit}`] = {
titre: `${gabaritTitle} ${motorisation}`,
unité: "€/an",
valeur: "coûts . voiture",
contexte: baseContexte,
}
} else {
rules[`empreinte . ${motorisation} . ${gabarit}`] = {
alternatives[`empreinte . ${motorisation} . ${gabarit}`] = {
titre: `Ensemble des ${gabaritTitle} ${motorisation}`,
}
rules[`coûts . ${motorisation} . ${gabarit}`] = {
alternatives[`coûts . ${motorisation} . ${gabarit}`] = {
titre: `Ensemble des ${gabaritTitle} ${motorisation}`,
}
for (const carburant of carburants) {
const carburantTitle =
rules[`voiture . thermique . carburant . ${carburant}`]?.titre ??
carburant
alternatives[`voiture . thermique . carburant . ${carburant}`]
?.titre ?? carburant

rules[`empreinte . ${motorisation} . ${gabarit} . ${carburant}`] = {
alternatives[
`empreinte . ${motorisation} . ${gabarit} . ${carburant}`
] = {
titre: `${gabaritTitle} ${motorisation} (${carburantTitle})`,
unité: "kgCO2eq/an",
valeur: "empreinte . voiture",
Expand All @@ -103,25 +107,28 @@ export default function generateAlternatives(rules) {
},
},
}
rules[`coûts . ${motorisation} . ${gabarit} . ${carburant}`] = {
titre: `${gabaritTitle} ${motorisation} (${carburantTitle})`,
unité: "€/an",
valeur: "coûts . voiture",
contexte: {
...baseContexte,
"voiture . thermique . carburant": `'${carburant}'`,
"voiture . thermique . consommation carburant": {
valeur: "voiture . thermique . consommation estimée",
contexte: {
"voiture . gabarit": `'${gabarit}'`,
"voiture . motorisation": `'${motorisation}'`,
"voiture . thermique . carburant": `'${carburant}'`,
alternatives[`coûts . ${motorisation} . ${gabarit} . ${carburant}`] =
{
titre: `${gabaritTitle} ${motorisation} (${carburantTitle})`,
unité: "€/an",
valeur: "coûts . voiture",
contexte: {
...baseContexte,
"voiture . thermique . carburant": `'${carburant}'`,
"voiture . thermique . consommation carburant": {
valeur: "voiture . thermique . consommation estimée",
contexte: {
"voiture . gabarit": `'${gabarit}'`,
"voiture . motorisation": `'${motorisation}'`,
"voiture . thermique . carburant": `'${carburant}'`,
},
},
},
},
}
}
}
}
}
}

return alternatives
}
52 changes: 52 additions & 0 deletions scripts/precompile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { writeFileSync } from "fs"
import { join, basename } from "path"
import { stringify } from "yaml"
import { getModelFromSource } from "@publicodes/tools/compilation"
import Engine from "publicodes"

import getPersonas from "./compile-personas.js"
import generateAlternatives from "./generate-alternatives.js"

const ROOT_PATH = new URL(".", import.meta.url).pathname
const SRC_FILES = join(ROOT_PATH, "../src/rules/")
const ALTERNATIVES_DEST_PATH = join(
ROOT_PATH,
"../src/rules/alternatives.publicodes",
)
const PERSONAS_DEST_PATH = join(ROOT_PATH, "../src/personas/personas.json")

const model = getModelFromSource(SRC_FILES)
const engine = check(model, "base")

const resolvedRules = Object.fromEntries(
Object.entries(engine.getParsedRules()).map(([dottedName, rule]) => {
delete rule.rawNode["avec"]
return [dottedName, rule.rawNode]
}),
)

const alternatives = generateAlternatives(resolvedRules)
console.log(`✅ './src/rules/alternatives.publicodes' generated`)
writeFileSync(
ALTERNATIVES_DEST_PATH,
`# GENERATED FILE - DO NOT EDIT\n\n${stringify(alternatives, {
aliasDuplicateObjects: false,
})}`,
)

const personas = getPersonas(model)
writeFileSync(PERSONAS_DEST_PATH, JSON.stringify(personas))
console.log(`✅ './src/personas/personas.json' generated`)

function check(rules, step) {
try {
const engine = new Engine(rules, { logger: { warn: () => {} } })
engine.evaluate("empreinte . voiture")
engine.evaluate("coûts . voiture")

return engine
} catch (e) {
console.error(`❌ Error at (${step}):\n${e.message}\n`)
process.exit(-1)
}
}
21 changes: 21 additions & 0 deletions src/personas/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Exports the personas object.
*
* It's defined in the `personas.yaml` file and allows to define named
* situations that can be feed into the engine.
*/

import { Situation } from "../../publicodes-build"
import _rawPersonas from "./personas.json"

export type Persona = {
titre: string
description?: string
situation: Situation
}

/**
* A set of named situations that can be feed into the engine and used for
* testing purposes or to provide examples.
*/
export default _rawPersonas as Record<string, Persona>
1 change: 1 addition & 0 deletions src/personas/personas.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"aller-retours travail électrique ville":{"titre":"Aller-retours travail en ville (électrique)","description":"Personne qui va travailler avec une petite voiture électrique en ville\n","situation":{"voiture . motorisation":"électrique","voiture . gabarit":"petite","usage . km annuels . connus":"non","usage . km annuels . calculés . quotidien":20,"usage . km annuels . calculés . vacances":0}},"grandes vacances familiales":{"titre":"Grandes vacances familiales (essence)","description":"Personne qui utilise une voiture essence pour partir en vacances en\nfamille.\n","situation":{"voiture . motorisation":"thermique","voiture . thermique . carburant":"essence E5 ou E10","voiture . gabarit":"berline","usage . km annuels . connus":"non","usage . km annuels . calculés . quotidien":5,"usage . km annuels . calculés . vacances":2000}},"famille usage régulier diesel":{"titre":"Usage régulier en famille (diesel)","description":"Personne qui utilise une voiture diesel pour les trajets quotidiens et\nles vacances en famille.\n\nElle a besoin d'une voiture spacieuse pour transporter ses enfants à l'école\net aller au travail.\n","situation":{"voiture . motorisation":"thermique","voiture . thermique . carburant":"gazole B7 ou B10","voiture . gabarit":"berline","usage . km annuels . connus":"non","usage . km annuels . calculés . quotidien":33,"usage . km annuels . calculés . vacances":2000}},"famille usage régulier biocarburant":{"titre":"Usage régulier en famille (biocarburant)","description":"Personne qui utilise une voiture diesel pour les trajets quotidiens et\nles vacances en famille.\n\nElle a besoin d'une voiture spacieuse pour transporter ses enfants à l'école\net aller au travail.\n","situation":{"voiture . motorisation":"thermique","voiture . thermique . carburant":"essence E85","voiture . gabarit":"berline","usage . km annuels . connus":"non","usage . km annuels . calculés . quotidien":33,"usage . km annuels . calculés . vacances":2000}},"famille usage régulier moyenne biocarburant":{"titre":"Usage régulier en famille (moyenne/biocarburant)","description":"Personne qui utilise une voiture diesel pour les trajets quotidiens et\nles vacances en famille.\n\nElle a besoin d'une voiture spacieuse pour transporter ses enfants à l'école\net aller au travail.\n","situation":{"voiture . motorisation":"thermique","voiture . thermique . carburant":"essence E85","voiture . gabarit":"moyenne","usage . km annuels . connus":"non","usage . km annuels . calculés . quotidien":33,"usage . km annuels . calculés . vacances":2000}}}
Loading

0 comments on commit 92131b3

Please sign in to comment.