@open3cl/engine 1.0.12 → 1.0.14
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/13.2_generateur_combustion_ch.js +1 -1
- package/features/dpe/domain/models/dpe.model.ts +9 -0
- package/features/dpe/domain/models/installation-chauffage.model.ts +26 -2
- package/features/dpe/domain/models/type-generateur.model.js +8 -0
- package/features/dpe/infrastructure/ch/chTv.store.js +94 -0
- package/features/dpe/infrastructure/ch/chTv.store.spec.js +99 -0
- package/features/dpe/infrastructure/ecs/ecsTv.store.js +5 -3
- package/features/dpe/infrastructure/ecs/ecsTv.store.spec.js +4 -0
- package/features/dpe/infrastructure/froid/frTv.store.js +4 -2
- package/features/dpe/infrastructure/tv.store.js +28 -0
- package/features/dpe/infrastructure/tv.store.spec.js +12 -0
- package/features/engine/domain/apport_et_besoin/apport-et-besoin.service.js +57 -3
- package/features/engine/domain/apport_et_besoin/apport-et-besoin.service.spec.js +117 -2
- package/features/engine/domain/apport_et_besoin/apport_gratuit/apport-gratuit.service.js +18 -2
- package/features/engine/domain/apport_et_besoin/apport_gratuit/apport-gratuit.service.spec.js +13 -2
- package/features/engine/domain/apport_et_besoin/ch/besoin-ch.service.js +150 -0
- package/features/engine/domain/apport_et_besoin/ch/besoin-ch.service.spec.js +145 -0
- package/features/engine/domain/apport_et_besoin/ch/perte-ch-recup.service.js +168 -0
- package/features/engine/domain/apport_et_besoin/ch/perte-ch-recup.service.spec.js +313 -0
- package/features/engine/domain/apport_et_besoin/ecs/perte-ecs-recup.service.js +12 -8
- package/features/engine/domain/apport_et_besoin/ecs/perte-ecs-recup.service.spec.js +28 -13
- package/features/engine/domain/ch/emetteur-ch.service.js +100 -0
- package/features/engine/domain/ch/emetteur-ch.service.spec.js +78 -0
- package/features/engine/domain/ch/generateur-ch.service.js +365 -0
- package/features/engine/domain/ch/generateur-ch.service.spec.js +734 -0
- package/features/engine/domain/ch/installation-ch.service.js +39 -0
- package/features/engine/domain/ch/installation-ch.service.spec.js +41 -0
- package/features/engine/domain/contexte.builder.js +1 -0
- package/features/engine/domain/contexte.builder.spec.js +2 -0
- package/features/engine/domain/ecs/generateur-ecs.service.js +2 -2
- package/features/engine/domain/ecs/installation-ecs.service.js +5 -5
- package/features/engine/domain/engine.service.js +13 -2
- package/features/engine/domain/models/contexte.model.ts +1 -0
- package/package.json +1 -1
|
@@ -7,6 +7,14 @@ import { BesoinFroidService } from './froid/besoin-froid.service.js';
|
|
|
7
7
|
import { ApportGratuitService } from './apport_gratuit/apport-gratuit.service.js';
|
|
8
8
|
import { PerteEcsRecupService } from './ecs/perte-ecs-recup.service.js';
|
|
9
9
|
import { InstallationEcsService } from '../ecs/installation-ecs.service.js';
|
|
10
|
+
import { PerteChRecupService } from './ch/perte-ch-recup.service.js';
|
|
11
|
+
import { BesoinChService } from './ch/besoin-ch.service.js';
|
|
12
|
+
import corpus from '../../../../../test/corpus-sano.json';
|
|
13
|
+
import { getAdemeFileJson } from '../../../../../test/test-helpers.js';
|
|
14
|
+
import { PRECISION_PERCENT } from '../../../../../test/constant.js';
|
|
15
|
+
import { DpeNormalizerService } from '../../../normalizer/domain/dpe-normalizer.service.js';
|
|
16
|
+
import { ContexteBuilder } from '../contexte.builder.js';
|
|
17
|
+
import { InstallationChService } from '../ch/installation-ch.service.js';
|
|
10
18
|
|
|
11
19
|
/** @type {SurfaceSudEquivalenteService} **/
|
|
12
20
|
let surfaceSudEquivalenteService;
|
|
@@ -20,12 +28,27 @@ let besoinFroidService;
|
|
|
20
28
|
/** @type {InstallationEcsService} **/
|
|
21
29
|
let installationEcsService;
|
|
22
30
|
|
|
31
|
+
/** @type {InstallationChService} **/
|
|
32
|
+
let installationChService;
|
|
33
|
+
|
|
23
34
|
/** @type {PerteEcsRecupService} **/
|
|
24
35
|
let perteEcsRecupService;
|
|
25
36
|
|
|
26
37
|
/** @type {ApportGratuitService} **/
|
|
27
38
|
let apportGratuitService;
|
|
28
39
|
|
|
40
|
+
/** @type {PerteChRecupService} **/
|
|
41
|
+
let perteChRecupService;
|
|
42
|
+
|
|
43
|
+
/** @type {BesoinChService} **/
|
|
44
|
+
let besoinChService;
|
|
45
|
+
|
|
46
|
+
/** @type {DpeNormalizerService} **/
|
|
47
|
+
let normalizerService;
|
|
48
|
+
|
|
49
|
+
/** @type {ContexteBuilder} **/
|
|
50
|
+
let contexteBuilder;
|
|
51
|
+
|
|
29
52
|
/** @type {ApportEtBesoinService} **/
|
|
30
53
|
let service;
|
|
31
54
|
|
|
@@ -37,18 +60,26 @@ describe('Calcul des apports et besoin du logement', () => {
|
|
|
37
60
|
tvStore = new BaieVitreeTvStore();
|
|
38
61
|
surfaceSudEquivalenteService = new SurfaceSudEquivalenteService(tvStore);
|
|
39
62
|
besoinEcsService = new BesoinEcsService();
|
|
63
|
+
besoinChService = new BesoinChService();
|
|
40
64
|
besoinFroidService = new BesoinFroidService();
|
|
41
65
|
installationEcsService = new InstallationEcsService();
|
|
66
|
+
installationChService = new InstallationChService();
|
|
42
67
|
perteEcsRecupService = new PerteEcsRecupService();
|
|
43
68
|
apportGratuitService = new ApportGratuitService();
|
|
69
|
+
perteChRecupService = new PerteChRecupService();
|
|
44
70
|
service = new ApportEtBesoinService(
|
|
45
71
|
besoinEcsService,
|
|
72
|
+
besoinChService,
|
|
46
73
|
installationEcsService,
|
|
74
|
+
installationChService,
|
|
47
75
|
perteEcsRecupService,
|
|
48
76
|
besoinFroidService,
|
|
49
77
|
surfaceSudEquivalenteService,
|
|
78
|
+
perteChRecupService,
|
|
50
79
|
apportGratuitService
|
|
51
80
|
);
|
|
81
|
+
normalizerService = new DpeNormalizerService();
|
|
82
|
+
contexteBuilder = new ContexteBuilder();
|
|
52
83
|
});
|
|
53
84
|
|
|
54
85
|
test('Determination des apports et besoin du logement', () => {
|
|
@@ -57,6 +88,10 @@ describe('Calcul des apports et besoin du logement', () => {
|
|
|
57
88
|
besoin_ecs: 1526,
|
|
58
89
|
besoin_ecs_depensier: 2685.3
|
|
59
90
|
});
|
|
91
|
+
vi.spyOn(besoinChService, 'execute').mockReturnValue({
|
|
92
|
+
besoin_ch_hp: 2563,
|
|
93
|
+
besoin_ch_depensier_hp: 3258.6
|
|
94
|
+
});
|
|
60
95
|
vi.spyOn(besoinFroidService, 'execute').mockReturnValue({
|
|
61
96
|
besoin_fr: 896,
|
|
62
97
|
besoin_fr_depensier: 1025.3
|
|
@@ -70,10 +105,16 @@ describe('Calcul des apports et besoin du logement', () => {
|
|
|
70
105
|
apport_interne_fr: 3345.2
|
|
71
106
|
});
|
|
72
107
|
vi.spyOn(installationEcsService, 'execute').mockReturnThis();
|
|
108
|
+
vi.spyOn(installationChService, 'execute').mockReturnThis();
|
|
73
109
|
vi.spyOn(perteEcsRecupService, 'execute').mockReturnValue({
|
|
74
110
|
pertes_distribution_ecs_recup: 354.2,
|
|
75
111
|
pertes_distribution_ecs_recup_depensier: 532.6,
|
|
76
|
-
pertes_stockage_ecs_recup: 25.9
|
|
112
|
+
pertes_stockage_ecs_recup: 25.9,
|
|
113
|
+
pertes_stockage_ecs_recup_depensier: 12.9
|
|
114
|
+
});
|
|
115
|
+
vi.spyOn(perteChRecupService, 'execute').mockReturnValue({
|
|
116
|
+
pertes_generateur_ch_recup: 102.2,
|
|
117
|
+
pertes_generateur_ch_recup_depensier: 153.4
|
|
77
118
|
});
|
|
78
119
|
|
|
79
120
|
/** @type {Contexte} */
|
|
@@ -84,6 +125,8 @@ describe('Calcul des apports et besoin du logement', () => {
|
|
|
84
125
|
surface_sud_equivalente: 18.5,
|
|
85
126
|
besoin_ecs: 1526,
|
|
86
127
|
besoin_ecs_depensier: 2685.3,
|
|
128
|
+
besoin_ch: 2080.7000000000003,
|
|
129
|
+
besoin_ch_depensier: 2559.7,
|
|
87
130
|
besoin_fr: 896,
|
|
88
131
|
besoin_fr_depensier: 1025.3,
|
|
89
132
|
apport_solaire_ch: 5236.9,
|
|
@@ -95,12 +138,84 @@ describe('Calcul des apports et besoin du logement', () => {
|
|
|
95
138
|
v40_ecs_journalier_depensier: 197.5,
|
|
96
139
|
pertes_distribution_ecs_recup: 354.2,
|
|
97
140
|
pertes_distribution_ecs_recup_depensier: 532.6,
|
|
98
|
-
|
|
141
|
+
pertes_generateur_ch_recup: 102.2,
|
|
142
|
+
pertes_generateur_ch_recup_depensier: 153.4,
|
|
143
|
+
pertes_stockage_ecs_recup: 25.9,
|
|
144
|
+
pertes_stockage_ecs_recup_depensier: 12.9
|
|
99
145
|
});
|
|
100
146
|
expect(surfaceSudEquivalenteService.execute).toHaveBeenCalledWith(ctx, logement.enveloppe);
|
|
101
147
|
expect(besoinEcsService.execute).toHaveBeenCalledWith(ctx);
|
|
102
148
|
expect(besoinFroidService.execute).toHaveBeenCalledWith(ctx, logement);
|
|
103
149
|
expect(apportGratuitService.apportSolaire).toHaveBeenCalledWith(ctx, logement);
|
|
104
150
|
expect(apportGratuitService.apportInterne).toHaveBeenCalledWith(ctx, logement);
|
|
151
|
+
expect(perteEcsRecupService.execute).toHaveBeenCalledWith(ctx, logement);
|
|
152
|
+
expect(perteChRecupService.execute).toHaveBeenCalledWith(ctx, logement);
|
|
153
|
+
expect(installationEcsService.execute).toHaveBeenCalledWith(ctx, logement, {
|
|
154
|
+
besoin_ecs: 1526,
|
|
155
|
+
besoin_ecs_depensier: 2685.3
|
|
156
|
+
});
|
|
157
|
+
expect(installationChService.execute).toHaveBeenCalledWith(ctx, logement);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe("Test d'intégration pour les besoins en chauffage", () => {
|
|
161
|
+
test.each(corpus)(
|
|
162
|
+
'Vérification de la DI besoin_ch des besoins en chauffage pour dpe %s',
|
|
163
|
+
(ademeId) => {
|
|
164
|
+
/**
|
|
165
|
+
* @type {Dpe}
|
|
166
|
+
*/
|
|
167
|
+
let dpeRequest = getAdemeFileJson(ademeId);
|
|
168
|
+
dpeRequest = normalizerService.normalize(dpeRequest);
|
|
169
|
+
|
|
170
|
+
dpeRequest.logement.donnees_de_calcul = {
|
|
171
|
+
apportsInterneDepensier: [],
|
|
172
|
+
apportsInterneCh: [],
|
|
173
|
+
apportsSolaire: [],
|
|
174
|
+
besoinChauffageHP: [],
|
|
175
|
+
besoinChauffageDepensierHP: []
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
/** @type {Contexte} */
|
|
179
|
+
const ctx = contexteBuilder.fromDpe(dpeRequest);
|
|
180
|
+
const apportEtBesoin = service.execute(ctx, dpeRequest.logement);
|
|
181
|
+
|
|
182
|
+
expect(
|
|
183
|
+
Math.abs(
|
|
184
|
+
apportEtBesoin.besoin_ch - dpeRequest.logement.sortie.apport_et_besoin.besoin_ch
|
|
185
|
+
) / (dpeRequest.logement.sortie.apport_et_besoin.besoin_ch || 1)
|
|
186
|
+
).toBeLessThan(PRECISION_PERCENT);
|
|
187
|
+
}
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
test.each(corpus)(
|
|
191
|
+
'Vérification de la DI besoin_ch_depensier des besoins en chauffage pour dpe %s',
|
|
192
|
+
(ademeId) => {
|
|
193
|
+
/**
|
|
194
|
+
* @type {Dpe}
|
|
195
|
+
*/
|
|
196
|
+
let dpeRequest = getAdemeFileJson(ademeId);
|
|
197
|
+
dpeRequest = normalizerService.normalize(dpeRequest);
|
|
198
|
+
|
|
199
|
+
dpeRequest.logement.donnees_de_calcul = {
|
|
200
|
+
apportsInterneDepensier: [],
|
|
201
|
+
apportsInterneCh: [],
|
|
202
|
+
apportsSolaire: [],
|
|
203
|
+
besoinChauffageHP: [],
|
|
204
|
+
besoinChauffageDepensierHP: []
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
/** @type {Contexte} */
|
|
208
|
+
const ctx = contexteBuilder.fromDpe(dpeRequest);
|
|
209
|
+
|
|
210
|
+
const apportEtBesoin = service.execute(ctx, dpeRequest.logement);
|
|
211
|
+
|
|
212
|
+
expect(
|
|
213
|
+
Math.abs(
|
|
214
|
+
apportEtBesoin.besoin_ch_depensier -
|
|
215
|
+
dpeRequest.logement.sortie.apport_et_besoin.besoin_ch_depensier
|
|
216
|
+
) / (dpeRequest.logement.sortie.apport_et_besoin.besoin_ch_depensier || 1)
|
|
217
|
+
).toBeLessThan(PRECISION_PERCENT);
|
|
218
|
+
}
|
|
219
|
+
);
|
|
105
220
|
});
|
|
106
221
|
});
|
|
@@ -46,7 +46,7 @@ export class ApportGratuitService {
|
|
|
46
46
|
|
|
47
47
|
return mois_liste.reduce(
|
|
48
48
|
(acc, mois) => {
|
|
49
|
-
|
|
49
|
+
const apportSolaire = this.apportSolaireMois(
|
|
50
50
|
ctx,
|
|
51
51
|
logement.enveloppe,
|
|
52
52
|
mois,
|
|
@@ -58,6 +58,9 @@ export class ApportGratuitService {
|
|
|
58
58
|
ctx.inertie.ilpa
|
|
59
59
|
)
|
|
60
60
|
);
|
|
61
|
+
acc.apport_solaire_ch += apportSolaire;
|
|
62
|
+
logement.donnees_de_calcul.apportsSolaire[mois] = apportSolaire;
|
|
63
|
+
|
|
61
64
|
if (clim.length > 0) {
|
|
62
65
|
acc.apport_solaire_fr += this.apportSolaireMois(
|
|
63
66
|
ctx,
|
|
@@ -84,7 +87,7 @@ export class ApportGratuitService {
|
|
|
84
87
|
|
|
85
88
|
return mois_liste.reduce(
|
|
86
89
|
(acc, mois) => {
|
|
87
|
-
|
|
90
|
+
const apportInterne = this.apportInterneMois(
|
|
88
91
|
ctx,
|
|
89
92
|
this.#frTvStore.getData(
|
|
90
93
|
'nref19',
|
|
@@ -94,6 +97,19 @@ export class ApportGratuitService {
|
|
|
94
97
|
ctx.inertie.ilpa
|
|
95
98
|
)
|
|
96
99
|
);
|
|
100
|
+
acc.apport_interne_ch += apportInterne;
|
|
101
|
+
logement.donnees_de_calcul.apportsInterneCh[mois] = apportInterne;
|
|
102
|
+
logement.donnees_de_calcul.apportsInterneDepensier[mois] = this.apportInterneMois(
|
|
103
|
+
ctx,
|
|
104
|
+
this.#frTvStore.getData(
|
|
105
|
+
'nref21',
|
|
106
|
+
ctx.altitude.value,
|
|
107
|
+
ctx.zoneClimatique.value,
|
|
108
|
+
mois,
|
|
109
|
+
ctx.inertie.ilpa
|
|
110
|
+
)
|
|
111
|
+
);
|
|
112
|
+
|
|
97
113
|
if (clim.length > 0) {
|
|
98
114
|
acc.apport_interne_fr += this.apportInterneMois(
|
|
99
115
|
ctx,
|
package/features/engine/domain/apport_et_besoin/apport_gratuit/apport-gratuit.service.spec.js
CHANGED
|
@@ -41,7 +41,10 @@ describe('Calcul des apports gratuits au logement', () => {
|
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
/** @type { Logement } **/
|
|
44
|
-
const logement = {
|
|
44
|
+
const logement = {
|
|
45
|
+
enveloppe: { porte_collection: {} },
|
|
46
|
+
donnees_de_calcul: { apportsSolaire: {} }
|
|
47
|
+
};
|
|
45
48
|
|
|
46
49
|
if (withClimatisation) {
|
|
47
50
|
logement.climatisation_collection = { climatisation: [{}] };
|
|
@@ -81,6 +84,8 @@ describe('Calcul des apports gratuits au logement', () => {
|
|
|
81
84
|
mois
|
|
82
85
|
);
|
|
83
86
|
}
|
|
87
|
+
|
|
88
|
+
expect(logement.donnees_de_calcul.apportsSolaire[mois]).toBe(185000);
|
|
84
89
|
}
|
|
85
90
|
});
|
|
86
91
|
|
|
@@ -106,7 +111,10 @@ describe('Calcul des apports gratuits au logement', () => {
|
|
|
106
111
|
};
|
|
107
112
|
|
|
108
113
|
/** @type { Logement } **/
|
|
109
|
-
const logement = {
|
|
114
|
+
const logement = {
|
|
115
|
+
enveloppe: { porte_collection: {} },
|
|
116
|
+
donnees_de_calcul: { apportsInterneCh: {}, apportsInterneDepensier: {} }
|
|
117
|
+
};
|
|
110
118
|
|
|
111
119
|
if (withClimatisation) {
|
|
112
120
|
logement.climatisation_collection = { climatisation: [{}] };
|
|
@@ -141,6 +149,9 @@ describe('Calcul des apports gratuits au logement', () => {
|
|
|
141
149
|
mois
|
|
142
150
|
);
|
|
143
151
|
}
|
|
152
|
+
|
|
153
|
+
expect(logement.donnees_de_calcul.apportsInterneCh[mois]).toBeCloseTo(1306.33, 2);
|
|
154
|
+
expect(logement.donnees_de_calcul.apportsInterneDepensier[mois]).toBeCloseTo(1306.33, 2);
|
|
144
155
|
}
|
|
145
156
|
});
|
|
146
157
|
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { mois_liste } from '../../../../../utils.js';
|
|
2
|
+
import { inject } from 'dioma';
|
|
3
|
+
import { FrTvStore } from '../../../../dpe/infrastructure/froid/frTv.store.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Calcul du besoin en chauffage
|
|
7
|
+
* Chapitre 2 - Expression du besoin de chauffage
|
|
8
|
+
*
|
|
9
|
+
* Methode_de_calcul_3CL_DPE_2021 - Page 7
|
|
10
|
+
* Octobre 2021
|
|
11
|
+
* @see consolide_anne…arrete_du_31_03_2021_relatif_aux_methodes_et_procedures_applicables.pdf
|
|
12
|
+
*/
|
|
13
|
+
export class BesoinChService {
|
|
14
|
+
/**
|
|
15
|
+
* @type {FrTvStore}
|
|
16
|
+
*/
|
|
17
|
+
#tvStore;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param tvStore {FrTvStore}
|
|
21
|
+
*/
|
|
22
|
+
constructor(tvStore = inject(FrTvStore)) {
|
|
23
|
+
this.#tvStore = tvStore;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Besoin de chauffage hors pertes récupérées
|
|
28
|
+
* 9.1.1 - Consommation de chauffage
|
|
29
|
+
*
|
|
30
|
+
* @param ctx {Contexte}
|
|
31
|
+
* @param logement {Logement}
|
|
32
|
+
* @return {{besoin_ch_hp: number, besoin_ch_depensier_hp: number, fraction_apport_gratuit_ch: number, fraction_apport_gratuit_depensier_ch: number}}
|
|
33
|
+
*/
|
|
34
|
+
execute(ctx, logement) {
|
|
35
|
+
const besoinCh = mois_liste.reduce(
|
|
36
|
+
(acc, mois) => {
|
|
37
|
+
const dh19 = this.#tvStore.getData(
|
|
38
|
+
'dh19',
|
|
39
|
+
ctx.altitude.value,
|
|
40
|
+
ctx.zoneClimatique.value,
|
|
41
|
+
mois,
|
|
42
|
+
ctx.inertie.ilpa
|
|
43
|
+
);
|
|
44
|
+
const dh21 = this.#tvStore.getData(
|
|
45
|
+
'dh21',
|
|
46
|
+
ctx.altitude.value,
|
|
47
|
+
ctx.zoneClimatique.value,
|
|
48
|
+
mois,
|
|
49
|
+
ctx.inertie.ilpa
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const besoinCh = this.besoinChHorsPertesRecuperees(ctx, logement, mois, dh19);
|
|
53
|
+
acc.besoin_ch_hp += besoinCh.besoinChMoisHP;
|
|
54
|
+
acc.fraction_apport_gratuit_ch += besoinCh.fractionApportGratuitMois;
|
|
55
|
+
logement.donnees_de_calcul.besoinChauffageHP[mois] = besoinCh.besoinChMoisHP;
|
|
56
|
+
|
|
57
|
+
const besoinChDepensier = this.besoinChHorsPertesRecuperees(ctx, logement, mois, dh21);
|
|
58
|
+
acc.besoin_ch_depensier_hp += besoinChDepensier.besoinChMoisHP;
|
|
59
|
+
acc.fraction_apport_gratuit_depensier_ch += besoinChDepensier.fractionApportGratuitMois;
|
|
60
|
+
logement.donnees_de_calcul.besoinChauffageDepensierHP[mois] =
|
|
61
|
+
besoinChDepensier.besoinChMoisHP;
|
|
62
|
+
|
|
63
|
+
acc.dh19 += dh19;
|
|
64
|
+
acc.dh21 += dh21;
|
|
65
|
+
return acc;
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
besoin_ch_hp: 0,
|
|
69
|
+
besoin_ch_depensier_hp: 0,
|
|
70
|
+
fraction_apport_gratuit_ch: 0,
|
|
71
|
+
fraction_apport_gratuit_depensier_ch: 0,
|
|
72
|
+
dh19: 0,
|
|
73
|
+
dh21: 0
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
besoinCh.fraction_apport_gratuit_ch /= besoinCh.dh19;
|
|
78
|
+
besoinCh.fraction_apport_gratuit_depensier_ch /= besoinCh.dh21;
|
|
79
|
+
|
|
80
|
+
delete besoinCh.dh19;
|
|
81
|
+
delete besoinCh.dh19;
|
|
82
|
+
|
|
83
|
+
return besoinCh;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Fraction des besoins de chauffage couverts par les apports gratuits pour un mois donné
|
|
88
|
+
* 6.1 Calcul de F
|
|
89
|
+
*
|
|
90
|
+
* @param ctx {Contexte}
|
|
91
|
+
* @param logement {Logement}
|
|
92
|
+
* @param mois {string}
|
|
93
|
+
* @param dh {number} - degrés-heures de chauffage sur le mois j (°Ch)
|
|
94
|
+
* @returns {number}
|
|
95
|
+
*/
|
|
96
|
+
fractionBesoinCh(ctx, logement, mois, dh) {
|
|
97
|
+
// Apports internes dans le logement sur le mois
|
|
98
|
+
const Ai = logement.donnees_de_calcul.apportsInterneCh[mois];
|
|
99
|
+
// Apports solaires dans le logement sur le mois durant la période de chauffe
|
|
100
|
+
const As = logement.donnees_de_calcul.apportsSolaire[mois];
|
|
101
|
+
|
|
102
|
+
if (dh === 0) return 0;
|
|
103
|
+
|
|
104
|
+
let pow;
|
|
105
|
+
switch (ctx.inertie.id) {
|
|
106
|
+
// Inertie très lourde ou lourde
|
|
107
|
+
case 1:
|
|
108
|
+
case 2:
|
|
109
|
+
pow = 3.6;
|
|
110
|
+
break;
|
|
111
|
+
// Inertie moyenne
|
|
112
|
+
case 3:
|
|
113
|
+
pow = 2.9;
|
|
114
|
+
break;
|
|
115
|
+
// Inertie légère
|
|
116
|
+
case 4:
|
|
117
|
+
pow = 2.5;
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const Xj = (As + Ai) / (logement.sortie.deperdition.deperdition_enveloppe * dh);
|
|
122
|
+
return (Xj - Xj ** pow) / (1 - Xj ** pow);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Besoin de chauffage hors pertes récupérées sur le mois (kWh) :
|
|
127
|
+
* 9.1.1 - Consommation de chauffage
|
|
128
|
+
*
|
|
129
|
+
* Fraction des besoins de chauffage couverts par les apports gratuits sur le mois
|
|
130
|
+
* 6.1 - Calcul de F
|
|
131
|
+
*
|
|
132
|
+
* @param ctx {Contexte}
|
|
133
|
+
* @param logement {Logement}
|
|
134
|
+
* @param mois {string}
|
|
135
|
+
* @param dh {number} - degrés-heures de chauffage sur le mois j (°Ch)
|
|
136
|
+
* @returns {{besoinChMoisHP: number, fractionApportGratuitMois: number}}
|
|
137
|
+
*/
|
|
138
|
+
besoinChHorsPertesRecuperees(ctx, logement, mois, dh) {
|
|
139
|
+
// Fraction des besoins de chauffage couverts par les apports gratuits pour un mois donné
|
|
140
|
+
const F = this.fractionBesoinCh(ctx, logement, mois, dh);
|
|
141
|
+
|
|
142
|
+
// Besoin de chauffage d’un logement par kelvin sur le mois j (W/K)
|
|
143
|
+
const BV = logement.sortie.deperdition.deperdition_enveloppe * (1 - F);
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
besoinChMoisHP: (BV * dh) / 1000,
|
|
147
|
+
fractionApportGratuitMois: F * dh
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
+
import { FrTvStore } from '../../../../dpe/infrastructure/froid/frTv.store.js';
|
|
3
|
+
import { BesoinChService } from './besoin-ch.service.js';
|
|
4
|
+
import { mois_liste } from '../../../../../utils.js';
|
|
5
|
+
|
|
6
|
+
/** @type {BesoinChService} **/
|
|
7
|
+
let service;
|
|
8
|
+
|
|
9
|
+
/** @type {FrTvStore} **/
|
|
10
|
+
let tvStore;
|
|
11
|
+
|
|
12
|
+
describe('Calcul des besoins en chauffage du logement', () => {
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
tvStore = new FrTvStore();
|
|
15
|
+
service = new BesoinChService(tvStore);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test.each([
|
|
19
|
+
{
|
|
20
|
+
inertie: 1,
|
|
21
|
+
expected: 0.24
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
inertie: 2,
|
|
25
|
+
expected: 0.24
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
inertie: 3,
|
|
29
|
+
expected: 0.23
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
inertie: 4,
|
|
33
|
+
expected: 0.22
|
|
34
|
+
}
|
|
35
|
+
])(
|
|
36
|
+
'Determination de la fraction des besoins de chauffage couverts par les apports gratuits pour un mois donné avec inertie = $inertie',
|
|
37
|
+
({ inertie, expected }) => {
|
|
38
|
+
/** @type {Contexte} */
|
|
39
|
+
const ctx = { inertie: { id: inertie } };
|
|
40
|
+
|
|
41
|
+
/** @type { Logement } **/
|
|
42
|
+
const logement = {
|
|
43
|
+
donnees_de_calcul: {
|
|
44
|
+
apportsInterneCh: { Janvier: 102.5 },
|
|
45
|
+
apportsSolaire: { Janvier: 12.5 }
|
|
46
|
+
},
|
|
47
|
+
sortie: { deperdition: { deperdition_enveloppe: 25.9 } }
|
|
48
|
+
};
|
|
49
|
+
expect(service.fractionBesoinCh(ctx, logement, 'Janvier', 18)).toBeCloseTo(expected, 2);
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
test('Besoin de chauffage hors pertes récupérées et fraction des apports gratuits pour un mois', () => {
|
|
54
|
+
/** @type {Contexte} */
|
|
55
|
+
const ctx = { inertie: { id: 1 } };
|
|
56
|
+
|
|
57
|
+
/** @type { Logement } **/
|
|
58
|
+
const logement = {
|
|
59
|
+
donnees_de_calcul: {
|
|
60
|
+
apportsInterneCh: { Janvier: 102.5 },
|
|
61
|
+
apportsSolaire: { Janvier: 12.5 }
|
|
62
|
+
},
|
|
63
|
+
sortie: { deperdition: { deperdition_enveloppe: 25.9 } }
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const besoinHP = service.besoinChHorsPertesRecuperees(ctx, logement, 'Janvier', 12.5);
|
|
67
|
+
expect(besoinHP.besoinChMoisHP).toBeCloseTo(0.2139, 4);
|
|
68
|
+
expect(besoinHP.fractionApportGratuitMois).toBeCloseTo(4.2412, 4);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('Besoin total de chauffage hors pertes récupérées et fraction des apports gratuits', () => {
|
|
72
|
+
vi.spyOn(tvStore, 'getData').mockReturnValue(10);
|
|
73
|
+
|
|
74
|
+
/** @type {Contexte} */
|
|
75
|
+
const ctx = {
|
|
76
|
+
inertie: { id: 1, ilpa: 1 },
|
|
77
|
+
altitude: { value: '400-800m' },
|
|
78
|
+
zoneClimatique: { value: 'h3c' }
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/** @type { Logement } **/
|
|
82
|
+
const logement = {
|
|
83
|
+
donnees_de_calcul: {
|
|
84
|
+
apportsInterneCh: {
|
|
85
|
+
Janvier: 102.5,
|
|
86
|
+
Février: 102.5,
|
|
87
|
+
Mars: 102.5,
|
|
88
|
+
Avril: 102.5,
|
|
89
|
+
Mai: 102.5,
|
|
90
|
+
Juin: 102.5,
|
|
91
|
+
Juillet: 102.5,
|
|
92
|
+
Aout: 102.5,
|
|
93
|
+
Septembre: 102.5,
|
|
94
|
+
Octobre: 102.5,
|
|
95
|
+
Novembre: 102.5,
|
|
96
|
+
Décembre: 102.5
|
|
97
|
+
},
|
|
98
|
+
apportsSolaire: {
|
|
99
|
+
Janvier: 102.5,
|
|
100
|
+
Février: 102.5,
|
|
101
|
+
Mars: 102.5,
|
|
102
|
+
Avril: 102.5,
|
|
103
|
+
Mai: 102.5,
|
|
104
|
+
Juin: 102.5,
|
|
105
|
+
Juillet: 102.5,
|
|
106
|
+
Aout: 102.5,
|
|
107
|
+
Septembre: 102.5,
|
|
108
|
+
Octobre: 102.5,
|
|
109
|
+
Novembre: 102.5,
|
|
110
|
+
Décembre: 102.5
|
|
111
|
+
},
|
|
112
|
+
besoinChauffageHP: {},
|
|
113
|
+
besoinChauffageDepensierHP: {}
|
|
114
|
+
},
|
|
115
|
+
sortie: { deperdition: { deperdition_enveloppe: 25.9 } }
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const besoinTotalHP = service.execute(ctx, logement);
|
|
119
|
+
expect(besoinTotalHP.besoin_ch_hp).toBeCloseTo(1.1388, 4);
|
|
120
|
+
expect(besoinTotalHP.besoin_ch_depensier_hp).toBeCloseTo(1.1388, 4);
|
|
121
|
+
expect(besoinTotalHP.fraction_apport_gratuit_ch).toBeCloseTo(0.6336, 4);
|
|
122
|
+
expect(besoinTotalHP.fraction_apport_gratuit_depensier_ch).toBeCloseTo(0.6336, 4);
|
|
123
|
+
|
|
124
|
+
for (const mois of mois_liste) {
|
|
125
|
+
expect(tvStore.getData).toHaveBeenCalledWith(
|
|
126
|
+
'dh19',
|
|
127
|
+
ctx.altitude.value,
|
|
128
|
+
ctx.zoneClimatique.value,
|
|
129
|
+
mois,
|
|
130
|
+
ctx.inertie.ilpa
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
expect(tvStore.getData).toHaveBeenCalledWith(
|
|
134
|
+
'dh21',
|
|
135
|
+
ctx.altitude.value,
|
|
136
|
+
ctx.zoneClimatique.value,
|
|
137
|
+
mois,
|
|
138
|
+
ctx.inertie.ilpa
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
expect(logement.donnees_de_calcul.besoinChauffageHP[mois]).toBeCloseTo(0.0949, 4);
|
|
142
|
+
expect(logement.donnees_de_calcul.besoinChauffageDepensierHP[mois]).toBeCloseTo(0.0949, 4);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
});
|