@open3cl/engine 1.0.0
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.js +76 -0
- package/10_clim.js +45 -0
- package/11_besoin_ecs.js +25 -0
- package/11_ecs.js +95 -0
- package/11_nadeq.js +87 -0
- package/11_nadeq.spec.js +55 -0
- package/12.4_pac.js +54 -0
- package/13.2_generateur_combustion.js +295 -0
- package/13.2_generateur_combustion_bouilleur.js +173 -0
- package/13.2_generateur_combustion_ch.js +195 -0
- package/13.2_generateur_combustion_chaudiere.js +151 -0
- package/13.2_generateur_pac.js +36 -0
- package/13_rendement_distribution_ecs.js +12 -0
- package/14_generateur_ecs.js +388 -0
- package/15_conso_aux.js +257 -0
- package/16.2_production_enr.js +328 -0
- package/16.2_production_enr.spec.js +251 -0
- package/16_conso_eclairage.js +37 -0
- package/2021_04_13_confort_ete.js +61 -0
- package/2021_04_13_qualite_isolation.js +174 -0
- package/3.1_b.js +141 -0
- package/3.2.1_mur.js +331 -0
- package/3.2.1_mur.spec.js +46 -0
- package/3.2.2_plancher_bas.js +259 -0
- package/3.2.2_plancher_bas.spec.js +88 -0
- package/3.2.3_plancher_haut.js +158 -0
- package/3.3.1.4_porte.js +32 -0
- package/3.3_baie_vitree.js +308 -0
- package/3.3_baie_vitree.spec.js +333 -0
- package/3.4_pont_thermique.js +463 -0
- package/3_deperdition.js +258 -0
- package/4_ventilation.js +197 -0
- package/5_conso_ventilation.js +127 -0
- package/6.1_apport_gratuit.js +61 -0
- package/6.1_apport_gratuit.spec.js +181 -0
- package/6.2_surface_sud_equivalente.js +109 -0
- package/7_inertie.js +178 -0
- package/7_inertie.spec.js +263 -0
- package/8_intermittence.js +5 -0
- package/9_besoin_ch.js +198 -0
- package/9_chauffage.js +291 -0
- package/9_chauffage.spec.js +101 -0
- package/9_conso_ch.js +95 -0
- package/9_conso_ch.spec.js +255 -0
- package/9_emetteur_ch.js +122 -0
- package/9_generateur_ch.js +230 -0
- package/9_generateur_ch.spec.js +87 -0
- package/README.md +43 -0
- package/apport_et_besoin.js +55 -0
- package/conso.js +529 -0
- package/conso.spec.js +90 -0
- package/core/assets/domain/add-additionnal-ue-values-tables.js +57 -0
- package/core/assets/domain/synchronize-assets.js +29 -0
- package/core/assets/domain/synchronize-assets.spec.js +37 -0
- package/core/assets/domain/synchronize-c1-tables.js +61 -0
- package/core/assets/domain/synchronize-c1-tables.spec.js +35 -0
- package/core/assets/domain/synchronize-dpe-ges-limit-values-tables.js +73 -0
- package/core/assets/domain/synchronize-dpe-ges-limit-values-tables.spec.js +72 -0
- package/core/assets/domain/synchronize-enum-tables.js +77 -0
- package/core/assets/domain/synchronize-enum-tables.spec.js +31 -0
- package/core/assets/domain/synchronize-solicitations-tables.js +72 -0
- package/core/assets/domain/synchronize-solicitations-tables.spec.js +47 -0
- package/core/assets/domain/synchronize-valeur-tables.js +146 -0
- package/core/assets/domain/synchronize-valeur-tables.spec.js +54 -0
- package/core/conf/infrastructure/application.config.js +33 -0
- package/core/file/infrastructure/adapter/file.store.js +75 -0
- package/core/file/infrastructure/adapter/file.store.spec.js +30 -0
- package/core/tv/infrastructure/assets/additional-ue-values.js +69 -0
- package/core/tv/infrastructure/tvs.store.js +40 -0
- package/core/tv/infrastructure/tvs.store.spec.js +34 -0
- package/core/util/infrastructure/object-util.js +23 -0
- package/core/util/infrastructure/object-util.spec.js +25 -0
- package/engine.js +503 -0
- package/enums.js +1155 -0
- package/ficheTechnique.js +86 -0
- package/ficheTechnique.spec.js +181 -0
- package/index.js +4 -0
- package/package.json +87 -0
- package/tv/18.2_sollicitations_ext.ods +0 -0
- package/tv/18.5_c1.ods +0 -0
- package/tv/dpe_ges_limit_values.ods +0 -0
- package/tv.js +80811 -0
- package/tvs.d.ts +7 -0
- package/utils.js +500 -0
- package/utils.spec.js +36 -0
package/3.2.1_mur.js
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import enums from './enums.js';
|
|
2
|
+
import {
|
|
3
|
+
tv,
|
|
4
|
+
requestInput,
|
|
5
|
+
requestInputID,
|
|
6
|
+
getKeyByValue,
|
|
7
|
+
bug_for_bug_compat,
|
|
8
|
+
getThicknessFromDescription
|
|
9
|
+
} from './utils.js';
|
|
10
|
+
import b from './3.1_b.js';
|
|
11
|
+
|
|
12
|
+
const scriptName = new URL(import.meta.url).pathname.split('/').pop();
|
|
13
|
+
|
|
14
|
+
function tv_umur0(di, de, du) {
|
|
15
|
+
const matcher = {
|
|
16
|
+
enum_materiaux_structure_mur_id: de.enum_materiaux_structure_mur_id
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Les matériaux 1, 6, 20, 27 ne sont pas concernés par les épaisseurs
|
|
21
|
+
* 1 - inconnu
|
|
22
|
+
* 6 - murs en pan de bois avec remplissage tout venant
|
|
23
|
+
* 20 - cloison de plâtre
|
|
24
|
+
* 27 - murs en ossature bois avec remplissage tout venant
|
|
25
|
+
*/
|
|
26
|
+
if (![1, 6, 20, 27].includes(parseInt(de.enum_materiaux_structure_mur_id))) {
|
|
27
|
+
matcher.epaisseur_structure = requestInput(de, du, 'epaisseur_structure', 'float');
|
|
28
|
+
if (!matcher.epaisseur_structure) {
|
|
29
|
+
/**
|
|
30
|
+
* Certains logiciels omettent le champ 'epaisseur_structure'
|
|
31
|
+
* Récupération de cette information si elle existe dans la description via regex "(\d+) cm"
|
|
32
|
+
* @type {number}
|
|
33
|
+
*/
|
|
34
|
+
matcher.epaisseur_structure = getThicknessFromDescription(de.description);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Si on n'a toujours pas de valeur pour 'epaisseur_structure', récupération de la valeur utilisée
|
|
38
|
+
* dans le DPE
|
|
39
|
+
*/
|
|
40
|
+
if (bug_for_bug_compat && de.tv_umur0_id && matcher.epaisseur_structure === 0) {
|
|
41
|
+
const rowUmur0 = tv('umur0', {
|
|
42
|
+
tv_umur0_id: de.tv_umur0_id
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
if (rowUmur0 && rowUmur0.epaisseur_structure) {
|
|
46
|
+
matcher.epaisseur_structure = rowUmur0.epaisseur_structure;
|
|
47
|
+
|
|
48
|
+
console.error(
|
|
49
|
+
`Aucune valeur trouvée pour epaisseur_structure (ni saisie, ni présente dans la description) pour le mur '${de.description}'.
|
|
50
|
+
Récupération et utilisation de la valeur ${rowUmur0.epaisseur_structure} depuis tv_umur0_id = ${de.tv_umur0_id}`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const row = tv('umur0', matcher);
|
|
57
|
+
if (row) {
|
|
58
|
+
di.umur0 = Number(row.umur0);
|
|
59
|
+
de.tv_umur0_id = Number(row.tv_umur0_id);
|
|
60
|
+
} else {
|
|
61
|
+
console.error('!! pas de valeur forfaitaire trouvée pour umur0 !!');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function tv_umur(di, de, du, pc_id, zc, effetJoule) {
|
|
66
|
+
if (bug_for_bug_compat && de.tv_umur_id) {
|
|
67
|
+
/**
|
|
68
|
+
* Vérification de la variable effet_joule
|
|
69
|
+
* Certains DPE utilise de manière erronée cette variable. Pour rester cohérent avec le DPE, utilisation de la variable
|
|
70
|
+
* effet_joule telle qu'elle est utilisée dans le DPE
|
|
71
|
+
*/
|
|
72
|
+
const rowUmur = tv('umur', {
|
|
73
|
+
tv_umur_id: de.tv_umur_id
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
if (rowUmur && rowUmur.effet_joule !== effetJoule) {
|
|
77
|
+
console.error(
|
|
78
|
+
`La variable effet_joule utilisée dans le DPE pour le mur '${de.description}' est ${rowUmur.effet_joule}.
|
|
79
|
+
Celle-ci devrait être ${effetJoule}. La valeur ${rowUmur.effet_joule} est conservée dans la suite des calculs`
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
effetJoule = rowUmur.effet_joule;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (rowUmur && rowUmur.enum_periode_construction_id.split('|')[0] !== pc_id) {
|
|
86
|
+
console.error(
|
|
87
|
+
`L'année de construction du bâtiment ${pc_id} ne correspond pas à celle utilisée dans le DPE pour le calcul de Umur pour le mur '${de.description}'.
|
|
88
|
+
Celle utilisée ${rowUmur.enum_periode_construction_id}. L'année de construction ${rowUmur.enum_periode_construction_id} est conservée dans la suite des calculs.`
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
pc_id = rowUmur.enum_periode_construction_id.split('|')[0];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const matcher = {
|
|
96
|
+
enum_periode_construction_id: pc_id,
|
|
97
|
+
enum_zone_climatique_id: zc,
|
|
98
|
+
effet_joule: effetJoule
|
|
99
|
+
};
|
|
100
|
+
const row = tv('umur', matcher, de);
|
|
101
|
+
if (row) {
|
|
102
|
+
di.umur = Number(row.umur);
|
|
103
|
+
de.tv_umur_id = Number(row.tv_umur_id);
|
|
104
|
+
} else {
|
|
105
|
+
console.error('!! pas de valeur forfaitaire trouvée pour umur !!');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function calc_umur0(di, de, du) {
|
|
110
|
+
const umur0_avant = du.umur0_avant;
|
|
111
|
+
const umur_avant = du.umur_avant;
|
|
112
|
+
|
|
113
|
+
const methode_saisie_u0 = requestInput(de, du, 'methode_saisie_u0');
|
|
114
|
+
switch (methode_saisie_u0) {
|
|
115
|
+
case 'type de paroi inconnu (valeur par défaut)':
|
|
116
|
+
/**
|
|
117
|
+
* Si le type de mur est inconnu, Umur0 = Umur_nu = 2.5.
|
|
118
|
+
*/
|
|
119
|
+
di.umur0 = '2.5';
|
|
120
|
+
break;
|
|
121
|
+
case 'déterminé selon le matériau et épaisseur à partir de la table de valeur forfaitaire':
|
|
122
|
+
requestInput(de, du, 'materiaux_structure_mur');
|
|
123
|
+
tv_umur0(di, de, du);
|
|
124
|
+
break;
|
|
125
|
+
case 'saisie direct u0 justifiée à partir des documents justificatifs autorisés':
|
|
126
|
+
case "saisie direct u0 correspondant à la performance de la paroi avec son isolation antérieure iti (umur_iti) lorsqu'il y a une surisolation ite réalisée":
|
|
127
|
+
di.umur0 = requestInput(de, du, 'umur0_saisi', 'float');
|
|
128
|
+
break;
|
|
129
|
+
case 'u0 non saisi car le u est saisi connu et justifié.':
|
|
130
|
+
break;
|
|
131
|
+
default:
|
|
132
|
+
console.warn('methode_saisie_u0 inconnue:', methode_saisie_u0);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (de.paroi_ancienne) {
|
|
136
|
+
// le champ `paroi_ancienne` a ete renomme en `enduit_isolant_paroi_ancienne`
|
|
137
|
+
de.enduit_isolant_paroi_ancienne = de.paroi_ancienne;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
let type_doublage = parseInt(de.enum_type_doublage_id);
|
|
141
|
+
|
|
142
|
+
// Certaines descriptions contiennent des informations sur le type de doublage
|
|
143
|
+
if (bug_for_bug_compat && (type_doublage === 1 || type_doublage === 2)) {
|
|
144
|
+
if (de.description.toLowerCase().indexOf('doublage connu (plâtre, brique') !== -1) {
|
|
145
|
+
type_doublage = 5;
|
|
146
|
+
} else if (de.description.toLowerCase().indexOf('doublage indéterminé avec lame') !== -1) {
|
|
147
|
+
type_doublage = 4;
|
|
148
|
+
} else if (de.description.toLowerCase().indexOf('doublage indéterminé ou lame') !== -1) {
|
|
149
|
+
type_doublage = 3;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Si présence d'un doublage
|
|
154
|
+
if (type_doublage > 2) {
|
|
155
|
+
let umur0Doublage;
|
|
156
|
+
|
|
157
|
+
// 3 - doublage indéterminé ou lame d'air inf 15 mm
|
|
158
|
+
if (type_doublage === 3) {
|
|
159
|
+
umur0Doublage = 1 / (1 / di.umur0 + 0.1);
|
|
160
|
+
} else if (type_doublage === 4 || type_doublage === 5) {
|
|
161
|
+
// 4 - doublage indéterminé avec lame d'air sup 15 mm
|
|
162
|
+
// 5 - doublage connu (plâtre brique bois)
|
|
163
|
+
umur0Doublage = 1 / (1 / di.umur0 + 0.21);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Certains DPE minorent di.umur0 à 2.5 avant d'appliquer le doublage. On vérifie ici si c'est le cas pour informer que
|
|
168
|
+
* le calcul du doublage se trouvera plus déperditif ici
|
|
169
|
+
*/
|
|
170
|
+
if (bug_for_bug_compat) {
|
|
171
|
+
checkDoublageWithMinUmur0(type_doublage, di, de, umur0_avant, umur_avant);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
di.umur0 = umur0Doublage;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (requestInput(de, du, 'enduit_isolant_paroi_ancienne', 'bool') === 1) {
|
|
178
|
+
const umur0Enduit = 1 / (1 / di.umur0 + 0.7);
|
|
179
|
+
di.umur0Enduit = umur0Enduit;
|
|
180
|
+
|
|
181
|
+
if (
|
|
182
|
+
bug_for_bug_compat &&
|
|
183
|
+
umur0_avant !== undefined &&
|
|
184
|
+
parseFloat(umur0_avant).toFixed(3) === Math.min(2.5, di.umur0).toFixed(3)
|
|
185
|
+
) {
|
|
186
|
+
console.error(`
|
|
187
|
+
Le mur ${de.description} est une paroi dite 'paroi ancienne avec enduit', la valeur de Umur0 devrait prendre en compte cet enduit et devrait être ${umur0Enduit}.
|
|
188
|
+
Cependant le DPE ne prend pas en compte l'enduit et utilise Umur0=${umur0_avant}. On garde cette valeur ${umur0_avant} dans la suite.
|
|
189
|
+
`);
|
|
190
|
+
di.umur0 = umur0_avant;
|
|
191
|
+
} else {
|
|
192
|
+
di.umur0 = umur0Enduit;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
di.umur0 = Math.min(2.5, di.umur0);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export default function calc_mur(mur, zc, pc_id, effetJoule) {
|
|
200
|
+
const de = mur.donnee_entree;
|
|
201
|
+
const du = {};
|
|
202
|
+
const di = {};
|
|
203
|
+
du.umur0_avant = mur.donnee_intermediaire?.umur0;
|
|
204
|
+
du.umur_avant = mur.donnee_intermediaire?.umur;
|
|
205
|
+
|
|
206
|
+
requestInput(de, du, 'surface_paroi_totale', 'float');
|
|
207
|
+
requestInput(de, du, 'orientation');
|
|
208
|
+
|
|
209
|
+
b(di, de, du, zc);
|
|
210
|
+
|
|
211
|
+
const methode_saisie_u = requestInput(de, du, 'methode_saisie_u');
|
|
212
|
+
switch (methode_saisie_u) {
|
|
213
|
+
case 'non isolé':
|
|
214
|
+
calc_umur0(di, de, du);
|
|
215
|
+
di.umur = Math.min(di.umur0, 2.5);
|
|
216
|
+
break;
|
|
217
|
+
case 'epaisseur isolation saisie justifiée par mesure ou observation':
|
|
218
|
+
case 'epaisseur isolation saisie justifiée à partir des documents justificatifs autorisés': {
|
|
219
|
+
calc_umur0(di, de, du);
|
|
220
|
+
const epaisseurIsolation = requestInput(de, du, 'epaisseur_isolation', 'int') * 0.01;
|
|
221
|
+
|
|
222
|
+
if (epaisseurIsolation) {
|
|
223
|
+
di.umur = 1 / (1 / Number(di.umur0) + epaisseurIsolation / 0.04);
|
|
224
|
+
} else {
|
|
225
|
+
console.error(
|
|
226
|
+
`Le mur ${mur.donnee_entree.description} ne possède pas de donnée d'entrée pour epaisseur_isolation
|
|
227
|
+
alors que methode_saisie_u = 'epaisseur isolation saisie'`
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
di.umur = Math.min(di.umur0, 2.5);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
case "resistance isolation saisie justifiée observation de l'isolant installé et mesure de son épaisseur":
|
|
236
|
+
case 'resistance isolation saisie justifiée à partir des documents justificatifs autorisés': {
|
|
237
|
+
calc_umur0(di, de, du);
|
|
238
|
+
const resistanceIsolation = requestInput(de, du, 'resistance_isolation', 'float');
|
|
239
|
+
|
|
240
|
+
if (resistanceIsolation) {
|
|
241
|
+
di.umur = 1 / (1 / Number(di.umur0) + resistanceIsolation);
|
|
242
|
+
} else {
|
|
243
|
+
console.error(
|
|
244
|
+
`Le mur ${mur.donnee_entree.description} ne possède pas de donnée d'entrée pour resistance_isolation
|
|
245
|
+
alors que methode_saisie_u = 'resistance isolation saisie'`
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
di.umur = Math.min(di.umur0, 2.5);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
case 'isolation inconnue (table forfaitaire)':
|
|
254
|
+
calc_umur0(di, de, du);
|
|
255
|
+
tv_umur(di, de, du, pc_id, zc, effetJoule);
|
|
256
|
+
di.umur = Math.min(di.umur, di.umur0);
|
|
257
|
+
break;
|
|
258
|
+
case "année d'isolation différente de l'année de construction saisie justifiée (table forfaitaire)": {
|
|
259
|
+
calc_umur0(di, de, du);
|
|
260
|
+
const pi_id = requestInputID(de, du, 'periode_isolation') || pc_id;
|
|
261
|
+
tv_umur(di, de, du, pi_id, zc, effetJoule);
|
|
262
|
+
di.umur = Math.min(di.umur, di.umur0);
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
case 'année de construction saisie (table forfaitaire)': {
|
|
266
|
+
calc_umur0(di, de, du);
|
|
267
|
+
// Si l'année d'isolation est connue, il faut l'utiliser et pas l'année de construction
|
|
268
|
+
let pi_id = de.enum_periode_isolation_id || pc_id;
|
|
269
|
+
if (!de.enum_periode_isolation_id) {
|
|
270
|
+
const pc = enums.periode_construction[pc_id];
|
|
271
|
+
switch (pc) {
|
|
272
|
+
case 'avant 1948':
|
|
273
|
+
case '1948-1974':
|
|
274
|
+
pi_id = parseInt(getKeyByValue(enums.periode_isolation, '1975-1977'), 10);
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
const tv_umur_avant = de.tv_umur_id;
|
|
279
|
+
tv_umur(di, de, du, pi_id, zc, effetJoule);
|
|
280
|
+
if (de.tv_umur_id !== tv_umur_avant && pi_id !== pc_id) {
|
|
281
|
+
console.warn(
|
|
282
|
+
`BUG(${scriptName}) Si année de construction <74 alors Année d'isolation=75-77 (3CL page 13)`
|
|
283
|
+
);
|
|
284
|
+
if (bug_for_bug_compat) tv_umur(di, de, du, pc_id, zc, effetJoule);
|
|
285
|
+
}
|
|
286
|
+
di.umur = Math.min(di.umur, di.umur0);
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
case 'saisie direct u justifiée (à partir des documents justificatifs autorisés)':
|
|
290
|
+
case 'saisie direct u depuis rset/rsee( etude rt2012/re2020)':
|
|
291
|
+
di.umur = requestInput(de, du, 'umur_saisi', 'float');
|
|
292
|
+
di.umur0 = mur.donnee_intermediaire?.umur0;
|
|
293
|
+
break;
|
|
294
|
+
default:
|
|
295
|
+
console.warn('methode_saisie_u inconnue:', methode_saisie_u);
|
|
296
|
+
}
|
|
297
|
+
mur.donnee_utilisateur = du;
|
|
298
|
+
mur.donnee_intermediaire = di;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Vérification si le calcul des déperditions des murs utilisent, dans le DPE d'origine, une minoration à 2.5 de Umur0
|
|
303
|
+
* pour l'application du doublage
|
|
304
|
+
* @param type_doublage {number}
|
|
305
|
+
* @param di {Donnee_intermediaire}
|
|
306
|
+
* @param de {Donnee_entree}
|
|
307
|
+
* @param umur0_avant {number}
|
|
308
|
+
* @param umur_avant {number}
|
|
309
|
+
*/
|
|
310
|
+
function checkDoublageWithMinUmur0(type_doublage, di, de, umur0_avant, umur_avant) {
|
|
311
|
+
let umur0Doublage;
|
|
312
|
+
|
|
313
|
+
// 3 - doublage indéterminé ou lame d'air inf 15 mm
|
|
314
|
+
if (type_doublage === 3) {
|
|
315
|
+
umur0Doublage = 1 / (1 / Math.min(2.5, di.umur0) + 0.1);
|
|
316
|
+
} else if (type_doublage === 4 || type_doublage === 5) {
|
|
317
|
+
// 4 - doublage indéterminé avec lame d'air sup 15 mm
|
|
318
|
+
// 5 - doublage connu (plâtre brique bois)
|
|
319
|
+
umur0Doublage = 1 / (1 / Math.min(2.5, di.umur0) + 0.21);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (
|
|
323
|
+
umur0_avant.toFixed(3) === umur0Doublage.toFixed(3) ||
|
|
324
|
+
umur_avant.toFixed(3) === umur0Doublage.toFixed(3)
|
|
325
|
+
) {
|
|
326
|
+
console.error(`
|
|
327
|
+
Le calcul Umur0 pour le mur ${de.description} utilise Umur0 minoré à 2.5 pour l'application du doublage alors qu'il est de ${di.umur0}.
|
|
328
|
+
Nous conservons ${di.umur0} pour la suite des calculs, les murs sont donc plus déperditifs que dans le DPE d'origine.
|
|
329
|
+
`);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import calc_mur from './3.2.1_mur.js';
|
|
2
|
+
|
|
3
|
+
describe('Recherche de bugs dans le calcul de déperdition des murs', () => {
|
|
4
|
+
/**
|
|
5
|
+
* @see : https://redfroggy.atlassian.net/browse/KAR-119
|
|
6
|
+
*/
|
|
7
|
+
test('calcul de déperdition pour les murs de 2213E0696993Z', () => {
|
|
8
|
+
const zc = 8; // H3
|
|
9
|
+
const pc_id = 2; // Période de construction (1948)
|
|
10
|
+
const ej = 0;
|
|
11
|
+
const mur = {
|
|
12
|
+
donnee_entree: {
|
|
13
|
+
description:
|
|
14
|
+
"Mur 2 Est - Inconnu donnant sur des circulations sans ouverture directe sur l'extérieur",
|
|
15
|
+
reference: '2021_08_24_18_02_58_7233440008111783',
|
|
16
|
+
tv_coef_reduction_deperdition_id: 78,
|
|
17
|
+
surface_aiu: 22,
|
|
18
|
+
surface_aue: 15,
|
|
19
|
+
enum_cfg_isolation_lnc_id: '2',
|
|
20
|
+
enum_type_adjacence_id: '14', // Circulation sans ouverture directe sur l'extérieur
|
|
21
|
+
enum_orientation_id: '3', // Est
|
|
22
|
+
surface_paroi_totale: 10.5,
|
|
23
|
+
surface_paroi_opaque: 10.5,
|
|
24
|
+
tv_umur0_id: 1,
|
|
25
|
+
enum_materiaux_structure_mur_id: '1', // Inconnu
|
|
26
|
+
enum_methode_saisie_u0_id: '2', // déterminé selon le matériau et épaisseur à partir de la table de valeur forfaitaire
|
|
27
|
+
paroi_ancienne: 0,
|
|
28
|
+
enum_type_doublage_id: '2', // absence de doublage
|
|
29
|
+
enum_type_isolation_id: '1', // inconnu
|
|
30
|
+
enum_periode_isolation_id: '2', // 1948-1974
|
|
31
|
+
tv_umur_id: 6, //
|
|
32
|
+
enum_methode_saisie_u_id: '8' // année de construction saisie (table forfaitaire)
|
|
33
|
+
},
|
|
34
|
+
donnee_intermediaire: {
|
|
35
|
+
b: 0.35,
|
|
36
|
+
umur: 2.5,
|
|
37
|
+
umur0: 2.5
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
calc_mur(mur, zc, pc_id, ej);
|
|
41
|
+
|
|
42
|
+
expect(mur.donnee_intermediaire.b).toBe(0.35);
|
|
43
|
+
expect(mur.donnee_intermediaire.umur).toBe(2.5);
|
|
44
|
+
expect(mur.donnee_intermediaire.umur0).toBe(2.5);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import enums from './enums.js';
|
|
2
|
+
import b from './3.1_b.js';
|
|
3
|
+
import { tv, requestInput, getKeyByValue, bug_for_bug_compat, getRange } from './utils.js';
|
|
4
|
+
|
|
5
|
+
const scriptName = new URL(import.meta.url).pathname.split('/').pop();
|
|
6
|
+
|
|
7
|
+
function tv_upb0(di, de, du) {
|
|
8
|
+
requestInput(de, du, 'type_plancher_bas');
|
|
9
|
+
const matcher = {
|
|
10
|
+
enum_type_plancher_bas_id: de.enum_type_plancher_bas_id
|
|
11
|
+
};
|
|
12
|
+
const row = tv('upb0', matcher, de);
|
|
13
|
+
if (row) {
|
|
14
|
+
di.upb0 = Number(row.upb0);
|
|
15
|
+
de.tv_upb0_id = Number(row.tv_upb0_id);
|
|
16
|
+
} else {
|
|
17
|
+
console.error('!! pas de valeur forfaitaire trouvée pour upb0 !!');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function tv_upb(di, de, du, pc_id, zc, effetJoule) {
|
|
22
|
+
if (bug_for_bug_compat && de.tv_upb_id) {
|
|
23
|
+
/**
|
|
24
|
+
* Vérification de la variable effet_joule
|
|
25
|
+
* Certains DPE utilise de manière erronée cette variable. Pour rester cohérent avec le DPE, utilisation de la variable
|
|
26
|
+
* effet_joule telle qu'elle est utilisée dans le DPE
|
|
27
|
+
*/
|
|
28
|
+
const rowUpb = tv('upb', {
|
|
29
|
+
tv_upb_id: de.tv_upb_id
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (rowUpb && rowUpb.effet_joule !== effetJoule) {
|
|
33
|
+
console.error(
|
|
34
|
+
`La variable effet_joule utilisée dans le DPE pour le plancher bas '${de.description}' est ${rowUpb.effet_joule}.
|
|
35
|
+
Celle-ci devrait être ${effetJoule}. La valeur ${rowUpb.effet_joule} est conservée dans la suite des calculs`
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
effetJoule = rowUpb.effet_joule;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const matcher = {
|
|
43
|
+
enum_periode_construction_id: pc_id,
|
|
44
|
+
enum_zone_climatique_id: zc,
|
|
45
|
+
effet_joule: effetJoule
|
|
46
|
+
};
|
|
47
|
+
const row = tv('upb', matcher, de);
|
|
48
|
+
if (row) {
|
|
49
|
+
di.upb = Number(row.upb);
|
|
50
|
+
de.tv_upb_id = Number(row.tv_upb_id);
|
|
51
|
+
} else {
|
|
52
|
+
console.error('!! pas de valeur forfaitaire trouvée pour upb !!');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const values_2s_p = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20];
|
|
57
|
+
|
|
58
|
+
function tv_ue(di, de, du, pc_id, pb_list) {
|
|
59
|
+
const type_adjacence = enums.type_adjacence[de.enum_type_adjacence_id];
|
|
60
|
+
let type_adjacence_plancher;
|
|
61
|
+
let upb1, upb2;
|
|
62
|
+
if (type_adjacence === 'terre-plein') {
|
|
63
|
+
if (Number(pc_id) < 7) {
|
|
64
|
+
type_adjacence_plancher = 'terre plein bâtiment construit avant 2001';
|
|
65
|
+
[upb1, upb2] = getRange(di.upb, [0.46, 0.59, 0.85, 1.5, 3.4]);
|
|
66
|
+
} else {
|
|
67
|
+
type_adjacence_plancher = 'terre plein bâtiment construit à partir de 2001';
|
|
68
|
+
[upb1, upb2] = getRange(di.upb, [0.31, 0.37, 0.46, 0.6, 0.85, 1.5, 3.4]);
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
type_adjacence_plancher = 'plancher sur vide sanitaire ou sous-sol non chauffé';
|
|
72
|
+
[upb1, upb2] = getRange(di.upb, [0.31, 0.34, 0.37, 0.41, 0.45, 0.83, 1.43, 3.33]);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* La surface Ue est la surface de tous les planchers bas ayant le même type d'adjacence
|
|
77
|
+
* Le périmètre Ue est le périmètre de tous les planchers bas ayant le même type d'adjacence
|
|
78
|
+
*/
|
|
79
|
+
const { surfaceUe, perimetreUe } = pb_list.reduce(
|
|
80
|
+
(acc, plancherBas) => {
|
|
81
|
+
if (plancherBas.donnee_entree.enum_type_adjacence_id === de.enum_type_adjacence_id) {
|
|
82
|
+
acc.surfaceUe +=
|
|
83
|
+
plancherBas.donnee_entree.surface_ue || plancherBas.donnee_entree.surface_paroi_opaque;
|
|
84
|
+
acc.perimetreUe += plancherBas.donnee_entree.perimetre_ue || 0;
|
|
85
|
+
}
|
|
86
|
+
return acc;
|
|
87
|
+
},
|
|
88
|
+
{ surfaceUe: 0, perimetreUe: 0 }
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const matcher = {
|
|
92
|
+
type_adjacence_plancher,
|
|
93
|
+
'2s_p': Math.round((2 * surfaceUe) / perimetreUe)
|
|
94
|
+
};
|
|
95
|
+
matcher['2s_p'] = values_2s_p.reduce((prev, curr) => {
|
|
96
|
+
return Math.abs(curr - matcher['2s_p']) < Math.abs(prev - matcher['2s_p']) ? curr : prev;
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
matcher['2s_p'] = `^${matcher['2s_p']}$`;
|
|
100
|
+
|
|
101
|
+
const matcher_1 = { ...matcher, ...{ upb: String(upb1) } };
|
|
102
|
+
const matcher_2 = { ...matcher, ...{ upb: String(upb2) } };
|
|
103
|
+
const row_1 = tv('ue', matcher_1);
|
|
104
|
+
const row_2 = tv('ue', matcher_2);
|
|
105
|
+
|
|
106
|
+
const delta_ue = Number(row_2.ue) - Number(row_1.ue);
|
|
107
|
+
const delta_upb = upb2 - upb1;
|
|
108
|
+
|
|
109
|
+
let ue;
|
|
110
|
+
if (delta_upb === 0) {
|
|
111
|
+
ue = Number(row_1.ue);
|
|
112
|
+
} else {
|
|
113
|
+
// Interpolation linéaire si di.upb n'est pas une valeur connue
|
|
114
|
+
ue = Number(row_1.ue) + (delta_ue * (di.upb - upb1)) / delta_upb;
|
|
115
|
+
}
|
|
116
|
+
de.ue = ue;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function calc_upb0(di, de, du) {
|
|
120
|
+
const methode_saisie_u0 = requestInput(de, du, 'methode_saisie_u0');
|
|
121
|
+
switch (methode_saisie_u0) {
|
|
122
|
+
case 'type de paroi inconnu (valeur par défaut)':
|
|
123
|
+
case 'déterminé selon le matériau et épaisseur à partir de la table de valeur forfaitaire':
|
|
124
|
+
tv_upb0(di, de, du);
|
|
125
|
+
break;
|
|
126
|
+
case 'saisie direct u0 justifiée à partir des documents justificatifs autorisés':
|
|
127
|
+
case "saisie direct u0 correspondant à la performance de la paroi avec son isolation antérieure iti (umur_iti) lorsqu'il y a une surisolation ite réalisée":
|
|
128
|
+
di.upb0 = requestInput(de, du, 'upb0_saisi', 'float');
|
|
129
|
+
break;
|
|
130
|
+
case 'u0 non saisi car le u est saisi connu et justifié.':
|
|
131
|
+
break;
|
|
132
|
+
default:
|
|
133
|
+
console.warn('methode_saisie_u0 inconnue:', methode_saisie_u0);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export default function calc_pb(pb, zc, pc_id, effetJoule, pb_list) {
|
|
138
|
+
const de = pb.donnee_entree;
|
|
139
|
+
const du = {};
|
|
140
|
+
const di = {};
|
|
141
|
+
di.upb0 = pb.donnee_intermediaire.upb0;
|
|
142
|
+
|
|
143
|
+
b(di, de, du, zc);
|
|
144
|
+
|
|
145
|
+
let methode_saisie_u = parseInt(de.enum_methode_saisie_u_id);
|
|
146
|
+
|
|
147
|
+
if (bug_for_bug_compat) {
|
|
148
|
+
// Si la résistance de l'isolation est connue mais que le mode de saisie de u n'est pas
|
|
149
|
+
// 'resistance isolation saisie justifiée'. On force cette méthode de saisie
|
|
150
|
+
if (de.resistance_isolation && ![5, 6].includes(methode_saisie_u)) {
|
|
151
|
+
console.error(`
|
|
152
|
+
La résistance de l'isolation du plancher bas ${de.description} est connue mais la méthode de saisie du facteur u
|
|
153
|
+
n'est pas 'resistance isolation saisie justifiée'. La méthode de saisie est modifiée pour la suite du calcul
|
|
154
|
+
`);
|
|
155
|
+
methode_saisie_u = 5;
|
|
156
|
+
}
|
|
157
|
+
// Si l'épaisseur de l'isolation est connue mais que le mode de saisie de u n'est pas
|
|
158
|
+
// 'epaisseur isolation saisie justifiée' on force cette méthode de saisie
|
|
159
|
+
if (de.epaisseur_isolation && ![3, 4].includes(methode_saisie_u)) {
|
|
160
|
+
console.error(`
|
|
161
|
+
L'épaisseur de l'isolation du plancher bas ${de.description} est connue mais la méthode de saisie du facteur u
|
|
162
|
+
n'est pas 'epaisseur isolation saisie justifiée'. La méthode de saisie est modifiée pour la suite du calcul
|
|
163
|
+
`);
|
|
164
|
+
methode_saisie_u = 3;
|
|
165
|
+
}
|
|
166
|
+
// Si Upb est saisi mais que le mode de saisie de u n'est pas 'saisie direct u' on force cette méthode de saisie.
|
|
167
|
+
if (de.upb_saisi && ![9, 10].includes(methode_saisie_u)) {
|
|
168
|
+
console.error(`
|
|
169
|
+
Upb du plancher bas ${de.description} est saisi mais la méthode de saisie du facteur u
|
|
170
|
+
n'est pas 'saisie direct u'. La méthode de saisie est modifiée pour la suite du calcul
|
|
171
|
+
`);
|
|
172
|
+
methode_saisie_u = 9;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
switch (methode_saisie_u) {
|
|
177
|
+
case 1:
|
|
178
|
+
// 1 - non isolé
|
|
179
|
+
calc_upb0(di, de, du);
|
|
180
|
+
di.upb = di.upb0;
|
|
181
|
+
break;
|
|
182
|
+
case 3:
|
|
183
|
+
case 4: {
|
|
184
|
+
// 3 - epaisseur isolation saisie justifiée par mesure ou observation
|
|
185
|
+
// 4 - epaisseur isolation saisie justifiée à partir des documents justificatifs autorisés
|
|
186
|
+
const e = parseFloat(de.epaisseur_isolation) * 0.01;
|
|
187
|
+
calc_upb0(di, de, du);
|
|
188
|
+
di.upb = 1 / (1 / di.upb0 + e / 0.042);
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
case 5:
|
|
192
|
+
case 6: {
|
|
193
|
+
// 5 - resistance isolation saisie justifiée observation de l'isolant installé et mesure de son épaisseur
|
|
194
|
+
// 6 - resistance isolation saisie justifiée à partir des documents justificatifs autorisés
|
|
195
|
+
const r = parseFloat(de.resistance_isolation);
|
|
196
|
+
calc_upb0(di, de, du);
|
|
197
|
+
di.upb = 1 / (1 / di.upb0 + r);
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
case 2:
|
|
201
|
+
case 7: {
|
|
202
|
+
// 2 - isolation inconnue (table forfaitaire)
|
|
203
|
+
// 7 - année d'isolation différente de l'année de construction saisie justifiée (table forfaitaire)
|
|
204
|
+
calc_upb0(di, de, du);
|
|
205
|
+
tv_upb(di, de, du, de.enum_periode_isolation_id || pc_id, zc, effetJoule);
|
|
206
|
+
di.upb = Math.min(di.upb, di.upb0);
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
case 8: {
|
|
210
|
+
// 8 - année de construction saisie (table forfaitaire)
|
|
211
|
+
// Si l'année d'isolation est connue, il faut l'utiliser et pas l'année de construction
|
|
212
|
+
let pi_id = de.enum_periode_isolation_id || pc_id;
|
|
213
|
+
if (!de.enum_periode_isolation_id) {
|
|
214
|
+
const pc = enums.periode_construction[pc_id];
|
|
215
|
+
switch (pc) {
|
|
216
|
+
case 'avant 1948':
|
|
217
|
+
case '1948-1974':
|
|
218
|
+
pi_id = getKeyByValue(enums.periode_isolation, '1975-1977');
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
calc_upb0(di, de, du);
|
|
223
|
+
const tv_upb_avant = de.tv_upb_id;
|
|
224
|
+
tv_upb(di, de, du, pi_id, zc, effetJoule);
|
|
225
|
+
if (de.tv_upb_id !== tv_upb_avant && pi_id !== pc_id) {
|
|
226
|
+
console.warn(
|
|
227
|
+
`BUG(${scriptName}) Si année de construction <74 alors Année d'isolation=75-77 (3CL page 17)`
|
|
228
|
+
);
|
|
229
|
+
if (bug_for_bug_compat) tv_upb(di, de, du, pc_id, zc, effetJoule);
|
|
230
|
+
}
|
|
231
|
+
di.upb = Math.min(di.upb, di.upb0);
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
case 9:
|
|
235
|
+
case 10:
|
|
236
|
+
// 9 - saisie direct u justifiée (à partir des documents justificatifs autorisés)
|
|
237
|
+
// 10 - saisie direct u depuis rset/rsee( etude rt2012/re2020)
|
|
238
|
+
di.upb = requestInput(de, du, 'upb_saisi', 'float');
|
|
239
|
+
break;
|
|
240
|
+
default:
|
|
241
|
+
console.warn('methode_saisie_u inconnue:', methode_saisie_u);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const type_adjacence = requestInput(de, du, 'type_adjacence');
|
|
245
|
+
switch (type_adjacence) {
|
|
246
|
+
case 'vide sanitaire':
|
|
247
|
+
case 'sous-sol non chauffé':
|
|
248
|
+
case 'terre-plein':
|
|
249
|
+
tv_ue(di, de, du, pc_id, pb_list);
|
|
250
|
+
di.upb_final = de.ue;
|
|
251
|
+
break;
|
|
252
|
+
default:
|
|
253
|
+
di.upb_final = di.upb;
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
pb.donnee_utilisateur = du;
|
|
258
|
+
pb.donnee_intermediaire = di;
|
|
259
|
+
}
|