@open3cl/engine 1.6.2 → 1.7.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.
Files changed (51) hide show
  1. package/10_besoin_fr.spec.js +1 -0
  2. package/10_clim.spec.js +1 -0
  3. package/11_besoin_ecs.spec.js +1 -0
  4. package/11_ecs.spec.js +1 -0
  5. package/12.4_pac.spec.js +1 -0
  6. package/13.2_generateur_combustion.spec.js +3 -3
  7. package/13.2_generateur_combustion_ch.spec.js +3 -3
  8. package/14_generateur_ecs.spec.js +1 -0
  9. package/15_conso_aux.js +121 -1
  10. package/15_conso_aux.spec.js +329 -4
  11. package/2021_04_13_confort_ete.spec.js +1 -0
  12. package/3.1_b.spec.js +1 -0
  13. package/3.2.1_mur.spec.js +1 -0
  14. package/3.2.2_plancher_bas.spec.js +1 -0
  15. package/3.2.3_plancher_haut.spec.js +1 -0
  16. package/3.3.1.4_porte.spec.js +1 -0
  17. package/3.3_baie_vitree.spec.js +1 -0
  18. package/3.4_pont_thermique.spec.js +1 -0
  19. package/4_ventilation.spec.js +1 -0
  20. package/5_conso_ventilation.spec.js +1 -0
  21. package/6.2_surface_sud_equivalente.js +2 -1
  22. package/6.2_surface_sud_equivalente.spec.js +1 -0
  23. package/9_besoin_ch.spec.js +1 -0
  24. package/9_chauffage.spec.js +3 -3
  25. package/9_conso_ch.spec.js +1 -0
  26. package/9_emetteur_ch.spec.js +1 -0
  27. package/9_generateur_ch.spec.js +1 -0
  28. package/README.md +412 -291
  29. package/conso.js +20 -6
  30. package/conso.spec.js +21 -0
  31. package/engine.js +19 -1
  32. package/engine.spec.js +96 -0
  33. package/package.json +15 -14
  34. package/features/engine/domain/apport_et_besoin/apport-et-besoin.service.spec.js +0 -222
  35. package/features/engine/domain/apport_et_besoin/ch/perte-ch-recup.service.spec.js +0 -345
  36. package/features/engine/domain/apport_et_besoin/ecs/besoin-ecs.service.spec.js +0 -87
  37. package/features/engine/domain/apport_et_besoin/ecs/perte-ecs-recup.service.spec.js +0 -260
  38. package/features/engine/domain/apport_et_besoin/froid/besoin-froid.service.spec.js +0 -272
  39. package/features/engine/domain/apport_et_besoin/surface-sud-equivalente.service.spec.js +0 -231
  40. package/features/engine/domain/ch/generateur-ch.service.spec.js +0 -849
  41. package/features/engine/domain/conso/froid/conso-froid.service.spec.js +0 -233
  42. package/features/engine/domain/ecs/installation-ecs.service.spec.js +0 -337
  43. package/features/engine/domain/enveloppe/baie_vitree/deperdition-baie-vitree.service.spec.js +0 -607
  44. package/features/engine/domain/enveloppe/deperdition-enveloppe.service.spec.js +0 -550
  45. package/features/engine/domain/enveloppe/espace_tampon/espace-tampon.service.spec.js +0 -82
  46. package/features/engine/domain/enveloppe/mur/deperdition-mur.service.spec.js +0 -542
  47. package/features/engine/domain/enveloppe/plancher_bas/deperdition-plancher-bas.service.spec.js +0 -430
  48. package/features/engine/domain/enveloppe/plancher_haut/deperdition-plancher-haut.service.spec.js +0 -411
  49. package/features/engine/domain/enveloppe/pont_thermique/deperdition-pont-thermique.service.spec.js +0 -653
  50. package/features/engine/domain/enveloppe/porte/deperdition-porte.service.spec.js +0 -117
  51. package/features/engine/domain/enveloppe/ventilation/deperdition-ventilation.service.spec.js +0 -508
