@open3cl/engine 1.0.5 → 1.0.7
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/11_nadeq.spec.js +3 -2
- package/16.2_production_enr.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.3_baie_vitree.spec.js +1 -0
- package/6.1_apport_gratuit.spec.js +1 -0
- package/7_inertie.spec.js +4 -3
- package/9_chauffage.spec.js +1 -0
- package/9_conso_ch.spec.js +1 -0
- package/9_generateur_ch.spec.js +1 -0
- package/conso.spec.js +1 -0
- package/core/assets/domain/synchronize-assets.spec.js +9 -9
- package/core/assets/domain/synchronize-c1-tables.spec.js +4 -4
- package/core/assets/domain/synchronize-dpe-ges-limit-values-tables.spec.js +6 -6
- package/core/assets/domain/synchronize-enum-tables.spec.js +10 -10
- package/core/assets/domain/synchronize-solicitations-tables.spec.js +6 -6
- package/core/assets/domain/synchronize-valeur-tables.spec.js +14 -14
- package/core/file/infrastructure/adapter/file.store.spec.js +5 -4
- package/core/tv/infrastructure/tvs.store.spec.js +3 -2
- package/core/util/infrastructure/object-util.spec.js +2 -1
- package/core/util/logger/log-service.js +47 -0
- package/features/dpe/domain/models/baie-ets.model.ts +12 -0
- package/features/dpe/domain/models/baie-vitree.model.ts +95 -0
- package/features/dpe/domain/models/climatisation.model.ts +25 -0
- package/features/dpe/domain/models/dpe.model.ts +194 -0
- package/features/dpe/domain/models/ets.model.ts +19 -0
- package/features/dpe/domain/models/installation-chauffage.model.ts +101 -0
- package/features/dpe/domain/models/installation-ecs.model.ts +76 -0
- package/features/dpe/domain/models/mur.model.ts +37 -0
- package/features/dpe/domain/models/plancher-bas.model.ts +38 -0
- package/features/dpe/domain/models/plancher-haut.model.ts +33 -0
- package/features/dpe/domain/models/pont-thermique.model.ts +21 -0
- package/features/dpe/domain/models/porte.model.ts +31 -0
- package/features/dpe/domain/models/production-elec-enr.model.ts +27 -0
- package/features/dpe/domain/models/sortie.model.ts +178 -0
- package/features/dpe/domain/models/type-habitation.model.js +8 -0
- package/features/dpe/domain/models/type-ventilation.model.js +8 -0
- package/features/dpe/domain/models/ventilation.model.ts +33 -0
- package/features/dpe/infrastructure/tv.store.js +389 -0
- package/features/dpe/infrastructure/tv.store.spec.js +690 -0
- package/features/engine/domain/constants.js +1 -0
- package/features/engine/domain/contexte.builder.js +140 -0
- package/features/engine/domain/contexte.builder.spec.js +152 -0
- package/features/engine/domain/engine.service.js +139 -0
- package/features/engine/domain/engine.service.spec.js +7 -0
- package/features/engine/domain/enveloppe/deperdition-enveloppe.service.js +262 -0
- package/features/engine/domain/enveloppe/deperdition-enveloppe.service.spec.js +282 -0
- package/features/engine/domain/enveloppe/deperdition.service.js +101 -0
- package/features/engine/domain/enveloppe/mur/deperdition-mur.service.js +168 -0
- package/features/engine/domain/enveloppe/mur/deperdition-mur.service.spec.js +345 -0
- package/features/engine/domain/enveloppe/plancher_bas/deperdition-plancher-bas.service.js +169 -0
- package/features/engine/domain/enveloppe/plancher_bas/deperdition-plancher-bas.service.spec.js +200 -0
- package/features/engine/domain/enveloppe/plancher_haut/deperdition-plancher-haut.service.js +136 -0
- package/features/engine/domain/enveloppe/plancher_haut/deperdition-plancher-haut.service.spec.js +211 -0
- package/features/engine/domain/enveloppe/porte/deperdition-porte.service.js +56 -0
- package/features/engine/domain/enveloppe/porte/deperdition-porte.service.spec.js +116 -0
- package/features/engine/domain/enveloppe/ventilation/deperdition-ventilation.service.js +338 -0
- package/features/engine/domain/enveloppe/ventilation/deperdition-ventilation.service.spec.js +393 -0
- package/features/engine/domain/models/contexte.model.ts +10 -0
- package/features/engine/domain/models/deperdition.model.ts +8 -0
- package/features/normalizer/domain/dpe-normalizer.service.js +24 -0
- package/features/normalizer/domain/dpe-normalizer.service.spec.js +3 -0
- package/ficheTechnique.spec.js +4 -3
- package/output.js +1 -0
- package/package.json +9 -8
- package/tv-v2.js +79121 -0
- package/utils.js +4 -8
- package/utils.spec.js +4 -3
package/features/engine/domain/enveloppe/plancher_bas/deperdition-plancher-bas.service.spec.js
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import corpus from '../../../../../../test/corpus-sano.json';
|
|
2
|
+
import { getAdemeFileJson } from '../../../../../../test/test-helpers.js';
|
|
3
|
+
import { ContexteBuilder } from '../../contexte.builder.js';
|
|
4
|
+
import { DpeNormalizerService } from '../../../../normalizer/domain/dpe-normalizer.service.js';
|
|
5
|
+
import { DeperditionPlancherBasService } from './deperdition-plancher-bas.service.js';
|
|
6
|
+
import { TvStore } from '../../../../dpe/infrastructure/tv.store.js';
|
|
7
|
+
import { beforeEach, describe, expect, test } from 'vitest';
|
|
8
|
+
|
|
9
|
+
/** @type {DeperditionPlancherBasService} **/
|
|
10
|
+
let service;
|
|
11
|
+
|
|
12
|
+
/** @type {DpeNormalizerService} **/
|
|
13
|
+
let normalizerService;
|
|
14
|
+
|
|
15
|
+
/** @type {ContexteBuilder} **/
|
|
16
|
+
let contexteBuilder;
|
|
17
|
+
|
|
18
|
+
describe('Calcul de déperdition des planchers bas', () => {
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
service = new DeperditionPlancherBasService(new TvStore());
|
|
21
|
+
normalizerService = new DpeNormalizerService();
|
|
22
|
+
contexteBuilder = new ContexteBuilder();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('Determination de upb, upb0 et upb_final', () => {
|
|
26
|
+
test('Plancher 1 - Dalle béton non isolée donnant sur un terre-plein', () => {
|
|
27
|
+
/** @type {Contexte} */
|
|
28
|
+
const ctx = {
|
|
29
|
+
effetJoule: false,
|
|
30
|
+
enumPeriodeConstructionId: '6',
|
|
31
|
+
zoneClimatiqueId: '3'
|
|
32
|
+
};
|
|
33
|
+
/** @type {PlancherBasDE} */
|
|
34
|
+
const de = {
|
|
35
|
+
enum_type_adjacence_id: '5',
|
|
36
|
+
enum_type_plancher_bas_id: '9',
|
|
37
|
+
enum_methode_saisie_u0_id: '2',
|
|
38
|
+
enum_type_isolation_id: '2',
|
|
39
|
+
enum_methode_saisie_u_id: '1',
|
|
40
|
+
calcul_ue: 1,
|
|
41
|
+
perimetre_ue: 19.2,
|
|
42
|
+
ue: 0.49684211
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const di = service.execute(ctx, de, []);
|
|
46
|
+
expect(di.upb).toBeCloseTo(2);
|
|
47
|
+
expect(di.upb0).toBeCloseTo(2);
|
|
48
|
+
expect(di.upb_final).toBeCloseTo(0.49684211);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('Plancher 1 - Plancher lourd type entrevous terre-cuite, poutrelles béton donnant sur un sous-sol non chauffé avec isolation intrinsèque ou en sous-face (5 cm)', () => {
|
|
52
|
+
/** @type {Contexte} */
|
|
53
|
+
const ctx = {
|
|
54
|
+
effetJoule: false,
|
|
55
|
+
enumPeriodeConstructionId: '6',
|
|
56
|
+
zoneClimatiqueId: '3'
|
|
57
|
+
};
|
|
58
|
+
/** @type {PlancherBasDE} */
|
|
59
|
+
const de = {
|
|
60
|
+
enum_type_adjacence_id: '6',
|
|
61
|
+
enum_type_plancher_bas_id: '11',
|
|
62
|
+
enum_methode_saisie_u0_id: '2',
|
|
63
|
+
enum_type_isolation_id: '4',
|
|
64
|
+
epaisseur_isolation: 5,
|
|
65
|
+
enum_methode_saisie_u_id: '3',
|
|
66
|
+
calcul_ue: 0,
|
|
67
|
+
perimetre_ue: 27,
|
|
68
|
+
surface_ue: 42.08,
|
|
69
|
+
ue: 0.37117494
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const di = service.execute(ctx, de, [{ donnee_entree: de }]);
|
|
73
|
+
expect(di.upb).toBeCloseTo(0.59154929577464788);
|
|
74
|
+
expect(di.upb0).toBeCloseTo(2);
|
|
75
|
+
expect(di.upb_final).toBeCloseTo(0.37117494);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('Plancher 2 - Plancher avec ou sans remplissage non isolé donnant sur un garage', () => {
|
|
79
|
+
/** @type {Contexte} */
|
|
80
|
+
const ctx = {
|
|
81
|
+
effetJoule: false,
|
|
82
|
+
enumPeriodeConstructionId: '6',
|
|
83
|
+
zoneClimatiqueId: '3'
|
|
84
|
+
};
|
|
85
|
+
/** @type {PlancherBasDE} */
|
|
86
|
+
const de = {
|
|
87
|
+
enum_type_adjacence_id: '21',
|
|
88
|
+
enum_type_plancher_bas_id: '2',
|
|
89
|
+
enum_methode_saisie_u0_id: '2',
|
|
90
|
+
enum_type_isolation_id: '2',
|
|
91
|
+
enum_methode_saisie_u_id: '1',
|
|
92
|
+
calcul_ue: 0
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const di = service.execute(ctx, de, []);
|
|
96
|
+
expect(di.upb).toBeCloseTo(1.45);
|
|
97
|
+
expect(di.upb0).toBeCloseTo(1.45);
|
|
98
|
+
expect(di.upb_final).toBeCloseTo(1.45);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('Test de plancher avec upb0 saisie', () => {
|
|
102
|
+
/** @type {Contexte} */
|
|
103
|
+
const ctx = {
|
|
104
|
+
effetJoule: false,
|
|
105
|
+
enumPeriodeConstructionId: '6',
|
|
106
|
+
zoneClimatiqueId: '3'
|
|
107
|
+
};
|
|
108
|
+
/** @type {PlancherBasDE} */
|
|
109
|
+
const de = {
|
|
110
|
+
enum_type_adjacence_id: '21',
|
|
111
|
+
enum_type_plancher_bas_id: '2',
|
|
112
|
+
enum_methode_saisie_u0_id: '9',
|
|
113
|
+
enum_type_isolation_id: '2',
|
|
114
|
+
enum_methode_saisie_u_id: '1',
|
|
115
|
+
calcul_ue: 0,
|
|
116
|
+
upb0_saisi: 3.2
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const di = service.execute(ctx, de, []);
|
|
120
|
+
expect(di.upb).toBeCloseTo(2);
|
|
121
|
+
expect(di.upb0).toBeCloseTo(3.2);
|
|
122
|
+
expect(di.upb_final).toBeCloseTo(2);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('Test de plancher avec type de paroi inconnue', () => {
|
|
126
|
+
/** @type {Contexte} */
|
|
127
|
+
const ctx = {
|
|
128
|
+
effetJoule: false,
|
|
129
|
+
enumPeriodeConstructionId: '6',
|
|
130
|
+
zoneClimatiqueId: '3'
|
|
131
|
+
};
|
|
132
|
+
/** @type {PlancherBasDE} */
|
|
133
|
+
const de = {
|
|
134
|
+
enum_type_adjacence_id: '21',
|
|
135
|
+
enum_type_plancher_bas_id: '1',
|
|
136
|
+
enum_methode_saisie_u0_id: '1',
|
|
137
|
+
enum_type_isolation_id: '2',
|
|
138
|
+
enum_methode_saisie_u_id: '1',
|
|
139
|
+
calcul_ue: 0
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const di = service.execute(ctx, de, []);
|
|
143
|
+
expect(di.upb).toBeCloseTo(2);
|
|
144
|
+
expect(di.upb0).toBeCloseTo(2);
|
|
145
|
+
expect(di.upb_final).toBeCloseTo(2);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test('Test de plancher avec upb directement saisie', () => {
|
|
149
|
+
/** @type {Contexte} */
|
|
150
|
+
const ctx = {
|
|
151
|
+
effetJoule: false,
|
|
152
|
+
enumPeriodeConstructionId: '6',
|
|
153
|
+
zoneClimatiqueId: '3'
|
|
154
|
+
};
|
|
155
|
+
/** @type {PlancherBasDE} */
|
|
156
|
+
const de = {
|
|
157
|
+
enum_type_adjacence_id: '21',
|
|
158
|
+
enum_type_plancher_bas_id: '1',
|
|
159
|
+
enum_methode_saisie_u0_id: '5',
|
|
160
|
+
enum_type_isolation_id: '2',
|
|
161
|
+
enum_methode_saisie_u_id: '9',
|
|
162
|
+
calcul_ue: 0,
|
|
163
|
+
upb_saisi: 1.25
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const di = service.execute(ctx, de, []);
|
|
167
|
+
expect(di.upb).toBeCloseTo(1.25);
|
|
168
|
+
expect(di.upb0).toBeUndefined();
|
|
169
|
+
expect(di.upb_final).toBeCloseTo(1.25);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe("Test d'intégration de plancher bas", () => {
|
|
174
|
+
test.each(corpus)('vérification des DI des pb pour dpe %s', (ademeId) => {
|
|
175
|
+
/**
|
|
176
|
+
* @type {Dpe}
|
|
177
|
+
*/
|
|
178
|
+
let dpeRequest = getAdemeFileJson(ademeId);
|
|
179
|
+
dpeRequest = normalizerService.normalize(dpeRequest);
|
|
180
|
+
|
|
181
|
+
/** @type {Contexte} */
|
|
182
|
+
const ctx = contexteBuilder.fromDpe(dpeRequest);
|
|
183
|
+
|
|
184
|
+
/** @type {PlancherBas[]} */
|
|
185
|
+
const pbs = dpeRequest.logement.enveloppe.plancher_bas_collection?.plancher_bas || [];
|
|
186
|
+
|
|
187
|
+
pbs.forEach((pb) => {
|
|
188
|
+
const di = service.execute(ctx, pb.donnee_entree, pbs);
|
|
189
|
+
|
|
190
|
+
if (pb.donnee_intermediaire) {
|
|
191
|
+
expect(di.upb0).toBeCloseTo(pb.donnee_intermediaire.upb0, 2);
|
|
192
|
+
} else {
|
|
193
|
+
expect(di.upb0).toBeUndefined();
|
|
194
|
+
}
|
|
195
|
+
expect(di.upb_final).toBeCloseTo(pb.donnee_intermediaire.upb_final, 2);
|
|
196
|
+
expect(di.b).toBeCloseTo(pb.donnee_intermediaire.b, 2);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
});
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { inject } from 'dioma';
|
|
2
|
+
import { PRECISION } from '../../constants.js';
|
|
3
|
+
import { DeperditionService } from '../deperdition.service.js';
|
|
4
|
+
import { TvStore } from '../../../../dpe/infrastructure/tv.store.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Calcul des déperditions de l’enveloppe GV
|
|
8
|
+
* Chapitre 3.2.3 Calcul des planchers haut
|
|
9
|
+
*
|
|
10
|
+
* Méthode de calcul 3CL-DPE 2021
|
|
11
|
+
* Octobre 2021
|
|
12
|
+
* @see consolide_anne…arrete_du_31_03_2021_relatif_aux_methodes_et_procedures_applicables.pdf
|
|
13
|
+
*/
|
|
14
|
+
export class DeperditionPlancherHautService extends DeperditionService {
|
|
15
|
+
/**
|
|
16
|
+
* @param tvStore {TvStore}
|
|
17
|
+
*/
|
|
18
|
+
constructor(tvStore = inject(TvStore)) {
|
|
19
|
+
super(tvStore);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param ctx {Contexte}
|
|
24
|
+
* @param phDE {PlancherHautDE}
|
|
25
|
+
* @return {PlancherHautDI}
|
|
26
|
+
*/
|
|
27
|
+
execute(ctx, phDE) {
|
|
28
|
+
const uph0 = this.#uph0(phDE);
|
|
29
|
+
const uph = this.#uph(phDE, uph0, ctx);
|
|
30
|
+
const b = this.b({
|
|
31
|
+
enumTypeAdjacenceId: phDE.enum_type_adjacence_id,
|
|
32
|
+
surfaceAiu: phDE.surface_aiu,
|
|
33
|
+
surfaceAue: phDE.surface_aue,
|
|
34
|
+
enumCfgIsolationLncId: phDE.enum_cfg_isolation_lnc_id,
|
|
35
|
+
zoneClimatiqueId: ctx.zoneClimatiqueId
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
/** @type {PlancherHautDI} */
|
|
39
|
+
return { uph0, uph, b };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param phDE {PlancherHautDE}
|
|
44
|
+
* @param uph0 {number}
|
|
45
|
+
* @param ctx {Contexte}
|
|
46
|
+
* @return {number|undefined}
|
|
47
|
+
*/
|
|
48
|
+
#uph(phDE, uph0, ctx) {
|
|
49
|
+
// On determine uph_nu (soit uph0 soit 2 comme valeur minimale forfaitaire)
|
|
50
|
+
const uphNu = Math.min(uph0, 2.5);
|
|
51
|
+
|
|
52
|
+
const enumPeriodeIsolationId = this.getEnumPeriodeIsolationId(
|
|
53
|
+
phDE.enum_periode_isolation_id,
|
|
54
|
+
ctx
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
// Selon l'isolation, on applique un calcul au uph nu pour simuler son isolation
|
|
58
|
+
let uph;
|
|
59
|
+
switch (phDE.enum_methode_saisie_u_id) {
|
|
60
|
+
case '1':
|
|
61
|
+
// non isolé
|
|
62
|
+
uph = uphNu;
|
|
63
|
+
break;
|
|
64
|
+
case '2': // isolation inconnue (table forfaitaire)
|
|
65
|
+
case '7': // année d'isolation différente de l'année de construction
|
|
66
|
+
case '8': // année de construction saisie
|
|
67
|
+
uph = Math.min(
|
|
68
|
+
uphNu,
|
|
69
|
+
this.tvStore.getUph(
|
|
70
|
+
enumPeriodeIsolationId,
|
|
71
|
+
this.#getTypeAdjacence(phDE),
|
|
72
|
+
ctx.zoneClimatiqueId,
|
|
73
|
+
ctx.effetJoule
|
|
74
|
+
)
|
|
75
|
+
);
|
|
76
|
+
break;
|
|
77
|
+
case '3': // epaisseur isolation saisie justifiée par mesure ou observation
|
|
78
|
+
case '4': // epaisseur isolation saisie (en cm)
|
|
79
|
+
uph = 1 / (1 / uphNu + (phDE.epaisseur_isolation * 0.01) / 0.04);
|
|
80
|
+
break;
|
|
81
|
+
case '5':
|
|
82
|
+
case '6': // resistance isolation saisie
|
|
83
|
+
uph = 1 / (1 / uphNu + phDE.resistance_isolation);
|
|
84
|
+
break;
|
|
85
|
+
default: // saisie direct de la valeur de u
|
|
86
|
+
uph = phDE.uph_saisi;
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return Math.round(parseFloat(uph) * PRECISION) / PRECISION;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @param phDE {PlancherHautDE}
|
|
95
|
+
* @return {number|undefined}
|
|
96
|
+
*/
|
|
97
|
+
#uph0(phDE) {
|
|
98
|
+
let uph0;
|
|
99
|
+
switch (phDE.enum_methode_saisie_u0_id) {
|
|
100
|
+
case '1':
|
|
101
|
+
case '2':
|
|
102
|
+
// type de paroi inconnu (valeur par défaut)
|
|
103
|
+
// déterminé selon le matériau et épaisseur à partir de la table de valeur forfaitaire
|
|
104
|
+
uph0 = this.tvStore.getUph0(phDE.enum_type_plancher_haut_id);
|
|
105
|
+
break;
|
|
106
|
+
case '5':
|
|
107
|
+
// u0 non saisi car le u est saisi connu et justifié
|
|
108
|
+
return;
|
|
109
|
+
default:
|
|
110
|
+
// Valeur saisie
|
|
111
|
+
return phDE.uph0_saisi;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return uph0;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Retourne le type d'adjacence à utiliser combles ou terrasse
|
|
119
|
+
* @see Méthode de calcul 3CL-DPE 2021 (cotobre 2021) chapitre 3.2.3.1
|
|
120
|
+
* "Lorsque le local au-dessus du logement est un local non chauffé, ou un local autre que d’habitation., Uph_tab est pris dans la catégorie « Terrasse »."
|
|
121
|
+
* @param phDE {PlancherHautDE}
|
|
122
|
+
* @return {'combles'|'terasse'}
|
|
123
|
+
*/
|
|
124
|
+
#getTypeAdjacence(phDE) {
|
|
125
|
+
switch (phDE.enum_type_adjacence_id) {
|
|
126
|
+
case '1':
|
|
127
|
+
// extérieur - type de ph != 'combles aménagés sous rampant'
|
|
128
|
+
return phDE.enum_type_plancher_haut_id === '12' ? 'combles' : 'terrasse';
|
|
129
|
+
case '7':
|
|
130
|
+
// locaux non chauffés non accessible
|
|
131
|
+
return 'terrasse';
|
|
132
|
+
default:
|
|
133
|
+
return 'combles';
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
package/features/engine/domain/enveloppe/plancher_haut/deperdition-plancher-haut.service.spec.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { getAdemeFileJson } from '../../../../../../test/test-helpers.js';
|
|
2
|
+
import { ContexteBuilder } from '../../contexte.builder.js';
|
|
3
|
+
import { DpeNormalizerService } from '../../../../normalizer/domain/dpe-normalizer.service.js';
|
|
4
|
+
import { DeperditionPlancherHautService } from './deperdition-plancher-haut.service.js';
|
|
5
|
+
import corpus from '../../../../../../test/corpus-sano.json';
|
|
6
|
+
import { TvStore } from '../../../../dpe/infrastructure/tv.store.js';
|
|
7
|
+
import { beforeEach, describe, expect, test } from 'vitest';
|
|
8
|
+
|
|
9
|
+
/** @type {DeperditionPlancherHautService} **/
|
|
10
|
+
let service;
|
|
11
|
+
|
|
12
|
+
/** @type {DpeNormalizerService} **/
|
|
13
|
+
let normalizerService;
|
|
14
|
+
|
|
15
|
+
/** @type {ContexteBuilder} **/
|
|
16
|
+
let contexteBuilder;
|
|
17
|
+
|
|
18
|
+
describe('Calcul de déperdition des planchers haut', () => {
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
service = new DeperditionPlancherHautService(new TvStore());
|
|
21
|
+
normalizerService = new DpeNormalizerService();
|
|
22
|
+
contexteBuilder = new ContexteBuilder();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('Determination de uph, uph0 et uph_final', () => {
|
|
26
|
+
test('(2187E1039187C) Plafond 2 : plafond bois sous solives bois', () => {
|
|
27
|
+
/** @type {Contexte} */
|
|
28
|
+
const ctx = {
|
|
29
|
+
effetJoule: false,
|
|
30
|
+
enumPeriodeConstructionId: '2',
|
|
31
|
+
zoneClimatiqueId: '3'
|
|
32
|
+
};
|
|
33
|
+
/** @type {PlancherHautDE} */
|
|
34
|
+
const de = {
|
|
35
|
+
enum_type_adjacence_id: '1',
|
|
36
|
+
enum_type_plancher_haut_id: '10',
|
|
37
|
+
enum_methode_saisie_u0_id: '2',
|
|
38
|
+
enum_type_isolation_id: '9',
|
|
39
|
+
enum_periode_isolation_id: '3',
|
|
40
|
+
enum_methode_saisie_u_id: '8'
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const di = service.execute(ctx, de);
|
|
44
|
+
expect(di.uph0).toBeCloseTo(2.3);
|
|
45
|
+
expect(di.uph).toBeCloseTo(0.75);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("(2287E0224445X) Plafond 2 - Plafond structure inconnu (sous combles perdus) donnant sur l'extérieur (combles aménagés) avec isolation intérieure (réalisée entre 1989 et 2000)", () => {
|
|
49
|
+
/** @type {Contexte} */
|
|
50
|
+
const ctx = {
|
|
51
|
+
effetJoule: false,
|
|
52
|
+
enumPeriodeConstructionId: '1',
|
|
53
|
+
zoneClimatiqueId: '3'
|
|
54
|
+
};
|
|
55
|
+
/** @type {PlancherHautDE} */
|
|
56
|
+
const de = {
|
|
57
|
+
enum_type_adjacence_id: '1', // extérieur
|
|
58
|
+
enum_type_plancher_haut_id: '1', // inconnu
|
|
59
|
+
enum_methode_saisie_u0_id: '2', // déterminé selon le matériau et épaisseur à partir de la table de valeur forfaitaire
|
|
60
|
+
enum_type_isolation_id: '3', // iti
|
|
61
|
+
enum_periode_isolation_id: '6', // 1989-2000
|
|
62
|
+
enum_methode_saisie_u_id: '7' // année d'isolation différente de l'année de construction saisie justifiée (table forfaitaire)
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const di = service.execute(ctx, de);
|
|
66
|
+
expect(di.uph0).toBeCloseTo(2.5);
|
|
67
|
+
expect(di.uph).toBeCloseTo(0.4); // Dans le DPE d'origine, uph (0.25) est pris dans la partie "comble" et pas "terrasse" alors que le local donne sur l'extérieur
|
|
68
|
+
expect(di.b).toBeCloseTo(1);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("(2387E0562437Q) Plafond 2 - Plafond structure inconnu (sous combles perdus) donnant sur l'extérieur (combles aménagés) avec isolation intérieure (réalisée entre 1989 et 2000)", () => {
|
|
72
|
+
/** @type {Contexte} */
|
|
73
|
+
const ctx = {
|
|
74
|
+
effetJoule: true,
|
|
75
|
+
enumPeriodeConstructionId: '1',
|
|
76
|
+
zoneClimatiqueId: '3'
|
|
77
|
+
};
|
|
78
|
+
/** @type {PlancherHautDE} */
|
|
79
|
+
const de = {
|
|
80
|
+
enum_type_adjacence_id: '1', // extérieur
|
|
81
|
+
enum_type_plancher_haut_id: '1', // inconnu
|
|
82
|
+
enum_methode_saisie_u0_id: '2', // déterminé selon le matériau et épaisseur à partir de la table de valeur forfaitaire
|
|
83
|
+
enum_type_isolation_id: '3', // iti
|
|
84
|
+
enum_periode_isolation_id: '8', // 2006-2012
|
|
85
|
+
enum_methode_saisie_u_id: '7' // année d'isolation différente de l'année de construction saisie justifiée (table forfaitaire)
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const di = service.execute(ctx, de);
|
|
89
|
+
expect(di.uph0).toBeCloseTo(2.5);
|
|
90
|
+
expect(di.uph).toBeCloseTo(0.27); // Dans le DPE d'origine, uph (0.2) est pris dans la partie "comble" et pas "terrasse" alors que le local donne sur l'extérieur
|
|
91
|
+
expect(di.b).toBeCloseTo(1);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test("(2287E0272588O) Plafond - Combles aménagés sous rampants donnant sur l'extérieur (combles aménagés) avec isolation intérieure (réalisée entre 1975 et 1977)", () => {
|
|
95
|
+
/** @type {Contexte} */
|
|
96
|
+
const ctx = {
|
|
97
|
+
effetJoule: true,
|
|
98
|
+
enumPeriodeConstructionId: '1',
|
|
99
|
+
zoneClimatiqueId: '3'
|
|
100
|
+
};
|
|
101
|
+
/** @type {PlancherHautDE} */
|
|
102
|
+
const de = {
|
|
103
|
+
enum_type_adjacence_id: '1', // extérieur
|
|
104
|
+
enum_type_plancher_haut_id: '12', // combles aménagés sous rampant
|
|
105
|
+
enum_methode_saisie_u0_id: '2', // déterminé selon le matériau et épaisseur à partir de la table de valeur forfaitaire
|
|
106
|
+
enum_type_isolation_id: '3', // iti
|
|
107
|
+
enum_periode_isolation_id: '3', // 1975-1977
|
|
108
|
+
enum_methode_saisie_u_id: '7' // année d'isolation différente de l'année de construction saisie justifiée (table forfaitaire)
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const di = service.execute(ctx, de);
|
|
112
|
+
expect(di.uph0).toBeCloseTo(2.5);
|
|
113
|
+
expect(di.uph).toBeCloseTo(0.5);
|
|
114
|
+
expect(di.b).toBeCloseTo(1);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test('Test de plancher avec uph directement saisie', () => {
|
|
118
|
+
/** @type {Contexte} */
|
|
119
|
+
const ctx = {
|
|
120
|
+
effetJoule: false,
|
|
121
|
+
enumPeriodeConstructionId: '6',
|
|
122
|
+
zoneClimatiqueId: '3'
|
|
123
|
+
};
|
|
124
|
+
/** @type {PlancherHautDE} */
|
|
125
|
+
const de = {
|
|
126
|
+
enum_type_adjacence_id: '21',
|
|
127
|
+
enum_type_plancher_haut_id: '1',
|
|
128
|
+
enum_methode_saisie_u0_id: '5',
|
|
129
|
+
enum_type_isolation_id: '2',
|
|
130
|
+
enum_methode_saisie_u_id: '9',
|
|
131
|
+
uph_saisi: 1.25
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const di = service.execute(ctx, de);
|
|
135
|
+
expect(di.uph).toBeCloseTo(1.25);
|
|
136
|
+
expect(di.uph0).toBeUndefined();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test('Test de plancher avec uph0 directement saisie', () => {
|
|
140
|
+
/** @type {Contexte} */
|
|
141
|
+
const ctx = {
|
|
142
|
+
effetJoule: false,
|
|
143
|
+
enumPeriodeConstructionId: '6',
|
|
144
|
+
zoneClimatiqueId: '3'
|
|
145
|
+
};
|
|
146
|
+
/** @type {PlancherHautDE} */
|
|
147
|
+
const de = {
|
|
148
|
+
enum_type_adjacence_id: '21',
|
|
149
|
+
enum_type_plancher_haut_id: '1',
|
|
150
|
+
enum_methode_saisie_u0_id: '3',
|
|
151
|
+
enum_type_isolation_id: '2',
|
|
152
|
+
enum_periode_isolation_id: '3',
|
|
153
|
+
enum_methode_saisie_u_id: '7',
|
|
154
|
+
uph0_saisi: 1.25
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const di = service.execute(ctx, de);
|
|
158
|
+
expect(di.uph0).toBeCloseTo(1.25);
|
|
159
|
+
expect(di.uph).toBeCloseTo(0.5);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
test('Test de plancher avec uph0 type de paroi inconnu (valeur par défaut)', () => {
|
|
163
|
+
/** @type {Contexte} */
|
|
164
|
+
const ctx = {
|
|
165
|
+
effetJoule: false,
|
|
166
|
+
enumPeriodeConstructionId: '6',
|
|
167
|
+
zoneClimatiqueId: '3'
|
|
168
|
+
};
|
|
169
|
+
/** @type {PlancherHautDE} */
|
|
170
|
+
const de = {
|
|
171
|
+
enum_type_adjacence_id: '1',
|
|
172
|
+
enum_type_plancher_haut_id: '1',
|
|
173
|
+
enum_methode_saisie_u0_id: '1',
|
|
174
|
+
enum_type_isolation_id: '1',
|
|
175
|
+
enum_methode_saisie_u_id: '7'
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const di = service.execute(ctx, de);
|
|
179
|
+
expect(di.uph0).toBeCloseTo(2.5);
|
|
180
|
+
expect(di.uph).toBeCloseTo(0.4);
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
describe("Test d'intégration de plancher haut", () => {
|
|
185
|
+
test.each(corpus)('vérification des DI des ph pour dpe %s', (ademeId) => {
|
|
186
|
+
/**
|
|
187
|
+
* @type {Dpe}
|
|
188
|
+
*/
|
|
189
|
+
let dpeRequest = getAdemeFileJson(ademeId);
|
|
190
|
+
dpeRequest = normalizerService.normalize(dpeRequest);
|
|
191
|
+
|
|
192
|
+
/** @type {Contexte} */
|
|
193
|
+
const ctx = contexteBuilder.fromDpe(dpeRequest);
|
|
194
|
+
|
|
195
|
+
/** @type {PlancherHaut[]} */
|
|
196
|
+
const phs = dpeRequest.logement.enveloppe.plancher_haut_collection?.plancher_haut || [];
|
|
197
|
+
|
|
198
|
+
phs.forEach((ph) => {
|
|
199
|
+
const di = service.execute(ctx, ph.donnee_entree);
|
|
200
|
+
|
|
201
|
+
if (ph.donnee_intermediaire) {
|
|
202
|
+
expect(di.uph0).toBeCloseTo(ph.donnee_intermediaire.uph0, 2);
|
|
203
|
+
} else {
|
|
204
|
+
expect(di.uph0).toBeUndefined();
|
|
205
|
+
}
|
|
206
|
+
expect(di.uph).toBeCloseTo(ph.donnee_intermediaire.uph, 2);
|
|
207
|
+
expect(di.b).toBeCloseTo(ph.donnee_intermediaire.b, 2);
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { inject } from 'dioma';
|
|
2
|
+
import { DeperditionService } from '../deperdition.service.js';
|
|
3
|
+
import { TvStore } from '../../../../dpe/infrastructure/tv.store.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Calcul des déperditions de l’enveloppe GV
|
|
7
|
+
* Chapitre 3.3.4 Coefficients U des portes
|
|
8
|
+
*
|
|
9
|
+
* Méthode de calcul 3CL-DPE 2021
|
|
10
|
+
* Octobre 2021
|
|
11
|
+
* @see consolide_anne…arrete_du_31_03_2021_relatif_aux_methodes_et_procedures_applicables.pdf
|
|
12
|
+
*
|
|
13
|
+
* Si le coefficient U des portes est connu et justifié, le saisir directement. Sinon, prendre les valeurs tabulées
|
|
14
|
+
*/
|
|
15
|
+
export class DeperditionPorteService extends DeperditionService {
|
|
16
|
+
/**
|
|
17
|
+
* @param tvStore {TvStore}
|
|
18
|
+
*/
|
|
19
|
+
constructor(tvStore = inject(TvStore)) {
|
|
20
|
+
super(tvStore);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @param ctx {Contexte}
|
|
25
|
+
* @param porteDE {PorteDE}
|
|
26
|
+
* @return {PorteDI}
|
|
27
|
+
*/
|
|
28
|
+
execute(ctx, porteDE) {
|
|
29
|
+
/** @type {PorteDI} */
|
|
30
|
+
const di = {
|
|
31
|
+
uporte: undefined,
|
|
32
|
+
b: undefined
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// @todo : Une porte vitrée avec plus de 60% de vitrage est traitée comme une porte-fenêtre avec soubassement.
|
|
36
|
+
|
|
37
|
+
if (['2', '3'].includes(porteDE.enum_methode_saisie_uporte_id)) {
|
|
38
|
+
// valeur justifiée saisie à partir des documents justificatifs autorisés
|
|
39
|
+
// saisie direct U depuis RSET/RSEE( etude RT2012/RE2020)
|
|
40
|
+
di.uporte = porteDE.uporte_saisi;
|
|
41
|
+
} else {
|
|
42
|
+
// valeur forfaitaire
|
|
43
|
+
di.uporte = this.tvStore.getUPorte(porteDE.enum_type_porte_id);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
di.b = this.b({
|
|
47
|
+
enumTypeAdjacenceId: porteDE.enum_type_adjacence_id,
|
|
48
|
+
surfaceAiu: porteDE.surface_aiu,
|
|
49
|
+
surfaceAue: porteDE.surface_aue,
|
|
50
|
+
enumCfgIsolationLncId: porteDE.enum_cfg_isolation_lnc_id,
|
|
51
|
+
zoneClimatiqueId: ctx.zoneClimatiqueId
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return di;
|
|
55
|
+
}
|
|
56
|
+
}
|