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
This commit is contained in:
Vendored
+79
@@ -0,0 +1,79 @@
|
||||
// geometrie.ts — moteur `commun.geometrie` : emprise, niveaux, hauteur, pente,
|
||||
// mitoyenneté → surfaces de parois, SHAB estimée, volume. Reprend les formules
|
||||
// de `calcSurfaces` du simulateur autoconstruction V1 (calculs), sans le DOM,
|
||||
// avec les coefficients sortis dans coefficients.ts.
|
||||
import { Trace } from './contrat.js';
|
||||
import { COEFFICIENTS } from './coefficients.js';
|
||||
import { arrondi2 } from './argent.js';
|
||||
import { VERSION } from '../version.js';
|
||||
export function calculeGeometrie(entrees, coefficients = COEFFICIENTS) {
|
||||
const trace = new Trace();
|
||||
const c = coefficients;
|
||||
const emprise = Math.max(0, entrees.emprise_m2 || 0);
|
||||
const niveaux = Math.max(1, Math.round(entrees.niveaux ?? 1));
|
||||
if (entrees.niveaux == null)
|
||||
trace.avertit('nombre de niveaux inconnu : 1 niveau supposé');
|
||||
let hauteur = entrees.hauteur_m ?? 0;
|
||||
if (!(hauteur > 0)) {
|
||||
hauteur = niveaux * c.geometrie_hauteur_etage_m.valeur;
|
||||
trace.avertit(`hauteur inconnue : ${niveaux} × ${c.geometrie_hauteur_etage_m.valeur} m supposés`);
|
||||
trace.source('geometrie_hauteur_etage_m', c.geometrie_hauteur_etage_m.valeur, c.geometrie_hauteur_etage_m.source, c.geometrie_hauteur_etage_m.date);
|
||||
}
|
||||
const hauteur_etage = hauteur / niveaux;
|
||||
let pente = entrees.pente_toit_deg;
|
||||
if (pente == null || !(pente >= 0) || pente >= 90) {
|
||||
pente = c.geometrie_pente_defaut_deg.valeur;
|
||||
trace.avertit(`pente de toit inconnue : ${pente}° supposés`);
|
||||
trace.source('geometrie_pente_defaut_deg', pente, c.geometrie_pente_defaut_deg.source, c.geometrie_pente_defaut_deg.date);
|
||||
}
|
||||
const mitoyen = Math.min(2, Math.max(0, Math.round(entrees.mitoyennete ?? 0)));
|
||||
// SHAB
|
||||
let shab;
|
||||
let shab_estimee;
|
||||
if (entrees.surface_habitable_m2 && entrees.surface_habitable_m2 > 0) {
|
||||
shab = entrees.surface_habitable_m2;
|
||||
shab_estimee = false;
|
||||
}
|
||||
else {
|
||||
shab = emprise * niveaux * c.geometrie_ratio_shab_emprise.valeur;
|
||||
shab_estimee = true;
|
||||
trace.avertit('surface habitable estimée depuis l\'emprise (aucune surface connue)');
|
||||
trace.source('geometrie_ratio_shab_emprise', c.geometrie_ratio_shab_emprise.valeur, c.geometrie_ratio_shab_emprise.source, c.geometrie_ratio_shab_emprise.date);
|
||||
}
|
||||
// Périmètre (V1 : √(S × 1,3) × 4) et part exposée
|
||||
const perimetre = 4 * Math.sqrt(emprise * c.geometrie_facteur_perimetre.valeur);
|
||||
trace.source('geometrie_facteur_perimetre', c.geometrie_facteur_perimetre.valeur, c.geometrie_facteur_perimetre.source, c.geometrie_facteur_perimetre.date);
|
||||
const perimetre_expose = perimetre * (1 - c.geometrie_part_mur_mitoyen.valeur * mitoyen);
|
||||
if (mitoyen > 0)
|
||||
trace.source('geometrie_part_mur_mitoyen', c.geometrie_part_mur_mitoyen.valeur, c.geometrie_part_mur_mitoyen.source, c.geometrie_part_mur_mitoyen.date);
|
||||
// Parois
|
||||
const murs_exterieurs = perimetre_expose * hauteur;
|
||||
const vitrage = shab * c.geometrie_ratio_vitrage_shab.valeur;
|
||||
trace.source('geometrie_ratio_vitrage_shab', arrondi2(c.geometrie_ratio_vitrage_shab.valeur), c.geometrie_ratio_vitrage_shab.source, c.geometrie_ratio_vitrage_shab.date);
|
||||
const murs_opaques = Math.max(0, murs_exterieurs - vitrage);
|
||||
const rad = (pente * Math.PI) / 180;
|
||||
const toiture = (emprise / Math.cos(rad)) * c.geometrie_majoration_toiture.valeur;
|
||||
trace.source('geometrie_majoration_toiture', c.geometrie_majoration_toiture.valeur, c.geometrie_majoration_toiture.source, c.geometrie_majoration_toiture.date);
|
||||
const volume = shab * hauteur_etage;
|
||||
const sorties = {
|
||||
shab_m2: arrondi2(shab),
|
||||
shab_estimee,
|
||||
perimetre_m: arrondi2(perimetre),
|
||||
perimetre_expose_m: arrondi2(perimetre_expose),
|
||||
murs_exterieurs_m2: arrondi2(murs_exterieurs),
|
||||
murs_opaques_m2: arrondi2(murs_opaques),
|
||||
vitrage_m2: arrondi2(vitrage),
|
||||
toiture_m2: arrondi2(toiture),
|
||||
plancher_bas_m2: arrondi2(emprise),
|
||||
volume_m3: arrondi2(volume),
|
||||
hauteur_m: arrondi2(hauteur),
|
||||
hauteur_etage_m: arrondi2(hauteur_etage),
|
||||
};
|
||||
return trace.resultat(sorties, VERSION);
|
||||
}
|
||||
export const geometrie = {
|
||||
id: 'commun.geometrie',
|
||||
calculer(entrees, donnees) {
|
||||
return calculeGeometrie(entrees, donnees?.coefficients ?? COEFFICIENTS);
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user