@@ -1,272 +0,0 @@
1
- import { beforeEach, describe, expect, test, vi } from 'vitest';
2
- import { DpeNormalizerService } from '../../../../normalizer/domain/dpe-normalizer.service.js';
3
- import { ContexteBuilder } from '../../contexte.builder.js';
4
- import corpus from '../../../../../../test/corpus-sano.json';
5
- import { getAdemeFileJson } from '../../../../../../test/test-helpers.js';
6
- import { FrTvStore } from '../../../../dpe/infrastructure/froid/frTv.store.js';
7
- import { ApportGratuitService } from '../apport_gratuit/apport-gratuit.service.js';
8
- import { BesoinFroidService } from './besoin-froid.service.js';
9
- import { describeIntegration } from '../../../../../../test/helpers/integration-test.js';
10
-
11
- /** @type {ApportGratuitService} **/
12
- let apportGratuitService;
13
-
14
- /** @type {BesoinFroidService} **/
15
- let service;
16
-
17
- /** @type {DpeNormalizerService} **/
18
- let normalizerService;
19
-
20
- /** @type {ContexteBuilder} **/
21
- let contexteBuilder;
22
-
23
- /** @type {FrTvStore} **/
24
- let tvStore;
25
-
26
- describe('Calcul des besoins en froid du logement', () => {
27
- beforeEach(() => {
28
- tvStore = new FrTvStore();
29
- apportGratuitService = new ApportGratuitService();
30
- service = new BesoinFroidService(tvStore, apportGratuitService);
31
- normalizerService = new DpeNormalizerService();
32
- contexteBuilder = new ContexteBuilder();
33
- });
34
-
35
- test('Besoins en froid à 0 si aucune climatisation dans le logement', () => {
36
- vi.spyOn(tvStore, 'getData').mockReturnValue(10);
37
-
38
- /** @type {Contexte} */
39
- const ctx = { zoneClimatique: { id: 1 } };
40
- expect(service.execute(ctx, {})).toStrictEqual({ besoin_fr: 0, besoin_fr_depensier: 0 });
41
- expect(service.execute(ctx, { enveloppe: {} })).toStrictEqual({
42
- besoin_fr: 0,
43
- besoin_fr_depensier: 0
44
- });
45
- expect(service.execute(ctx, { climatisation_collection: {} })).toStrictEqual({
46
- besoin_fr: 0,
47
- besoin_fr_depensier: 0
48
- });
49
- expect(service.execute(ctx, { climatisation_collection: { climatisation: [] } })).toStrictEqual(
50
- { besoin_fr: 0, besoin_fr_depensier: 0 }
51
- );
52
-
53
- expect(tvStore.getData).not.toHaveBeenCalled();
54
- });
55
-
56
- describe('Determination du besoin en froid pour un mois donné', () => {
57
- test.each([
58
- {
59
- data: 0,
60
- aijFr: 1,
61
- asjFr: 0.2,
62
- inertie: 4,
63
- depensier: false,
64
- expected: 0
65
- },
66
- {
67
- data: 0,
68
- aijFr: 1,
69
- asjFr: 0.2,
70
- inertie: 4,
71
- depensier: true,
72
- expected: 0
73
- },
74
- {
75
- data: 58,
76
- aijFr: 1,
77
- asjFr: 0.2,
78
- inertie: 4,
79
- depensier: false,
80
- expected: 0
81
- },
82
- {
83
- data: 58,
84
- aijFr: 1,
85
- asjFr: 0.2,
86
- inertie: 4,
87
- depensier: true,
88
- expected: 0
89
- },
90
- {
91
- data: 30,
92
- aijFr: 1000,
93
- asjFr: 2580,
94
- inertie: 4,
95
- depensier: false,
96
- expected: 6.25
97
- },
98
- {
99
- data: 30,
100
- aijFr: 1000,
101
- asjFr: 2580,
102
- inertie: 4,
103
- depensier: true,
104
- expected: 0
105
- },
106
- {
107
- data: 30,
108
- aijFr: 1500,
109
- asjFr: 5580,
110
- inertie: 4,
111
- depensier: true,
112
- expected: 12.38
113
- },
114
- {
115
- data: 30,
116
- aijFr: 10000,
117
- asjFr: 2000,
118
- inertie: 4,
119
- depensier: false,
120
- expected: 16.72
121
- },
122
- {
123
- data: 30,
124
- aijFr: 10000,
125
- asjFr: 2000,
126
- inertie: 1,
127
- depensier: true,
128
- expected: 20.25
129
- },
130
- {
131
- data: 30,
132
- aijFr: 10000,
133
- asjFr: 2000,
134
- inertie: 2,
135
- depensier: true,
136
- expected: 20.25
137
- },
138
- {
139
- data: 30,
140
- aijFr: 10000,
141
- asjFr: 2000,
142
- inertie: 3,
143
- depensier: true,
144
- expected: 19.66
145
- },
146
- {
147
- data: 30,
148
- aijFr: 10000,
149
- asjFr: 2000,
150
- inertie: 4,
151
- depensier: true,
152
- expected: 19.22
153
- }
154
- ])(
155
- 'nref: $data, eFr: $data, tempExtMoyClim: $data, aijFr: $aijFr, asjFr: $asjFr,' +
156
- 'inertie: $inertie, depensier: $depensier',
157
- ({ data, aijFr, asjFr, inertie, depensier, expected }) => {
158
- vi.spyOn(tvStore, 'getData').mockReturnValue(data);
159
- vi.spyOn(apportGratuitService, 'apportInterneMois').mockReturnValue(aijFr);
160
- vi.spyOn(apportGratuitService, 'apportSolaireMois').mockReturnValue(asjFr);
161
-
162
- /** @type {Logement} **/
163
- const logement = {
164
- enveloppe: {},
165
- sortie: { deperdition: { deperdition_enveloppe: 100 } }
166
- };
167
-
168
- /** @type {Contexte} */
169
- const ctx = {
170
- altitude: { value: '400-800m' },
171
- zoneClimatique: { value: 'h1a' },
172
- inertie: { id: inertie },
173
- surfaceHabitable: 25
174
- };
175
-
176
- const ssd = service.besoinFrMois(ctx, logement, 'Janvier', depensier);
177
-
178
- expect(tvStore.getData).toHaveBeenCalledWith(
179
- depensier ? 'nref26' : 'nref28',
180
- '400-800m',
181
- 'h1a',
182
- 'Janvier'
183
- );
184
- if (data > 0) {
185
- expect(tvStore.getData).toHaveBeenCalledWith(
186
- depensier ? 'e_fr_26' : 'e_fr_28',
187
- '400-800m',
188
- 'h1a',
189
- 'Janvier'
190
- );
191
- expect(tvStore.getData).toHaveBeenCalledWith(
192
- depensier ? 'textmoy_clim_26' : 'textmoy_clim_28',
193
- '400-800m',
194
- 'h1a',
195
- 'Janvier'
196
- );
197
- expect(apportGratuitService.apportInterneMois).toHaveBeenCalledWith(ctx, data);
198
- expect(apportGratuitService.apportSolaireMois).toHaveBeenCalledWith(
199
- ctx,
200
- {},
201
- 'Janvier',
202
- data
203
- );
204
- }
205
-
206
- expect(ssd).toBeCloseTo(expected, 2);
207
- }
208
- );
209
- });
210
-
211
- test('Sommation du besoin en froid sur les douze mois en présence de climatisation', () => {
212
- // Climatisation présente : execute doit agréger besoinFrMois sur les 12 mois.
213
- // besoinFrMois est doublé pour n'évaluer que la logique d'agrégation.
214
- vi.spyOn(service, 'besoinFrMois').mockImplementation((ctx, logement, mois, depensier) =>
215
- depensier ? 5 : 2
216
- );
217
-
218
- /** @type {Contexte} */
219
- const ctx = { zoneClimatique: { id: 1 } };
220
-
221
- /** @type {Logement} */
222
- const logement = { climatisation_collection: { climatisation: [{}] } };
223
-
224
- const res = service.execute(ctx, logement);
225
-
226
- expect(res).toStrictEqual({ besoin_fr: 24, besoin_fr_depensier: 60 });
227
- expect(service.besoinFrMois).toHaveBeenCalledTimes(24);
228
- });
229
-
230
- test('Facteur d’utilisation lorsque le ratio de bilan thermique Rbth vaut exactement 1', () => {
231
- // Branche fut = a / (a + 1) : atteinte uniquement quand Rbth === 1.
232
- // Rbth = (aijFr + asjFr) / (GV * (tempExtMoyClim - 28) * nref)
233
- // = 6000 / (100 * (30 - 28) * 30) = 1
234
- vi.spyOn(tvStore, 'getData').mockReturnValue(30);
235
- vi.spyOn(apportGratuitService, 'apportInterneMois').mockReturnValue(6000);
236
- vi.spyOn(apportGratuitService, 'apportSolaireMois').mockReturnValue(0);
237
-
238
- /** @type {Logement} **/
239
- const logement = { enveloppe: {}, sortie: { deperdition: { deperdition_enveloppe: 100 } } };
240
-
241
- /** @type {Contexte} */
242
- const ctx = {
243
- altitude: { value: '400-800m' },
244
- zoneClimatique: { value: 'h1a' },
245
- inertie: { id: 4 },
246
- surfaceHabitable: 25
247
- };
248
-
249
- // Valeur de référence de régression (module réel exécuté avec ces entrées)
250
- expect(service.besoinFrMois(ctx, logement, 'Janvier', false)).toBeCloseTo(9.608856088560886, 9);
251
- });
252
-
253
- describeIntegration("Test d'intégration pour le besoin en froid", () => {
254
- test.each(corpus)('vérification des sorties besoin_fr pour dpe %s', (ademeId) => {
255
- /**
256
- * @type {Dpe}
257
- */
258
- let dpeRequest = getAdemeFileJson(ademeId);
259
- dpeRequest = normalizerService.normalize(dpeRequest);
260
-
261
- /** @type {Contexte} */
262
- const ctx = contexteBuilder.fromDpe(dpeRequest);
263
-
264
- const ecs = service.execute(ctx, dpeRequest.logement);
265
- expect(ecs.besoin_fr).toBeCloseTo(dpeRequest.logement.sortie.apport_et_besoin.besoin_fr, 2);
266
- expect(ecs.besoin_fr_depensier).toBeCloseTo(
267
- dpeRequest.logement.sortie.apport_et_besoin.besoin_fr_depensier,
268
- 2
269
- );
270
- });
271
- });
272
- });
@@ -1,231 +0,0 @@
1
- import corpus from '../../../../../test/corpus-sano.json';
2
- import { beforeEach, describe, expect, test, vi } from 'vitest';
3
- import { DpeNormalizerService } from '../../../normalizer/domain/dpe-normalizer.service.js';
4
- import { ContexteBuilder } from '../contexte.builder.js';
5
- import { SurfaceSudEquivalenteService } from './surface-sud-equivalente.service.js';
6
- import { getAdemeFileJson } from '../../../../../test/test-helpers.js';
7
- import { BaieVitreeTvStore } from '../../../dpe/infrastructure/enveloppe/baieVitreeTv.store.js';
8
- import { describeIntegration } from '../../../../../test/helpers/integration-test.js';
9
-
10
- /** @type {SurfaceSudEquivalenteService} **/
11
- let service;
12
-
13
- /** @type {DpeNormalizerService} **/
14
- let normalizerService;
15
-
16
- /** @type {ContexteBuilder} **/
17
- let contexteBuilder;
18
-
19
- /** @type {BaieVitreeTvStore} **/
20
- let tvStore;
21
-
22
- describe('Calcul de la surface sud équivalente du logement', () => {
23
- beforeEach(() => {
24
- tvStore = new BaieVitreeTvStore();
25
- service = new SurfaceSudEquivalenteService(tvStore);
26
- normalizerService = new DpeNormalizerService();
27
- contexteBuilder = new ContexteBuilder();
28
- });
29
-
30
- describe('Determination de la surface sud équivalente pour une baie vitrée bv et pendant un mois donné', () => {
31
- test.each([
32
- {
33
- enumOrientationId: 2,
34
- enumInclinaisonVitrageId: 3,
35
- fe1: 1,
36
- fe2: 1,
37
- sw: 0.2,
38
- coeff: 1,
39
- expected: 5
40
- },
41
- {
42
- enumOrientationId: 2,
43
- enumInclinaisonVitrageId: undefined,
44
- fe1: 1,
45
- fe2: 1,
46
- sw: 0.2,
47
- coeff: 1,
48
- expected: 5
49
- },
50
- {
51
- enumOrientationId: 2,
52
- enumInclinaisonVitrageId: undefined,
53
- fe1: 1,
54
- fe2: 1,
55
- sw: 0.2,
56
- coeff: undefined,
57
- expected: 1
58
- },
59
- {
60
- enumOrientationId: 2,
61
- enumInclinaisonVitrageId: 3,
62
- fe1: 0.5,
63
- fe2: 0.5,
64
- sw: 0.2,
65
- coeff: 1,
66
- expected: 1.25
67
- },
68
- {
69
- enumOrientationId: 2,
70
- enumInclinaisonVitrageId: 3,
71
- fe1: undefined,
72
- fe2: undefined,
73
- sw: 0.2,
74
- coeff: 1,
75
- expected: 5
76
- }
77
- ])(
78
- 'enumOrientationId: $enumOrientationId, enumInclinaisonVitrageId: $enumInclinaisonVitrageId, fe1: $fe1,' +
79
- 'fe2: $fe2, sw: $sw, coeff: $coeff',
80
- ({
81
- enumOrientationId,
82
- enumInclinaisonVitrageId = undefined,
83
- fe1,
84
- fe2,
85
- sw,
86
- coeff = undefined,
87
- expected
88
- }) => {
89
- vi.spyOn(tvStore, 'getCoefficientBaieVitree').mockReturnValue(0.5);
90
-
91
- /** @type {BaieVitree} */
92
- const baieVitree = {
93
- donnee_entree: {
94
- enum_orientation_id: enumOrientationId,
95
- enum_inclinaison_vitrage_id: enumInclinaisonVitrageId,
96
- surface_totale_baie: 10
97
- },
98
- donnee_intermediaire: { fe1, fe2, sw }
99
- };
100
-
101
- const ssd = service.ssdBaieMois(baieVitree, '1', 'Janvier', coeff);
102
-
103
- if (enumInclinaisonVitrageId === undefined) {
104
- enumInclinaisonVitrageId = 3;
105
- }
106
-
107
- expect(tvStore.getCoefficientBaieVitree).toHaveBeenCalledWith(
108
- enumOrientationId,
109
- enumInclinaisonVitrageId,
110
- 1,
111
- 'Janvier'
112
- );
113
- expect(ssd).toBe(expected);
114
- }
115
- );
116
- });
117
-
118
- describe('Determination de la surface sud équivalente des baies vitrées bv', () => {
119
- test("Aucune pour les baies vitrées qui ne donnent pas sur l'extérieur", () => {
120
- expect(service.execute({}, [])).toBe(0);
121
-
122
- /** @type {Enveloppe} */
123
- const enveloppe = {
124
- baie_vitree_collection: {
125
- baie_vitree: [
126
- {
127
- donnee_entree: { enum_type_adjacence_id: 18 }
128
- }
129
- ]
130
- }
131
- };
132
- expect(service.ssdMois({}, enveloppe, 'Janvier')).toBe(0);
133
- });
134
-
135
- test("Baies vitrées donnant sur l'extérieur", () => {
136
- vi.spyOn(tvStore, 'getCoefficientBaieVitree').mockReturnValue(0.5);
137
-
138
- /** @type {Contexte} */
139
- const ctx = { zoneClimatique: { id: 1 } };
140
-
141
- /** @type {Enveloppe} */
142
- const enveloppe = {
143
- baie_vitree_collection: {
144
- baie_vitree: [
145
- {
146
- donnee_entree: {
147
- enum_type_adjacence_id: 1,
148
- enum_orientation_id: 2,
149
- surface_totale_baie: 10
150
- },
151
- donnee_intermediaire: { sw: 1 }
152
- }
153
- ]
154
- }
155
- };
156
- expect(service.ssdMois(ctx, enveloppe, 'Janvier')).toBe(5);
157
- expect(tvStore.getCoefficientBaieVitree).toHaveBeenCalledWith(2, 3, 1, 'Janvier');
158
- });
159
-
160
- test('Baies vitrées donnant sur un espace tampon solarisé', () => {
161
- vi.spyOn(tvStore, 'getCoefficientBaieVitree').mockReturnValue(0.5);
162
-
163
- /** @type {Contexte} */
164
- const ctx = { zoneClimatique: { id: 1 } };
165
-
166
- /** @type {Enveloppe} */
167
- const enveloppe = {
168
- baie_vitree_collection: {
169
- baie_vitree: [
170
- {
171
- donnee_entree: {
172
- enum_type_adjacence_id: 10,
173
- enum_orientation_id: 2,
174
- surface_totale_baie: 10
175
- },
176
- donnee_intermediaire: { sw: 1 }
177
- },
178
- {
179
- donnee_entree: {
180
- enum_type_adjacence_id: 1,
181
- enum_orientation_id: 2,
182
- surface_totale_baie: 10
183
- },
184
- donnee_intermediaire: { sw: 1 }
185
- }
186
- ]
187
- },
188
- ets_collection: {
189
- ets: {
190
- donnee_intermediaire: { bver: 0.6, coef_transparence_ets: 0.4 },
191
- baie_ets_collection: {
192
- baie_ets: {
193
- donnee_entree: {
194
- enum_inclinaison_vitrage_id: 3,
195
- enum_orientation_id: 1,
196
- surface_totale_baie: 7
197
- }
198
- }
199
- }
200
- }
201
- }
202
- };
203
-
204
- expect(service.ssdMois(ctx, enveloppe, 'Janvier')).toBe(6.5224);
205
- expect(tvStore.getCoefficientBaieVitree).toHaveBeenCalledWith(2, 3, 1, 'Janvier');
206
- expect(tvStore.getCoefficientBaieVitree).toHaveBeenCalledWith(1, 3, 1, 'Janvier');
207
- });
208
- });
209
-
210
- describeIntegration("Test d'intégration pour surface sud équivalente", () => {
211
- test.each(corpus)(
212
- 'vérification des DI de la surface sud équivalente pour dpe %s',
213
- (ademeId) => {
214
- /**
215
- * @type {Dpe}
216
- */
217
- let dpeRequest = getAdemeFileJson(ademeId);
218
- dpeRequest = normalizerService.normalize(dpeRequest);
219
-
220
- /** @type {Contexte} */
221
- const ctx = contexteBuilder.fromDpe(dpeRequest);
222
-
223
- const sse = service.execute(ctx, dpeRequest.logement.enveloppe);
224
- expect(sse).toBeCloseTo(
225
- dpeRequest.logement.sortie.apport_et_besoin.surface_sud_equivalente,
226
- 2
227
- );
228
- }
229
- );
230
- });
231
- });