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
161 lines
7.4 KiB
JavaScript
161 lines
7.4 KiB
JavaScript
// 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;
|
||
}
|