Files
moteurs/dist/commun/coefficients.js
T
JulesandClaude Fable 5.1 69809df5d1 LOT P1.0 : paquet @transformer/moteurs v0.1.0
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
2026-09-28 17:06:49 +02:00

161 lines
7.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// coefficients.ts — chaque grandeur physique UNE fois, avec source et date.
//
// Règle : le document de recherche l'emporte sur le code quand ils divergent
// (SPEC phase 1 §4.1, LOT P1.0 point 5). La table lisible par Jules est
// docs/CONSTANTES.md (une ligne par grandeur : ancienne(s) valeur(s) →
// retenue, source, date). Le jeu de coefficients d'ORIGINE (valeurs du code
// de calculs.trans-former.fr au 28/09/2026) vit dans
// fixtures/coefficients-2026-05.json et sert au test de non-régression.
//
// Les poids d'axes, modulateurs, matrices d'adéquation et tolérances de
// algo-config.json ne sont PAS ici : ce sont des heuristiques de conception,
// non sourcées, livrées comme données (fixtures/algo-config.json) et injectées.
const D_RECHERCHE = '2026-04-28';
const D_LOT = '2026-09-28';
const S_EAU = '1 PROJETS/DEV/Simulateur autonomie V2/01-recherche-eau.md';
const S_ENERGIE = '1 PROJETS/DEV/Simulateur autonomie V2/02-recherche-energie.md';
const S_BRIEF = '1 PROJETS/DEV/Simulateur autonomie V2/99-brief-atis-dev.md';
const S_V1 = 'calculs.trans-former.fr, simulateur autoconstruction V1 (public/simulateurs/autoconstruction/app.js, calcSurfaces)';
/** Table harmonisée (LOT P1.0, 28/09/2026). Référence tant que Jules ne met pas de veto (R-7). */
export const COEFFICIENTS = {
captage_rendement: {
valeur: 0.8,
source: `${S_EAU} §3 « Captable max » et §7 n°6 (NF EN 16941-1, recueil Nény p.16)`,
date: D_RECHERCHE,
note: 'fourchette 0,75 (zone sèche) à 0,85 (zone humide, gouttières optimisées) ; le code portait 0,7 (scoreurs), 0,8 (taux) et 0,85 (V1 bioclimatique)',
},
captage_rendement_par_toiture: {
valeur: { tuile: 0.85, ardoise: 0.85, gravillonnee: 0.5, vegetalisee: 0.3 },
source: `${S_EAU} §7 n°6 (ADEME, réf. NF EN 16941-1)`,
date: D_RECHERCHE,
note: 'à brancher quand le formulaire demande le type de toiture ; non utilisé en v0.1',
},
besoin_eau_l_j_pers: {
valeur: 150,
source: `${S_EAU} §3 « Besoin eau » (INSEE / Eau France 2024) ; ${S_BRIEF} §7.1`,
date: D_RECHERCHE,
note: '54 750 L/an/personne ; le V1 comptait 46,5 m³/an',
},
part_eau_substituable: {
valeur: 0.7,
source: `${S_EAU} §3 ; ${S_BRIEF} §7.1 (WC 30 + douche 60 + lessive 30 + jardin 25 L/j sur 150)`,
date: D_RECHERCHE,
note: 'le V1 comptait 32 % (15 m³ sur 46,5)',
},
orientation_pv: {
valeur: { sud: 1, 'sud-est': 0.95, 'sud-ouest': 0.95, est: 0.8, ouest: 0.8, nord: 0.6 },
source: `${S_ENERGIE} §3.2 « Variantes orientation toiture »`,
date: D_RECHERCHE,
note: 'source : SE/SO 95 %, E/O 80-85 %, N 60-65 % (bas de fourchette retenu) ; le brief §7.2 prenait les milieux 0,82 et 0,62 ; le code portait 0,93 / 0,78 / 0,40',
},
productible_pv_kwh_kwc: {
valeur: {
par: 'zone_rt',
table: { H1a: 1000, H1b: 1050, H1c: 1200, H2a: 1100, H2b: 1200, H2c: 1250, H2d: 1300, H3: 1400 },
defaut: 1100,
},
source: `${S_ENERGIE} §3.2 (PVGIS, sud 30°, pertes 14 %)`,
date: D_RECHERCHE,
note: 'H1a : moyenne Lille 950 / Paris 1 050 ; H2d : interpolé entre H2c et H3 par la MOE, non sourcé (déclaré en avertissement) ; défaut = H2a ; le code portait une table par zone biogéographique allant jusqu\'à 1 550, au-dessus du maximum de la source',
},
autoconso_sans_batterie: {
valeur: 0.3,
source: `${S_ENERGIE} §3.2 ; ${S_BRIEF} §7.2`,
date: D_RECHERCHE,
note: 'absent du code : la couverture énergie comparait la production brute au besoin',
},
autoconso_avec_batterie_10kwh: {
valeur: 0.7,
source: `${S_ENERGIE} §3.2 ; ${S_BRIEF} §7.2`,
date: D_RECHERCHE,
note: 'entre 0 et 10 kWh de batterie, le moteur interpole linéairement (choix MOE, non sourcé)',
},
besoin_elec_kwh_pers_an: {
valeur: 1000,
source: `${S_ENERGIE} §3.1 (ADEME 2023, RTE 2024) ; ${S_BRIEF} §7.2`,
date: D_RECHERCHE,
note: 'fourchette 900 à 1 200 ; hors chauffage électrique, ECS et véhicule',
},
dju_defaut_par_classe_rt: {
valeur: { H1: 2800, H2: 2200, H3: 1500 },
source: 'heuristique de conception V2 (calibrage.js et algo-config.json), non sourcée',
date: '2026-05-01',
note: 'repli seulement : la table france_climat porte un DJU par département',
},
ml_haie_par_pers: {
valeur: 25,
source: `${S_BRIEF} §7.3 (correction Jules du 28/04/2026) ; 03-recherche-alimentation.md §5`,
date: D_RECHERCHE,
note: '50 ml/personne pour un excédent transformable',
},
contexte_defaut: {
valeur: { zone_rt: 'H2a', zone_biogeo_code: 4, pluviometrie_mm: 800, dju: 2200 },
source: 'heuristique de conception V2 (algo.js deriveContexte, simulation.js), non sourcée',
date: '2026-05-01',
note: 'appliqué seulement si le département est absent de france_climat ; toujours déclaré en avertissement',
},
geometrie_ratio_shab_emprise: {
valeur: 0.8,
source: 'heuristique MOE (murs extérieurs ~0,3 m, refends, escalier), non sourcée',
date: D_LOT,
note: 'hypothèse porteuse du P1.2 : à confronter à la surface DPE des adresses A et B (écart visé < 20 %)',
},
geometrie_ratio_vitrage_shab: {
valeur: 1 / 6,
source: `${S_V1} (vit = S/6) ; règle RT 2012 (baies ≥ 1/6 de la SHAB)`,
date: '2025-01-01',
note: 'la SPEC §4.1 écrit « 15 % » ; 1/6 = 16,7 %',
},
geometrie_hauteur_etage_m: {
valeur: 2.5,
source: 'heuristique MOE (hauteur sous plafond courante), non sourcée',
date: D_LOT,
},
geometrie_facteur_perimetre: {
valeur: 1.3,
source: `${S_V1} (perimetre = √(S × 1,3) × 4)`,
date: '2025-01-01',
},
geometrie_part_mur_mitoyen: {
valeur: 0.25,
source: 'heuristique MOE (un côté mitoyen = un quart du périmètre), non sourcée',
date: D_LOT,
},
geometrie_majoration_toiture: {
valeur: 1.05,
source: `${S_V1} (toiture = S / cos α × 1,05)`,
date: '2025-01-01',
},
geometrie_pente_defaut_deg: {
valeur: 30,
source: 'heuristique MOE (pente courante des toitures à deux versants), non sourcée',
date: D_LOT,
},
};
/** Clés de la table, pour valider un jeu de coefficients injecté (fixture, veto). */
export const CLES_COEFFICIENTS = Object.keys(COEFFICIENTS);
/**
* Vérifie qu'un objet a la forme d'une table de coefficients (toutes les clés,
* chaque entrée avec valeur, source et date). Renvoie la liste des défauts.
*/
export function verifieTableCoefficients(table) {
const erreurs = [];
if (!table || typeof table !== 'object')
return ['table absente ou non objet'];
const t = table;
for (const cle of CLES_COEFFICIENTS) {
const c = t[cle];
if (!c || typeof c !== 'object') {
erreurs.push(`${cle} : absent`);
continue;
}
if (!('valeur' in c))
erreurs.push(`${cle} : valeur absente`);
if (typeof c.source !== 'string' || !c.source)
erreurs.push(`${cle} : source absente`);
if (typeof c.date !== 'string' || !/^\d{4}-\d{2}-\d{2}$/.test(c.date))
erreurs.push(`${cle} : date absente ou non AAAA-MM-JJ`);
}
return erreurs;
}