@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.
Files changed (85) hide show
  1. package/10_besoin_fr.js +76 -0
  2. package/10_clim.js +45 -0
  3. package/11_besoin_ecs.js +25 -0
  4. package/11_ecs.js +95 -0
  5. package/11_nadeq.js +87 -0
  6. package/11_nadeq.spec.js +55 -0
  7. package/12.4_pac.js +54 -0
  8. package/13.2_generateur_combustion.js +295 -0
  9. package/13.2_generateur_combustion_bouilleur.js +173 -0
  10. package/13.2_generateur_combustion_ch.js +195 -0
  11. package/13.2_generateur_combustion_chaudiere.js +151 -0
  12. package/13.2_generateur_pac.js +36 -0
  13. package/13_rendement_distribution_ecs.js +12 -0
  14. package/14_generateur_ecs.js +388 -0
  15. package/15_conso_aux.js +257 -0
  16. package/16.2_production_enr.js +328 -0
  17. package/16.2_production_enr.spec.js +251 -0
  18. package/16_conso_eclairage.js +37 -0
  19. package/2021_04_13_confort_ete.js +61 -0
  20. package/2021_04_13_qualite_isolation.js +174 -0
  21. package/3.1_b.js +141 -0
  22. package/3.2.1_mur.js +331 -0
  23. package/3.2.1_mur.spec.js +46 -0
  24. package/3.2.2_plancher_bas.js +259 -0
  25. package/3.2.2_plancher_bas.spec.js +88 -0
  26. package/3.2.3_plancher_haut.js +158 -0
  27. package/3.3.1.4_porte.js +32 -0
  28. package/3.3_baie_vitree.js +308 -0
  29. package/3.3_baie_vitree.spec.js +333 -0
  30. package/3.4_pont_thermique.js +463 -0
  31. package/3_deperdition.js +258 -0
  32. package/4_ventilation.js +197 -0
  33. package/5_conso_ventilation.js +127 -0
  34. package/6.1_apport_gratuit.js +61 -0
  35. package/6.1_apport_gratuit.spec.js +181 -0
  36. package/6.2_surface_sud_equivalente.js +109 -0
  37. package/7_inertie.js +178 -0
  38. package/7_inertie.spec.js +263 -0
  39. package/8_intermittence.js +5 -0
  40. package/9_besoin_ch.js +198 -0
  41. package/9_chauffage.js +291 -0
  42. package/9_chauffage.spec.js +101 -0
  43. package/9_conso_ch.js +95 -0
  44. package/9_conso_ch.spec.js +255 -0
  45. package/9_emetteur_ch.js +122 -0
  46. package/9_generateur_ch.js +230 -0
  47. package/9_generateur_ch.spec.js +87 -0
  48. package/README.md +43 -0
  49. package/apport_et_besoin.js +55 -0
  50. package/conso.js +529 -0
  51. package/conso.spec.js +90 -0
  52. package/core/assets/domain/add-additionnal-ue-values-tables.js +57 -0
  53. package/core/assets/domain/synchronize-assets.js +29 -0
  54. package/core/assets/domain/synchronize-assets.spec.js +37 -0
  55. package/core/assets/domain/synchronize-c1-tables.js +61 -0
  56. package/core/assets/domain/synchronize-c1-tables.spec.js +35 -0
  57. package/core/assets/domain/synchronize-dpe-ges-limit-values-tables.js +73 -0
  58. package/core/assets/domain/synchronize-dpe-ges-limit-values-tables.spec.js +72 -0
  59. package/core/assets/domain/synchronize-enum-tables.js +77 -0
  60. package/core/assets/domain/synchronize-enum-tables.spec.js +31 -0
  61. package/core/assets/domain/synchronize-solicitations-tables.js +72 -0
  62. package/core/assets/domain/synchronize-solicitations-tables.spec.js +47 -0
  63. package/core/assets/domain/synchronize-valeur-tables.js +146 -0
  64. package/core/assets/domain/synchronize-valeur-tables.spec.js +54 -0
  65. package/core/conf/infrastructure/application.config.js +33 -0
  66. package/core/file/infrastructure/adapter/file.store.js +75 -0
  67. package/core/file/infrastructure/adapter/file.store.spec.js +30 -0
  68. package/core/tv/infrastructure/assets/additional-ue-values.js +69 -0
  69. package/core/tv/infrastructure/tvs.store.js +40 -0
  70. package/core/tv/infrastructure/tvs.store.spec.js +34 -0
  71. package/core/util/infrastructure/object-util.js +23 -0
  72. package/core/util/infrastructure/object-util.spec.js +25 -0
  73. package/engine.js +503 -0
  74. package/enums.js +1155 -0
  75. package/ficheTechnique.js +86 -0
  76. package/ficheTechnique.spec.js +181 -0
  77. package/index.js +4 -0
  78. package/package.json +87 -0
  79. package/tv/18.2_sollicitations_ext.ods +0 -0
  80. package/tv/18.5_c1.ods +0 -0
  81. package/tv/dpe_ges_limit_values.ods +0 -0
  82. package/tv.js +80811 -0
  83. package/tvs.d.ts +7 -0
  84. package/utils.js +500 -0
  85. package/utils.spec.js +36 -0
