@open3cl/engine 1.7.0 → 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.
- package/10_besoin_fr.spec.js +1 -0
- package/10_clim.spec.js +1 -0
- package/11_besoin_ecs.spec.js +1 -0
- package/11_ecs.spec.js +1 -0
- package/12.4_pac.spec.js +1 -0
- package/13.2_generateur_combustion.spec.js +3 -3
- package/13.2_generateur_combustion_ch.spec.js +3 -3
- package/14_generateur_ecs.spec.js +1 -0
- package/15_conso_aux.spec.js +3 -3
- package/2021_04_13_confort_ete.spec.js +1 -0
- package/3.1_b.spec.js +1 -0
- package/3.2.1_mur.spec.js +1 -0
- package/3.2.2_plancher_bas.spec.js +1 -0
- package/3.2.3_plancher_haut.spec.js +1 -0
- package/3.3.1.4_porte.spec.js +1 -0
- package/3.3_baie_vitree.spec.js +1 -0
- package/3.4_pont_thermique.spec.js +1 -0
- package/4_ventilation.spec.js +1 -0
- package/5_conso_ventilation.spec.js +1 -0
- package/6.2_surface_sud_equivalente.spec.js +1 -0
- package/9_besoin_ch.spec.js +1 -0
- package/9_chauffage.spec.js +3 -3
- package/9_conso_ch.spec.js +1 -0
- package/9_emetteur_ch.spec.js +1 -0
- package/9_generateur_ch.spec.js +1 -0
- package/README.md +412 -291
- package/conso.spec.js +1 -0
- package/engine.js +3 -1
- package/engine.spec.js +1 -0
- package/package.json +15 -14
- package/features/engine/domain/apport_et_besoin/apport-et-besoin.service.spec.js +0 -222
- package/features/engine/domain/apport_et_besoin/ch/perte-ch-recup.service.spec.js +0 -345
- package/features/engine/domain/apport_et_besoin/ecs/besoin-ecs.service.spec.js +0 -87
- package/features/engine/domain/apport_et_besoin/ecs/perte-ecs-recup.service.spec.js +0 -260
- package/features/engine/domain/apport_et_besoin/froid/besoin-froid.service.spec.js +0 -272
- package/features/engine/domain/apport_et_besoin/surface-sud-equivalente.service.spec.js +0 -231
- package/features/engine/domain/ch/generateur-ch.service.spec.js +0 -849
- package/features/engine/domain/conso/froid/conso-froid.service.spec.js +0 -233
- package/features/engine/domain/ecs/installation-ecs.service.spec.js +0 -337
- package/features/engine/domain/enveloppe/baie_vitree/deperdition-baie-vitree.service.spec.js +0 -607
- package/features/engine/domain/enveloppe/deperdition-enveloppe.service.spec.js +0 -550
- package/features/engine/domain/enveloppe/espace_tampon/espace-tampon.service.spec.js +0 -82
- package/features/engine/domain/enveloppe/mur/deperdition-mur.service.spec.js +0 -542
- package/features/engine/domain/enveloppe/plancher_bas/deperdition-plancher-bas.service.spec.js +0 -430
- package/features/engine/domain/enveloppe/plancher_haut/deperdition-plancher-haut.service.spec.js +0 -411
- package/features/engine/domain/enveloppe/pont_thermique/deperdition-pont-thermique.service.spec.js +0 -653
- package/features/engine/domain/enveloppe/porte/deperdition-porte.service.spec.js +0 -117
- package/features/engine/domain/enveloppe/ventilation/deperdition-ventilation.service.spec.js +0 -508
package/conso.spec.js
CHANGED
|
@@ -38,6 +38,7 @@ vi.mock('./tv.js', () => ({
|
|
|
38
38
|
}));
|
|
39
39
|
|
|
40
40
|
vi.mock('./utils.js', () => ({
|
|
41
|
+
set_bug_for_bug_compat: vi.fn(),
|
|
41
42
|
tv: vi.fn((table, matcher) => {
|
|
42
43
|
// Réseau de chaleur "R1" connu, "R2" inconnu
|
|
43
44
|
if (matcher?.identifiant_reseau === 'R1') return { contenu_co2_acv: 0.15 };
|
package/engine.js
CHANGED
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
collectionCanBeEmpty,
|
|
24
24
|
containsAnySubstring,
|
|
25
25
|
isEffetJoule,
|
|
26
|
+
set_bug_for_bug_compat,
|
|
26
27
|
use_enum_as_string,
|
|
27
28
|
useEnumAsString,
|
|
28
29
|
xmlParser
|
|
@@ -32,7 +33,7 @@ import getFicheTechnique from './ficheTechnique.js';
|
|
|
32
33
|
import { ProductionENR } from './16.2_production_enr.js';
|
|
33
34
|
import DpeSanitizerService from './dpe-sanitizer.service.js';
|
|
34
35
|
|
|
35
|
-
const LIB_VERSION = '1.7.
|
|
36
|
+
const LIB_VERSION = '1.7.1';
|
|
36
37
|
|
|
37
38
|
const dpeSanitizerService = new DpeSanitizerService();
|
|
38
39
|
|
|
@@ -71,6 +72,7 @@ export function calcul_3cl_xml(dpeXmlContent, options) {
|
|
|
71
72
|
* @return {FullDpe}
|
|
72
73
|
*/
|
|
73
74
|
export function calcul_3cl(inputDpe, options) {
|
|
75
|
+
set_bug_for_bug_compat();
|
|
74
76
|
if (!options) options = { sanitize: true };
|
|
75
77
|
let dpe;
|
|
76
78
|
if (options.sanitize) {
|
package/engine.spec.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open3cl/engine",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "Open Source 3CL-DPE engine",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|
|
@@ -13,13 +13,11 @@
|
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
15
|
"http-server": "http-server",
|
|
16
|
-
"test": "vitest run",
|
|
16
|
+
"test": "vitest run src",
|
|
17
17
|
"test:unit": "vitest run src",
|
|
18
18
|
"test:unit:ci": "vitest run src --coverage",
|
|
19
|
-
"test:int": "vitest run test",
|
|
20
|
-
"test:int:ci": "vitest run test --coverage",
|
|
21
19
|
"test:corpus": "node test/corpus/run_all_corpus_checks.js",
|
|
22
|
-
"test:corpus:all": "node test/corpus/run_all_corpus_checks.js",
|
|
20
|
+
"test:corpus:all": "node test/corpus/run_all_corpus_checks.js && npm run reports:readme",
|
|
23
21
|
"test:corpus:all+database": "npm run test:corpus:all && node test/corpus/corpus_database.js",
|
|
24
22
|
"qa:lint": "eslint .",
|
|
25
23
|
"qa:lint:fix": "npm run qa:lint -- --fix",
|
|
@@ -30,7 +28,8 @@
|
|
|
30
28
|
"prepare": "husky install",
|
|
31
29
|
"assets:sync": "node scripts/synchronize_assets.js",
|
|
32
30
|
"version:update": "node scripts/update_version.js",
|
|
33
|
-
"reports:preview": "npm run http-server dist/reports/corpus -o"
|
|
31
|
+
"reports:preview": "npm run http-server dist/reports/corpus -o",
|
|
32
|
+
"reports:readme": "node scripts/generate_corpus_readme.js"
|
|
34
33
|
},
|
|
35
34
|
"repository": {
|
|
36
35
|
"type": "git",
|
|
@@ -42,11 +41,12 @@
|
|
|
42
41
|
],
|
|
43
42
|
"dependencies": {
|
|
44
43
|
"dioma": "^0.4.6",
|
|
45
|
-
"fast-xml-parser": "^
|
|
44
|
+
"fast-xml-parser": "^5.11.1",
|
|
46
45
|
"http-server": "^14.1.1",
|
|
47
|
-
"lodash-es": "4.
|
|
48
|
-
"mathjs": "^15.
|
|
49
|
-
"winston": "3.
|
|
46
|
+
"lodash-es": "^4.18.1",
|
|
47
|
+
"mathjs": "^15.2.0",
|
|
48
|
+
"winston": "^3.19.0",
|
|
49
|
+
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@aws-sdk/client-s3": "^3.1013.0",
|
|
@@ -59,11 +59,10 @@
|
|
|
59
59
|
"@semantic-release/git": "^10.0.1",
|
|
60
60
|
"@semantic-release/github": "^12.0.2",
|
|
61
61
|
"@types/node": "^20.12.4",
|
|
62
|
-
"@vitest/coverage-v8": "^3.
|
|
62
|
+
"@vitest/coverage-v8": "^3.2.7",
|
|
63
63
|
"ansi-colors": "^4.1.3",
|
|
64
64
|
"cli-progress": "^3.12.0",
|
|
65
65
|
"deep-object-diff": "^1.1.9",
|
|
66
|
-
"duckdb": "^1.3.2",
|
|
67
66
|
"eslint": "^8.57.0",
|
|
68
67
|
"eslint-config-prettier": "^9.1.0",
|
|
69
68
|
"eslint-config-standard": "^17.1.0",
|
|
@@ -78,11 +77,13 @@
|
|
|
78
77
|
"prettier": "^3.2.5",
|
|
79
78
|
"pretty-quick": "^4.0.0",
|
|
80
79
|
"semantic-release": "^25.0.2",
|
|
81
|
-
"vitest": "3.
|
|
82
|
-
"xlsx": "0.18.5"
|
|
80
|
+
"vitest": "3.2.7"
|
|
83
81
|
},
|
|
84
82
|
"author": "Open3Cl",
|
|
85
83
|
"license": "GPL-3.0",
|
|
84
|
+
"engines": {
|
|
85
|
+
"node": ">=24.14.1"
|
|
86
|
+
},
|
|
86
87
|
"bugs": {
|
|
87
88
|
"url": "https://github.com/Open3CL/engine/issues"
|
|
88
89
|
},
|
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
-
import { SurfaceSudEquivalenteService } from './surface-sud-equivalente.service.js';
|
|
3
|
-
import { BaieVitreeTvStore } from '../../../dpe/infrastructure/enveloppe/baieVitreeTv.store.js';
|
|
4
|
-
import { ApportEtBesoinService } from './apport-et-besoin.service.js';
|
|
5
|
-
import { BesoinEcsService } from './ecs/besoin-ecs.service.js';
|
|
6
|
-
import { BesoinFroidService } from './froid/besoin-froid.service.js';
|
|
7
|
-
import { ApportGratuitService } from './apport_gratuit/apport-gratuit.service.js';
|
|
8
|
-
import { PerteEcsRecupService } from './ecs/perte-ecs-recup.service.js';
|
|
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';
|
|
18
|
-
import { describeIntegration } from '../../../../../test/helpers/integration-test.js';
|
|
19
|
-
|
|
20
|
-
/** @type {SurfaceSudEquivalenteService} **/
|
|
21
|
-
let surfaceSudEquivalenteService;
|
|
22
|
-
|
|
23
|
-
/** @type {BesoinEcsService} **/
|
|
24
|
-
let besoinEcsService;
|
|
25
|
-
|
|
26
|
-
/** @type {BesoinFroidService} **/
|
|
27
|
-
let besoinFroidService;
|
|
28
|
-
|
|
29
|
-
/** @type {InstallationEcsService} **/
|
|
30
|
-
let installationEcsService;
|
|
31
|
-
|
|
32
|
-
/** @type {InstallationChService} **/
|
|
33
|
-
let installationChService;
|
|
34
|
-
|
|
35
|
-
/** @type {PerteEcsRecupService} **/
|
|
36
|
-
let perteEcsRecupService;
|
|
37
|
-
|
|
38
|
-
/** @type {ApportGratuitService} **/
|
|
39
|
-
let apportGratuitService;
|
|
40
|
-
|
|
41
|
-
/** @type {PerteChRecupService} **/
|
|
42
|
-
let perteChRecupService;
|
|
43
|
-
|
|
44
|
-
/** @type {BesoinChService} **/
|
|
45
|
-
let besoinChService;
|
|
46
|
-
|
|
47
|
-
/** @type {DpeNormalizerService} **/
|
|
48
|
-
let normalizerService;
|
|
49
|
-
|
|
50
|
-
/** @type {ContexteBuilder} **/
|
|
51
|
-
let contexteBuilder;
|
|
52
|
-
|
|
53
|
-
/** @type {ApportEtBesoinService} **/
|
|
54
|
-
let service;
|
|
55
|
-
|
|
56
|
-
/** @type {BaieVitreeTvStore} **/
|
|
57
|
-
let tvStore;
|
|
58
|
-
|
|
59
|
-
describe('Calcul des apports et besoin du logement', () => {
|
|
60
|
-
beforeEach(() => {
|
|
61
|
-
tvStore = new BaieVitreeTvStore();
|
|
62
|
-
surfaceSudEquivalenteService = new SurfaceSudEquivalenteService(tvStore);
|
|
63
|
-
besoinEcsService = new BesoinEcsService();
|
|
64
|
-
besoinChService = new BesoinChService();
|
|
65
|
-
besoinFroidService = new BesoinFroidService();
|
|
66
|
-
installationEcsService = new InstallationEcsService();
|
|
67
|
-
installationChService = new InstallationChService();
|
|
68
|
-
perteEcsRecupService = new PerteEcsRecupService();
|
|
69
|
-
apportGratuitService = new ApportGratuitService();
|
|
70
|
-
perteChRecupService = new PerteChRecupService();
|
|
71
|
-
service = new ApportEtBesoinService(
|
|
72
|
-
besoinEcsService,
|
|
73
|
-
besoinChService,
|
|
74
|
-
installationEcsService,
|
|
75
|
-
installationChService,
|
|
76
|
-
perteEcsRecupService,
|
|
77
|
-
besoinFroidService,
|
|
78
|
-
surfaceSudEquivalenteService,
|
|
79
|
-
perteChRecupService,
|
|
80
|
-
apportGratuitService
|
|
81
|
-
);
|
|
82
|
-
normalizerService = new DpeNormalizerService();
|
|
83
|
-
contexteBuilder = new ContexteBuilder();
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
test('Determination des apports et besoin du logement', () => {
|
|
87
|
-
vi.spyOn(surfaceSudEquivalenteService, 'execute').mockReturnValue(18.5);
|
|
88
|
-
vi.spyOn(besoinEcsService, 'execute').mockReturnValue({
|
|
89
|
-
besoin_ecs: 1526,
|
|
90
|
-
besoin_ecs_depensier: 2685.3
|
|
91
|
-
});
|
|
92
|
-
vi.spyOn(besoinChService, 'execute').mockReturnValue({
|
|
93
|
-
besoin_ch_hp: 2563,
|
|
94
|
-
besoin_ch_depensier_hp: 3258.6
|
|
95
|
-
});
|
|
96
|
-
vi.spyOn(besoinFroidService, 'execute').mockReturnValue({
|
|
97
|
-
besoin_fr: 896,
|
|
98
|
-
besoin_fr_depensier: 1025.3
|
|
99
|
-
});
|
|
100
|
-
vi.spyOn(apportGratuitService, 'apportSolaire').mockReturnValue({
|
|
101
|
-
apport_solaire_ch: 5236.9,
|
|
102
|
-
apport_solaire_fr: 145.2
|
|
103
|
-
});
|
|
104
|
-
vi.spyOn(apportGratuitService, 'apportInterne').mockReturnValue({
|
|
105
|
-
apport_interne_ch: 1236.9,
|
|
106
|
-
apport_interne_fr: 3345.2
|
|
107
|
-
});
|
|
108
|
-
vi.spyOn(installationEcsService, 'execute').mockReturnThis();
|
|
109
|
-
vi.spyOn(installationChService, 'execute').mockReturnThis();
|
|
110
|
-
vi.spyOn(perteEcsRecupService, 'execute').mockReturnValue({
|
|
111
|
-
pertes_distribution_ecs_recup: 354.2,
|
|
112
|
-
pertes_distribution_ecs_recup_depensier: 532.6,
|
|
113
|
-
pertes_stockage_ecs_recup: 25.9,
|
|
114
|
-
pertes_stockage_ecs_recup_depensier: 12.9
|
|
115
|
-
});
|
|
116
|
-
vi.spyOn(perteChRecupService, 'execute').mockReturnValue({
|
|
117
|
-
pertes_generateur_ch_recup: 102.2,
|
|
118
|
-
pertes_generateur_ch_recup_depensier: 153.4
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
/** @type {Contexte} */
|
|
122
|
-
const ctx = { zoneClimatique: { id: 1 }, nadeq: 2.5 };
|
|
123
|
-
/** @type { Logement } **/
|
|
124
|
-
const logement = { enveloppe: {} };
|
|
125
|
-
expect(service.execute(ctx, logement)).toStrictEqual({
|
|
126
|
-
surface_sud_equivalente: 18.5,
|
|
127
|
-
besoin_ecs: 1526,
|
|
128
|
-
besoin_ecs_depensier: 2685.3,
|
|
129
|
-
besoin_ch: 2080.7000000000003,
|
|
130
|
-
besoin_ch_depensier: 2559.7,
|
|
131
|
-
besoin_fr: 896,
|
|
132
|
-
besoin_fr_depensier: 1025.3,
|
|
133
|
-
apport_solaire_ch: 5236.9,
|
|
134
|
-
apport_solaire_fr: 145.2,
|
|
135
|
-
apport_interne_ch: 1236.9,
|
|
136
|
-
apport_interne_fr: 3345.2,
|
|
137
|
-
nadeq: 2.5,
|
|
138
|
-
v40_ecs_journalier: 140,
|
|
139
|
-
v40_ecs_journalier_depensier: 197.5,
|
|
140
|
-
pertes_distribution_ecs_recup: 354.2,
|
|
141
|
-
pertes_distribution_ecs_recup_depensier: 532.6,
|
|
142
|
-
pertes_generateur_ch_recup: 102.2,
|
|
143
|
-
pertes_generateur_ch_recup_depensier: 153.4,
|
|
144
|
-
pertes_stockage_ecs_recup: 25.9,
|
|
145
|
-
pertes_stockage_ecs_recup_depensier: 12.9
|
|
146
|
-
});
|
|
147
|
-
expect(surfaceSudEquivalenteService.execute).toHaveBeenCalledWith(ctx, logement.enveloppe);
|
|
148
|
-
expect(besoinEcsService.execute).toHaveBeenCalledWith(ctx);
|
|
149
|
-
expect(besoinFroidService.execute).toHaveBeenCalledWith(ctx, logement);
|
|
150
|
-
expect(apportGratuitService.apportSolaire).toHaveBeenCalledWith(ctx, logement);
|
|
151
|
-
expect(apportGratuitService.apportInterne).toHaveBeenCalledWith(ctx, logement);
|
|
152
|
-
expect(perteEcsRecupService.execute).toHaveBeenCalledWith(ctx, logement);
|
|
153
|
-
expect(perteChRecupService.execute).toHaveBeenCalledWith(ctx, logement);
|
|
154
|
-
expect(installationEcsService.execute).toHaveBeenCalledWith(ctx, logement, {
|
|
155
|
-
besoin_ecs: 1526,
|
|
156
|
-
besoin_ecs_depensier: 2685.3
|
|
157
|
-
});
|
|
158
|
-
expect(installationChService.execute).toHaveBeenCalledWith(ctx, logement);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
describeIntegration("Test d'intégration pour les besoins en chauffage", () => {
|
|
162
|
-
test.each(corpus)(
|
|
163
|
-
'Vérification de la DI besoin_ch des besoins en chauffage pour dpe %s',
|
|
164
|
-
(ademeId) => {
|
|
165
|
-
/**
|
|
166
|
-
* @type {Dpe}
|
|
167
|
-
*/
|
|
168
|
-
let dpeRequest = getAdemeFileJson(ademeId);
|
|
169
|
-
dpeRequest = normalizerService.normalize(dpeRequest);
|
|
170
|
-
|
|
171
|
-
dpeRequest.logement.donnees_de_calcul = {
|
|
172
|
-
apportsInterneDepensier: [],
|
|
173
|
-
apportsInterneCh: [],
|
|
174
|
-
apportsSolaire: [],
|
|
175
|
-
besoinChauffageHP: [],
|
|
176
|
-
besoinChauffageDepensierHP: []
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
/** @type {Contexte} */
|
|
180
|
-
const ctx = contexteBuilder.fromDpe(dpeRequest);
|
|
181
|
-
const apportEtBesoin = service.execute(ctx, dpeRequest.logement);
|
|
182
|
-
|
|
183
|
-
expect(
|
|
184
|
-
Math.abs(
|
|
185
|
-
apportEtBesoin.besoin_ch - dpeRequest.logement.sortie.apport_et_besoin.besoin_ch
|
|
186
|
-
) / (dpeRequest.logement.sortie.apport_et_besoin.besoin_ch || 1)
|
|
187
|
-
).toBeLessThan(PRECISION_PERCENT);
|
|
188
|
-
}
|
|
189
|
-
);
|
|
190
|
-
|
|
191
|
-
test.each(corpus)(
|
|
192
|
-
'Vérification de la DI besoin_ch_depensier des besoins en chauffage pour dpe %s',
|
|
193
|
-
(ademeId) => {
|
|
194
|
-
/**
|
|
195
|
-
* @type {Dpe}
|
|
196
|
-
*/
|
|
197
|
-
let dpeRequest = getAdemeFileJson(ademeId);
|
|
198
|
-
dpeRequest = normalizerService.normalize(dpeRequest);
|
|
199
|
-
|
|
200
|
-
dpeRequest.logement.donnees_de_calcul = {
|
|
201
|
-
apportsInterneDepensier: [],
|
|
202
|
-
apportsInterneCh: [],
|
|
203
|
-
apportsSolaire: [],
|
|
204
|
-
besoinChauffageHP: [],
|
|
205
|
-
besoinChauffageDepensierHP: []
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
/** @type {Contexte} */
|
|
209
|
-
const ctx = contexteBuilder.fromDpe(dpeRequest);
|
|
210
|
-
|
|
211
|
-
const apportEtBesoin = service.execute(ctx, dpeRequest.logement);
|
|
212
|
-
|
|
213
|
-
expect(
|
|
214
|
-
Math.abs(
|
|
215
|
-
apportEtBesoin.besoin_ch_depensier -
|
|
216
|
-
dpeRequest.logement.sortie.apport_et_besoin.besoin_ch_depensier
|
|
217
|
-
) / (dpeRequest.logement.sortie.apport_et_besoin.besoin_ch_depensier || 1)
|
|
218
|
-
).toBeLessThan(PRECISION_PERCENT);
|
|
219
|
-
}
|
|
220
|
-
);
|
|
221
|
-
});
|
|
222
|
-
});
|
|
@@ -1,345 +0,0 @@
|
|
|
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
|
-
import { describeIntegration } from '../../../../../../test/helpers/integration-test.js';
|
|
13
|
-
|
|
14
|
-
/** @type {PerteChRecupService} **/
|
|
15
|
-
let service;
|
|
16
|
-
|
|
17
|
-
/** @type {BesoinChService} **/
|
|
18
|
-
let besoinChService;
|
|
19
|
-
|
|
20
|
-
/** @type {ApportGratuitService} **/
|
|
21
|
-
let apportGratuitService;
|
|
22
|
-
|
|
23
|
-
/** @type {FrTvStore} **/
|
|
24
|
-
let tvStore;
|
|
25
|
-
|
|
26
|
-
/** @type {DpeNormalizerService} **/
|
|
27
|
-
let normalizerService;
|
|
28
|
-
|
|
29
|
-
/** @type {ContexteBuilder} **/
|
|
30
|
-
let contexteBuilder;
|
|
31
|
-
|
|
32
|
-
describe('Calcul des pertes de génération de chauffage récupérées', () => {
|
|
33
|
-
beforeEach(() => {
|
|
34
|
-
tvStore = new FrTvStore();
|
|
35
|
-
service = new PerteChRecupService(tvStore);
|
|
36
|
-
besoinChService = new BesoinChService();
|
|
37
|
-
apportGratuitService = new ApportGratuitService();
|
|
38
|
-
normalizerService = new DpeNormalizerService();
|
|
39
|
-
contexteBuilder = new ContexteBuilder();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test.each([
|
|
43
|
-
{
|
|
44
|
-
label: 'Installation CH uniquement avec ventouse, utilisation de nref',
|
|
45
|
-
enumUsageGenerateurId: 1,
|
|
46
|
-
presenceVentouse: 1,
|
|
47
|
-
expected: 562.5
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
label: 'Installation CH uniquement sans ventouse, utilisation de nref',
|
|
51
|
-
enumUsageGenerateurId: 1,
|
|
52
|
-
presenceVentouse: 0,
|
|
53
|
-
expected: 375
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
label: "Installation CH uniquement sans ventouse, pas d'utilisation de nref",
|
|
57
|
-
enumUsageGenerateurId: 1,
|
|
58
|
-
presenceVentouse: 0,
|
|
59
|
-
nref: 500,
|
|
60
|
-
expected: 7971.08
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
label: 'Installation ECS uniquement avec ventouse',
|
|
64
|
-
enumUsageGenerateurId: 2,
|
|
65
|
-
presenceVentouse: 1,
|
|
66
|
-
expected: 114.94
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
label: 'Installation ECS uniquement sans ventouse',
|
|
70
|
-
enumUsageGenerateurId: 2,
|
|
71
|
-
presenceVentouse: 0,
|
|
72
|
-
expected: 76.627
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
label: 'Installation ECS + CH avec ventouse, utilisation de nref',
|
|
76
|
-
enumUsageGenerateurId: 3,
|
|
77
|
-
presenceVentouse: 1,
|
|
78
|
-
expected: 562.5
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
label: 'Installation ECS + CH sans ventouse, utilisation de nref',
|
|
82
|
-
enumUsageGenerateurId: 3,
|
|
83
|
-
presenceVentouse: 0,
|
|
84
|
-
expected: 375
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
label: "Installation ECS + CH sans ventouse, pas d'utilisation de nref",
|
|
88
|
-
enumUsageGenerateurId: 3,
|
|
89
|
-
presenceVentouse: 0,
|
|
90
|
-
nref: 450,
|
|
91
|
-
expected: 10729.642
|
|
92
|
-
}
|
|
93
|
-
])(
|
|
94
|
-
'Calcul des pertes récupérées de génération pour le chauffage sur un mois pour $label',
|
|
95
|
-
({ enumUsageGenerateurId, presenceVentouse, nref = undefined, expected }) => {
|
|
96
|
-
/** @type {GenerateurChauffage[]} */
|
|
97
|
-
const generateurs = [
|
|
98
|
-
{
|
|
99
|
-
donnee_entree: {
|
|
100
|
-
presence_ventouse: presenceVentouse,
|
|
101
|
-
enum_usage_generateur_id: enumUsageGenerateurId
|
|
102
|
-
},
|
|
103
|
-
donnee_intermediaire: { pn: 25000, qp0: 125 }
|
|
104
|
-
}
|
|
105
|
-
];
|
|
106
|
-
|
|
107
|
-
expect(service.Qrec(generateurs, nref ?? 12.5, 1532.9)).toBeCloseTo(expected, 3);
|
|
108
|
-
}
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
test('Filtre des générateurs avec pertes de génération', () => {
|
|
112
|
-
const generateur1 = {
|
|
113
|
-
donnee_entree: {}
|
|
114
|
-
};
|
|
115
|
-
const generateur2 = {
|
|
116
|
-
donnee_entree: { position_volume_chauffe: 0, enum_type_generateur_ch_id: 45 }
|
|
117
|
-
};
|
|
118
|
-
const generateur3 = {
|
|
119
|
-
donnee_entree: { position_volume_chauffe: 0, enum_type_generateur_ch_id: 50 }
|
|
120
|
-
};
|
|
121
|
-
const generateur4 = {
|
|
122
|
-
donnee_entree: { position_volume_chauffe: 1, enum_type_generateur_ch_id: 50 }
|
|
123
|
-
};
|
|
124
|
-
const generateur5 = {
|
|
125
|
-
donnee_entree: { position_volume_chauffe: 1, enum_type_generateur_ch_id: 48 }
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
/** @type {Logement} */
|
|
129
|
-
let logement = { installation_chauffage_collection: {} };
|
|
130
|
-
expect(service.generateursWithPertesGeneration(logement)).toStrictEqual([]);
|
|
131
|
-
|
|
132
|
-
logement.installation_chauffage_collection = { installation_chauffage: [] };
|
|
133
|
-
expect(service.generateursWithPertesGeneration(logement)).toStrictEqual([]);
|
|
134
|
-
|
|
135
|
-
logement.installation_chauffage_collection = {
|
|
136
|
-
installation_chauffage: [{ generateur_chauffage_collection: {} }]
|
|
137
|
-
};
|
|
138
|
-
expect(service.generateursWithPertesGeneration(logement)).toStrictEqual([]);
|
|
139
|
-
|
|
140
|
-
logement.installation_chauffage_collection = {
|
|
141
|
-
installation_chauffage: [{ generateur_chauffage_collection: { generateur_chauffage: [] } }]
|
|
142
|
-
};
|
|
143
|
-
expect(service.generateursWithPertesGeneration(logement)).toStrictEqual([]);
|
|
144
|
-
|
|
145
|
-
logement.installation_chauffage_collection = {
|
|
146
|
-
installation_chauffage: [
|
|
147
|
-
{
|
|
148
|
-
generateur_chauffage_collection: {
|
|
149
|
-
generateur_chauffage: [generateur1, generateur2, generateur3]
|
|
150
|
-
}
|
|
151
|
-
},
|
|
152
|
-
{ generateur_chauffage_collection: { generateur_chauffage: [generateur4, generateur5] } }
|
|
153
|
-
]
|
|
154
|
-
};
|
|
155
|
-
expect(service.generateursWithPertesGeneration(logement)).toStrictEqual([generateur5]);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
test.each([
|
|
159
|
-
{
|
|
160
|
-
label: 'Installation CH en mode conventionnel',
|
|
161
|
-
depensier: false,
|
|
162
|
-
expected: 288
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
label: 'Installation CH en mode dépensier',
|
|
166
|
-
depensier: true,
|
|
167
|
-
expected: 540
|
|
168
|
-
}
|
|
169
|
-
])('Pertes de chauffage récupérées pour $label', ({ depensier, expected }) => {
|
|
170
|
-
vi.spyOn(tvStore, 'getData').mockReturnValue(depensier ? 1.5 : 0.8);
|
|
171
|
-
|
|
172
|
-
/** @type {Contexte} */
|
|
173
|
-
const ctx = {
|
|
174
|
-
altitude: { value: '400-800m' },
|
|
175
|
-
zoneClimatique: { value: 'h1a' },
|
|
176
|
-
inertie: { ilpa: 1 }
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
/** @type {Logement} */
|
|
180
|
-
const logement = {
|
|
181
|
-
installation_chauffage_collection: {
|
|
182
|
-
installation_chauffage: [
|
|
183
|
-
{
|
|
184
|
-
generateur_chauffage_collection: {
|
|
185
|
-
generateur_chauffage: [
|
|
186
|
-
{
|
|
187
|
-
donnee_entree: {
|
|
188
|
-
position_volume_chauffe: 1,
|
|
189
|
-
enum_type_generateur_ch_id: 48,
|
|
190
|
-
enum_usage_generateur_id: 1
|
|
191
|
-
},
|
|
192
|
-
donnee_intermediaire: { pn: 25000, qp0: 125 }
|
|
193
|
-
}
|
|
194
|
-
]
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
]
|
|
198
|
-
},
|
|
199
|
-
donnees_de_calcul: {
|
|
200
|
-
besoinChauffageHP: {
|
|
201
|
-
Janvier: 102.5,
|
|
202
|
-
Février: 102.5,
|
|
203
|
-
Mars: 102.5,
|
|
204
|
-
Avril: 102.5,
|
|
205
|
-
Mai: 102.5,
|
|
206
|
-
Juin: 102.5,
|
|
207
|
-
Juillet: 102.5,
|
|
208
|
-
Aout: 102.5,
|
|
209
|
-
Septembre: 102.5,
|
|
210
|
-
Octobre: 102.5,
|
|
211
|
-
Novembre: 102.5,
|
|
212
|
-
Décembre: 102.5
|
|
213
|
-
},
|
|
214
|
-
besoinChauffageDepensierHP: {
|
|
215
|
-
Janvier: 112.5,
|
|
216
|
-
Février: 112.5,
|
|
217
|
-
Mars: 112.5,
|
|
218
|
-
Avril: 112.5,
|
|
219
|
-
Mai: 112.5,
|
|
220
|
-
Juin: 112.5,
|
|
221
|
-
Juillet: 112.5,
|
|
222
|
-
Aout: 112.5,
|
|
223
|
-
Septembre: 112.5,
|
|
224
|
-
Octobre: 112.5,
|
|
225
|
-
Novembre: 112.5,
|
|
226
|
-
Décembre: 112.5
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
expect(service.pertesGenerateurChRecup(ctx, logement, depensier)).toBeCloseTo(expected, 3);
|
|
232
|
-
for (const mois of mois_liste) {
|
|
233
|
-
expect(tvStore.getData).toHaveBeenCalledWith(
|
|
234
|
-
depensier ? 'nref21' : 'nref19',
|
|
235
|
-
'400-800m',
|
|
236
|
-
'h1a',
|
|
237
|
-
mois,
|
|
238
|
-
1
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
test('Qrec vaut 0 pour un usage de générateur inconnu (aucune durée de récupération)', () => {
|
|
244
|
-
// enum_usage_generateur_id hors {1, 2, 3} : le switch ne définit pas Dperj (undefined),
|
|
245
|
-
// le produit devient NaN et la garde `|| 0` ramène la contribution à 0.
|
|
246
|
-
/** @type {GenerateurChauffage[]} */
|
|
247
|
-
const generateurs = [
|
|
248
|
-
{
|
|
249
|
-
donnee_entree: { presence_ventouse: 0, enum_usage_generateur_id: 99 },
|
|
250
|
-
donnee_intermediaire: { pn: 25000, qp0: 125 }
|
|
251
|
-
}
|
|
252
|
-
];
|
|
253
|
-
|
|
254
|
-
expect(service.Qrec(generateurs, 12.5, 1532.9)).toBe(0);
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
test('Conversion en kWh des pertes de génération récupérées (execute)', () => {
|
|
258
|
-
// On isole execute de la formule mensuelle : pertesGenerateurChRecup est doublée pour
|
|
259
|
-
// ne vérifier que la conversion Wh -> kWh (division par 1000) et le mapping des 2 champs.
|
|
260
|
-
vi.spyOn(service, 'pertesGenerateurChRecup').mockImplementation((ctx, logement, depensier) =>
|
|
261
|
-
depensier ? 6000 : 3000
|
|
262
|
-
);
|
|
263
|
-
|
|
264
|
-
const res = service.execute({}, {});
|
|
265
|
-
|
|
266
|
-
expect(res).toStrictEqual({
|
|
267
|
-
pertes_generateur_ch_recup: 3,
|
|
268
|
-
pertes_generateur_ch_recup_depensier: 6
|
|
269
|
-
});
|
|
270
|
-
expect(service.pertesGenerateurChRecup).toHaveBeenCalledWith({}, {}, false);
|
|
271
|
-
expect(service.pertesGenerateurChRecup).toHaveBeenCalledWith({}, {}, true);
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
describeIntegration("Test d'intégration des installations CH", () => {
|
|
275
|
-
test.each(corpus)('vérification des pertes de génération ch pour dpe %s', (ademeId) => {
|
|
276
|
-
let dpeRequest = getAdemeFileJson(ademeId);
|
|
277
|
-
dpeRequest = normalizerService.normalize(dpeRequest);
|
|
278
|
-
dpeRequest.logement.donnees_de_calcul = {
|
|
279
|
-
apportsInterneDepensier: [],
|
|
280
|
-
apportsInterneCh: [],
|
|
281
|
-
apportsSolaire: [],
|
|
282
|
-
besoinChauffageHP: [],
|
|
283
|
-
besoinChauffageDepensierHP: []
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
/** @type {Contexte} */
|
|
287
|
-
const ctx = contexteBuilder.fromDpe(dpeRequest);
|
|
288
|
-
apportGratuitService.apportInterne(ctx, dpeRequest.logement);
|
|
289
|
-
apportGratuitService.apportSolaire(ctx, dpeRequest.logement);
|
|
290
|
-
besoinChService.execute(ctx, dpeRequest.logement);
|
|
291
|
-
const pertesGeneration = service.execute(ctx, dpeRequest.logement);
|
|
292
|
-
|
|
293
|
-
const expectedValue = dpeRequest.logement.sortie.apport_et_besoin.pertes_generateur_ch_recup;
|
|
294
|
-
const calculatedValue = pertesGeneration.pertes_generateur_ch_recup;
|
|
295
|
-
|
|
296
|
-
expect_or(
|
|
297
|
-
() =>
|
|
298
|
-
expect(Math.abs(calculatedValue - expectedValue) / (expectedValue || 1)).toBeLessThan(
|
|
299
|
-
PRECISION_PERCENT
|
|
300
|
-
),
|
|
301
|
-
() =>
|
|
302
|
-
expect(
|
|
303
|
-
Math.abs(calculatedValue - expectedValue * 1000) / (expectedValue * 1000 || 1)
|
|
304
|
-
).toBeLessThan(PRECISION_PERCENT)
|
|
305
|
-
);
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
test.each(corpus)(
|
|
309
|
-
'vérification des pertes de génération ch depensier des installations CH pour dpe %s',
|
|
310
|
-
(ademeId) => {
|
|
311
|
-
let dpeRequest = getAdemeFileJson(ademeId);
|
|
312
|
-
dpeRequest = normalizerService.normalize(dpeRequest);
|
|
313
|
-
dpeRequest.logement.donnees_de_calcul = {
|
|
314
|
-
apportsInterneDepensier: [],
|
|
315
|
-
apportsInterneCh: [],
|
|
316
|
-
apportsSolaire: [],
|
|
317
|
-
besoinChauffageHP: [],
|
|
318
|
-
besoinChauffageDepensierHP: []
|
|
319
|
-
};
|
|
320
|
-
|
|
321
|
-
/** @type {Contexte} */
|
|
322
|
-
const ctx = contexteBuilder.fromDpe(dpeRequest);
|
|
323
|
-
apportGratuitService.apportInterne(ctx, dpeRequest.logement);
|
|
324
|
-
apportGratuitService.apportSolaire(ctx, dpeRequest.logement);
|
|
325
|
-
besoinChService.execute(ctx, dpeRequest.logement);
|
|
326
|
-
const pertesGeneration = service.execute(ctx, dpeRequest.logement);
|
|
327
|
-
|
|
328
|
-
const expectedValue =
|
|
329
|
-
dpeRequest.logement.sortie.apport_et_besoin.pertes_generateur_ch_recup_depensier;
|
|
330
|
-
const calculatedValue = pertesGeneration.pertes_generateur_ch_recup_depensier;
|
|
331
|
-
|
|
332
|
-
expect_or(
|
|
333
|
-
() =>
|
|
334
|
-
expect(Math.abs(calculatedValue - expectedValue) / (expectedValue || 1)).toBeLessThan(
|
|
335
|
-
PRECISION_PERCENT
|
|
336
|
-
),
|
|
337
|
-
() =>
|
|
338
|
-
expect(
|
|
339
|
-
Math.abs(calculatedValue - expectedValue * 1000) / (expectedValue * 1000 || 1)
|
|
340
|
-
).toBeLessThan(PRECISION_PERCENT)
|
|
341
|
-
);
|
|
342
|
-
}
|
|
343
|
-
);
|
|
344
|
-
});
|
|
345
|
-
});
|