@open3cl/engine 1.6.1 → 1.6.2
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/10_besoin_fr.spec.js +122 -0
- package/10_clim.spec.js +116 -0
- package/11_besoin_ecs.spec.js +69 -0
- package/11_ecs.spec.js +282 -0
- package/11_nadeq.spec.js +37 -0
- package/12.4_pac.spec.js +131 -0
- package/13.2_generateur_combustion.js +2 -0
- package/13.2_generateur_combustion.spec.js +537 -0
- package/13.2_generateur_combustion_bouilleur.js +4 -1
- package/13.2_generateur_combustion_bouilleur.spec.js +74 -0
- package/13.2_generateur_combustion_ch.spec.js +323 -0
- package/13.2_generateur_combustion_chaudiere.spec.js +85 -0
- package/13.2_generateur_pac.spec.js +64 -0
- package/13_rendement_distribution_ecs.spec.js +38 -0
- package/14_generateur_ecs.js +4 -4
- package/14_generateur_ecs.spec.js +745 -0
- package/15_conso_aux.spec.js +225 -0
- package/16.2_production_enr.spec.js +188 -0
- package/16_conso_eclairage.spec.js +62 -0
- package/2021_04_13_confort_ete.spec.js +159 -0
- package/2021_04_13_qualite_isolation.js +1 -1
- package/2021_04_13_qualite_isolation.spec.js +286 -0
- package/3.1_b.js +1 -1
- package/3.1_b.spec.js +367 -0
- package/3.2.1_mur.spec.js +812 -39
- package/3.2.2_plancher_bas.spec.js +643 -78
- package/3.2.3_plancher_haut.spec.js +452 -0
- package/3.3.1.4_porte.spec.js +114 -0
- package/3.3_baie_vitree.spec.js +449 -295
- package/3.4_pont_thermique.spec.js +890 -0
- package/3_deperdition.spec.js +397 -0
- package/4_ventilation.js +1 -1
- package/4_ventilation.spec.js +406 -0
- package/5_conso_ventilation.spec.js +186 -0
- package/6.2_surface_sud_equivalente.spec.js +138 -0
- package/8_intermittence.spec.js +33 -0
- package/9_besoin_ch.js +2 -2
- package/9_besoin_ch.spec.js +381 -0
- package/9_chauffage.js +4 -0
- package/9_chauffage.spec.js +478 -92
- package/9_conso_ch.spec.js +502 -248
- package/9_emetteur_ch.spec.js +339 -0
- package/9_generateur_ch.spec.js +467 -81
- package/apport_et_besoin.spec.js +126 -0
- package/conso.js +1 -1
- package/conso.spec.js +471 -82
- package/core/assets/domain/add-additionnal-ue-values-tables.spec.js +53 -0
- package/core/assets/domain/synchronize-solicitations-tables.spec.js +25 -0
- package/core/assets/domain/synchronize-valeur-tables.spec.js +48 -0
- package/core/conf/infrastructure/application.config.spec.js +35 -0
- package/core/file/infrastructure/adapter/csv-parser.store.spec.js +31 -13
- package/core/file/infrastructure/adapter/file.store.spec.js +148 -12
- package/core/tv/infrastructure/assets/additional-ue-values.spec.js +36 -0
- package/core/util/infrastructure/object-util.spec.js +20 -0
- package/core/util/logger/log-service.js +16 -7
- package/core/util/logger/log-service.spec.js +101 -0
- package/dpe-sanitizer.service.spec.js +138 -0
- package/engine.js +4 -1
- package/engine.spec.js +854 -0
- package/enums.spec.js +46 -0
- package/features/dpe/domain/models/type-generateur.model.js +1 -2
- package/features/dpe/domain/models/type-generateur.model.spec.js +25 -0
- package/features/dpe/domain/models/type-habitation.model.spec.js +41 -0
- package/features/dpe/domain/models/type-stockage.model.spec.js +18 -0
- package/features/dpe/domain/models/type-ventilation.model.spec.js +19 -0
- package/features/dpe/infrastructure/ch/chTv.store.spec.js +4 -4
- package/features/dpe/infrastructure/enveloppe/baieVitreeTv.store.js +14 -2
- package/features/dpe/infrastructure/enveloppe/baieVitreeTv.store.spec.js +16 -0
- package/features/dpe/infrastructure/tv.store.js +28 -9
- package/features/dpe/infrastructure/tv.store.spec.js +44 -0
- package/features/engine/domain/apport_et_besoin/apport-et-besoin.service.spec.js +2 -1
- package/features/engine/domain/apport_et_besoin/ch/besoin-ch.service.spec.js +18 -0
- package/features/engine/domain/apport_et_besoin/ch/perte-ch-recup.service.spec.js +33 -1
- package/features/engine/domain/apport_et_besoin/ecs/besoin-ecs.service.spec.js +21 -1
- package/features/engine/domain/apport_et_besoin/ecs/perte-ecs-recup.service.spec.js +41 -1
- package/features/engine/domain/apport_et_besoin/froid/besoin-froid.service.spec.js +44 -1
- package/features/engine/domain/apport_et_besoin/surface-sud-equivalente.service.spec.js +2 -1
- package/features/engine/domain/ch/generateur-ch.service.js +2 -0
- package/features/engine/domain/ch/generateur-ch.service.spec.js +117 -2
- package/features/engine/domain/ch/installation-ch.service.spec.js +14 -0
- package/features/engine/domain/conso/froid/conso-froid.service.spec.js +82 -1
- package/features/engine/domain/constants.spec.js +14 -0
- package/features/engine/domain/contexte.builder.spec.js +21 -0
- package/features/engine/domain/ecs/generateur-ecs.service.spec.js +11 -0
- package/features/engine/domain/ecs/installation-ecs.service.spec.js +55 -2
- package/features/engine/domain/engine.service.spec.js +227 -4
- package/features/engine/domain/enveloppe/baie_vitree/deperdition-baie-vitree.service.spec.js +124 -1
- package/features/engine/domain/enveloppe/deperdition-enveloppe.service.spec.js +270 -2
- package/features/engine/domain/enveloppe/deperdition.service.spec.js +141 -0
- package/features/engine/domain/enveloppe/espace_tampon/espace-tampon.service.spec.js +2 -1
- package/features/engine/domain/enveloppe/mur/deperdition-mur.service.spec.js +117 -1
- package/features/engine/domain/enveloppe/plancher_bas/deperdition-plancher-bas.service.spec.js +134 -1
- package/features/engine/domain/enveloppe/plancher_haut/deperdition-plancher-haut.service.spec.js +126 -1
- package/features/engine/domain/enveloppe/pont_thermique/deperdition-pont-thermique.service.spec.js +18 -1
- package/features/engine/domain/enveloppe/porte/deperdition-porte.service.spec.js +2 -1
- package/features/engine/domain/enveloppe/ventilation/deperdition-ventilation.service.spec.js +67 -1
- package/features/normalizer/domain/dpe-normalizer.service.js +1 -1
- package/features/normalizer/domain/dpe-normalizer.service.spec.js +53 -2
- package/ficheTechnique.spec.js +26 -0
- package/index.spec.js +54 -0
- package/package.json +5 -2
- package/preprocessor/index.js +20 -0
- package/preprocessor/index.spec.js +15 -0
- package/tv.spec.js +38 -0
- package/utils.js +43 -1
- package/utils.spec.js +518 -2
- package/output.js +0 -1
package/9_generateur_ch.spec.js
CHANGED
|
@@ -1,94 +1,480 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { describe, expect, test } from 'vitest';
|
|
1
|
+
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Dépendances mockées pour isoler `9_generateur_ch.js` :
|
|
5
|
+
* - `enums` : libellés des types de générateurs (ch / ecs) ;
|
|
6
|
+
* - `utils` : `requestInput` / `requestInputID` (accès aux données d'entrée),
|
|
7
|
+
* `tv` (tables de valeurs) et `tvColumnIDs` (listes d'ids par colonne) ;
|
|
8
|
+
* - `15_conso_aux` : consommations d'auxiliaires (génération / distribution) ;
|
|
9
|
+
* - `9_conso_ch` : `conso_ch` (délégation finale) ;
|
|
10
|
+
* - `13.2_generateur_combustion_ch` / `12.4_pac` / `13.2_generateur_combustion` :
|
|
11
|
+
* calculs spécialisés (combustion / PAC) pilotés par des espions.
|
|
12
|
+
*
|
|
13
|
+
* On vérifie la logique d'aiguillage propre au module (type de générateur,
|
|
14
|
+
* récupération d'énergie, auxiliaires, parois anciennes) sans dépendre des
|
|
15
|
+
* données réelles des tables.
|
|
16
|
+
*/
|
|
17
|
+
vi.mock('./enums.js', () => ({
|
|
18
|
+
default: {
|
|
19
|
+
type_generateur_ch: {
|
|
20
|
+
1: 'chaudière gaz',
|
|
21
|
+
2: 'générateur à air chaud',
|
|
22
|
+
5: 'chaudière fioul',
|
|
23
|
+
10: 'pac air/eau'
|
|
24
|
+
},
|
|
25
|
+
type_generateur_ecs: {
|
|
26
|
+
1: 'chaudière gaz'
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
vi.mock('./utils.js', () => ({
|
|
32
|
+
requestInput: vi.fn(),
|
|
33
|
+
requestInputID: vi.fn(),
|
|
34
|
+
tv: vi.fn(),
|
|
35
|
+
tvColumnIDs: vi.fn()
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
vi.mock('./15_conso_aux.js', () => ({
|
|
39
|
+
conso_aux_distribution_ch: vi.fn(),
|
|
40
|
+
conso_aux_gen: vi.fn()
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
vi.mock('./9_conso_ch.js', () => ({
|
|
44
|
+
conso_ch: vi.fn()
|
|
45
|
+
}));
|
|
46
|
+
|
|
47
|
+
vi.mock('./13.2_generateur_combustion_ch.js', () => ({
|
|
48
|
+
calc_generateur_combustion_ch: vi.fn()
|
|
49
|
+
}));
|
|
50
|
+
|
|
51
|
+
vi.mock('./12.4_pac.js', () => ({
|
|
52
|
+
scopOrCop: vi.fn()
|
|
53
|
+
}));
|
|
54
|
+
|
|
55
|
+
vi.mock('./13.2_generateur_combustion.js', () => ({
|
|
56
|
+
updateGenerateurCombustion: vi.fn()
|
|
57
|
+
}));
|
|
58
|
+
|
|
59
|
+
const {
|
|
60
|
+
calc_Qrec_gen_j,
|
|
61
|
+
type_generateur_ch,
|
|
62
|
+
checkForGeneratorType,
|
|
63
|
+
calc_generateur_ch,
|
|
64
|
+
hasConsoForAuxDistribution
|
|
65
|
+
} = await import('./9_generateur_ch.js');
|
|
66
|
+
const { requestInput, requestInputID, tv, tvColumnIDs } = await import('./utils.js');
|
|
67
|
+
const { conso_aux_distribution_ch, conso_aux_gen } = await import('./15_conso_aux.js');
|
|
68
|
+
const { conso_ch } = await import('./9_conso_ch.js');
|
|
69
|
+
const { calc_generateur_combustion_ch } = await import('./13.2_generateur_combustion_ch.js');
|
|
70
|
+
const { scopOrCop } = await import('./12.4_pac.js');
|
|
71
|
+
const { updateGenerateurCombustion } = await import('./13.2_generateur_combustion.js');
|
|
72
|
+
|
|
73
|
+
beforeEach(() => {
|
|
74
|
+
vi.mocked(requestInput).mockReset();
|
|
75
|
+
vi.mocked(requestInputID).mockReset();
|
|
76
|
+
vi.mocked(tv).mockReset();
|
|
77
|
+
vi.mocked(tvColumnIDs).mockReset();
|
|
78
|
+
vi.mocked(conso_aux_distribution_ch).mockReset();
|
|
79
|
+
vi.mocked(conso_aux_gen).mockReset();
|
|
80
|
+
vi.mocked(conso_ch).mockReset();
|
|
81
|
+
vi.mocked(calc_generateur_combustion_ch).mockReset();
|
|
82
|
+
vi.mocked(scopOrCop).mockReset();
|
|
83
|
+
vi.mocked(updateGenerateurCombustion).mockReset();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 9.1.1 Pertes récupérées de génération pour le chauffage (Qrec_gen)
|
|
88
|
+
* @see : Methode_de_calcul_3CL_DPE_2021-338.pdf - §9.1.1
|
|
89
|
+
*/
|
|
90
|
+
describe('calc_Qrec_gen_j - pertes de génération récupérées', () => {
|
|
91
|
+
/** Générateur minimal en volume chauffé, non "air chaud". */
|
|
92
|
+
function generateur(overridesDe = {}, di = { pn: 10000, qp0: 100 }) {
|
|
93
|
+
return {
|
|
12
94
|
donnee_entree: {
|
|
13
|
-
description: 'Electrique - Convecteur électrique NFC, NF** et NF***',
|
|
14
|
-
reference: 'Generateur:2024_07_11_09_30_44_722898200737262#1',
|
|
15
|
-
reference_generateur_mixte: '',
|
|
16
|
-
ref_produit_generateur_ch: 'Sans Objet',
|
|
17
|
-
enum_type_generateur_ch_id: '98',
|
|
18
|
-
enum_usage_generateur_id: '1',
|
|
19
|
-
enum_type_energie_id: '1',
|
|
20
95
|
position_volume_chauffe: 1,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
96
|
+
enum_type_generateur_ch_id: '1',
|
|
97
|
+
presence_ventouse: 0,
|
|
98
|
+
...overridesDe
|
|
99
|
+
},
|
|
100
|
+
donnee_intermediaire: di
|
|
26
101
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
test('générateur hors volume chauffé : aucune récupération', () => {
|
|
105
|
+
const gen = generateur({ position_volume_chauffe: 0 });
|
|
106
|
+
expect(calc_Qrec_gen_j(gen, 50, 1000)).toBe(0);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('générateur à air chaud : aucune récupération', () => {
|
|
110
|
+
const gen = generateur({ enum_type_generateur_ch_id: '2' });
|
|
111
|
+
expect(calc_Qrec_gen_j(gen, 50, 1000)).toBe(0);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test('usage chauffage (sans ventouse, Cper = 0.5) : Dperj plafonné aux pertes de chauffage', () => {
|
|
115
|
+
vi.mocked(requestInput).mockReturnValue('chauffage');
|
|
116
|
+
const gen = generateur();
|
|
117
|
+
// 0.48 * 0.5 * 100 * min(50, 1.3*1000/(0.3*10000)) = 24 * 0.4333.. = 10.4
|
|
118
|
+
expect(calc_Qrec_gen_j(gen, 50, 1000)).toBeCloseTo(10.4, 9);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test('présence de ventouse : Cper = 0.75 augmente la récupération', () => {
|
|
122
|
+
vi.mocked(requestInput).mockReturnValue('chauffage');
|
|
123
|
+
const gen = generateur({ presence_ventouse: 1 });
|
|
124
|
+
// 0.48 * 0.75 * 100 * 0.4333.. = 15.6
|
|
125
|
+
expect(calc_Qrec_gen_j(gen, 50, 1000)).toBeCloseTo(15.6, 9);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test('usage ecs : pertes proportionnelles au nombre d’heures de référence', () => {
|
|
129
|
+
vi.mocked(requestInput).mockReturnValue('ecs');
|
|
130
|
+
const gen = generateur();
|
|
131
|
+
// 0.48 * 0.5 * 100 * (50*1790/8760)
|
|
132
|
+
expect(calc_Qrec_gen_j(gen, 50, 1000)).toBeCloseTo(245.20547945205482, 9);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test('usage chauffage + ecs : cumul plafonné au nombre d’heures de référence', () => {
|
|
136
|
+
vi.mocked(requestInput).mockReturnValue('chauffage + ecs');
|
|
137
|
+
const gen = generateur();
|
|
138
|
+
// min(50, 0.4333.. + 10.2168..) => 10.6502..
|
|
139
|
+
expect(calc_Qrec_gen_j(gen, 50, 1000)).toBeCloseTo(255.6054794520548, 9);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test('usage inconnu : Dperj indéfini => récupération nulle (|| 0)', () => {
|
|
143
|
+
vi.mocked(requestInput).mockReturnValue('autre');
|
|
144
|
+
const gen = generateur();
|
|
145
|
+
expect(calc_Qrec_gen_j(gen, 50, 1000)).toBe(0);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Détermination du type de générateur exploitable pour un usage donné.
|
|
151
|
+
*/
|
|
152
|
+
describe('type_generateur_ch - sélection du type selon l’usage', () => {
|
|
153
|
+
test('usage chauffage : renvoie directement le type saisi', () => {
|
|
154
|
+
vi.mocked(requestInputID).mockReturnValue('5');
|
|
155
|
+
expect(type_generateur_ch({}, {}, {}, 'chauffage')).toBe('5');
|
|
156
|
+
expect(requestInputID).toHaveBeenCalledWith({}, {}, 'type_generateur_ch');
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test('usage chauffage + ecs : restreint aux types communs chauffage/ECS', () => {
|
|
160
|
+
vi.mocked(requestInputID).mockReturnValue('1');
|
|
161
|
+
const res = type_generateur_ch({}, {}, {}, 'chauffage + ecs');
|
|
162
|
+
expect(res).toBe('1');
|
|
163
|
+
// seul le type '1' (chaudière gaz) est commun aux deux enums
|
|
164
|
+
expect(vi.mocked(requestInputID).mock.calls[0][3]).toEqual(['1']);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test('usage non géré : avertissement et retour indéfini', () => {
|
|
168
|
+
const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
169
|
+
expect(type_generateur_ch({}, {}, {}, 'refroidissement')).toBeUndefined();
|
|
170
|
+
expect(warn).toHaveBeenCalled();
|
|
171
|
+
warn.mockRestore();
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* checkForGeneratorType : classification combustion / PAC, cas particulier 119.
|
|
177
|
+
*/
|
|
178
|
+
describe('checkForGeneratorType - classification du générateur', () => {
|
|
179
|
+
beforeEach(() => {
|
|
180
|
+
vi.mocked(tvColumnIDs).mockImplementation((file) =>
|
|
181
|
+
file === 'generateur_combustion' ? ['5', '119'] : ['10']
|
|
182
|
+
);
|
|
183
|
+
vi.mocked(requestInput).mockReturnValue('chauffage');
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test('générateur à combustion', () => {
|
|
187
|
+
vi.mocked(requestInputID).mockReturnValue('5');
|
|
188
|
+
const de = {};
|
|
189
|
+
const du = {};
|
|
190
|
+
checkForGeneratorType({}, de, {}, du);
|
|
191
|
+
expect(du.isCombustionGenerator).toBe(true);
|
|
192
|
+
expect(du.isPacGenerator).toBe(false);
|
|
193
|
+
expect(updateGenerateurCombustion).toHaveBeenCalledWith({}, de, 'ch');
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
test('pompe à chaleur', () => {
|
|
197
|
+
vi.mocked(requestInputID).mockReturnValue('10');
|
|
198
|
+
const du = {};
|
|
199
|
+
checkForGeneratorType({}, {}, {}, du);
|
|
200
|
+
expect(du.isPacGenerator).toBe(true);
|
|
201
|
+
expect(du.isCombustionGenerator).toBe(false);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test('générateur ni combustion ni PAC', () => {
|
|
205
|
+
vi.mocked(requestInputID).mockReturnValue('99');
|
|
206
|
+
const du = {};
|
|
207
|
+
checkForGeneratorType({}, {}, {}, du);
|
|
208
|
+
expect(du.isPacGenerator).toBe(false);
|
|
209
|
+
expect(du.isCombustionGenerator).toBe(false);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test('cas 119 avec tv_generateur_combustion_id : premier type de combustion adopté', () => {
|
|
213
|
+
vi.mocked(requestInputID).mockReturnValue('119');
|
|
214
|
+
vi.mocked(tv).mockReturnValue({ enum_type_generateur_ch_id: '7|8' });
|
|
215
|
+
const de = { tv_generateur_combustion_id: 42 };
|
|
216
|
+
const du = {};
|
|
217
|
+
checkForGeneratorType({}, de, {}, du);
|
|
218
|
+
expect(de.enum_type_generateur_ch_id).toBe('7');
|
|
219
|
+
expect(du.isCombustionGenerator).toBe(true);
|
|
220
|
+
expect(du.isPacGenerator).toBe(false);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
test('cas 119 avec tv_generateur_combustion_id mais ligne sans type : combustion sans réécriture', () => {
|
|
224
|
+
vi.mocked(requestInputID).mockReturnValue('119');
|
|
225
|
+
vi.mocked(tv).mockReturnValue({ enum_type_generateur_ch_id: undefined });
|
|
226
|
+
const de = { tv_generateur_combustion_id: 42 };
|
|
227
|
+
const du = {};
|
|
228
|
+
checkForGeneratorType({}, de, {}, du);
|
|
229
|
+
expect(de.enum_type_generateur_ch_id).toBeUndefined();
|
|
230
|
+
expect(du.isCombustionGenerator).toBe(true);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
test('cas 119 avec tv_generateur_combustion_id mais aucune ligne trouvée', () => {
|
|
234
|
+
vi.mocked(requestInputID).mockReturnValue('119');
|
|
235
|
+
vi.mocked(tv).mockReturnValue(null);
|
|
236
|
+
const de = { tv_generateur_combustion_id: 42 };
|
|
237
|
+
const du = {};
|
|
238
|
+
checkForGeneratorType({}, de, {}, du);
|
|
239
|
+
expect(du.isCombustionGenerator).toBe(true);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test('cas 119 avec tv_scop_id : classé comme PAC', () => {
|
|
243
|
+
vi.mocked(requestInputID).mockReturnValue('119');
|
|
244
|
+
const de = { tv_scop_id: 7 };
|
|
245
|
+
const du = {};
|
|
246
|
+
checkForGeneratorType({}, de, {}, du);
|
|
247
|
+
expect(du.isPacGenerator).toBe(true);
|
|
248
|
+
expect(du.isCombustionGenerator).toBe(false);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
test('cas 119 par défaut : rendement de génération, premier type adopté', () => {
|
|
252
|
+
vi.mocked(requestInputID).mockReturnValue('119');
|
|
253
|
+
vi.mocked(tv).mockReturnValue({ enum_type_generateur_ch_id: '9|10' });
|
|
254
|
+
const de = { tv_rendement_generation_id: 3 };
|
|
255
|
+
const du = {};
|
|
256
|
+
checkForGeneratorType({}, de, {}, du);
|
|
257
|
+
expect(de.enum_type_generateur_ch_id).toBe('9');
|
|
258
|
+
expect(du.isPacGenerator).toBe(false);
|
|
259
|
+
expect(du.isCombustionGenerator).toBe(false);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
test('cas 119 par défaut sans ligne de rendement : aucune réécriture', () => {
|
|
263
|
+
vi.mocked(requestInputID).mockReturnValue('119');
|
|
264
|
+
vi.mocked(tv).mockReturnValue(null);
|
|
265
|
+
const de = { tv_rendement_generation_id: 3, enum_type_generateur_ch_id: '119' };
|
|
266
|
+
const du = {};
|
|
267
|
+
checkForGeneratorType({}, de, {}, du);
|
|
268
|
+
expect(de.enum_type_generateur_ch_id).toBe('119');
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* 15 Consommations d'auxiliaires de distribution : générateurs concernés.
|
|
274
|
+
* @see : Methode_de_calcul_3CL_DPE_2021-338.pdf - §15
|
|
275
|
+
*/
|
|
276
|
+
describe('hasConsoForAuxDistribution - éligibilité aux auxiliaires de distribution', () => {
|
|
277
|
+
test('générateurs éligibles (chacune des plages)', () => {
|
|
278
|
+
expect(hasConsoForAuxDistribution(110)).toBe(true); // >= 106
|
|
279
|
+
expect(hasConsoForAuxDistribution(60)).toBe(true); // 55..97
|
|
280
|
+
expect(hasConsoForAuxDistribution(50)).toBe(true); // 48..52
|
|
281
|
+
expect(hasConsoForAuxDistribution(10)).toBe(true); // 4..19
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
test('générateurs exclus (PAC air/air, poêles, radiateurs, effet joule)', () => {
|
|
285
|
+
expect(hasConsoForAuxDistribution(3)).toBe(false);
|
|
286
|
+
expect(hasConsoForAuxDistribution(20)).toBe(false);
|
|
287
|
+
expect(hasConsoForAuxDistribution(53)).toBe(false);
|
|
288
|
+
expect(hasConsoForAuxDistribution(100)).toBe(false);
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* calc_generateur_ch : aiguillage du rendement puis délégations.
|
|
294
|
+
*/
|
|
295
|
+
describe('calc_generateur_ch - orchestration du calcul générateur', () => {
|
|
296
|
+
/** dpe avec un mur non ancien, inertie légère => parois anciennes = false. */
|
|
297
|
+
function dpeSimple() {
|
|
298
|
+
return {
|
|
299
|
+
logement: {
|
|
300
|
+
enveloppe: {
|
|
301
|
+
inertie: { enum_classe_inertie_id: '3' },
|
|
302
|
+
mur_collection: {
|
|
303
|
+
mur: [
|
|
304
|
+
{
|
|
305
|
+
donnee_intermediaire: { b: 1 },
|
|
306
|
+
donnee_entree: { enum_materiaux_structure_mur_id: '1' }
|
|
307
|
+
}
|
|
308
|
+
]
|
|
309
|
+
}
|
|
310
|
+
}
|
|
54
311
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const bch = 8001.0714;
|
|
58
|
-
const bch_dep = 9714.925476692655;
|
|
59
|
-
const GV = 150.18558182166174;
|
|
60
|
-
const Sh = 22.76;
|
|
61
|
-
const Sc = 22.76;
|
|
62
|
-
const hsp = 2.5700000000000003;
|
|
63
|
-
const ca_id = 1;
|
|
64
|
-
const zc_id = 1;
|
|
65
|
-
const ac = 1;
|
|
312
|
+
};
|
|
313
|
+
}
|
|
66
314
|
|
|
315
|
+
function generateur(de = {}, du = {}, di = {}) {
|
|
316
|
+
return {
|
|
317
|
+
donnee_entree: { enum_type_generateur_ch_id: '1', ...de },
|
|
318
|
+
donnee_utilisateur: du,
|
|
319
|
+
donnee_intermediaire: di
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const emetteur = (lien) => ({
|
|
324
|
+
donnee_entree: {
|
|
325
|
+
enum_lien_generateur_emetteur_id: lien,
|
|
326
|
+
enum_type_emission_distribution_id: 'ed1'
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
function appel(gen, em_ch, dpe = dpeSimple()) {
|
|
67
331
|
calc_generateur_ch(
|
|
68
332
|
dpe,
|
|
69
|
-
|
|
70
|
-
|
|
333
|
+
gen,
|
|
334
|
+
0,
|
|
71
335
|
em_ch,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
336
|
+
'installation de chauffage simple',
|
|
337
|
+
1000,
|
|
338
|
+
2000,
|
|
339
|
+
150,
|
|
340
|
+
100,
|
|
341
|
+
2.5,
|
|
342
|
+
1,
|
|
343
|
+
1,
|
|
344
|
+
0,
|
|
345
|
+
-9.5,
|
|
346
|
+
{},
|
|
347
|
+
100,
|
|
348
|
+
[gen]
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
test('PAC avec un unique émetteur : scopOrCop appelé sur cet émetteur', () => {
|
|
353
|
+
const gen = generateur({}, { isPacGenerator: true });
|
|
354
|
+
appel(gen, [emetteur('1')]);
|
|
355
|
+
expect(scopOrCop).toHaveBeenCalledWith(
|
|
356
|
+
gen.donnee_intermediaire,
|
|
357
|
+
gen.donnee_entree,
|
|
358
|
+
gen.donnee_utilisateur,
|
|
359
|
+
1,
|
|
360
|
+
'ed1',
|
|
361
|
+
'ch'
|
|
82
362
|
);
|
|
363
|
+
// délégations finales
|
|
364
|
+
expect(conso_aux_gen).toHaveBeenCalled();
|
|
365
|
+
expect(conso_ch).toHaveBeenCalled();
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
test('PAC avec plusieurs émetteurs : sélection par lien générateur/émetteur', () => {
|
|
369
|
+
vi.mocked(requestInputID).mockReturnValue('2');
|
|
370
|
+
const gen = generateur({}, { isPacGenerator: true });
|
|
371
|
+
appel(gen, [emetteur('1'), emetteur('2')]);
|
|
372
|
+
// l'émetteur de lien '2' est retenu (enum_type_emission_distribution_id = 'ed1')
|
|
373
|
+
expect(scopOrCop).toHaveBeenCalled();
|
|
374
|
+
expect(scopOrCop.mock.calls[0][4]).toBe('ed1');
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
test('PAC sans émetteur correspondant : repli sur scop/cop saisis', () => {
|
|
378
|
+
const err = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
379
|
+
vi.mocked(requestInputID).mockReturnValue('inconnu');
|
|
380
|
+
const gen = generateur({ description: 'PAC' }, { isPacGenerator: true }, { scop: 3.2 });
|
|
381
|
+
appel(gen, [emetteur('1'), emetteur('2')]);
|
|
382
|
+
expect(scopOrCop).not.toHaveBeenCalled();
|
|
383
|
+
expect(gen.donnee_intermediaire.rg).toBe(3.2);
|
|
384
|
+
expect(gen.donnee_intermediaire.rg_dep).toBe(3.2);
|
|
385
|
+
expect(err).toHaveBeenCalled();
|
|
386
|
+
err.mockRestore();
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
test('PAC sans émetteur ni scop : repli sur le cop saisi', () => {
|
|
390
|
+
const err = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
391
|
+
vi.mocked(requestInputID).mockReturnValue('inconnu');
|
|
392
|
+
const gen = generateur({ description: 'PAC' }, { isPacGenerator: true }, { cop: 2.7 });
|
|
393
|
+
appel(gen, [emetteur('1'), emetteur('2')]);
|
|
394
|
+
expect(gen.donnee_intermediaire.rg).toBe(2.7);
|
|
395
|
+
expect(gen.donnee_intermediaire.rg_dep).toBe(2.7);
|
|
396
|
+
err.mockRestore();
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
test('générateur à combustion : délégué à calc_generateur_combustion_ch', () => {
|
|
400
|
+
const gen = generateur({}, { isCombustionGenerator: true });
|
|
401
|
+
appel(gen, [emetteur('1')]);
|
|
402
|
+
expect(calc_generateur_combustion_ch).toHaveBeenCalled();
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
test('générateur standard : rendement de génération lu en table', () => {
|
|
406
|
+
vi.mocked(requestInputID).mockReturnValue('1');
|
|
407
|
+
vi.mocked(tv).mockReturnValue({ rg: '0.85', tv_rendement_generation_id: '77' });
|
|
408
|
+
const gen = generateur();
|
|
409
|
+
appel(gen, [emetteur('1')]);
|
|
410
|
+
expect(gen.donnee_intermediaire.rendement_generation).toBe(0.85);
|
|
411
|
+
expect(gen.donnee_intermediaire.rg).toBe(0.85);
|
|
412
|
+
expect(gen.donnee_entree.tv_rendement_generation_id).toBe(77);
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
test('générateur standard sans ligne de rendement : message d’erreur', () => {
|
|
416
|
+
const err = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
417
|
+
vi.mocked(requestInputID).mockReturnValue('1');
|
|
418
|
+
vi.mocked(tv).mockReturnValue(null);
|
|
419
|
+
const gen = generateur();
|
|
420
|
+
appel(gen, [emetteur('1')]);
|
|
421
|
+
expect(err).toHaveBeenCalled();
|
|
422
|
+
err.mockRestore();
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
test('générateur éligible aux auxiliaires de distribution : conso_aux_distribution_ch appelé', () => {
|
|
426
|
+
vi.mocked(requestInputID).mockReturnValue('1');
|
|
427
|
+
vi.mocked(tv).mockReturnValue({ rg: '0.9', tv_rendement_generation_id: '1' });
|
|
428
|
+
const gen = generateur({ enum_type_generateur_ch_id: '110' });
|
|
429
|
+
appel(gen, [emetteur('1')]);
|
|
430
|
+
expect(conso_aux_distribution_ch).toHaveBeenCalled();
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
test('générateur non éligible aux auxiliaires de distribution : conso_aux_distribution_ch ignoré', () => {
|
|
434
|
+
vi.mocked(requestInputID).mockReturnValue('1');
|
|
435
|
+
vi.mocked(tv).mockReturnValue({ rg: '0.9', tv_rendement_generation_id: '1' });
|
|
436
|
+
const gen = generateur({ enum_type_generateur_ch_id: '100' });
|
|
437
|
+
appel(gen, [emetteur('1')]);
|
|
438
|
+
expect(conso_aux_distribution_ch).not.toHaveBeenCalled();
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
test('bâtiment à parois anciennes et inertie lourde transmis à conso_ch', () => {
|
|
442
|
+
vi.mocked(requestInputID).mockReturnValue('1');
|
|
443
|
+
vi.mocked(tv).mockReturnValue({ rg: '0.9', tv_rendement_generation_id: '1' });
|
|
444
|
+
const gen = generateur();
|
|
445
|
+
const dpe = {
|
|
446
|
+
logement: {
|
|
447
|
+
enveloppe: {
|
|
448
|
+
inertie: { enum_classe_inertie_id: '1' }, // inertie lourde
|
|
449
|
+
mur_collection: {
|
|
450
|
+
mur: [
|
|
451
|
+
{
|
|
452
|
+
donnee_intermediaire: { b: 1 },
|
|
453
|
+
donnee_entree: { enum_materiaux_structure_mur_id: '2' } // matériau ancien
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
// mur avec b = 0 => ignoré dans le décompte
|
|
457
|
+
donnee_intermediaire: { b: 0 },
|
|
458
|
+
donnee_entree: { enum_materiaux_structure_mur_id: '1' }
|
|
459
|
+
}
|
|
460
|
+
]
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
appel(gen, [emetteur('1')], dpe);
|
|
466
|
+
// paroi_ancienne (13e argument) transmis à conso_ch
|
|
467
|
+
expect(vi.mocked(conso_ch).mock.calls[0][12]).toBe(true);
|
|
468
|
+
});
|
|
83
469
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
470
|
+
test('générateur sans données utilisateur/intermédiaire initiales : valeurs par défaut', () => {
|
|
471
|
+
vi.mocked(requestInputID).mockReturnValue('1');
|
|
472
|
+
vi.mocked(tv).mockReturnValue({ rg: '0.9', tv_rendement_generation_id: '1' });
|
|
473
|
+
const gen = {
|
|
474
|
+
donnee_entree: { enum_type_generateur_ch_id: '1' }
|
|
475
|
+
};
|
|
476
|
+
appel(gen, [emetteur('1')]);
|
|
477
|
+
expect(gen.donnee_intermediaire).toBeDefined();
|
|
478
|
+
expect(gen.donnee_utilisateur).toBeDefined();
|
|
93
479
|
});
|
|
94
480
|
});
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Dépendances mockées pour isoler `apport_et_besoin.js` (pur assembleur) :
|
|
5
|
+
* - `enums` : mapping zone/altitude/inertie ;
|
|
6
|
+
* - besoins ECS / froid, apports internes / solaires, surface sud équivalente :
|
|
7
|
+
* simples délégations dont on contrôle le retour ;
|
|
8
|
+
* - `Nadeq` : service de calcul du nombre d'adultes équivalents, remplacé par
|
|
9
|
+
* une classe factice via `vi.hoisted`.
|
|
10
|
+
*/
|
|
11
|
+
const { calculateNadeq } = vi.hoisted(() => ({ calculateNadeq: vi.fn() }));
|
|
12
|
+
|
|
13
|
+
vi.mock('./enums.js', () => ({
|
|
14
|
+
default: {
|
|
15
|
+
zone_climatique: { 0: 'h1a' },
|
|
16
|
+
classe_altitude: { 0: 'ca1' },
|
|
17
|
+
classe_inertie: { 0: 'moyenne' }
|
|
18
|
+
}
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
vi.mock('./6.2_surface_sud_equivalente.js', () => ({ calc_sse: vi.fn() }));
|
|
22
|
+
vi.mock('./10_besoin_fr.js', () => ({ default: vi.fn() }));
|
|
23
|
+
vi.mock('./11_besoin_ecs.js', () => ({ default: vi.fn() }));
|
|
24
|
+
vi.mock('./6.1_apport_gratuit.js', () => ({ calc_ai: vi.fn(), calc_as: vi.fn() }));
|
|
25
|
+
vi.mock('./11_nadeq.js', () => ({ Nadeq: vi.fn(() => ({ calculateNadeq })) }));
|
|
26
|
+
|
|
27
|
+
const { default: calc_apport_et_besoin } = await import('./apport_et_besoin.js');
|
|
28
|
+
const { calc_sse } = await import('./6.2_surface_sud_equivalente.js');
|
|
29
|
+
const { default: calc_besoin_fr } = await import('./10_besoin_fr.js');
|
|
30
|
+
const { default: calc_besoin_ecs } = await import('./11_besoin_ecs.js');
|
|
31
|
+
const { calc_ai, calc_as } = await import('./6.1_apport_gratuit.js');
|
|
32
|
+
|
|
33
|
+
/** Logement minimal contenant les collections lues par l'assembleur. */
|
|
34
|
+
function logementFixture() {
|
|
35
|
+
return {
|
|
36
|
+
enveloppe: {
|
|
37
|
+
inertie: { enum_classe_inertie_id: 0 },
|
|
38
|
+
baie_vitree_collection: { baie_vitree: ['bv'] },
|
|
39
|
+
ets_collection: { ets: ['ets'] }
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
beforeEach(() => {
|
|
45
|
+
calculateNadeq.mockReset().mockReturnValue(2.5);
|
|
46
|
+
vi.mocked(calc_sse).mockReset().mockReturnValue(7);
|
|
47
|
+
vi.mocked(calc_besoin_ecs).mockReset().mockReturnValue({ besoin_ecs: 1 });
|
|
48
|
+
vi.mocked(calc_besoin_fr)
|
|
49
|
+
.mockReset()
|
|
50
|
+
.mockImplementation(() => ({ besoin_fr: 5, besoin_fr_depensier: 6 }));
|
|
51
|
+
vi.mocked(calc_ai)
|
|
52
|
+
.mockReset()
|
|
53
|
+
.mockImplementation(() => ({ apport_interne_ch: 10, apport_interne_fr: 20 }));
|
|
54
|
+
vi.mocked(calc_as)
|
|
55
|
+
.mockReset()
|
|
56
|
+
.mockImplementation(() => ({ apport_solaire_ch: 30, apport_solaire_fr: 40 }));
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Calcul des apports et besoins (assembleur chauffage / froid / ECS)
|
|
61
|
+
* @see : Methode_de_calcul_3CL_DPE_2021-338.pdf
|
|
62
|
+
*/
|
|
63
|
+
describe('calc_apport_et_besoin', () => {
|
|
64
|
+
test('agrège les besoins, apports et volumes ECS (climatisation présente)', () => {
|
|
65
|
+
const ret = calc_apport_et_besoin(
|
|
66
|
+
logementFixture(),
|
|
67
|
+
'maison',
|
|
68
|
+
[],
|
|
69
|
+
['clim'],
|
|
70
|
+
100,
|
|
71
|
+
1,
|
|
72
|
+
250,
|
|
73
|
+
0,
|
|
74
|
+
0,
|
|
75
|
+
0
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
expect(ret.nadeq).toBe(2.5);
|
|
79
|
+
// volumes d'ECS journaliers : 56 L et 79 L (dépensier) par adulte équivalent
|
|
80
|
+
expect(ret.v40_ecs_journalier).toBe(140);
|
|
81
|
+
expect(ret.v40_ecs_journalier_depensier).toBe(197.5);
|
|
82
|
+
expect(ret.surface_sud_equivalente).toBe(7);
|
|
83
|
+
// fusion des retours délégués
|
|
84
|
+
expect(ret.besoin_ecs).toBe(1);
|
|
85
|
+
expect(ret.besoin_fr).toBe(5);
|
|
86
|
+
expect(ret.besoin_fr_depensier).toBe(6);
|
|
87
|
+
expect(ret.apport_interne_fr).toBe(20);
|
|
88
|
+
expect(ret.apport_solaire_fr).toBe(40);
|
|
89
|
+
expect(ret.apport_interne_ch).toBe(10);
|
|
90
|
+
expect(ret.apport_solaire_ch).toBe(30);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test('délègue avec les bons libellés (altitude/zone/inertie) et collections', () => {
|
|
94
|
+
const logement = logementFixture();
|
|
95
|
+
calc_apport_et_besoin(logement, 'maison', [], ['clim'], 100, 1, 250, 4, 0, 0);
|
|
96
|
+
|
|
97
|
+
expect(calculateNadeq).toHaveBeenCalledWith(logement);
|
|
98
|
+
expect(calc_besoin_ecs).toHaveBeenCalledWith('ca1', 'h1a', 2.5);
|
|
99
|
+
expect(calc_besoin_fr).toHaveBeenCalledWith(
|
|
100
|
+
'ca1',
|
|
101
|
+
'h1a',
|
|
102
|
+
100,
|
|
103
|
+
2.5,
|
|
104
|
+
250,
|
|
105
|
+
'moyenne',
|
|
106
|
+
['bv'],
|
|
107
|
+
['ets']
|
|
108
|
+
);
|
|
109
|
+
// les apports internes/solaires reçoivent l'indicateur ilpa
|
|
110
|
+
expect(calc_ai).toHaveBeenCalledWith(4, 'ca1', 'h1a', 100, 2.5);
|
|
111
|
+
expect(calc_as).toHaveBeenCalledWith(4, 'ca1', 'h1a', ['bv'], ['ets']);
|
|
112
|
+
expect(calc_sse).toHaveBeenCalledWith('ca1', 'h1a', ['bv'], ['ets']);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('sans climatisation : besoins de froid et apports de froid remis à zéro', () => {
|
|
116
|
+
const ret = calc_apport_et_besoin(logementFixture(), 'maison', [], [], 100, 1, 250, 0, 0, 0);
|
|
117
|
+
|
|
118
|
+
expect(ret.besoin_fr).toBe(0);
|
|
119
|
+
expect(ret.besoin_fr_depensier).toBe(0);
|
|
120
|
+
expect(ret.apport_interne_fr).toBe(0);
|
|
121
|
+
expect(ret.apport_solaire_fr).toBe(0);
|
|
122
|
+
// les apports de chauffage restent inchangés
|
|
123
|
+
expect(ret.apport_interne_ch).toBe(10);
|
|
124
|
+
expect(ret.apport_solaire_ch).toBe(30);
|
|
125
|
+
});
|
|
126
|
+
});
|