package/engine.js ADDED
@@ -0,0 +1,503 @@
1
+ import enums from './enums.js';
2
+ import calc_deperdition from './3_deperdition.js';
3
+ import calc_apport_et_besoin from './apport_et_besoin.js';
4
+ import calc_clim from './10_clim.js';
5
+ import calc_ecs from './11_ecs.js';
6
+ import calc_besoin_ch from './9_besoin_ch.js';
7
+ import calc_chauffage, { tauxChargeForGenerator } from './9_chauffage.js';
8
+ import calc_confort_ete from './2021_04_13_confort_ete.js';
9
+ import calc_qualite_isolation from './2021_04_13_qualite_isolation.js';
10
+ import calc_conso from './conso.js';
11
+ import {
12
+ add_references,
13
+ bug_for_bug_compat,
14
+ collectionCanBeEmpty,
15
+ containsAnySubstring,
16
+ isEffetJoule,
17
+ sanitize_dpe
18
+ } from './utils.js';
19
+ import { Inertie } from './7_inertie.js';
20
+ import getFicheTechnique from './ficheTechnique.js';
21
+ import { ProductionENR } from './16.2_production_enr.js';
22
+
23
+ function calc_th(map_id) {
24
+ const map = enums.methode_application_dpe_log[map_id];
25
+ if (map.includes('maison')) return 'maison';
26
+ else if (map.includes('appartement')) return 'appartement';
27
+ else if (map.includes('immeuble')) return 'immeuble';
28
+ console.error(`Methode application DPE inconnue ${map_id} ${map}`);
29
+ return null;
30
+ }
31
+
32
+ const inertie = new Inertie();
33
+ const productionENR = new ProductionENR();
34
+
35
+ export function calcul_3cl(dpe) {
36
+ sanitize_dpe(dpe);
37
+ const modele = enums.modele_dpe[dpe.administratif.enum_modele_dpe_id];
38
+ if (modele !== 'dpe 3cl 2021 méthode logement') {
39
+ console.error('Moteur dpe non implémenté pour le modèle: ' + modele);
40
+ return null;
41
+ }
42
+ const logement = dpe.logement;
43
+
44
+ const cg = logement.caracteristique_generale;
45
+ const map_id = cg.enum_methode_application_dpe_log_id;
46
+ const th = calc_th(map_id);
47
+
48
+ if (logement.enveloppe === undefined) {
49
+ console.warn('vide: logement.enveloppe');
50
+ return null;
51
+ } else if (!logement.enveloppe.mur_collection) {
52
+ console.warn('vide: logement.enveloppe.mur_collection');
53
+ return null;
54
+ } else if (
55
+ !logement.enveloppe.plancher_haut_collection ||
56
+ !logement.enveloppe.plancher_haut_collection.plancher_haut.length
57
+ ) {
58
+ /**
59
+ * Vérification si le plancher haut est considéré comme non déperditif et peut donc être vide
60
+ * - Pas de pont thermique ou pas de pont thermique de type murs / plancher haut
61
+ * (enum_type_liaison_id === 1 : liaison 'plancher haut / mur').
62
+ * - Déperdition plancher_haut === 0 (donne probablement sur un autre local chauffé)
63
+ */
64
+ if (collectionCanBeEmpty(logement, 'plancher_haut', 3)) {
65
+ logement.enveloppe.plancher_haut_collection = {
66
+ plancher_haut: []
67
+ };
68
+ } else {
69
+ console.error('plancher_bas_collection should not be empty');
70
+ return null;
71
+ }
72
+ } else if (
73
+ !logement.enveloppe.plancher_bas_collection ||
74
+ !logement.enveloppe.plancher_bas_collection.plancher_bas.length
75
+ ) {
76
+ /**
77
+ * Vérification si le plancher bas est considéré comme non déperditif et peut donc être vide
78
+ * - Pas de pont thermique ou pas de pont thermique de type murs / plancher bas
79
+ * (enum_type_liaison_id === 1 : liaison 'plancher bas / mur').
80
+ * - Déperdition plancher_bas === 0 (donne probablement sur un autre local chauffé)
81
+ */
82
+ if (collectionCanBeEmpty(logement, 'plancher_bas', 1)) {
83
+ logement.enveloppe.plancher_bas_collection = {
84
+ plancher_bas: []
85
+ };
86
+ } else {
87
+ console.error('plancher_bas_collection should not be empty');
88
+ return null;
89
+ }
90
+ }
91
+
92
+ add_references(logement.enveloppe);
93
+
94
+ // TODO commit version to package.json during release process
95
+ /* const package_version = require('../package.json').version; */
96
+ const package_version = 'alpha';
97
+ dpe.administratif.diagnostiqueur = { version_moteur_calcul: `Open3CL ${package_version}` };
98
+ const env = logement.enveloppe;
99
+ let Sh;
100
+ let ShChauffageAndEcs;
101
+ // TODO requestInput Sh
102
+ if (th === 'maison' || th === 'appartement') Sh = cg.surface_habitable_logement;
103
+ else if (th === 'immeuble') Sh = cg.surface_habitable_immeuble;
104
+
105
+ /**
106
+ * Certains DPE appartement sont générés à partir des données du DPE immeuble, la surface à prendre en compte est
107
+ * celle de l'immeuble pour les besoins ECS
108
+ * 10 - dpe appartement généré à partir des données DPE immeuble chauffage individuel ecs individuel
109
+ * 11 - dpe appartement généré à partir des données DPE immeuble chauffage collectif ecs individuel
110
+ * 12 - dpe appartement généré à partir des données DPE immeuble chauffage individuel ecs collectif
111
+ * 13 - dpe appartement généré à partir des données DPE immeuble chauffage collectif ecs collectif
112
+ * 15 - dpe issu d'une étude thermique réglementaire RT2012 bâtiment : appartement chauffage collectif ecs collectif
113
+ * 16 - dpe issu d'une étude thermique réglementaire RT2012 bâtiment : appartement chauffage individuel ecs collectif
114
+ * 19 - dpe issu d'une étude energie environement réglementaire RE2020 bâtiment : appartement chauffage collectif ecs collectif
115
+ * 20 - dpe issu d'une étude energie environement réglementaire RE2020 bâtiment : appartement chauffage individuel ecs collectif
116
+ * 22 - dpe issu d'une étude thermique réglementaire RT2012 bâtiment : appartement chauffage individuel ecs individuel
117
+ * 23 - dpe issu d'une étude thermique réglementaire RT2012 bâtiment : appartement chauffage collectif ecs individuel
118
+ * 24 - dpe issu d'une étude energie environement réglementaire RE2020 bâtiment : appartement chauffage collectif ecs individuel
119
+ * 25 - dpe issu d'une étude energie environement réglementaire RE2020 bâtiment : appartement chauffage individuel ecs individuel
120
+ * 33 - dpe appartement généré à partir des données DPE immeuble chauffage mixte (collectif-individuel) ecs individuel
121
+ * 34 - dpe appartement généré à partir des données DPE immeuble chauffage mixte (collectif-individuel) ecs collectif
122
+ * 38 - dpe appartement généré à partir des données DPE immeuble chauffage mixte (collectif-individuel) ecs mixte (collectif-individuel)
123
+ * 39 - dpe appartement généré à partir des données DPE immeuble chauffage individuel ecs mixte (collectif-individuel)
124
+ * 40 - dpe appartement généré à partir des données DPE immeuble chauffage collectif ecs mixte (collectif-individuel)
125
+ */
126
+ if (
127
+ [
128
+ '10',
129
+ '11',
130
+ '12',
131
+ '13',
132
+ '15',
133
+ '16',
134
+ '19',
135
+ '20',
136
+ '22',
137
+ '23',
138
+ '24',
139
+ '25',
140
+ '33',
141
+ '34',
142
+ '38',
143
+ '39',
144
+ '40'
145
+ ].includes(map_id)
146
+ ) {
147
+ ShChauffageAndEcs = cg.surface_habitable_immeuble;
148
+ } else {
149
+ ShChauffageAndEcs = Sh;
150
+ }
151
+
152
+ const zc_id = logement.meteo.enum_zone_climatique_id;
153
+ const ca_id = logement.meteo.enum_classe_altitude_id;
154
+
155
+ const instal_ch = logement.installation_chauffage_collection.installation_chauffage;
156
+ const bv_list = env.baie_vitree_collection.baie_vitree;
157
+
158
+ bv_list.forEach((baieVitree) => {
159
+ const donneeEntree = baieVitree.donnee_entree;
160
+
161
+ // Si pas d'information sur la présence de joint => vérification dans les fiches techniques
162
+ if (donneeEntree.presence_joint === undefined) {
163
+ const orientation = enums.orientation[donneeEntree.enum_orientation_id];
164
+ const typeVitrage = enums.type_vitrage[donneeEntree.enum_type_vitrage_id];
165
+ const typeBaie = enums.type_baie[donneeEntree.enum_type_baie_id];
166
+ const typeMateriauxMenuiserie =
167
+ enums.type_materiaux_menuiserie[donneeEntree.enum_type_materiaux_menuiserie_id];
168
+
169
+ const ficheTechnique = getFicheTechnique(dpe, '4', 'joint', [
170
+ orientation,
171
+ typeVitrage,
172
+ typeBaie,
173
+ typeMateriauxMenuiserie
174
+ ]);
175
+
176
+ if (ficheTechnique) {
177
+ if (ficheTechnique.valeur.toLowerCase() === 'oui') {
178
+ donneeEntree.presence_joint = 1;
179
+ } else if (ficheTechnique.valeur.toLowerCase() === 'non') {
180
+ donneeEntree.presence_joint = 0;
181
+ } else {
182
+ console.warn(`
183
+ La valeur de la sous-fiche technique pour la présence de joint de la baie vitrée ${baieVitree.donnee_entree.description} est inconnue
184
+ `);
185
+ }
186
+ }
187
+ }
188
+ });
189
+
190
+ /**
191
+ * 4 - Calcul des déperditions par renouvellement d’air
192
+ * Les valeurs des coefficients de protection E et F sont différents si plusieurs façades sont exposées ou non
193
+ */
194
+ const ficheTechniqueFacadesExposees = getFicheTechnique(dpe, '10', 'exposées');
195
+ const ficheTechniqueVentilationPost2012 = getFicheTechnique(
196
+ dpe,
197
+ '10',
198
+ 'après 2012',
199
+ [],
200
+ 'valeur'
201
+ );
202
+
203
+ logement.ventilation_collection.ventilation.forEach((ventilation) => {
204
+ ventilation.donnee_entree.ficheTechniqueFacadesExposees = ficheTechniqueFacadesExposees;
205
+ ventilation.donnee_entree.ficheTechniqueVentilationPost2012 = ficheTechniqueVentilationPost2012;
206
+ });
207
+
208
+ const deperdition = calc_deperdition(
209
+ cg,
210
+ zc_id,
211
+ th,
212
+ isEffetJoule(instal_ch),
213
+ dpe,
214
+ ShChauffageAndEcs
215
+ );
216
+ const GV = deperdition.deperdition_enveloppe;
217
+
218
+ const calculatedInertie = inertie.calculateInertie(env);
219
+
220
+ if (calculatedInertie.enum_classe_inertie_id !== env.inertie.enum_classe_inertie_id) {
221
+ console.error(
222
+ `La classe d'inertie du DPE ${env.inertie.enum_classe_inertie_id} est différente
223
+ de la classe d'inertie calculée ${calculatedInertie.enum_classe_inertie_id}`
224
+ );
225
+ }
226
+
227
+ const inertie_id = env.inertie.enum_classe_inertie_id;
228
+
229
+ /**
230
+ * Inertie ID
231
+ * 1 - Très lourde
232
+ * 2 - Lourde
233
+ */
234
+ const ilpa =
235
+ logement.meteo.batiment_materiaux_anciens === 1 && ['1', '2'].includes(inertie_id) ? '1' : '0';
236
+
237
+ const ecs = logement.installation_ecs_collection.installation_ecs || [];
238
+ const Nb_lgt = cg.nombre_appartement || 1;
239
+ const hsp = cg.hsp;
240
+ const clim = logement.climatisation_collection.climatisation || [];
241
+ let apport_et_besoin = calc_apport_et_besoin(
242
+ logement,
243
+ th,
244
+ ecs,
245
+ clim,
246
+ ShChauffageAndEcs,
247
+ Nb_lgt,
248
+ GV,
249
+ ilpa,
250
+ ca_id,
251
+ zc_id
252
+ );
253
+
254
+ const bfr = apport_et_besoin.besoin_fr;
255
+ const bfr_dep = apport_et_besoin.besoin_fr_depensier;
256
+ clim.forEach((clim) => calc_clim(clim, bfr, bfr_dep, zc_id, ShChauffageAndEcs));
257
+
258
+ /**
259
+ * La consommation ECS est obtenu pour certains types de DPE par virtualisation des générateurs collectifs en générateurs individuels virtuels
260
+ * 4 - dpe appartement individuel chauffage individuel ecs collectif
261
+ * 5 - dpe appartement individuel chauffage collectif ecs collectif
262
+ * 32 - dpe appartement individuel chauffage mixte (collectif-individuel) ecs collectif
263
+ * 35 - dpe appartement individuel chauffage mixte (collectif-individuel) ecs mixte (collectif-individuel)
264
+ * 36 - dpe appartement individuel chauffage individuel ecs mixte (collectif-individuel)
265
+ * 37 - dpe appartement individuel chauffage collectif ecs mixte (collectif-individuel)
266
+ */
267
+ const virtualisationECS = ['4', '5', '32', '35', '36', '37'].includes(map_id);
268
+
269
+ let becs = apport_et_besoin.besoin_ecs;
270
+ let becs_dep = apport_et_besoin.besoin_ecs_depensier;
271
+
272
+ /**
273
+ * 11.4 Plusieurs systèmes d’ECS (limité à 2 systèmes différents par logement)
274
+ * Les besoins en ECS pour chaque générateur sont / 2
275
+ */
276
+ if (ecs.length > 1) {
277
+ becs /= 2;
278
+ becs_dep /= 2;
279
+ }
280
+
281
+ ecs.forEach((ecs) => {
282
+ if (bug_for_bug_compat) {
283
+ /**
284
+ * Réalignement si besoin de la variable position_volume_chauffe
285
+ * Si une fiche technique pour cette variable est présente, elle est prise en compte
286
+ * Les valeurs de position_volume_chauffe n'étant pas toujours utilisées de la même manière
287
+ * dans tous les DPEs (parfois 0 = 'Oui', d'autres 0 = 'Non')
288
+ */
289
+ ecs.generateur_ecs_collection.generateur_ecs.forEach((generateur) => {
290
+ if (generateur.donnee_entree.description) {
291
+ const ficheProductionVolumeHabitable = getFicheTechnique(
292
+ dpe,
293
+ '8',
294
+ 'hors volume habitable',
295
+ [generateur.donnee_entree.description]
296
+ );
297
+
298
+ if (ficheProductionVolumeHabitable) {
299
+ const pvcFicheTechnique = containsAnySubstring(ficheProductionVolumeHabitable.valeur, [
300
+ 'hors volume habitable',
301
+ 'oui'
302
+ ])
303
+ ? 0
304
+ : 1;
305
+
306
+ if (generateur.donnee_entree.position_volume_chauffe !== pvcFicheTechnique) {
307
+ console.error(
308
+ `La valeur de la variable position_volume_chauffe pour le générateur ECS ${generateur.donnee_entree.description}
309
+ ne correspond pas à celle présente dans la fiche technique "${ficheProductionVolumeHabitable.description}".
310
+ La valeur de la fiche technique est prise en compte.`
311
+ );
312
+
313
+ generateur.donnee_entree.position_volume_chauffe = pvcFicheTechnique;
314
+ }
315
+ }
316
+ }
317
+
318
+ /**
319
+ * Si utilisation mixte chauffage + ECS, on compare le type de générateur ECS au générateur de chauffage associé
320
+ * Réalignement si besoin de la donnée. Le type de générateur ECS est quelques fois erroné
321
+ * enum_usage_generateur_id = 3 - chauffage + ecs
322
+ */
323
+ if (generateur.donnee_entree.enum_usage_generateur_id === '3') {
324
+ const referenceGenerateurMixte = generateur.donnee_entree.reference_generateur_mixte;
325
+
326
+ if (referenceGenerateurMixte) {
327
+ // Récupération du générateur de chauffage associé à la production ECS
328
+ const generateurMixte = instal_ch
329
+ .flatMap(
330
+ (installation) => installation.generateur_chauffage_collection.generateur_chauffage
331
+ )
332
+ .find(
333
+ (generateurChauffage) =>
334
+ generateurChauffage.donnee_entree.reference_generateur_mixte ===
335
+ referenceGenerateurMixte
336
+ );
337
+
338
+ if (generateurMixte) {
339
+ const generateurLabel =
340
+ enums.type_generateur_ch[generateurMixte.donnee_entree.enum_type_generateur_ch_id];
341
+
342
+ if (generateurLabel) {
343
+ // Récupération s'il existe de l'id du générateur ECS qui a le même libellé que le générateur de chauffage associé
344
+ const newEcsGenerateurId =
345
+ Object.entries(enums.type_generateur_ecs).find(
346
+ ([, label]) => label === generateurLabel
347
+ )?.[0] ?? null;
348
+
349
+ if (
350
+ newEcsGenerateurId &&
351
+ newEcsGenerateurId !== generateur.donnee_entree.enum_type_generateur_ecs_id
352
+ ) {
353
+ console.error(
354
+ `Le type de générateur ECS ${generateur.donnee_entree.description} ne correspond pas à celui
355
+ du générateur de chauffage associé "${generateurLabel}".
356
+ Le type de générateur de chauffage "${generateurLabel}" est utilisé pour les calculs ECS.`
357
+ );
358
+
359
+ generateur.donnee_entree.enum_type_generateur_ecs_id = newEcsGenerateurId;
360
+ }
361
+ }
362
+ }
363
+ }
364
+ }
365
+ });
366
+ }
367
+ calc_ecs(dpe, ecs, becs, becs_dep, GV, ca_id, zc_id, th, virtualisationECS);
368
+ });
369
+
370
+ /**
371
+ * 8. Modélisation de l’intermittence
372
+ * En immeuble collectif, le chauffage mixte, c'est-à-dire dont une partie est facturée collectivement et une autre
373
+ * individuellement, est traité au niveau de l’intermittence comme un système collectif avec comptage individuel.
374
+ */
375
+ const ficheTechniqueComptage = getFicheTechnique(dpe, '7', 'Présence comptage');
376
+
377
+ const ac = cg.annee_construction;
378
+ // needed for apport_et_besoin
379
+ instal_ch.forEach((ch) => {
380
+ ch.donnee_entree.ficheTechniqueComptage = ficheTechniqueComptage;
381
+ calc_chauffage(
382
+ dpe,
383
+ ch,
384
+ ca_id,
385
+ zc_id,
386
+ inertie_id,
387
+ map_id,
388
+ 0,
389
+ 0,
390
+ GV,
391
+ ShChauffageAndEcs,
392
+ hsp,
393
+ ac,
394
+ ilpa
395
+ );
396
+ });
397
+
398
+ const ets = env.ets_collection.ets;
399
+
400
+ const besoin_ch = calc_besoin_ch(
401
+ ilpa,
402
+ ca_id,
403
+ zc_id,
404
+ inertie_id,
405
+ ShChauffageAndEcs,
406
+ GV,
407
+ apport_et_besoin.nadeq,
408
+ ecs,
409
+ instal_ch,
410
+ bv_list,
411
+ ets
412
+ );
413
+ apport_et_besoin = { ...apport_et_besoin, ...besoin_ch };
414
+
415
+ const bch = apport_et_besoin.besoin_ch;
416
+ const bch_dep = apport_et_besoin.besoin_ch_depensier;
417
+
418
+ /**
419
+ * 13.2.1.2 Présence d’un ou plusieurs générateurs à combustion indépendants
420
+ * Calcul des taux de charge pour chacun des générateurs de chauffage
421
+ */
422
+ tauxChargeForGenerator(instal_ch, GV, ca_id, zc_id);
423
+
424
+ instal_ch.forEach((ch) => {
425
+ calc_chauffage(
426
+ dpe,
427
+ ch,
428
+ ca_id,
429
+ zc_id,
430
+ inertie_id,
431
+ map_id,
432
+ bch,
433
+ bch_dep,
434
+ GV,
435
+ ShChauffageAndEcs,
436
+ hsp,
437
+ ac,
438
+ ilpa
439
+ );
440
+ });
441
+
442
+ const vt_list = logement.ventilation_collection.ventilation;
443
+
444
+ let prorataECS = 1;
445
+ let prorataChauffage = 1;
446
+
447
+ /**
448
+ * Besoins ECS pour les DPEs avec ECS collectif et répartition proratisés à la surface
449
+ *
450
+ * 15 - dpe issu d'une étude thermique réglementaire RT2012 bâtiment : appartement chauffage collectif ecs collectif
451
+ * 16 - dpe issu d'une étude thermique réglementaire RT2012 bâtiment : appartement chauffage individuel ecs collectif
452
+ * 19 - dpe issu d'une étude energie environement réglementaire RE2020 bâtiment : appartement chauffage collectif ecs collectif
453
+ * 20 - dpe issu d'une étude energie environement réglementaire RE2020 bâtiment : appartement chauffage individuel ecs collectif
454
+ * 22 - dpe issu d'une étude thermique réglementaire RT2012 bâtiment : appartement chauffage individuel ecs individuel
455
+ * 23 - dpe issu d'une étude thermique réglementaire RT2012 bâtiment : appartement chauffage collectif ecs individuel
456
+ * 24 - dpe issu d'une étude energie environement réglementaire RE2020 bâtiment : appartement chauffage collectif ecs individuel
457
+ * 25 - dpe issu d'une étude energie environement réglementaire RE2020 bâtiment : appartement chauffage individuel ecs individuel
458
+ */
459
+ if (['15', '16', '19', '20', '22', '23', '24', '25'].includes(map_id)) {
460
+ prorataECS = Sh / ShChauffageAndEcs;
461
+ }
462
+
463
+ if (
464
+ ['11', '13', '15', '16', '19', '20', '22', '23', '24', '25', /*'33', '34',*/ '40'].includes(
465
+ map_id
466
+ )
467
+ ) {
468
+ prorataChauffage = Sh / ShChauffageAndEcs;
469
+ }
470
+
471
+ const conso = calc_conso(
472
+ Sh,
473
+ zc_id,
474
+ ca_id,
475
+ vt_list,
476
+ instal_ch,
477
+ ecs,
478
+ clim,
479
+ prorataECS,
480
+ prorataChauffage
481
+ );
482
+
483
+ const production_electricite = productionENR.calculateEnr(
484
+ dpe.logement.production_elec_enr,
485
+ conso,
486
+ Sh,
487
+ th,
488
+ zc_id
489
+ );
490
+
491
+ // get all baie_vitree orientations
492
+ const ph_list = env.plancher_haut_collection.plancher_haut || [];
493
+ logement.sortie = {
494
+ deperdition,
495
+ apport_et_besoin,
496
+ confort_ete: calc_confort_ete(inertie_id, bv_list, ph_list),
497
+ qualite_isolation: calc_qualite_isolation(env, deperdition),
498
+ production_electricite,
499
+ ...conso
500
+ };
501
+
502
+ return dpe;
503
+ }