@open3cl/engine 1.7.3 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/11_besoin_ecs.js +5 -2
- package/11_ecs.js +99 -2
- package/11_ecs.spec.js +139 -1
- package/13.2_generateur_combustion_ch.js +34 -2
- package/13.2_generateur_combustion_ch.spec.js +148 -15
- package/README.md +19 -34
- package/conso.js +11 -7
- package/engine.js +3 -2
- package/package.json +6 -2
package/11_besoin_ecs.js
CHANGED
|
@@ -24,11 +24,14 @@ export function calc_besoin_ecs_j(ca, mois, zc, nadeq, depensier) {
|
|
|
24
24
|
export default function calc_besoin_ecs(ca, zc, nadeq) {
|
|
25
25
|
const ret = {
|
|
26
26
|
besoin_ecs: 0,
|
|
27
|
-
besoin_ecs_depensier: 0
|
|
27
|
+
besoin_ecs_depensier: 0,
|
|
28
|
+
besoin_ecs_par_mois: {}
|
|
28
29
|
};
|
|
29
30
|
for (const mois of mois_liste) {
|
|
30
|
-
|
|
31
|
+
const becs_j = calc_besoin_ecs_j(ca, mois, zc, nadeq, false);
|
|
32
|
+
ret.besoin_ecs += becs_j;
|
|
31
33
|
ret.besoin_ecs_depensier += calc_besoin_ecs_j(ca, mois, zc, nadeq, true);
|
|
34
|
+
ret.besoin_ecs_par_mois[mois] = becs_j;
|
|
32
35
|
}
|
|
33
36
|
return ret;
|
|
34
37
|
}
|
package/11_ecs.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import enums from './enums.js';
|
|
2
2
|
import calc_gen_ecs from './14_generateur_ecs.js';
|
|
3
|
-
import { tv, requestInput } from './utils.js';
|
|
3
|
+
import { tv, requestInput, mois_liste, Njj } from './utils.js';
|
|
4
4
|
|
|
5
5
|
function tv_rendement_distribution_ecs(di, de, du, pvc) {
|
|
6
6
|
let matcher = {};
|
|
@@ -49,6 +49,89 @@ function tv_rendement_distribution_ecs(di, de, du, pvc) {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Calcul de la consommation des auxiliaires de distribution ECS - CAS IMMEUBLE
|
|
54
|
+
* Calcul installation par installation pour les réseaux collectifs bouclés ou avec traçage.
|
|
55
|
+
*
|
|
56
|
+
* @param {object} de - donnee_entree de l'installation ECS
|
|
57
|
+
* @param {number} surfaceImmeuble - surface habitable totale de l'immeuble (m²)
|
|
58
|
+
* @param {object} becsParMois - besoin ECS mensuel de l'immeuble {Janvier: X, Février: X, ...} [kWh]
|
|
59
|
+
* @returns {number} conso_auxiliaire_distribution_ecs_installation [Wh]
|
|
60
|
+
*/
|
|
61
|
+
function calc_auxiliaire_distribution_ecs_immeuble(de, surfaceImmeuble, becsParMois) {
|
|
62
|
+
const type_installation = enums.type_installation[de.enum_type_installation_id];
|
|
63
|
+
|
|
64
|
+
// Seulement pour les installations collectives
|
|
65
|
+
if (!type_installation || !type_installation.includes('collective')) {
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const enum_bouclage_id = String(de.enum_bouclage_reseau_ecs_id);
|
|
70
|
+
const surface_installation = de.surface_habitable || 0;
|
|
71
|
+
const surface_immeuble_total = surfaceImmeuble || 1;
|
|
72
|
+
const ratio_surface = surface_installation / surface_immeuble_total;
|
|
73
|
+
|
|
74
|
+
// CAS 1 : réseau non bouclé → 0
|
|
75
|
+
if (enum_bouclage_id === '1') {
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// CAS 3 : traçage → 0.14 × BECS_annuel × ratio_surface [Wh]
|
|
80
|
+
if (enum_bouclage_id === '3') {
|
|
81
|
+
const becs_annuel_kwh = Object.values(becsParMois).reduce((acc, v) => acc + v, 0);
|
|
82
|
+
// becs_annuel est en kWh → × 1000 pour obtenir des Wh
|
|
83
|
+
return 0.14 * becs_annuel_kwh * 1000 * ratio_surface;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// CAS 2 : réseau bouclé → calcul complet 9 étapes [Wh]
|
|
87
|
+
if (enum_bouclage_id === '2') {
|
|
88
|
+
const Sh_inst = surface_installation;
|
|
89
|
+
const Niv_inst = Number(de.nombre_niveau_installation_ecs) || 1;
|
|
90
|
+
|
|
91
|
+
// Étape 3 : Calcul de Lb pour l'installation i
|
|
92
|
+
// Lb = 1.2 × (1.1 × Sh_inst/nombre_niveaux + 4 × nombre_niveaux)
|
|
93
|
+
const Lb = 1.2 * (1.1 * (Sh_inst / Niv_inst) + 4 * Niv_inst);
|
|
94
|
+
|
|
95
|
+
// Étape 4 : DeltaPb = 0.2 × Lb + 10
|
|
96
|
+
const DeltaPb = 0.2 * Lb + 10;
|
|
97
|
+
|
|
98
|
+
let Qcirc_annuel = 0;
|
|
99
|
+
|
|
100
|
+
for (const mois of mois_liste) {
|
|
101
|
+
const Njj_mois = Njj[mois];
|
|
102
|
+
const becs_immeuble_j_kwh = becsParMois[mois] || 0;
|
|
103
|
+
|
|
104
|
+
// Étape 1 : Qdwj_i [kWh]
|
|
105
|
+
const Qdwj_i = 0.24 * becs_immeuble_j_kwh * ratio_surface;
|
|
106
|
+
|
|
107
|
+
// Étape 2 : qdwj_i [m³/h]
|
|
108
|
+
// Note: la spec officielle utilise Qdwj en Wh et divise par 1000 ensuite.
|
|
109
|
+
// Le moteur fournit becs en kWh, donc Qdwj est en kWh → on ne divise pas par 1000.
|
|
110
|
+
const qdwj_i = Qdwj_i / (5.815 * 5 * Njj_mois);
|
|
111
|
+
|
|
112
|
+
// Étape 5 : Phyd,j [W]
|
|
113
|
+
// Phyd,j = DeltaPb [kPa] × 1000 × qdwj_i [m³/h] / 3600
|
|
114
|
+
const Phyd_j = (DeltaPb * 1000 * qdwj_i) / 3600;
|
|
115
|
+
|
|
116
|
+
// Étape 6 : Effcirb,j (rendement pompe)
|
|
117
|
+
const Effcirb_j = Phyd_j > 0 ? 0.035 * Math.pow(Phyd_j, 0.45) : 0;
|
|
118
|
+
|
|
119
|
+
// Étape 7 : Pcirb,j [W] = max(Phyd,j / Effcirb,j, 20)
|
|
120
|
+
const Pcirb_j = Effcirb_j > 0 ? Math.max(Phyd_j / Effcirb_j, 20) : 20;
|
|
121
|
+
|
|
122
|
+
// Étape 8 : Qcirb,j [Wh]
|
|
123
|
+
const Qcirb_j = (5 * Pcirb_j + 19 * 20) * Njj_mois;
|
|
124
|
+
|
|
125
|
+
Qcirc_annuel += Qcirb_j;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Étape 9 : conso annuelle en Wh
|
|
129
|
+
return Qcirc_annuel;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
52
135
|
export default function calc_ecs(
|
|
53
136
|
dpe,
|
|
54
137
|
ecs,
|
|
@@ -61,7 +144,8 @@ export default function calc_ecs(
|
|
|
61
144
|
virtualisationECS,
|
|
62
145
|
surfaceImmeuble,
|
|
63
146
|
nombreAppartements,
|
|
64
|
-
isImmeubleSystemEcsIndividuels
|
|
147
|
+
isImmeubleSystemEcsIndividuels,
|
|
148
|
+
becsParMois
|
|
65
149
|
) {
|
|
66
150
|
const de = ecs.donnee_entree;
|
|
67
151
|
const di = {};
|
|
@@ -101,6 +185,19 @@ export default function calc_ecs(
|
|
|
101
185
|
0
|
|
102
186
|
);
|
|
103
187
|
|
|
188
|
+
// Calcul de la consommation des auxiliaires de distribution ECS pour l'immeuble
|
|
189
|
+
// Résultat en Wh, converti en kWh pour cohérence avec le reste du moteur
|
|
190
|
+
if (th === 'immeuble' && becsParMois && Object.keys(becsParMois).length > 0) {
|
|
191
|
+
const conso_aux_wh = calc_auxiliaire_distribution_ecs_immeuble(
|
|
192
|
+
de,
|
|
193
|
+
surfaceImmeuble,
|
|
194
|
+
becsParMois
|
|
195
|
+
);
|
|
196
|
+
di.conso_auxiliaire_distribution_ecs = conso_aux_wh / 1000;
|
|
197
|
+
} else {
|
|
198
|
+
di.conso_auxiliaire_distribution_ecs = 0;
|
|
199
|
+
}
|
|
200
|
+
|
|
104
201
|
ecs.donnee_intermediaire = di;
|
|
105
202
|
ecs.donnee_utilisateur = du;
|
|
106
203
|
}
|
package/11_ecs.spec.js
CHANGED
|
@@ -21,7 +21,10 @@ vi.mock('./enums.js', () => ({
|
|
|
21
21
|
vi.mock('./utils.js', () => ({
|
|
22
22
|
set_bug_for_bug_compat: vi.fn(),
|
|
23
23
|
tv: vi.fn(),
|
|
24
|
-
requestInput: vi.fn()
|
|
24
|
+
requestInput: vi.fn(),
|
|
25
|
+
// Calendrier réduit à deux mois pour le calcul mensuel des auxiliaires de distribution
|
|
26
|
+
mois_liste: ['Janvier', 'Février'],
|
|
27
|
+
Njj: { Janvier: 31, Février: 28 }
|
|
25
28
|
}));
|
|
26
29
|
|
|
27
30
|
vi.mock('./14_generateur_ecs.js', () => ({
|
|
@@ -281,3 +284,138 @@ describe('calc_ecs - agrégation des consommations', () => {
|
|
|
281
284
|
expect(ecs.donnee_intermediaire.conso_ecs_depensier).toBe(28);
|
|
282
285
|
});
|
|
283
286
|
});
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Consommation des auxiliaires de distribution ECS - cas immeuble
|
|
290
|
+
* Seuls les réseaux collectifs bouclés ou avec traçage consomment de l'énergie.
|
|
291
|
+
*/
|
|
292
|
+
describe('calc_ecs - auxiliaires de distribution ECS (immeuble)', () => {
|
|
293
|
+
/** Calcule l'ECS d'un immeuble et retourne la conso des auxiliaires de distribution [kWh]. */
|
|
294
|
+
function consoAuxDistribution(deExtra, becsParMois, surfaceImmeuble = 400, th = 'immeuble') {
|
|
295
|
+
const ecs = makeEcs({ tv_rendement_distribution_ecs_id: '5', ...deExtra });
|
|
296
|
+
calc_ecs(
|
|
297
|
+
{},
|
|
298
|
+
ecs,
|
|
299
|
+
100,
|
|
300
|
+
200,
|
|
301
|
+
1,
|
|
302
|
+
'ca1',
|
|
303
|
+
'h1a',
|
|
304
|
+
th,
|
|
305
|
+
false,
|
|
306
|
+
surfaceImmeuble,
|
|
307
|
+
null,
|
|
308
|
+
false,
|
|
309
|
+
becsParMois
|
|
310
|
+
);
|
|
311
|
+
return ecs.donnee_intermediaire.conso_auxiliaire_distribution_ecs;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
test.each([
|
|
315
|
+
['logement autre qu’un immeuble', 'maison', { Janvier: 1000 }],
|
|
316
|
+
['besoin mensuel absent', 'immeuble', undefined],
|
|
317
|
+
['besoin mensuel vide', 'immeuble', {}]
|
|
318
|
+
])('%s : pas de consommation', (_libelle, th, becsParMois) => {
|
|
319
|
+
expect(
|
|
320
|
+
consoAuxDistribution(
|
|
321
|
+
{ enum_type_installation_id: '2', enum_bouclage_reseau_ecs_id: '2' },
|
|
322
|
+
becsParMois,
|
|
323
|
+
400,
|
|
324
|
+
th
|
|
325
|
+
)
|
|
326
|
+
).toBe(0);
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
test.each([
|
|
330
|
+
['type d’installation inconnu', { enum_type_installation_id: '9' }],
|
|
331
|
+
['installation individuelle', { enum_type_installation_id: '1' }],
|
|
332
|
+
[
|
|
333
|
+
'réseau collectif non bouclé',
|
|
334
|
+
{ enum_type_installation_id: '2', enum_bouclage_reseau_ecs_id: '1' }
|
|
335
|
+
],
|
|
336
|
+
['type de bouclage non renseigné', { enum_type_installation_id: '2' }]
|
|
337
|
+
])('%s : pas de consommation', (_libelle, de) => {
|
|
338
|
+
expect(consoAuxDistribution(de, { Janvier: 1000 })).toBe(0);
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
test('réseau avec traçage : 0,14 × besoin annuel × ratio de surface', () => {
|
|
342
|
+
const conso = consoAuxDistribution(
|
|
343
|
+
{ enum_type_installation_id: '2', enum_bouclage_reseau_ecs_id: 3, surface_habitable: 100 },
|
|
344
|
+
{ Janvier: 100, Février: 50 }
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
// 0,14 × 150 kWh × 1000 × (100 / 400) = 5250 Wh => 5,25 kWh
|
|
348
|
+
expect(conso).toBeCloseTo(5.25, 9);
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
test('réseau avec traçage sans surfaces renseignées : ratio de surface nul', () => {
|
|
352
|
+
const conso = consoAuxDistribution(
|
|
353
|
+
{ enum_type_installation_id: '3', enum_bouclage_reseau_ecs_id: '3' },
|
|
354
|
+
{ Janvier: 100 },
|
|
355
|
+
null
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
// surface_habitable absente => 0 ; surface de l'immeuble absente => 1
|
|
359
|
+
expect(conso).toBe(0);
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
test('réseau bouclé sans besoin : puissance minimale du circulateur de 20 W', () => {
|
|
363
|
+
const conso = consoAuxDistribution(
|
|
364
|
+
{ enum_type_installation_id: '2', enum_bouclage_reseau_ecs_id: '2', surface_habitable: 100 },
|
|
365
|
+
{ Janvier: 0 }
|
|
366
|
+
);
|
|
367
|
+
|
|
368
|
+
// Pcirb = 20 W chaque mois : (5 × 20 + 19 × 20) × (31 + 28) jours = 28320 Wh
|
|
369
|
+
expect(conso).toBeCloseTo(28.32, 9);
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
test('réseau bouclé à faible besoin : puissance du circulateur ramenée au minimum de 20 W', () => {
|
|
373
|
+
const conso = consoAuxDistribution(
|
|
374
|
+
{
|
|
375
|
+
enum_type_installation_id: '2',
|
|
376
|
+
enum_bouclage_reseau_ecs_id: '2',
|
|
377
|
+
surface_habitable: 100,
|
|
378
|
+
nombre_niveau_installation_ecs: 2
|
|
379
|
+
},
|
|
380
|
+
{ Janvier: 1000, Février: 1000 }
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
// Phyd / Effcirb < 20 W => Pcirb = 20 W, identique au cas sans besoin
|
|
384
|
+
expect(conso).toBeCloseTo(28.32, 9);
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
test('réseau bouclé : calcul complet de la consommation du circulateur', () => {
|
|
388
|
+
const conso = consoAuxDistribution(
|
|
389
|
+
{
|
|
390
|
+
enum_type_installation_id: '2',
|
|
391
|
+
enum_bouclage_reseau_ecs_id: '2',
|
|
392
|
+
surface_habitable: 100,
|
|
393
|
+
nombre_niveau_installation_ecs: '2'
|
|
394
|
+
},
|
|
395
|
+
{ Janvier: 10000 }
|
|
396
|
+
);
|
|
397
|
+
|
|
398
|
+
// Lb = 1,2 × (1,1 × 100 / 2 + 4 × 2) = 75,6 m ; ΔPb = 0,2 × Lb + 10 = 25,12 kPa
|
|
399
|
+
// Janvier : Phyd ≈ 4,645 W => Pcirb ≈ 66,49 W ; Février (besoin absent) : Pcirb = 20 W
|
|
400
|
+
// Référence de régression (calcul des 9 étapes de la méthode) : 35526,3879475995 Wh
|
|
401
|
+
expect(conso).toBeCloseTo(35.526387947599495, 9);
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
test('réseau bouclé sans nombre de niveaux : un seul niveau par défaut', () => {
|
|
405
|
+
const avecUnNiveau = consoAuxDistribution(
|
|
406
|
+
{
|
|
407
|
+
enum_type_installation_id: '2',
|
|
408
|
+
enum_bouclage_reseau_ecs_id: '2',
|
|
409
|
+
surface_habitable: 100,
|
|
410
|
+
nombre_niveau_installation_ecs: 1
|
|
411
|
+
},
|
|
412
|
+
{ Janvier: 10000 }
|
|
413
|
+
);
|
|
414
|
+
const sansNiveau = consoAuxDistribution(
|
|
415
|
+
{ enum_type_installation_id: '2', enum_bouclage_reseau_ecs_id: '2', surface_habitable: 100 },
|
|
416
|
+
{ Janvier: 10000 }
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
expect(sansNiveau).toBe(avecUnNiveau);
|
|
420
|
+
});
|
|
421
|
+
});
|
|
@@ -32,13 +32,43 @@ const K = {
|
|
|
32
32
|
'réseau de froid urbain': undefined
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Planchers / plafonds chauffants sur réseau d'eau chaude « basse ou moyenne température
|
|
37
|
+
* (inf 65°c) » (enum_type_emission_distribution_id 12, 14, 16, 18).
|
|
38
|
+
*/
|
|
39
|
+
export const EMISSION_PLANCHER_PLAFOND_CHAUFFANT_BT = ['12', '14', '16', '18'];
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Température de distribution à utiliser pour les tables temp_fonc_30 / temp_fonc_100.
|
|
43
|
+
*
|
|
44
|
+
* Un plancher (ou plafond) chauffant à eau < 65 °C fonctionne en basse température : comme le
|
|
45
|
+
* moteur de référence CSTB (Tribu), qui déduit la ligne « basse » du type d'émetteur plancher
|
|
46
|
+
* chauffant, on retient « basse » (id 2) lorsque le DPE déclare « moyenne » (id 3) pour ces
|
|
47
|
+
* émetteurs. Les logiciels du marché (ex. LICIEL) calculent ainsi mais exportent « moyenne ».
|
|
48
|
+
*
|
|
49
|
+
* @param emChDe {object} donnee_entree de l'émetteur
|
|
50
|
+
* @param emChDu {object} donnee_utilisateur de l'émetteur
|
|
51
|
+
* @return {string|undefined}
|
|
52
|
+
*/
|
|
53
|
+
export function tempDistributionChPourTempFonc(emChDe, emChDu) {
|
|
54
|
+
const tempDistribution = requestInputID(emChDe, emChDu, 'temp_distribution_ch');
|
|
55
|
+
const typeEmission = String(emChDe?.enum_type_emission_distribution_id ?? '');
|
|
56
|
+
if (
|
|
57
|
+
String(tempDistribution) === '3' &&
|
|
58
|
+
EMISSION_PLANCHER_PLAFOND_CHAUFFANT_BT.includes(typeEmission)
|
|
59
|
+
) {
|
|
60
|
+
return '2';
|
|
61
|
+
}
|
|
62
|
+
return tempDistribution;
|
|
63
|
+
}
|
|
64
|
+
|
|
35
65
|
export function tv_temp_fonc_30_100(di, de, du, em_ch, ac) {
|
|
36
66
|
for (const em of em_ch) {
|
|
37
67
|
const em_ch_de = em.donnee_entree;
|
|
38
68
|
const em_ch_du = em.donnee_utilisateur;
|
|
39
69
|
const matcher = {
|
|
40
70
|
enum_type_generateur_ch_id: de.enum_type_generateur_ch_id,
|
|
41
|
-
enum_temp_distribution_ch_id:
|
|
71
|
+
enum_temp_distribution_ch_id: tempDistributionChPourTempFonc(em_ch_de, em_ch_du),
|
|
42
72
|
periode_emetteurs: requestInput(em_ch_de, em_ch_du, 'periode_installation_emetteur')
|
|
43
73
|
};
|
|
44
74
|
|
|
@@ -180,7 +210,9 @@ export function calc_generateur_combustion_ch(dpe, di, de, du) {
|
|
|
180
210
|
|
|
181
211
|
// Pveil and QP0 are in kW
|
|
182
212
|
const Pveil = di.pveil / 1000;
|
|
183
|
-
|
|
213
|
+
// rg est d'abord calculé sur PCS (puis × k pour revenir en PCI) : QP0 doit donc être exprimé
|
|
214
|
+
// sur PCS, comme dans QPx() (qp0 × k). Cf. issue #205.
|
|
215
|
+
const QP0 = (di.qp0 * k) / 1000;
|
|
184
216
|
|
|
185
217
|
const rg_pcs = Pmfou / (Pmcons + 0.45 * QP0 + Pveil);
|
|
186
218
|
const rg_pcs_dep = Pmfou_dep / (Pmcons_dep + 0.45 * QP0 + Pveil);
|
|
@@ -38,7 +38,7 @@ vi.mock('./utils.js', () => ({
|
|
|
38
38
|
requestInputID: vi.fn((de, du, field) => de[`enum_${field}_id`])
|
|
39
39
|
}));
|
|
40
40
|
|
|
41
|
-
const { tv_temp_fonc_30_100, calc_generateur_combustion_ch } =
|
|
41
|
+
const { tv_temp_fonc_30_100, tempDistributionChPourTempFonc, calc_generateur_combustion_ch } =
|
|
42
42
|
await import('./13.2_generateur_combustion_ch.js');
|
|
43
43
|
const { tv } = await import('./utils.js');
|
|
44
44
|
|
|
@@ -138,6 +138,75 @@ describe('tv_temp_fonc_30_100 - températures de fonctionnement', () => {
|
|
|
138
138
|
expect(errSpy).toHaveBeenCalledTimes(2);
|
|
139
139
|
errSpy.mockRestore();
|
|
140
140
|
});
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Plancher / plafond chauffant à eau < 65 °C : la ligne « basse » est retenue même si le DPE
|
|
144
|
+
* déclare « moyenne » (comportement du moteur de référence CSTB / Tribu).
|
|
145
|
+
*/
|
|
146
|
+
test.each(['12', '14', '16', '18'])(
|
|
147
|
+
'plancher/plafond chauffant BT (émission %s) déclaré « moyenne » : ligne « basse » utilisée',
|
|
148
|
+
(typeEmission) => {
|
|
149
|
+
tv.mockReturnValue({ tv_temp_fonc_30_id: '1', temp_fonc_30: '24.5' });
|
|
150
|
+
tv_temp_fonc_30_100(
|
|
151
|
+
{},
|
|
152
|
+
{ enum_type_generateur_ch_id: '97' },
|
|
153
|
+
{},
|
|
154
|
+
[emetteur({ enum_type_emission_distribution_id: typeEmission })],
|
|
155
|
+
2018
|
|
156
|
+
);
|
|
157
|
+
expect(tv).toHaveBeenCalledWith(
|
|
158
|
+
'temp_fonc_30',
|
|
159
|
+
expect.objectContaining({ enum_temp_distribution_ch_id: '2' })
|
|
160
|
+
);
|
|
161
|
+
expect(tv).toHaveBeenCalledWith(
|
|
162
|
+
'temp_fonc_100',
|
|
163
|
+
expect.objectContaining({ enum_temp_distribution_ch_id: '2' })
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
test.each([
|
|
169
|
+
['radiateur (35), moyenne', '35', '3', '3'],
|
|
170
|
+
['plancher chauffant HT (13), moyenne', '13', '3', '3'],
|
|
171
|
+
['plancher chauffant BT (14), haute', '14', '4', '4'],
|
|
172
|
+
['plancher chauffant BT (14), basse', '14', '2', '2']
|
|
173
|
+
])(
|
|
174
|
+
'%s : température de distribution déclarée conservée',
|
|
175
|
+
(_, typeEmission, declaree, attendue) => {
|
|
176
|
+
tv.mockReturnValue({ tv_temp_fonc_30_id: '1', temp_fonc_30: '40' });
|
|
177
|
+
tv_temp_fonc_30_100(
|
|
178
|
+
{},
|
|
179
|
+
{ enum_type_generateur_ch_id: '97' },
|
|
180
|
+
{},
|
|
181
|
+
[
|
|
182
|
+
emetteur({
|
|
183
|
+
enum_type_emission_distribution_id: typeEmission,
|
|
184
|
+
enum_temp_distribution_ch_id: declaree
|
|
185
|
+
})
|
|
186
|
+
],
|
|
187
|
+
2018
|
|
188
|
+
);
|
|
189
|
+
expect(tv).toHaveBeenCalledWith(
|
|
190
|
+
'temp_fonc_30',
|
|
191
|
+
expect.objectContaining({ enum_temp_distribution_ch_id: attendue })
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
describe('tempDistributionChPourTempFonc', () => {
|
|
198
|
+
test('émetteur sans type d’émission : température déclarée renvoyée telle quelle', () => {
|
|
199
|
+
expect(tempDistributionChPourTempFonc({ enum_temp_distribution_ch_id: '3' }, {})).toBe('3');
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test('type d’émission numérique (14) : reconnu comme plancher chauffant BT', () => {
|
|
203
|
+
expect(
|
|
204
|
+
tempDistributionChPourTempFonc(
|
|
205
|
+
{ enum_temp_distribution_ch_id: 3, enum_type_emission_distribution_id: 14 },
|
|
206
|
+
{}
|
|
207
|
+
)
|
|
208
|
+
).toBe('2');
|
|
209
|
+
});
|
|
141
210
|
});
|
|
142
211
|
|
|
143
212
|
/**
|
|
@@ -156,9 +225,9 @@ describe('calc_generateur_combustion_ch - rendement de génération', () => {
|
|
|
156
225
|
};
|
|
157
226
|
calc_generateur_combustion_ch({}, di, de, { cdimref: 0.8, cdimrefDep: 0.6 });
|
|
158
227
|
// valeurs de référence de régression (module réel, enums réels équivalents)
|
|
159
|
-
expect(di.rg).toBeCloseTo(0.
|
|
160
|
-
expect(di.rg_dep).toBeCloseTo(0.
|
|
161
|
-
expect(di.rendement_generation).toBeCloseTo(0.
|
|
228
|
+
expect(di.rg).toBeCloseTo(0.8575549045559866, 9);
|
|
229
|
+
expect(di.rg_dep).toBeCloseTo(0.8700736982536121, 9);
|
|
230
|
+
expect(di.rendement_generation).toBeCloseTo(0.8575549045559866, 9);
|
|
162
231
|
});
|
|
163
232
|
|
|
164
233
|
test('chaudière bois : branche de calcul dédiée (QP50 / QP100)', () => {
|
|
@@ -171,8 +240,8 @@ describe('calc_generateur_combustion_ch - rendement de génération', () => {
|
|
|
171
240
|
};
|
|
172
241
|
calc_generateur_combustion_ch({}, di, de, { cdimref: 0.9, cdimrefDep: 0.7 });
|
|
173
242
|
// valeurs de référence de régression
|
|
174
|
-
expect(di.rg).toBeCloseTo(0.
|
|
175
|
-
expect(di.rg_dep).toBeCloseTo(0.
|
|
243
|
+
expect(di.rg).toBeCloseTo(0.7040089707689774, 9);
|
|
244
|
+
expect(di.rg_dep).toBeCloseTo(0.713512984577247, 9);
|
|
176
245
|
});
|
|
177
246
|
|
|
178
247
|
test('chaudière à condensation avec régulation : température de fonctionnement à 30 % utilisée', () => {
|
|
@@ -186,8 +255,8 @@ describe('calc_generateur_combustion_ch - rendement de génération', () => {
|
|
|
186
255
|
};
|
|
187
256
|
calc_generateur_combustion_ch({}, di, de, { cdimref: 0.8, cdimrefDep: 0.6 });
|
|
188
257
|
// valeurs de référence de régression
|
|
189
|
-
expect(di.rg).toBeCloseTo(0.
|
|
190
|
-
expect(di.rg_dep).toBeCloseTo(0.
|
|
258
|
+
expect(di.rg).toBeCloseTo(0.9275325681176758, 9);
|
|
259
|
+
expect(di.rg_dep).toBeCloseTo(0.9340267431264844, 9);
|
|
191
260
|
});
|
|
192
261
|
|
|
193
262
|
test('radiateur à gaz : branche de calcul dédiée', () => {
|
|
@@ -201,8 +270,8 @@ describe('calc_generateur_combustion_ch - rendement de génération', () => {
|
|
|
201
270
|
};
|
|
202
271
|
calc_generateur_combustion_ch({}, di, de, { cdimref: 0.8, cdimrefDep: 0.6 });
|
|
203
272
|
// valeurs de référence de régression
|
|
204
|
-
expect(di.rg).toBeCloseTo(0.
|
|
205
|
-
expect(di.rg_dep).toBeCloseTo(0.
|
|
273
|
+
expect(di.rg).toBeCloseTo(0.8842491989709215, 9);
|
|
274
|
+
expect(di.rg_dep).toBeCloseTo(0.8862325713702337, 9);
|
|
206
275
|
});
|
|
207
276
|
|
|
208
277
|
test('générateur à air chaud : branche de calcul dédiée', () => {
|
|
@@ -231,8 +300,8 @@ describe('calc_generateur_combustion_ch - rendement de génération', () => {
|
|
|
231
300
|
};
|
|
232
301
|
calc_generateur_combustion_ch({}, di, de, { cdimref: 0.8, cdimrefDep: 0.6 });
|
|
233
302
|
// valeurs de référence de régression
|
|
234
|
-
expect(di.rg).toBeCloseTo(0.
|
|
235
|
-
expect(di.rg_dep).toBeCloseTo(0.
|
|
303
|
+
expect(di.rg).toBeCloseTo(0.8505103134051144, 9);
|
|
304
|
+
expect(di.rg_dep).toBeCloseTo(0.8649097139284332, 9);
|
|
236
305
|
});
|
|
237
306
|
|
|
238
307
|
test('type de générateur inconnu : aucun rendement calculé (avertissement)', () => {
|
|
@@ -262,8 +331,8 @@ describe('calc_generateur_combustion_ch - rendement de génération', () => {
|
|
|
262
331
|
};
|
|
263
332
|
calc_generateur_combustion_ch({}, di, de, {});
|
|
264
333
|
// Cdimref = 0 -> x/0 = Infinity -> min(1, ...) = 1 pour tous les x, nominal = dépensier
|
|
265
|
-
expect(di.rg).toBeCloseTo(0.
|
|
266
|
-
expect(di.rg_dep).toBeCloseTo(0.
|
|
334
|
+
expect(di.rg).toBeCloseTo(0.8963697027040485, 9);
|
|
335
|
+
expect(di.rg_dep).toBeCloseTo(0.8963697027040485, 9);
|
|
267
336
|
});
|
|
268
337
|
|
|
269
338
|
test('bug_for_bug_compat : correction de qp0 exprimé en kW (< 1) vers des W', () => {
|
|
@@ -281,7 +350,7 @@ describe('calc_generateur_combustion_ch - rendement de génération', () => {
|
|
|
281
350
|
// qp0 < 1 -> multiplié par 1000 => 200 (passage kW -> W)
|
|
282
351
|
expect(di.qp0).toBe(200);
|
|
283
352
|
// valeur de référence de régression (chaudière standard, pn = 20000, qp0 corrigé à 200)
|
|
284
|
-
expect(di.rg).toBeCloseTo(0.
|
|
353
|
+
expect(di.rg).toBeCloseTo(0.8557877790761849, 9);
|
|
285
354
|
warnSpy.mockRestore();
|
|
286
355
|
});
|
|
287
356
|
|
|
@@ -320,4 +389,68 @@ describe('calc_generateur_combustion_ch - rendement de génération', () => {
|
|
|
320
389
|
// Avec régulation (tf plus basse) le rendement est plus élevé
|
|
321
390
|
expect(diAvec.rg).toBeGreaterThan(diSans.rg);
|
|
322
391
|
});
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Référence externe (et non régression) : autotest État CSTB `APP2-0-1`, moteur
|
|
395
|
+
* Moteur_DPE.dll v2025.11.1.0 (Tribu). Chaudière gaz à condensation 2001-2015, Pn = 23 kW,
|
|
396
|
+
* valeurs par défaut. Les grandeurs intermédiaires ci-dessous sont celles de la sortie Tribu
|
|
397
|
+
* (Rpn, Rpint, Qp0, Tfonc30/100, Cdimref = 0.05 / TchFinal(Ch_5)).
|
|
398
|
+
* Avant correctif (QP0 non converti sur PCS) : rg = 0.8597041838253313. Cf. issue #205.
|
|
399
|
+
*/
|
|
400
|
+
test('autotest État APP2-0-1 : rg identique à Tribu (QP0 exprimé sur PCS)', () => {
|
|
401
|
+
const di = {
|
|
402
|
+
pn: 23000,
|
|
403
|
+
rpn: 0.9236172783601759,
|
|
404
|
+
rpint: 0.983617278360176,
|
|
405
|
+
qp0: 230,
|
|
406
|
+
pveil: 0,
|
|
407
|
+
temp_fonc_30: 38,
|
|
408
|
+
temp_fonc_100: 80
|
|
409
|
+
};
|
|
410
|
+
const de = {
|
|
411
|
+
enum_type_generateur_ch_id: '96',
|
|
412
|
+
enum_type_energie_id: '2',
|
|
413
|
+
type_energie: 'gaz naturel',
|
|
414
|
+
presence_regulation_combustion: true,
|
|
415
|
+
description: 'Chaudière gaz condensation'
|
|
416
|
+
};
|
|
417
|
+
const cdimref = 0.05 / 0.00603495141488493;
|
|
418
|
+
calc_generateur_combustion_ch({}, di, de, { cdimref, cdimrefDep: cdimref });
|
|
419
|
+
// Rg Tribu (sortie APP2-0-1_Sortie.xml) : 0.8511886946001722
|
|
420
|
+
expect(di.rg).toBeCloseTo(0.8511886946001722, 12);
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
test('les pertes à charge nulle QP0 réduisent le rendement de génération', () => {
|
|
424
|
+
const di = () => ({
|
|
425
|
+
pn: 23000,
|
|
426
|
+
rpn: 0.92,
|
|
427
|
+
rpint: 0.98,
|
|
428
|
+
qp0: 230,
|
|
429
|
+
pveil: 0,
|
|
430
|
+
temp_fonc_30: 38,
|
|
431
|
+
temp_fonc_100: 80
|
|
432
|
+
});
|
|
433
|
+
const de = {
|
|
434
|
+
enum_type_generateur_ch_id: '96',
|
|
435
|
+
enum_type_energie_id: '2',
|
|
436
|
+
presence_regulation_combustion: true,
|
|
437
|
+
description: 't'
|
|
438
|
+
};
|
|
439
|
+
const avecPertes = di();
|
|
440
|
+
calc_generateur_combustion_ch(
|
|
441
|
+
{},
|
|
442
|
+
avecPertes,
|
|
443
|
+
{ ...de, type_energie: 'gaz naturel' },
|
|
444
|
+
{ cdimref: 8 }
|
|
445
|
+
);
|
|
446
|
+
const sansPertes = { ...di(), qp0: 0 };
|
|
447
|
+
calc_generateur_combustion_ch(
|
|
448
|
+
{},
|
|
449
|
+
sansPertes,
|
|
450
|
+
{ ...de, type_energie: 'gaz naturel' },
|
|
451
|
+
{ cdimref: 8 }
|
|
452
|
+
);
|
|
453
|
+
// le terme 0.45 × QP0 réduit bien le rendement
|
|
454
|
+
expect(avecPertes.rg).toBeLessThan(sansPertes.rg);
|
|
455
|
+
});
|
|
323
456
|
});
|
package/README.md
CHANGED
|
@@ -23,8 +23,6 @@ Implémentation open source du moteur Open3CL de l'ADEME.
|
|
|
23
23
|
·
|
|
24
24
|
<a href="https://github.com/Open3CL/engine/issues/new?labels=enhancement&template=feature-request---.md">Créer une feature</a>
|
|
25
25
|
·
|
|
26
|
-
<a href="https://open3cl.github.io/engine/build/">Démo en ligne</a>
|
|
27
|
-
·
|
|
28
26
|
<a href="https://open3cl.github.io/engine/reports/corpus">Rapports de corpus</a>
|
|
29
27
|
</p>
|
|
30
28
|
</div>
|
|
@@ -57,7 +55,6 @@ Implémentation open source du moteur Open3CL de l'ADEME.
|
|
|
57
55
|
<li><a href="#api-publique">API publique</a></li>
|
|
58
56
|
<li><a href="#options-de-calcul">Options de calcul</a></li>
|
|
59
57
|
<li><a href="#lire-le-résultat">Lire le résultat</a></li>
|
|
60
|
-
<li><a href="#tester-un-dpe-sans-écrire-de-code">Tester un DPE sans écrire de code</a></li>
|
|
61
58
|
</ul>
|
|
62
59
|
</li>
|
|
63
60
|
<li><a href="#-tests-de-corpus">Tests de corpus</a>
|
|
@@ -142,12 +139,11 @@ flowchart LR
|
|
|
142
139
|
|
|
143
140
|
### L'écosystème Open3CL
|
|
144
141
|
|
|
145
|
-
| Ressource | Description
|
|
146
|
-
| :-------------------------------------------------------------------- |
|
|
147
|
-
| [open3cl.fr](https://open3cl.fr) | Le site du projet
|
|
148
|
-
| [
|
|
149
|
-
| [
|
|
150
|
-
| [@open3cl/engine](https://www.npmjs.com/package/@open3cl/engine) | Le paquet npm |
|
|
142
|
+
| Ressource | Description |
|
|
143
|
+
| :-------------------------------------------------------------------- | :-------------------------------------------------------- |
|
|
144
|
+
| [open3cl.fr](https://open3cl.fr) | Le site du projet |
|
|
145
|
+
| [Rapports de corpus](https://open3cl.github.io/engine/reports/corpus) | Le tableau de bord interactif des résultats sur DPE réels |
|
|
146
|
+
| [@open3cl/engine](https://www.npmjs.com/package/@open3cl/engine) | Le paquet npm |
|
|
151
147
|
|
|
152
148
|
<p align="right">(<a href="#readme-top">Retour sommaire</a>)</p>
|
|
153
149
|
|
|
@@ -292,17 +288,6 @@ Le DPE renvoyé est l'objet d'entrée, enrichi de `logement.sortie` :
|
|
|
292
288
|
| `sortie.confort_ete` / `qualite_isolation` | Indicateurs de confort d'été et de qualité d'isolation |
|
|
293
289
|
| `sortie.production_electricite` | Production photovoltaïque |
|
|
294
290
|
|
|
295
|
-
### Tester un DPE sans écrire de code
|
|
296
|
-
|
|
297
|
-
Le [démonstrateur en ligne](https://open3cl.github.io/engine/build/) accepte un DPE au format XML, l'envoie au moteur et
|
|
298
|
-
affiche **côte à côte** les valeurs du DPE d'origine, celles calculées par Open3CL, et le différentiel.
|
|
299
|
-
|
|
300
|
-
C'est le moyen le plus rapide de qualifier un écart : problème dans le DPE d'origine, ou bug dans la librairie ?
|
|
301
|
-
|
|
302
|
-
<p align="right">(<a href="#readme-top">Retour sommaire</a>)</p>
|
|
303
|
-
|
|
304
|
-
---
|
|
305
|
-
|
|
306
291
|
## 🧪 Tests de corpus
|
|
307
292
|
|
|
308
293
|
> Un corpus, c'est une liste de numéros de DPE réels. Le moteur les rejoue **tous**, compare ses sorties à celles du
|
|
@@ -385,7 +370,7 @@ Ces résultats sont **générés automatiquement** à la fin de `npm run test:co
|
|
|
385
370
|
|
|
386
371
|
<!-- CORPUS:START -->
|
|
387
372
|
|
|
388
|
-
> **Version `1.
|
|
373
|
+
> **Version `1.8.0`** · à publier · branche `main` · généré le 2026-09-24
|
|
389
374
|
> Seuil de tolérance **5%**
|
|
390
375
|
|
|
391
376
|
<table>
|
|
@@ -418,24 +403,24 @@ Ces résultats sont **générés automatiquement** à la fin de `npm run test:co
|
|
|
418
403
|
|
|
419
404
|
<table>
|
|
420
405
|
<tr>
|
|
421
|
-
<td align="center"><strong>5,
|
|
422
|
-
<td align="center"><strong>4,
|
|
423
|
-
<td align="center"><strong>0,
|
|
424
|
-
<td align="center"><strong>
|
|
406
|
+
<td align="center"><strong>5,43 ms</strong><br/><sub>moyenne</sub></td>
|
|
407
|
+
<td align="center"><strong>4,72 ms</strong><br/><sub>médiane</sub></td>
|
|
408
|
+
<td align="center"><strong>0,11 ms</strong><br/><sub>min</sub></td>
|
|
409
|
+
<td align="center"><strong>594,4 ms</strong><br/><sub>max</sub></td>
|
|
425
410
|
</tr>
|
|
426
411
|
</table>
|
|
427
412
|
|
|
428
413
|
| Corpus | Moyenne | Médiane | Min | Max | p95 | p99 |
|
|
429
414
|
| :--------------------------------------------- | ------: | ------: | ------: | -------: | ------: | ------: |
|
|
430
|
-
| **Généraliste** | 4,
|
|
431
|
-
| **Appartement · chauffage individuel (2025)** | 3,
|
|
432
|
-
| **Logement individuel (2025)** |
|
|
433
|
-
| **Maison individuelle (2025)** |
|
|
434
|
-
| **Immeuble · chauffage individuel** | 6,
|
|
435
|
-
| **Appartement · chauffage collectif (2025)** |
|
|
436
|
-
| **Immeuble · chauffage collectif** |
|
|
437
|
-
| **Immeuble · chauffage mixte** |
|
|
438
|
-
| **Individuel généré depuis l'immeuble (2026)** |
|
|
415
|
+
| **Généraliste** | 4,33 ms | 3,93 ms | 0,21 ms | 30,4 ms | 7,86 ms | 10,9 ms |
|
|
416
|
+
| **Appartement · chauffage individuel (2025)** | 3,61 ms | 3,20 ms | 1,24 ms | 26,4 ms | 6,48 ms | 10,4 ms |
|
|
417
|
+
| **Logement individuel (2025)** | 5,42 ms | 4,74 ms | 1,53 ms | 61,7 ms | 10,6 ms | 14,8 ms |
|
|
418
|
+
| **Maison individuelle (2025)** | 6,55 ms | 5,93 ms | 1,72 ms | 50,5 ms | 11,9 ms | 16,0 ms |
|
|
419
|
+
| **Immeuble · chauffage individuel** | 6,70 ms | 5,75 ms | 0,11 ms | 111,2 ms | 13,5 ms | 22,6 ms |
|
|
420
|
+
| **Appartement · chauffage collectif (2025)** | 3,84 ms | 3,46 ms | 1,11 ms | 58,2 ms | 6,43 ms | 9,51 ms |
|
|
421
|
+
| **Immeuble · chauffage collectif** | 5,43 ms | 4,58 ms | 0,13 ms | 99,6 ms | 10,2 ms | 18,9 ms |
|
|
422
|
+
| **Immeuble · chauffage mixte** | 6,56 ms | 5,20 ms | 0,21 ms | 594,4 ms | 14,5 ms | 25,1 ms |
|
|
423
|
+
| **Individuel généré depuis l'immeuble (2026)** | 6,44 ms | 5,70 ms | 1,76 ms | 43,1 ms | 12,3 ms | 18,5 ms |
|
|
439
424
|
|
|
440
425
|
<sub>La moyenne est tirée vers le haut par les DPE collectifs, dont le coût atteint plusieurs
|
|
441
426
|
dizaines de fois la médiane : c’est la médiane qui décrit le cas courant, et p95/p99 le cas
|
package/conso.js
CHANGED
|
@@ -249,6 +249,7 @@ export default function calc_conso(
|
|
|
249
249
|
null,
|
|
250
250
|
prorataECS,
|
|
251
251
|
prorataChauffage,
|
|
252
|
+
ecs,
|
|
252
253
|
conso_aux_distribution_ecs_total
|
|
253
254
|
),
|
|
254
255
|
ep_conso: calc_conso_pond(
|
|
@@ -262,6 +263,7 @@ export default function calc_conso(
|
|
|
262
263
|
coeffEp,
|
|
263
264
|
prorataECS,
|
|
264
265
|
prorataChauffage,
|
|
266
|
+
ecs,
|
|
265
267
|
conso_aux_distribution_ecs_total
|
|
266
268
|
),
|
|
267
269
|
emission_ges: calc_conso_pond(
|
|
@@ -275,6 +277,7 @@ export default function calc_conso(
|
|
|
275
277
|
coef_ges,
|
|
276
278
|
prorataECS,
|
|
277
279
|
prorataChauffage,
|
|
280
|
+
ecs,
|
|
278
281
|
conso_aux_distribution_ecs_total
|
|
279
282
|
),
|
|
280
283
|
cout: calc_conso_pond(
|
|
@@ -288,6 +291,7 @@ export default function calc_conso(
|
|
|
288
291
|
coef_cout,
|
|
289
292
|
prorataECS,
|
|
290
293
|
prorataChauffage,
|
|
294
|
+
ecs,
|
|
291
295
|
conso_aux_distribution_ecs_total
|
|
292
296
|
)
|
|
293
297
|
};
|
|
@@ -343,7 +347,8 @@ export default function calc_conso(
|
|
|
343
347
|
'',
|
|
344
348
|
null,
|
|
345
349
|
prorataECS,
|
|
346
|
-
prorataChauffage
|
|
350
|
+
prorataChauffage,
|
|
351
|
+
type_energie === 'électricité' ? ecs : []
|
|
347
352
|
);
|
|
348
353
|
conso_en = {
|
|
349
354
|
conso_ch: conso_en._ch,
|
|
@@ -474,7 +479,7 @@ function calc_conso_pond(
|
|
|
474
479
|
coef,
|
|
475
480
|
prorataECS,
|
|
476
481
|
prorataChauffage,
|
|
477
|
-
|
|
482
|
+
ecs_installations
|
|
478
483
|
) {
|
|
479
484
|
const ret = {};
|
|
480
485
|
ret.auxiliaire_ventilation = vt_list.reduce((acc, vt) => {
|
|
@@ -538,11 +543,10 @@ function calc_conso_pond(
|
|
|
538
543
|
return acc + getConso(coef, 'électricité auxiliaire', conso);
|
|
539
544
|
}, 0);
|
|
540
545
|
|
|
541
|
-
ret.auxiliaire_distribution_ecs =
|
|
542
|
-
|
|
543
|
-
'électricité auxiliaire',
|
|
544
|
-
|
|
545
|
-
);
|
|
546
|
+
ret.auxiliaire_distribution_ecs = ecs_installations.reduce((acc, inst) => {
|
|
547
|
+
const conso = inst.donnee_intermediaire.conso_auxiliaire_distribution_ecs || 0;
|
|
548
|
+
return acc + getConso(coef, 'électricité auxiliaire', conso);
|
|
549
|
+
}, 0);
|
|
546
550
|
|
|
547
551
|
ret.ecs = getEcsConso(gen_ecs, 'conso_ecs', coef, prorataECS, prefix);
|
|
548
552
|
|
package/engine.js
CHANGED
|
@@ -33,7 +33,7 @@ import getFicheTechnique from './ficheTechnique.js';
|
|
|
33
33
|
import { ProductionENR } from './16.2_production_enr.js';
|
|
34
34
|
import DpeSanitizerService from './dpe-sanitizer.service.js';
|
|
35
35
|
|
|
36
|
-
const LIB_VERSION = '1.
|
|
36
|
+
const LIB_VERSION = '1.8.1';
|
|
37
37
|
|
|
38
38
|
const dpeSanitizerService = new DpeSanitizerService();
|
|
39
39
|
|
|
@@ -437,7 +437,8 @@ export function calcul_3cl(inputDpe, options) {
|
|
|
437
437
|
virtualisationECS,
|
|
438
438
|
dpe.logement.caracteristique_generale.surface_habitable_immeuble,
|
|
439
439
|
dpe.logement.caracteristique_generale.nombre_appartement,
|
|
440
|
-
isImmeubleSystemEcsIndividuels
|
|
440
|
+
isImmeubleSystemEcsIndividuels,
|
|
441
|
+
apport_et_besoin.besoin_ecs_par_mois || {}
|
|
441
442
|
);
|
|
442
443
|
|
|
443
444
|
if (!dpeGenereImmeuble) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open3cl/engine",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "Open Source 3CL-DPE engine",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
"assets:sync": "node scripts/synchronize_assets.js",
|
|
30
30
|
"version:update": "node scripts/update_version.js",
|
|
31
31
|
"reports:preview": "npm run http-server dist/reports/corpus -o",
|
|
32
|
-
"reports:readme": "node scripts/generate_corpus_readme.js"
|
|
32
|
+
"reports:readme": "node scripts/generate_corpus_readme.js",
|
|
33
|
+
"reports:stamp": "node scripts/stamp_corpus_release.js",
|
|
34
|
+
"reports:version": "node scripts/corpus_version.js"
|
|
33
35
|
},
|
|
34
36
|
"repository": {
|
|
35
37
|
"type": "git",
|
|
@@ -52,6 +54,7 @@
|
|
|
52
54
|
"@commitlint/cz-commitlint": "^19.2.0",
|
|
53
55
|
"@duckdb/node-api": "^1.3.2-alpha.25",
|
|
54
56
|
"@semantic-release/changelog": "^6.0.3",
|
|
57
|
+
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
55
58
|
"@semantic-release/exec": "^7.1.0",
|
|
56
59
|
"@semantic-release/git": "^10.0.1",
|
|
57
60
|
"@semantic-release/github": "^12.0.2",
|
|
@@ -70,6 +73,7 @@
|
|
|
70
73
|
"fast-csv": "^5.0.2",
|
|
71
74
|
"http-server": "^14.1.1",
|
|
72
75
|
"husky": "^9.0.11",
|
|
76
|
+
"js-yaml": "^4.3.2",
|
|
73
77
|
"jscpd": "^3.5.10",
|
|
74
78
|
"piscina": "^5.1.2",
|
|
75
79
|
"prettier": "^3.2.5",
|