Extraction du cœur autonomie de calculs.trans-former.fr (12 modules, sans singleton, couplages sans mutation, console derrière debug), découpage en trois moteurs d'axe + intégrateur (mode global = calculs, mode par_axe = plateforme), moteurs commun.contexte (Corse 2A/2B, DOM 97x corrigés) et commun.geometrie, table des coefficients harmonisés (docs/CONSTANTES.md pour Jules, R-7), validation structurelle des données (schemas/), tests hors ligne : 28 assertions d'origine + épingle générée depuis le code d'astro-pro + écarts d'harmonisation figés + contrat des moteurs. dist/ committé. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019UBHYPdeQYy2m1GVJp6b12
77 lines
3.4 KiB
JavaScript
77 lines
3.4 KiB
JavaScript
// pin-origine.mjs — génère fixtures/sorties-origine-<date>.json DEPUIS LE CODE
|
|
// D'ORIGINE (clone astro-pro, src/lib/autonomie), pas depuis ce paquet : c'est
|
|
// ce qui fait du test de non-régression une vraie épingle.
|
|
//
|
|
// Rejouable seulement avec un clone d'astro-pro à la révision d'origine
|
|
// (master c628cf9 au 2026-09-28) : ASTRO_PRO_DIR=~/dev/astro-pro par défaut.
|
|
// Usage : node scripts/pin-origine.mjs [AAAA-MM-JJ]
|
|
import { readFileSync, writeFileSync } from 'node:fs'
|
|
import { homedir } from 'node:os'
|
|
import { join } from 'node:path'
|
|
import { pathToFileURL } from 'node:url'
|
|
|
|
const ASTRO = process.env.ASTRO_PRO_DIR ?? join(homedir(), 'dev', 'astro-pro')
|
|
const date = process.argv[2] ?? new Date().toISOString().slice(0, 10)
|
|
const lib = (f) => pathToFileURL(join(ASTRO, 'src', 'lib', 'autonomie', f)).href
|
|
|
|
const { selectionner } = await import(lib('algo.js'))
|
|
const { configPourAxes } = await import(lib('axes-actifs.js'))
|
|
const { initConfig } = await import(lib('calibrage.js'))
|
|
|
|
const fx = new URL('../fixtures/', import.meta.url)
|
|
const lire = (f) => JSON.parse(readFileSync(new URL(f, fx), 'utf8'))
|
|
const options = lire('options.json')
|
|
const postes = lire('postes.json')
|
|
const climat = lire('france_climat.json')
|
|
const config = lire('algo-config.json')
|
|
const profils = lire('profils-reference.json')
|
|
initConfig(config)
|
|
|
|
const AXES = ['eau', 'energie', 'alim']
|
|
const resume = (r) => ({
|
|
total_eur_ht: r.total_eur_ht,
|
|
status: r.status,
|
|
ecart_budget_pct: r.ecart_budget_pct,
|
|
axes: Object.fromEntries(
|
|
AXES.map((a) => [
|
|
a,
|
|
{
|
|
budget_alloue: r.axes[a]?.budget_alloue ?? 0,
|
|
poids: r.axes[a]?.poids ?? 0,
|
|
sous_total_eur_ht: r.axes[a]?.sous_total_eur_ht ?? 0,
|
|
postes: (r.axes[a]?.postes ?? []).map((p) => ({
|
|
poste_id: p.poste_id,
|
|
typologie_choisie: p.typologie_choisie,
|
|
dimension: p.dimension ? { valeur: p.dimension.valeur, unite: p.dimension.unite } : null,
|
|
cout_eur_ht: p.cout_eur_ht,
|
|
force_par_couplage: !!p.force_par_couplage,
|
|
})),
|
|
},
|
|
]),
|
|
),
|
|
couplages: r.couplages,
|
|
})
|
|
|
|
const sortie = {
|
|
_commentaire: `Sorties de selectionner() D'ORIGINE (astro-pro src/lib/autonomie, coefficients du code) sur les trois profils de référence, générées le ${date} par scripts/pin-origine.mjs. 'global' = pipeline complet ; 'par_axe' = mode un seul axe actif (configPourAxes) avec le budget que le pipeline global avait alloué à cet axe.`,
|
|
date,
|
|
profils: {},
|
|
}
|
|
for (const profil of profils) {
|
|
const global = selectionner(profil.inputs, options, postes, climat, config, false)
|
|
const par_axe = {}
|
|
for (const axe of AXES) {
|
|
const budget = global.axes[axe]?.budget_alloue ?? 0
|
|
const actifs = Object.fromEntries(AXES.map((a) => [a, a === axe]))
|
|
const r = selectionner({ ...profil.inputs, budget_eur: budget }, options, postes, climat, configPourAxes(config, actifs), false)
|
|
par_axe[axe] = { budget_axe: budget, ...resume(r) }
|
|
}
|
|
sortie.profils[profil.nom] = { inputs: profil.inputs, global: resume(global), par_axe }
|
|
}
|
|
const cible = new URL(`sorties-origine-${date}.json`, fx)
|
|
writeFileSync(cible, JSON.stringify(sortie, null, 2) + '\n', 'utf8')
|
|
console.log(`écrit : fixtures/sorties-origine-${date}.json`)
|
|
for (const [nom, p] of Object.entries(sortie.profils)) {
|
|
console.log(`${nom} : total ${p.global.total_eur_ht} (${p.global.status})`, AXES.map((a) => `${a}=${p.global.axes[a].postes.map((x) => x.typologie_choisie).join('+')}`).join(' | '))
|
|
}
|