@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
|
@@ -0,0 +1,168 @@
|
|
|
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 des pertes récupérées de génération de chauffage
|
|
7
|
+
* Chapitre 9.1.1 Consommation de chauffage
|
|
8
|
+
*
|
|
9
|
+
* Données calculées
|
|
10
|
+
* — pertes_generateur_ch_recup : pertes récupérées de génération pour le chauffage (kWh)
|
|
11
|
+
* — pertes_generateur_ch_recup_depensier : pertes récupérées de génération pour le chauffage (kWh) pour le scénario dépensier
|
|
12
|
+
*
|
|
13
|
+
* Methode_de_calcul_3CL_DPE_2021 - Page 57
|
|
14
|
+
* Octobre 2021
|
|
15
|
+
* @see consolide_anne…arrete_du_31_03_2021_relatif_aux_methodes_et_procedures_applicables.pdf
|
|
16
|
+
*/
|
|
17
|
+
export class PerteChRecupService {
|
|
18
|
+
/**
|
|
19
|
+
* @type {FrTvStore}
|
|
20
|
+
*/
|
|
21
|
+
#tvStore;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @param tvStore {FrTvStore}
|
|
25
|
+
*/
|
|
26
|
+
constructor(tvStore = inject(FrTvStore)) {
|
|
27
|
+
this.#tvStore = tvStore;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Pertes récupérées des générateurs de chauffage pour le chauffage (kWh)
|
|
32
|
+
*
|
|
33
|
+
* @param ctx {Contexte}
|
|
34
|
+
* @param logement {Logement}
|
|
35
|
+
* @return {{pertes_generateur_ch_recup: number, pertes_generateur_ch_recup_depensier: number}}
|
|
36
|
+
*/
|
|
37
|
+
execute(ctx, logement) {
|
|
38
|
+
return {
|
|
39
|
+
pertes_generateur_ch_recup: this.pertesGenerateurChRecup(ctx, logement, false) / 1000,
|
|
40
|
+
pertes_generateur_ch_recup_depensier: this.pertesGenerateurChRecup(ctx, logement, true) / 1000
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Pertes récupérées des générateurs de chauffage pour le chauffage (Wh)
|
|
46
|
+
* 9.1.1 Consommation de chauffage
|
|
47
|
+
*
|
|
48
|
+
* @param ctx {Contexte}
|
|
49
|
+
* @param logement {Logement}
|
|
50
|
+
* @param depensier {boolean}
|
|
51
|
+
* @returns {number}
|
|
52
|
+
*/
|
|
53
|
+
pertesGenerateurChRecup(ctx, logement, depensier) {
|
|
54
|
+
const generateursWithPertesGeneration = this.generateursWithPertesGeneration(logement);
|
|
55
|
+
|
|
56
|
+
return mois_liste.reduce((acc, mois) => {
|
|
57
|
+
return (
|
|
58
|
+
acc +
|
|
59
|
+
this.Qrec(
|
|
60
|
+
generateursWithPertesGeneration,
|
|
61
|
+
this.#tvStore.getData(
|
|
62
|
+
depensier ? 'nref21' : 'nref19',
|
|
63
|
+
ctx.altitude.value,
|
|
64
|
+
ctx.zoneClimatique.value,
|
|
65
|
+
mois,
|
|
66
|
+
ctx.inertie.ilpa
|
|
67
|
+
),
|
|
68
|
+
depensier
|
|
69
|
+
? logement.donnees_de_calcul.besoinChauffageDepensierHP[mois]
|
|
70
|
+
: logement.donnees_de_calcul.besoinChauffageHP[mois]
|
|
71
|
+
)
|
|
72
|
+
);
|
|
73
|
+
}, 0);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Pertes récupérées des générateurs de chauffage pour le chauffage
|
|
78
|
+
* 9.1.1 Consommation de chauffage
|
|
79
|
+
*
|
|
80
|
+
* Seules les pertes des générateurs en volume chauffé sont récupérables.
|
|
81
|
+
* Les pertes récupérées des générateurs d’air chaud sont nulles.
|
|
82
|
+
*
|
|
83
|
+
* @param logement {Logement}
|
|
84
|
+
*/
|
|
85
|
+
generateursWithPertesGeneration(logement) {
|
|
86
|
+
const installationsCh =
|
|
87
|
+
logement.installation_chauffage_collection?.installation_chauffage || [];
|
|
88
|
+
|
|
89
|
+
return installationsCh.reduce((acc, installation) => {
|
|
90
|
+
// Liste des générateurs de chauffage pour lesquels il y a une récupération d'énergie
|
|
91
|
+
return acc.concat(
|
|
92
|
+
(installation.generateur_chauffage_collection?.generateur_chauffage || []).filter(
|
|
93
|
+
(generateurChauffage) => {
|
|
94
|
+
const generateurChauffageDE = generateurChauffage.donnee_entree;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* 50 - générateur à air chaud à combustion avant 2006
|
|
98
|
+
* 51 - générateur à air chaud à combustion standard a partir de 2006
|
|
99
|
+
* 52 - générateur à air chaud à combustion à condensation a partir de 2006
|
|
100
|
+
*/
|
|
101
|
+
return (
|
|
102
|
+
(generateurChauffageDE.position_volume_chauffe ?? 0) === 1 &&
|
|
103
|
+
![50, 51, 52].includes(parseInt(generateurChauffageDE.enum_type_generateur_ch_id))
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
);
|
|
108
|
+
}, []);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Pertes récupérées de génération pour le chauffage sur le mois j (Wh)
|
|
113
|
+
*
|
|
114
|
+
* @param generateurs {GenerateurChauffage[]}
|
|
115
|
+
* @param nref {number}
|
|
116
|
+
* @param besoinChauffageMois {number}
|
|
117
|
+
* @constructor
|
|
118
|
+
*/
|
|
119
|
+
Qrec(generateurs, nref, besoinChauffageMois) {
|
|
120
|
+
return generateurs.reduce((acc, generateur) => {
|
|
121
|
+
const generateurChauffageDE = generateur.donnee_entree;
|
|
122
|
+
const generateurChauffageDI = generateur.donnee_intermediaire;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Part des pertes par les parois égale à 0,75 pour les équipements à ventouse ou assistés par ventilateur
|
|
126
|
+
* et 0,5 pour les autres
|
|
127
|
+
* @type {number}
|
|
128
|
+
*/
|
|
129
|
+
const Cper = parseInt(generateurChauffageDE.presence_ventouse || 0) === 1 ? 0.75 : 0.5;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Durée pendant laquelle les pertes sont récupérées sur le mois (h)
|
|
133
|
+
*/
|
|
134
|
+
let Dperj;
|
|
135
|
+
switch (parseInt(generateurChauffageDE.enum_usage_generateur_id)) {
|
|
136
|
+
case 1:
|
|
137
|
+
// Pour les générateurs assurant le chauffage uniquement
|
|
138
|
+
Dperj = Math.min(
|
|
139
|
+
nref,
|
|
140
|
+
this.#pertes_gen_ch(besoinChauffageMois, generateurChauffageDI.pn)
|
|
141
|
+
);
|
|
142
|
+
break;
|
|
143
|
+
case 2:
|
|
144
|
+
// Pour les générateurs assurant l’ECS uniquement
|
|
145
|
+
Dperj = this.#pertes_gen_ecs(nref);
|
|
146
|
+
break;
|
|
147
|
+
case 3:
|
|
148
|
+
// Pour les générateurs assurant le chauffage et l’ECS
|
|
149
|
+
Dperj = Math.min(
|
|
150
|
+
nref,
|
|
151
|
+
this.#pertes_gen_ch(besoinChauffageMois, generateurChauffageDI.pn) +
|
|
152
|
+
this.#pertes_gen_ecs(nref)
|
|
153
|
+
);
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return acc + 0.48 * Cper * generateurChauffageDI.qp0 * Dperj || 0;
|
|
158
|
+
}, 0);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
#pertes_gen_ch(Bch, pn) {
|
|
162
|
+
return (1.3 * Bch * 1000) / (0.3 * pn);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
#pertes_gen_ecs(nref) {
|
|
166
|
+
return (nref * 1790) / 8760;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
+
import corpus from '../../../../../../test/corpus-sano.json';
|
|
3
|
+
import { expect_or, getAdemeFileJson } from '../../../../../../test/test-helpers.js';
|
|
4
|
+
import { DpeNormalizerService } from '../../../../normalizer/domain/dpe-normalizer.service.js';
|
|
5
|
+
import { ContexteBuilder } from '../../contexte.builder.js';
|
|
6
|
+
import { FrTvStore } from '../../../../dpe/infrastructure/froid/frTv.store.js';
|
|
7
|
+
import { mois_liste } from '../../../../../utils.js';
|
|
8
|
+
import { PerteChRecupService } from './perte-ch-recup.service.js';
|
|
9
|
+
import { BesoinChService } from './besoin-ch.service.js';
|
|
10
|
+
import { ApportGratuitService } from '../apport_gratuit/apport-gratuit.service.js';
|
|
11
|
+
import { PRECISION_PERCENT } from '../../../../../../test/constant.js';
|
|
12
|
+
|
|
13
|
+
/** @type {PerteChRecupService} **/
|
|
14
|
+
let service;
|
|
15
|
+
|
|
16
|
+
/** @type {BesoinChService} **/
|
|
17
|
+
let besoinChService;
|
|
18
|
+
|
|
19
|
+
/** @type {ApportGratuitService} **/
|
|
20
|
+
let apportGratuitService;
|
|
21
|
+
|
|
22
|
+
/** @type {FrTvStore} **/
|
|
23
|
+
let tvStore;
|
|
24
|
+
|
|
25
|
+
/** @type {DpeNormalizerService} **/
|
|
26
|
+
let normalizerService;
|
|
27
|
+
|
|
28
|
+
/** @type {ContexteBuilder} **/
|
|
29
|
+
let contexteBuilder;
|
|
30
|
+
|
|
31
|
+
describe('Calcul des pertes de génération de chauffage récupérées', () => {
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
tvStore = new FrTvStore();
|
|
34
|
+
service = new PerteChRecupService(tvStore);
|
|
35
|
+
besoinChService = new BesoinChService();
|
|
36
|
+
apportGratuitService = new ApportGratuitService();
|
|
37
|
+
normalizerService = new DpeNormalizerService();
|
|
38
|
+
contexteBuilder = new ContexteBuilder();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test.each([
|
|
42
|
+
{
|
|
43
|
+
label: 'Installation CH uniquement avec ventouse, utilisation de nref',
|
|
44
|
+
enumUsageGenerateurId: 1,
|
|
45
|
+
presenceVentouse: 1,
|
|
46
|
+
expected: 562.5
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
label: 'Installation CH uniquement sans ventouse, utilisation de nref',
|
|
50
|
+
enumUsageGenerateurId: 1,
|
|
51
|
+
presenceVentouse: 0,
|
|
52
|
+
expected: 375
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
label: "Installation CH uniquement sans ventouse, pas d'utilisation de nref",
|
|
56
|
+
enumUsageGenerateurId: 1,
|
|
57
|
+
presenceVentouse: 0,
|
|
58
|
+
nref: 500,
|
|
59
|
+
expected: 7971.08
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
label: 'Installation ECS uniquement avec ventouse',
|
|
63
|
+
enumUsageGenerateurId: 2,
|
|
64
|
+
presenceVentouse: 1,
|
|
65
|
+
expected: 114.94
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
label: 'Installation ECS uniquement sans ventouse',
|
|
69
|
+
enumUsageGenerateurId: 2,
|
|
70
|
+
presenceVentouse: 0,
|
|
71
|
+
expected: 76.627
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
label: 'Installation ECS + CH avec ventouse, utilisation de nref',
|
|
75
|
+
enumUsageGenerateurId: 3,
|
|
76
|
+
presenceVentouse: 1,
|
|
77
|
+
expected: 562.5
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
label: 'Installation ECS + CH sans ventouse, utilisation de nref',
|
|
81
|
+
enumUsageGenerateurId: 3,
|
|
82
|
+
presenceVentouse: 0,
|
|
83
|
+
expected: 375
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
label: "Installation ECS + CH sans ventouse, pas d'utilisation de nref",
|
|
87
|
+
enumUsageGenerateurId: 3,
|
|
88
|
+
presenceVentouse: 0,
|
|
89
|
+
nref: 450,
|
|
90
|
+
expected: 10729.642
|
|
91
|
+
}
|
|
92
|
+
])(
|
|
93
|
+
'Calcul des pertes récupérées de génération pour le chauffage sur un mois pour $label',
|
|
94
|
+
({ enumUsageGenerateurId, presenceVentouse, nref = undefined, expected }) => {
|
|
95
|
+
/** @type {GenerateurChauffage[]} */
|
|
96
|
+
const generateurs = [
|
|
97
|
+
{
|
|
98
|
+
donnee_entree: {
|
|
99
|
+
presence_ventouse: presenceVentouse,
|
|
100
|
+
enum_usage_generateur_id: enumUsageGenerateurId
|
|
101
|
+
},
|
|
102
|
+
donnee_intermediaire: { pn: 25000, qp0: 125 }
|
|
103
|
+
}
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
expect(service.Qrec(generateurs, nref ?? 12.5, 1532.9)).toBeCloseTo(expected, 3);
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
test('Filtre des générateurs avec pertes de génération', () => {
|
|
111
|
+
const generateur1 = {
|
|
112
|
+
donnee_entree: {}
|
|
113
|
+
};
|
|
114
|
+
const generateur2 = {
|
|
115
|
+
donnee_entree: { position_volume_chauffe: 0, enum_type_generateur_ch_id: 45 }
|
|
116
|
+
};
|
|
117
|
+
const generateur3 = {
|
|
118
|
+
donnee_entree: { position_volume_chauffe: 0, enum_type_generateur_ch_id: 50 }
|
|
119
|
+
};
|
|
120
|
+
const generateur4 = {
|
|
121
|
+
donnee_entree: { position_volume_chauffe: 1, enum_type_generateur_ch_id: 50 }
|
|
122
|
+
};
|
|
123
|
+
const generateur5 = {
|
|
124
|
+
donnee_entree: { position_volume_chauffe: 1, enum_type_generateur_ch_id: 48 }
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/** @type {Logement} */
|
|
128
|
+
let logement = { installation_chauffage_collection: {} };
|
|
129
|
+
expect(service.generateursWithPertesGeneration(logement)).toStrictEqual([]);
|
|
130
|
+
|
|
131
|
+
logement.installation_chauffage_collection = { installation_chauffage: [] };
|
|
132
|
+
expect(service.generateursWithPertesGeneration(logement)).toStrictEqual([]);
|
|
133
|
+
|
|
134
|
+
logement.installation_chauffage_collection = {
|
|
135
|
+
installation_chauffage: [{ generateur_chauffage_collection: {} }]
|
|
136
|
+
};
|
|
137
|
+
expect(service.generateursWithPertesGeneration(logement)).toStrictEqual([]);
|
|
138
|
+
|
|
139
|
+
logement.installation_chauffage_collection = {
|
|
140
|
+
installation_chauffage: [{ generateur_chauffage_collection: { generateur_chauffage: [] } }]
|
|
141
|
+
};
|
|
142
|
+
expect(service.generateursWithPertesGeneration(logement)).toStrictEqual([]);
|
|
143
|
+
|
|
144
|
+
logement.installation_chauffage_collection = {
|
|
145
|
+
installation_chauffage: [
|
|
146
|
+
{
|
|
147
|
+
generateur_chauffage_collection: {
|
|
148
|
+
generateur_chauffage: [generateur1, generateur2, generateur3]
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
{ generateur_chauffage_collection: { generateur_chauffage: [generateur4, generateur5] } }
|
|
152
|
+
]
|
|
153
|
+
};
|
|
154
|
+
expect(service.generateursWithPertesGeneration(logement)).toStrictEqual([generateur5]);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test.each([
|
|
158
|
+
{
|
|
159
|
+
label: 'Installation CH en mode conventionnel',
|
|
160
|
+
depensier: false,
|
|
161
|
+
expected: 288
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
label: 'Installation CH en mode dépensier',
|
|
165
|
+
depensier: true,
|
|
166
|
+
expected: 540
|
|
167
|
+
}
|
|
168
|
+
])('Pertes de chauffage récupérées pour $label', ({ depensier, expected }) => {
|
|
169
|
+
vi.spyOn(tvStore, 'getData').mockReturnValue(depensier ? 1.5 : 0.8);
|
|
170
|
+
|
|
171
|
+
/** @type {Contexte} */
|
|
172
|
+
const ctx = {
|
|
173
|
+
altitude: { value: '400-800m' },
|
|
174
|
+
zoneClimatique: { value: 'h1a' },
|
|
175
|
+
inertie: { ilpa: 1 }
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
/** @type {Logement} */
|
|
179
|
+
const logement = {
|
|
180
|
+
installation_chauffage_collection: {
|
|
181
|
+
installation_chauffage: [
|
|
182
|
+
{
|
|
183
|
+
generateur_chauffage_collection: {
|
|
184
|
+
generateur_chauffage: [
|
|
185
|
+
{
|
|
186
|
+
donnee_entree: {
|
|
187
|
+
position_volume_chauffe: 1,
|
|
188
|
+
enum_type_generateur_ch_id: 48,
|
|
189
|
+
enum_usage_generateur_id: 1
|
|
190
|
+
},
|
|
191
|
+
donnee_intermediaire: { pn: 25000, qp0: 125 }
|
|
192
|
+
}
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
]
|
|
197
|
+
},
|
|
198
|
+
donnees_de_calcul: {
|
|
199
|
+
besoinChauffageHP: {
|
|
200
|
+
Janvier: 102.5,
|
|
201
|
+
Février: 102.5,
|
|
202
|
+
Mars: 102.5,
|
|
203
|
+
Avril: 102.5,
|
|
204
|
+
Mai: 102.5,
|
|
205
|
+
Juin: 102.5,
|
|
206
|
+
Juillet: 102.5,
|
|
207
|
+
Aout: 102.5,
|
|
208
|
+
Septembre: 102.5,
|
|
209
|
+
Octobre: 102.5,
|
|
210
|
+
Novembre: 102.5,
|
|
211
|
+
Décembre: 102.5
|
|
212
|
+
},
|
|
213
|
+
besoinChauffageDepensierHP: {
|
|
214
|
+
Janvier: 112.5,
|
|
215
|
+
Février: 112.5,
|
|
216
|
+
Mars: 112.5,
|
|
217
|
+
Avril: 112.5,
|
|
218
|
+
Mai: 112.5,
|
|
219
|
+
Juin: 112.5,
|
|
220
|
+
Juillet: 112.5,
|
|
221
|
+
Aout: 112.5,
|
|
222
|
+
Septembre: 112.5,
|
|
223
|
+
Octobre: 112.5,
|
|
224
|
+
Novembre: 112.5,
|
|
225
|
+
Décembre: 112.5
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
expect(service.pertesGenerateurChRecup(ctx, logement, depensier)).toBeCloseTo(expected, 3);
|
|
231
|
+
for (const mois of mois_liste) {
|
|
232
|
+
expect(tvStore.getData).toHaveBeenCalledWith(
|
|
233
|
+
depensier ? 'nref21' : 'nref19',
|
|
234
|
+
'400-800m',
|
|
235
|
+
'h1a',
|
|
236
|
+
mois,
|
|
237
|
+
1
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
describe("Test d'intégration des installations CH", () => {
|
|
243
|
+
test.each(corpus)('vérification des pertes de génération ch pour dpe %s', (ademeId) => {
|
|
244
|
+
let dpeRequest = getAdemeFileJson(ademeId);
|
|
245
|
+
dpeRequest = normalizerService.normalize(dpeRequest);
|
|
246
|
+
dpeRequest.logement.donnees_de_calcul = {
|
|
247
|
+
apportsInterneDepensier: [],
|
|
248
|
+
apportsInterneCh: [],
|
|
249
|
+
apportsSolaire: [],
|
|
250
|
+
besoinChauffageHP: [],
|
|
251
|
+
besoinChauffageDepensierHP: []
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
/** @type {Contexte} */
|
|
255
|
+
const ctx = contexteBuilder.fromDpe(dpeRequest);
|
|
256
|
+
apportGratuitService.apportInterne(ctx, dpeRequest.logement);
|
|
257
|
+
apportGratuitService.apportSolaire(ctx, dpeRequest.logement);
|
|
258
|
+
besoinChService.execute(ctx, dpeRequest.logement);
|
|
259
|
+
const pertesGeneration = service.execute(ctx, dpeRequest.logement);
|
|
260
|
+
|
|
261
|
+
const expectedValue = dpeRequest.logement.sortie.apport_et_besoin.pertes_generateur_ch_recup;
|
|
262
|
+
const calculatedValue = pertesGeneration.pertes_generateur_ch_recup;
|
|
263
|
+
|
|
264
|
+
expect_or(
|
|
265
|
+
() =>
|
|
266
|
+
expect(Math.abs(calculatedValue - expectedValue) / (expectedValue || 1)).toBeLessThan(
|
|
267
|
+
PRECISION_PERCENT
|
|
268
|
+
),
|
|
269
|
+
() =>
|
|
270
|
+
expect(
|
|
271
|
+
Math.abs(calculatedValue - expectedValue * 1000) / (expectedValue * 1000 || 1)
|
|
272
|
+
).toBeLessThan(PRECISION_PERCENT)
|
|
273
|
+
);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
test.each(corpus)(
|
|
277
|
+
'vérification des pertes de génération ch depensier des installations CH pour dpe %s',
|
|
278
|
+
(ademeId) => {
|
|
279
|
+
let dpeRequest = getAdemeFileJson(ademeId);
|
|
280
|
+
dpeRequest = normalizerService.normalize(dpeRequest);
|
|
281
|
+
dpeRequest.logement.donnees_de_calcul = {
|
|
282
|
+
apportsInterneDepensier: [],
|
|
283
|
+
apportsInterneCh: [],
|
|
284
|
+
apportsSolaire: [],
|
|
285
|
+
besoinChauffageHP: [],
|
|
286
|
+
besoinChauffageDepensierHP: []
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
/** @type {Contexte} */
|
|
290
|
+
const ctx = contexteBuilder.fromDpe(dpeRequest);
|
|
291
|
+
apportGratuitService.apportInterne(ctx, dpeRequest.logement);
|
|
292
|
+
apportGratuitService.apportSolaire(ctx, dpeRequest.logement);
|
|
293
|
+
besoinChService.execute(ctx, dpeRequest.logement);
|
|
294
|
+
const pertesGeneration = service.execute(ctx, dpeRequest.logement);
|
|
295
|
+
|
|
296
|
+
const expectedValue =
|
|
297
|
+
dpeRequest.logement.sortie.apport_et_besoin.pertes_generateur_ch_recup_depensier;
|
|
298
|
+
const calculatedValue = pertesGeneration.pertes_generateur_ch_recup_depensier;
|
|
299
|
+
|
|
300
|
+
expect_or(
|
|
301
|
+
() =>
|
|
302
|
+
expect(Math.abs(calculatedValue - expectedValue) / (expectedValue || 1)).toBeLessThan(
|
|
303
|
+
PRECISION_PERCENT
|
|
304
|
+
),
|
|
305
|
+
() =>
|
|
306
|
+
expect(
|
|
307
|
+
Math.abs(calculatedValue - expectedValue * 1000) / (expectedValue * 1000 || 1)
|
|
308
|
+
).toBeLessThan(PRECISION_PERCENT)
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
);
|
|
312
|
+
});
|
|
313
|
+
});
|
|
@@ -29,20 +29,23 @@ export class PerteEcsRecupService {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
+
* Pertes de distribution et de stockage ECS (kWh)
|
|
32
33
|
* @param ctx {Contexte}
|
|
33
34
|
* @param logement {Logement}
|
|
34
|
-
* @return {{pertes_distribution_ecs_recup: number, pertes_distribution_ecs_recup_depensier: number, pertes_stockage_ecs_recup: number}}
|
|
35
|
+
* @return {{pertes_distribution_ecs_recup: number, pertes_distribution_ecs_recup_depensier: number, pertes_stockage_ecs_recup: number, pertes_stockage_ecs_recup_depensier: number}}
|
|
35
36
|
*/
|
|
36
37
|
execute(ctx, logement) {
|
|
37
38
|
return {
|
|
38
|
-
pertes_distribution_ecs_recup: this.pertesDistributionEcsRecup(ctx, logement, false),
|
|
39
|
-
pertes_distribution_ecs_recup_depensier:
|
|
40
|
-
|
|
39
|
+
pertes_distribution_ecs_recup: this.pertesDistributionEcsRecup(ctx, logement, false) / 1000,
|
|
40
|
+
pertes_distribution_ecs_recup_depensier:
|
|
41
|
+
this.pertesDistributionEcsRecup(ctx, logement, true) / 1000,
|
|
42
|
+
pertes_stockage_ecs_recup: this.pertesStockageEcsRecup(ctx, logement, false) / 1000,
|
|
43
|
+
pertes_stockage_ecs_recup_depensier: this.pertesStockageEcsRecup(ctx, logement, true) / 1000
|
|
41
44
|
};
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
/**
|
|
45
|
-
* Pertes récupérées de distribution d’ECS pour le chauffage
|
|
48
|
+
* Pertes récupérées de distribution d’ECS pour le chauffage (Wh)
|
|
46
49
|
* 9.1.1 Consommation de chauffage
|
|
47
50
|
*
|
|
48
51
|
* @param ctx {Contexte}
|
|
@@ -89,14 +92,15 @@ export class PerteEcsRecupService {
|
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
/**
|
|
92
|
-
* Pertes récupérées du stockage d’ECS pour le chauffage
|
|
95
|
+
* Pertes récupérées du stockage d’ECS pour le chauffage (Wh)
|
|
93
96
|
* 9.1.1 Consommation de chauffage
|
|
94
97
|
*
|
|
95
98
|
* @param ctx {Contexte}
|
|
96
99
|
* @param logement {Logement}
|
|
100
|
+
* @param depensier {boolean}
|
|
97
101
|
* @returns {number}
|
|
98
102
|
*/
|
|
99
|
-
pertesStockageEcsRecup(ctx, logement) {
|
|
103
|
+
pertesStockageEcsRecup(ctx, logement, depensier) {
|
|
100
104
|
const installationsEcs = logement.installation_ecs_collection?.installation_ecs || [];
|
|
101
105
|
|
|
102
106
|
let pertesStockage = installationsEcs.reduce((acc, installation) => {
|
|
@@ -111,7 +115,7 @@ export class PerteEcsRecupService {
|
|
|
111
115
|
acc +
|
|
112
116
|
pertesStockage *
|
|
113
117
|
this.#tvStore.getData(
|
|
114
|
-
'nref19',
|
|
118
|
+
depensier ? 'nref21' : 'nref19',
|
|
115
119
|
ctx.altitude.value,
|
|
116
120
|
ctx.zoneClimatique.value,
|
|
117
121
|
mois,
|
|
@@ -38,15 +38,15 @@ describe('Calcul des pertes de distribution et stockage récupérées', () => {
|
|
|
38
38
|
{
|
|
39
39
|
label: 'Installation ECS en mode conventionnel',
|
|
40
40
|
depensier: false,
|
|
41
|
-
expected: 0.
|
|
41
|
+
expected: 0.192
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
label: 'Installation ECS en mode dépensier',
|
|
45
45
|
depensier: true,
|
|
46
|
-
expected: 0.
|
|
46
|
+
expected: 0.725
|
|
47
47
|
}
|
|
48
48
|
])('Calcul des pertes de distribution récupérées pour $label', ({ depensier, expected }) => {
|
|
49
|
-
vi.spyOn(tvStore, 'getData').mockReturnValue(1.5);
|
|
49
|
+
vi.spyOn(tvStore, 'getData').mockReturnValue(depensier ? 1.5 : 0.8);
|
|
50
50
|
|
|
51
51
|
/** @type {Contexte} */
|
|
52
52
|
const ctx = {
|
|
@@ -75,7 +75,7 @@ describe('Calcul des pertes de distribution et stockage récupérées', () => {
|
|
|
75
75
|
}
|
|
76
76
|
};
|
|
77
77
|
|
|
78
|
-
expect(service.pertesDistributionEcsRecup(ctx, logement, depensier)).toBeCloseTo(expected,
|
|
78
|
+
expect(service.pertesDistributionEcsRecup(ctx, logement, depensier)).toBeCloseTo(expected, 3);
|
|
79
79
|
for (const mois of mois_liste) {
|
|
80
80
|
expect(tvStore.getData).toHaveBeenCalledWith(
|
|
81
81
|
depensier ? 'nref21' : 'nref19',
|
|
@@ -87,8 +87,19 @@ describe('Calcul des pertes de distribution et stockage récupérées', () => {
|
|
|
87
87
|
}
|
|
88
88
|
});
|
|
89
89
|
|
|
90
|
-
test(
|
|
91
|
-
|
|
90
|
+
test.each([
|
|
91
|
+
{
|
|
92
|
+
label: 'Installation ECS en mode conventionnel',
|
|
93
|
+
depensier: false,
|
|
94
|
+
expected: 63.209
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
label: 'Installation ECS en mode dépensier',
|
|
98
|
+
depensier: true,
|
|
99
|
+
expected: 118.516
|
|
100
|
+
}
|
|
101
|
+
])('Calcul des pertes de stockage récupérées pour $label', ({ depensier, expected }) => {
|
|
102
|
+
vi.spyOn(tvStore, 'getData').mockReturnValue(depensier ? 1.5 : 0.8);
|
|
92
103
|
|
|
93
104
|
/** @type {Contexte} */
|
|
94
105
|
const ctx = {
|
|
@@ -101,15 +112,21 @@ describe('Calcul des pertes de distribution et stockage récupérées', () => {
|
|
|
101
112
|
const logement = {
|
|
102
113
|
installation_ecs_collection: {
|
|
103
114
|
installation_ecs: [
|
|
104
|
-
{ donnee_utilisateur: { QgwRecuperable:
|
|
115
|
+
{ donnee_utilisateur: { QgwRecuperable: 120012 } },
|
|
105
116
|
{ donnee_utilisateur: { QgwRecuperable: 150 } }
|
|
106
117
|
]
|
|
107
118
|
}
|
|
108
119
|
};
|
|
109
120
|
|
|
110
|
-
expect(service.pertesStockageEcsRecup(ctx, logement)).toBeCloseTo(
|
|
121
|
+
expect(service.pertesStockageEcsRecup(ctx, logement, depensier)).toBeCloseTo(expected, 3);
|
|
111
122
|
for (const mois of mois_liste) {
|
|
112
|
-
expect(tvStore.getData).toHaveBeenCalledWith(
|
|
123
|
+
expect(tvStore.getData).toHaveBeenCalledWith(
|
|
124
|
+
depensier ? 'nref21' : 'nref19',
|
|
125
|
+
'400-800m',
|
|
126
|
+
'h1a',
|
|
127
|
+
mois,
|
|
128
|
+
1
|
|
129
|
+
);
|
|
113
130
|
}
|
|
114
131
|
});
|
|
115
132
|
|
|
@@ -142,6 +159,7 @@ describe('Calcul des pertes de distribution et stockage récupérées', () => {
|
|
|
142
159
|
);
|
|
143
160
|
}
|
|
144
161
|
);
|
|
162
|
+
|
|
145
163
|
test.each(corpus)(
|
|
146
164
|
'vérification des pertes de distribution ecs recup depensier des installations ECS pour dpe %s',
|
|
147
165
|
(ademeId) => {
|
|
@@ -170,6 +188,7 @@ describe('Calcul des pertes de distribution et stockage récupérées', () => {
|
|
|
170
188
|
);
|
|
171
189
|
}
|
|
172
190
|
);
|
|
191
|
+
|
|
173
192
|
test.each(corpus)(
|
|
174
193
|
'vérification des pertes de stockage ecs recup des installations ECS pour dpe %s',
|
|
175
194
|
(ademeId) => {
|
|
@@ -190,10 +209,6 @@ describe('Calcul des pertes de distribution et stockage récupérées', () => {
|
|
|
190
209
|
expect(pertesStockage.pertes_stockage_ecs_recup).toBeCloseTo(
|
|
191
210
|
dpeRequest.logement.sortie.apport_et_besoin.pertes_stockage_ecs_recup
|
|
192
211
|
),
|
|
193
|
-
() =>
|
|
194
|
-
expect(pertesStockage.pertes_stockage_ecs_recup).toBeCloseTo(
|
|
195
|
-
dpeRequest.logement.sortie.apport_et_besoin.pertes_stockage_ecs_recup * 1000
|
|
196
|
-
),
|
|
197
212
|
() =>
|
|
198
213
|
expect(pertesStockage.pertes_stockage_ecs_recup * 1000).toBeCloseTo(
|
|
199
214
|
dpeRequest.logement.sortie.apport_et_besoin.pertes_stockage_ecs_recup
|