v0.1.1 : version et dist reconstruit
Patch (AGENTS règle 5 : correction, aucune sortie nouvelle — la quantité d'un poste passe par `dimension`, qui existait). Étiquette et merge au checkpoint de la session de pilotage ; montée dans reinnover le même jour (ouvre P1.2b). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tgtn7bJxTLiL2fRCkQMgtR
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
91c755f884
commit
8465bf7204
Vendored
+66
-2
@@ -8,6 +8,13 @@
|
||||
// Note (origine, conservée) : le marqueur `_conflit_avec` de la passe 2 est
|
||||
// posé sur des copies de postes et n'atteint jamais la sortie ; le
|
||||
// « downgrade planifié » n'a donc jamais lieu. À corriger en patch, avec test.
|
||||
//
|
||||
// Correctif v0.1.1 (SPEC menu §12 n° 2 et 5) : une ligne forcée que plus
|
||||
// aucune ligne ne requiert est RETIRÉE (passe 0). À l'origine, un accessoire
|
||||
// forcé (conduit, ballon tampon, filière d'épuration) survivait au retrait ou
|
||||
// au downgrade de son principal, verrouillé pour toujours par
|
||||
// `force_par_couplage` — d'où des conduits sans poêle et des planchers de
|
||||
// coût infranchissables (statut INSUFFISANT à 6 000 € mais OK à 3 000 €).
|
||||
import { cout_typologie, dimension_optimale } from './dimension.js';
|
||||
function copieSelection(selection) {
|
||||
const copie = {};
|
||||
@@ -20,6 +27,62 @@ function copieSelection(selection) {
|
||||
}
|
||||
return copie;
|
||||
}
|
||||
const AXES_LIST = ['eau', 'energie', 'alim'];
|
||||
/** Codes requis (alias résolus) par les lignes NON forcées de la sélection. */
|
||||
export function codesRequisPar(axes, alias) {
|
||||
const requis = new Set();
|
||||
for (const axe of AXES_LIST) {
|
||||
for (const p of axes[axe]?.postes ?? []) {
|
||||
if (p.force_par_couplage)
|
||||
continue;
|
||||
for (const r of p.couplages_requis || [])
|
||||
requis.add(alias[r] || r);
|
||||
}
|
||||
}
|
||||
return requis;
|
||||
}
|
||||
/** Codes des lignes NON forcées (les choix de postes, par opposition aux accessoires forcés). */
|
||||
export function codesChoisis(axes) {
|
||||
const codes = new Set();
|
||||
for (const axe of AXES_LIST)
|
||||
for (const p of axes[axe]?.postes ?? [])
|
||||
if (!p.force_par_couplage)
|
||||
codes.add(p.typologie_choisie);
|
||||
return codes;
|
||||
}
|
||||
/**
|
||||
* Retire EN PLACE les lignes forcées devenues inutiles et recalcule les
|
||||
* sous-totaux : celles que plus aucune ligne ne requiert (orphelines), et
|
||||
* celles dont la typologie est déjà le choix d'un poste (le requis est
|
||||
* satisfait par ce choix, la ligne forcée est absorbée). Rend le journal.
|
||||
*/
|
||||
export function retireForcesOrphelins(axes, alias) {
|
||||
const requis = codesRequisPar(axes, alias);
|
||||
const choisis = codesChoisis(axes);
|
||||
const log = [];
|
||||
for (const axe of AXES_LIST) {
|
||||
const a = axes[axe];
|
||||
if (!a)
|
||||
continue;
|
||||
const gardes = [];
|
||||
for (const p of a.postes) {
|
||||
if (p.force_par_couplage && !requis.has(p.typologie_choisie)) {
|
||||
log.push('RETIRE "' + p.typologie_choisie + '" (plus requis par aucun poste) -' + (p.cout_eur_ht || 0) + 'EUR dans axe ' + axe);
|
||||
}
|
||||
else if (p.force_par_couplage && choisis.has(p.typologie_choisie)) {
|
||||
log.push('ABSORBE "' + p.typologie_choisie + '" (déjà le choix d\'un poste) -' + (p.cout_eur_ht || 0) + 'EUR dans axe ' + axe);
|
||||
}
|
||||
else {
|
||||
gardes.push(p);
|
||||
}
|
||||
}
|
||||
if (gardes.length !== a.postes.length) {
|
||||
a.postes = gardes;
|
||||
a.sous_total_eur_ht = gardes.reduce((s, p) => s + (p.cout_eur_ht || 0), 0);
|
||||
}
|
||||
}
|
||||
return log;
|
||||
}
|
||||
/**
|
||||
* Post-traitement déterministe des couplages.
|
||||
*
|
||||
@@ -41,10 +104,11 @@ export function appliqueCouplages(selection_recue, options, postes, reglages, _d
|
||||
function resolveCode(code) {
|
||||
return alias[code] || code;
|
||||
}
|
||||
const axes_list = ['eau', 'energie', 'alim'];
|
||||
const axes_list = AXES_LIST;
|
||||
// Passe 0 (v0.1.1) : lâcher les accessoires forcés dont le principal a disparu.
|
||||
const couplages_log = retireForcesOrphelins(selection, alias);
|
||||
const tous_postes = axes_list.flatMap((axe) => (selection[axe] && selection[axe].postes ? selection[axe].postes : []).map((p) => Object.assign({}, p, { _axe: axe })));
|
||||
const codes_selectionnes = new Set(tous_postes.map((p) => p.typologie_choisie));
|
||||
const couplages_log = [];
|
||||
// Passe 1 : couplages_requis
|
||||
for (const poste of tous_postes) {
|
||||
const requis_list = poste.couplages_requis || [];
|
||||
|
||||
Reference in New Issue
Block a user