@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
@@ -0,0 +1,251 @@
1
+ import { ProductionENR } from './16.2_production_enr.js';
2
+
3
+ describe('production ENR unit tests', () => {
4
+ /**
5
+ * @see : Methode_de_calcul_3CL_DPE_2021-338.pdf Page 103
6
+ */
7
+ const productionENR = new ProductionENR();
8
+
9
+ test('should get conso elect au', () => {
10
+ // surface * 29 pour une maison
11
+ expect(productionENR.getCelecAu('maison', 10)).toBe(290);
12
+
13
+ // surface * (27 + 1.1) pour un appartement
14
+ expect(productionENR.getCelecAu('appartement', 10)).toBe(281);
15
+ });
16
+
17
+ test('should get ppv 0 without ENR', () => {
18
+ let productionElecEnr = {};
19
+ expect(productionENR.getPpv(productionElecEnr, 1)).toBe(0);
20
+
21
+ productionElecEnr.panneaux_pv_collection = {};
22
+ expect(productionENR.getPpv(productionElecEnr, 1)).toBe(0);
23
+
24
+ productionElecEnr.panneaux_pv_collection = {
25
+ panneaux_pv: []
26
+ };
27
+ expect(productionENR.getPpv(productionElecEnr, 1)).toBe(0);
28
+ });
29
+
30
+ test('should get ppv 0 with unknown coef_orientation_pv', () => {
31
+ let productionElecEnr = {
32
+ panneaux_pv_collection: {
33
+ panneaux_pv: [
34
+ {
35
+ enum_orientation_pv_id: 12,
36
+ enum_inclinaison_pv_id: 12
37
+ },
38
+ {
39
+ enum_orientation_pv_id: 15,
40
+ enum_inclinaison_pv_id: 12
41
+ }
42
+ ]
43
+ }
44
+ };
45
+ expect(productionENR.getPpv(productionElecEnr, 1)).toBe(0);
46
+ });
47
+
48
+ it.each([
49
+ [2826.8015616000007, 8, 9.6],
50
+ [2120.1011712, undefined, 9.6]
51
+ ])(
52
+ 'should get ppv %s with nombre module %s and surface totale capteur %s',
53
+ (ppv, nombre_module, surface_totale_capteurs) => {
54
+ let productionElecEnr = {
55
+ panneaux_pv_collection: {
56
+ panneaux_pv: [
57
+ {
58
+ surface_totale_capteurs: surface_totale_capteurs,
59
+ nombre_module: nombre_module,
60
+ enum_orientation_pv_id: 1,
61
+ enum_inclinaison_pv_id: 2
62
+ }
63
+ ]
64
+ }
65
+ };
66
+ expect(productionENR.getPpv(productionElecEnr, 1)).toBe(ppv);
67
+ }
68
+ );
69
+
70
+ test('should update ef conso', () => {
71
+ const productionElectricite = {
72
+ conso_elec_ac_fr: 100,
73
+ conso_elec_ac_ch: 150,
74
+ conso_elec_ac_ecs: 200,
75
+ conso_elec_ac_eclairage: 250,
76
+ conso_elec_ac_auxiliaire: 300
77
+ };
78
+
79
+ const conso = {
80
+ ef_conso: {
81
+ conso_ecs: 1000,
82
+ conso_ch: 500,
83
+ conso_fr: 800,
84
+ conso_eclairage: 900,
85
+ conso_totale_auxiliaire: 1250,
86
+ conso_5_usages: 1500,
87
+ conso_5_usages_m2: 100
88
+ }
89
+ };
90
+
91
+ productionENR.updateEfConso(productionElectricite, conso, 10);
92
+
93
+ expect(conso).toStrictEqual({
94
+ ef_conso: {
95
+ conso_ecs: 800,
96
+ conso_ch: 350,
97
+ conso_fr: 700,
98
+ conso_eclairage: 650,
99
+ conso_totale_auxiliaire: 950,
100
+ conso_5_usages: 500,
101
+ conso_5_usages_m2: 50
102
+ }
103
+ });
104
+ });
105
+
106
+ test('should get tapl', () => {
107
+ let productionElectricite = productionENR.getTapl({}, {}, 158, 2500);
108
+
109
+ expect(productionElectricite).toStrictEqual({
110
+ conso_elec_ac_ch: 0,
111
+ conso_elec_ac_eclairage: 0,
112
+ conso_elec_ac_ecs: 0,
113
+ conso_elec_ac_fr: 0,
114
+ conso_elec_ac_auxiliaire_distribution_ch: 0,
115
+ conso_elec_ac_auxiliaire_distribution_ecs: 0,
116
+ conso_elec_ac_auxiliaire_generation_ch: 0,
117
+ conso_elec_ac_auxiliaire_generation_ecs: 0,
118
+ conso_elec_ac_ventilation: 0,
119
+ conso_elec_ac_autre_usage: 0.028440000000000003
120
+ });
121
+
122
+ const consoElec = {
123
+ conso_ch: 1000,
124
+ conso_ecs: 1500
125
+ };
126
+
127
+ const efConso = {
128
+ conso_ecs: 1000,
129
+ conso_ch: 500,
130
+ conso_fr: 800,
131
+ conso_eclairage: 900,
132
+ conso_auxiliaire_distribution_ch: 250,
133
+ conso_auxiliaire_distribution_ecs: 110,
134
+ conso_auxiliaire_generation_ch: 100,
135
+ conso_auxiliaire_generation_ecs: 120,
136
+ conso_auxiliaire_ventilation: 150,
137
+ conso_totale_auxiliaire: 1250,
138
+ conso_5_usages: 1500,
139
+ conso_5_usages_m2: 100
140
+ };
141
+
142
+ productionElectricite = productionENR.getTapl(efConso, consoElec, 158, 2500);
143
+
144
+ expect(productionElectricite).toStrictEqual({
145
+ conso_elec_ac_ch: 0.008,
146
+ conso_elec_ac_eclairage: 0.018,
147
+ conso_elec_ac_ecs: 0.03,
148
+ conso_elec_ac_fr: 0.08,
149
+ conso_elec_ac_auxiliaire_distribution_ch: 0.005,
150
+ conso_elec_ac_auxiliaire_distribution_ecs: 0.0022,
151
+ conso_elec_ac_auxiliaire_generation_ch: 0.0008,
152
+ conso_elec_ac_auxiliaire_generation_ecs: 0.0024,
153
+ conso_elec_ac_ventilation: 0.03,
154
+ conso_elec_ac_autre_usage: 0.028440000000000003
155
+ });
156
+ });
157
+
158
+ test('should calculate conso elec', () => {
159
+ let productionElecEnr = {
160
+ panneaux_pv_collection: {
161
+ panneaux_pv: [
162
+ {
163
+ nombre_module: 8,
164
+ enum_orientation_pv_id: 1,
165
+ enum_inclinaison_pv_id: 2
166
+ }
167
+ ]
168
+ }
169
+ };
170
+
171
+ let productionElectricite = {
172
+ conso_elec_ac: 0,
173
+ production_pv: 0,
174
+ conso_elec_ac_ch: 0,
175
+ conso_elec_ac_auxiliaire_generation_ch: 0,
176
+ conso_elec_ac_ecs: 0,
177
+ conso_elec_ac_auxiliaire_generation_ecs: 0,
178
+ conso_elec_ac_fr: 0,
179
+ conso_elec_ac_ventilation: 0,
180
+ conso_elec_ac_eclairage: 0,
181
+ conso_elec_ac_auxiliaire_distribution_ecs: 0,
182
+ conso_elec_ac_auxiliaire_distribution_ch: 0,
183
+ conso_elec_ac_auxiliaire: 0,
184
+ conso_elec_ac_autre_usage: 0
185
+ };
186
+
187
+ const conso = {
188
+ ef_conso: {
189
+ conso_ecs: 1000,
190
+ conso_ch: 500,
191
+ conso_fr: 800,
192
+ conso_eclairage: 900,
193
+ conso_totale_auxiliaire: 1250,
194
+ conso_5_usages: 1500,
195
+ conso_5_usages_m2: 100
196
+ },
197
+ sortie_par_energie_collection: {
198
+ sortie_par_energie: [
199
+ {
200
+ enum_type_energie_id: '1',
201
+ conso_5_usages: 1500,
202
+ conso_ch: 1000,
203
+ conso_ecs: 1500
204
+ }
205
+ ]
206
+ }
207
+ };
208
+
209
+ productionENR.calculateConsoElecAc(
210
+ productionElectricite,
211
+ productionElecEnr,
212
+ conso,
213
+ 1,
214
+ 'maison',
215
+ 100
216
+ );
217
+
218
+ expect(productionElectricite).toStrictEqual({
219
+ conso_elec_ac: 1039.8691678904038,
220
+ production_pv: 2826.8015616000007,
221
+ conso_elec_ac_ch: 12.64278623574959,
222
+ conso_elec_ac_auxiliaire_generation_ch: 0,
223
+ conso_elec_ac_ecs: 47.41044838406096,
224
+ conso_elec_ac_auxiliaire_generation_ecs: 0,
225
+ conso_elec_ac_fr: 126.42786235749591,
226
+ conso_elec_ac_ventilation: 0,
227
+ conso_elec_ac_eclairage: 28.44626903043658,
228
+ conso_elec_ac_auxiliaire_distribution_ecs: 0,
229
+ conso_elec_ac_auxiliaire_distribution_ch: 0,
230
+ conso_elec_ac_auxiliaire: 0,
231
+ conso_elec_ac_autre_usage: 860.1136363636363
232
+ });
233
+
234
+ expect(productionElecEnr).toStrictEqual({
235
+ donnee_intermediaire: {
236
+ conso_elec_ac: 1039.8691678904038,
237
+ production_pv: 2826.8015616000007,
238
+ taux_autoproduction: 0.2363339017932736
239
+ },
240
+ panneaux_pv_collection: {
241
+ panneaux_pv: [
242
+ {
243
+ enum_inclinaison_pv_id: 2,
244
+ enum_orientation_pv_id: 1,
245
+ nombre_module: 8
246
+ }
247
+ ]
248
+ }
249
+ });
250
+ });
251
+ });
@@ -0,0 +1,37 @@
1
+ import enums from './enums.js';
2
+
3
+ /**
4
+ * Nombre moyen d'heures d'éclairage annuel pour chacune des zones
5
+ * @type {{h1a: number, h1b: number, h1c: number, h2a: number, h2b: number, h2c: number, h2d: number, h3: number}}
6
+ */
7
+ const Nh = {
8
+ h1a: 1500,
9
+ h1b: 1445,
10
+ h1c: 1476,
11
+ h2a: 1500,
12
+ h2b: 1531,
13
+ h2c: 1566,
14
+ h2d: 1566,
15
+ h3: 1506
16
+ };
17
+
18
+ /**
19
+ * 16.1 Consommation d’éclairage (Cecl)
20
+ * @param zc_id
21
+ * @returns {number}
22
+ */
23
+ export default function calc_conso_eclairage(zc_id) {
24
+ const zc = enums.zone_climatique[zc_id];
25
+
26
+ // Coefficient correspondant au taux d'utilisation de l'éclairage en l'absence d'éclairage naturel. Il prend la
27
+ // valeur de 0,9 pour une commande de l’éclairage par interrupteur (considéré dans les logements).
28
+ const C = 0.9;
29
+
30
+ // Puissance d’éclairage conventionnelle, égale à 1,4 W/m2
31
+ const Pecl = 1.4;
32
+
33
+ // Nombre d’heures de fonctionnement de l’éclairage sur l'année
34
+ const nh = Nh[zc];
35
+
36
+ return (C * Pecl * nh) / 1000;
37
+ }
@@ -0,0 +1,61 @@
1
+ import enums from './enums.js';
2
+ import { getKeyByValue, requestInput } from './utils.js';
3
+
4
+ export default function calc_confort_ete(inertie_id, bv, ph) {
5
+ const classe_inertie = enums.classe_inertie[inertie_id];
6
+
7
+ const orientations = bv.reduce((acc, bv) => {
8
+ const orientation = bv.donnee_entree.enum_orientation_id;
9
+ if (!acc.includes(orientation)) acc.push(orientation);
10
+ return acc;
11
+ }, []);
12
+ const aspect_traversant = orientations.length > 1 ? 1 : 0;
13
+
14
+ const isolation_toiture = ph.reduce((acc, ph) => {
15
+ const de = ph.donnee_entree;
16
+ const du = ph.donnee_utilisateur;
17
+ const type_adjacence = requestInput(de, du, 'type_adjacence');
18
+ if (type_adjacence === 'extérieur') {
19
+ const type_isolation = requestInput(de, du, 'type_isolation');
20
+ if (type_isolation === 'inconnu' || type_isolation === 'non isolé') return 0;
21
+ }
22
+ return acc;
23
+ }, 1);
24
+
25
+ let inertie_lourde = 0;
26
+ if (classe_inertie === 'lourde') inertie_lourde = 1;
27
+ if (classe_inertie === 'très lourde') inertie_lourde = 1;
28
+
29
+ // TODO use `presence_protection_solaire_exterieure` ??
30
+ const protection_solaire_exterieure = bv.reduce((acc, bv) => {
31
+ const de = bv.donnee_entree;
32
+ const du = bv.donnee_utilisateur;
33
+ const orientation = requestInput(de, du, 'orientation');
34
+ if (orientation === 'nord') return acc;
35
+ const type_fermerture = requestInput(de, du, 'type_fermeture');
36
+ if (type_fermerture === 'abscence de fermeture pour la baie vitrée') return 0;
37
+ return acc;
38
+ }, 1);
39
+
40
+ const confort_ete = {
41
+ inertie_lourde,
42
+ aspect_traversant,
43
+ isolation_toiture,
44
+ protection_solaire_exterieure,
45
+ brasseur_air: 0
46
+ };
47
+
48
+ const nv_bon =
49
+ confort_ete.inertie_lourde + confort_ete.aspect_traversant + confort_ete.brasseur_air;
50
+ let nv_confort_ete;
51
+ if (confort_ete.protection_solaire_exterieure === 0 || confort_ete.isolation_toiture === 0) {
52
+ nv_confort_ete = 'insuffisant';
53
+ } else if (nv_bon >= 2) nv_confort_ete = 'bon';
54
+ else nv_confort_ete = 'moyen';
55
+
56
+ confort_ete.enum_indicateur_confort_ete_id = getKeyByValue(
57
+ enums.indicateur_confort_ete,
58
+ nv_confort_ete
59
+ );
60
+ return confort_ete;
61
+ }
@@ -0,0 +1,174 @@
1
+ /**
2
+ * @returns {number}
3
+ */
4
+ function qualite_isol(dep, surface, seuil1, seuil2, seuil3) {
5
+ /**
6
+ * 1 - Très bonne
7
+ * 2 - Bonne
8
+ * 3 - Moyenne
9
+ * 4 - Insuffisante
10
+ */
11
+ let u = 0;
12
+
13
+ if (dep && surface) {
14
+ u = dep / surface;
15
+ }
16
+
17
+ if (u < seuil1) return 1;
18
+ else if (u < seuil2) return 2;
19
+ else if (u < seuil3) return 3;
20
+ return 4;
21
+ }
22
+
23
+ export default function calc_qualite_isolation(enveloppe, dp) {
24
+ /**
25
+ * enum_type_adjacence_id = 22 - Local non déperditif (local à usage d'habitation chauffé)
26
+ */
27
+ const mur_list = (enveloppe.mur_collection.mur || []).filter(
28
+ (mur) => mur.donnee_entree.enum_type_adjacence_id !== '22' && mur.donnee_intermediaire.b > 0
29
+ );
30
+
31
+ const planchersHauts = enveloppe.plancher_haut_collection.plancher_haut || [];
32
+ const planchersBas = (enveloppe.plancher_bas_collection.plancher_bas || []).filter(
33
+ (mur) => mur.donnee_entree.enum_type_adjacence_id !== '22'
34
+ );
35
+ const baiesVitrees = (enveloppe.baie_vitree_collection.baie_vitree || []).filter(
36
+ (porte) => porte.donnee_intermediaire.b > 0
37
+ );
38
+ const portes = (enveloppe.porte_collection.porte || []).filter(
39
+ (porte) => porte.donnee_intermediaire.b > 0
40
+ );
41
+
42
+ let phCombleAmenagee = [];
43
+ let phCombleToitTerrasse = [];
44
+ let phComblePerdue = [];
45
+
46
+ planchersHauts.forEach((plancherHaut) => {
47
+ if (plancherHaut.donnee_entree.enum_type_adjacence_id !== '1') {
48
+ phComblePerdue.push(plancherHaut);
49
+ } else {
50
+ if (
51
+ plancherHaut.donnee_entree.enum_type_plancher_haut_id === '12' ||
52
+ plancherHaut.donnee_entree.description?.toLowerCase().indexOf('combles aménagés') !== -1
53
+ ) {
54
+ phCombleAmenagee.push(plancherHaut);
55
+ } else {
56
+ phCombleToitTerrasse.push(plancherHaut);
57
+ }
58
+ }
59
+ });
60
+
61
+ const Umurs = mur_list.reduce(
62
+ (acc, mur) => acc + mur.donnee_entree.surface_paroi_opaque * mur.donnee_intermediaire.umur,
63
+ 0
64
+ );
65
+ const surfaceMurs = mur_list.reduce(
66
+ (acc, mur) => acc + mur.donnee_entree.surface_paroi_opaque,
67
+ 0
68
+ );
69
+
70
+ const UplancherBas = planchersBas.reduce(
71
+ (acc, pb) => acc + pb.donnee_entree.surface_paroi_opaque * pb.donnee_intermediaire.upb,
72
+ 0
73
+ );
74
+ const surfacePlanchersBas = planchersBas.reduce(
75
+ (acc, pb) => acc + pb.donnee_entree.surface_paroi_opaque,
76
+ 0
77
+ );
78
+
79
+ const UphComblesAmenagees = phCombleAmenagee.reduce(
80
+ (acc, ph) => acc + ph.donnee_entree.surface_paroi_opaque * ph.donnee_intermediaire.uph,
81
+ 0
82
+ );
83
+ const UphComblesPerdues = phComblePerdue.reduce(
84
+ (acc, ph) => acc + ph.donnee_entree.surface_paroi_opaque * ph.donnee_intermediaire.uph,
85
+ 0
86
+ );
87
+ const UphToitsTerrasses = phCombleToitTerrasse.reduce(
88
+ (acc, ph) => acc + ph.donnee_entree.surface_paroi_opaque * ph.donnee_intermediaire.uph,
89
+ 0
90
+ );
91
+
92
+ const surfaceComblesAmenagees = phCombleAmenagee
93
+ .filter((mur) => mur.donnee_entree.enum_type_adjacence_id !== '22')
94
+ .reduce((acc, ph) => acc + ph.donnee_entree.surface_paroi_opaque, 0);
95
+ const surfaceComblesPerdues = phComblePerdue
96
+ .filter((mur) => mur.donnee_entree.enum_type_adjacence_id !== '22')
97
+ .reduce((acc, ph) => acc + ph.donnee_entree.surface_paroi_opaque, 0);
98
+ const surfaceToitsTerrasses = phCombleToitTerrasse
99
+ .filter((mur) => mur.donnee_entree.enum_type_adjacence_id !== '22')
100
+ .reduce((acc, ph) => acc + ph.donnee_entree.surface_paroi_opaque, 0);
101
+
102
+ const Umenuiseries =
103
+ baiesVitrees.reduce(
104
+ (acc, bv) =>
105
+ acc + bv.donnee_entree.surface_totale_baie * bv.donnee_intermediaire.u_menuiserie,
106
+ 0
107
+ ) +
108
+ portes.reduce(
109
+ (acc, porte) => acc + porte.donnee_entree.surface_porte * porte.donnee_intermediaire.uporte,
110
+ 0
111
+ );
112
+ const surfacePortes = portes.reduce((acc, porte) => acc + porte.donnee_entree.surface_porte, 0);
113
+ const surfaceBaiesVitrees = baiesVitrees.reduce(
114
+ (acc, bv) => acc + bv.donnee_entree.surface_totale_baie,
115
+ 0
116
+ );
117
+
118
+ const deperdition =
119
+ dp.deperdition_mur +
120
+ dp.deperdition_plancher_bas +
121
+ dp.deperdition_plancher_haut +
122
+ dp.deperdition_baie_vitree +
123
+ dp.deperdition_porte +
124
+ dp.deperdition_pont_thermique;
125
+ const surfacePlanchersHauts =
126
+ surfaceComblesAmenagees + surfaceComblesPerdues + surfaceToitsTerrasses;
127
+ const surfaceDeperditives =
128
+ surfaceMurs + surfacePlanchersBas + surfacePlanchersHauts + surfaceBaiesVitrees + surfacePortes;
129
+ const ubat = deperdition / surfaceDeperditives;
130
+
131
+ const ret = {
132
+ ubat,
133
+ qualite_isol_enveloppe: qualite_isol(deperdition, surfaceDeperditives, 0.45, 0.65, 0.85),
134
+ qualite_isol_mur: qualite_isol(Umurs, surfaceMurs, 0.3, 0.45, 0.65),
135
+ qualite_isol_plancher_bas: qualite_isol(UplancherBas, surfacePlanchersBas, 0.25, 0.45, 0.65),
136
+ qualite_isol_menuiserie: qualite_isol(
137
+ Umenuiseries,
138
+ surfaceBaiesVitrees + surfacePortes,
139
+ 1.6,
140
+ 2.2,
141
+ 3
142
+ )
143
+ };
144
+
145
+ if (UphComblesAmenagees > 0) {
146
+ ret.qualite_isol_plancher_haut_comble_amenage = qualite_isol(
147
+ UphComblesAmenagees,
148
+ surfaceComblesAmenagees,
149
+ 0.18,
150
+ 0.25,
151
+ 0.3
152
+ );
153
+ }
154
+ if (UphToitsTerrasses > 0) {
155
+ ret.qualite_isol_plancher_haut_toit_terrasse = qualite_isol(
156
+ UphToitsTerrasses,
157
+ surfaceToitsTerrasses,
158
+ 0.25,
159
+ 0.3,
160
+ 0.35
161
+ );
162
+ }
163
+ if (UphComblesPerdues > 0) {
164
+ ret.qualite_isol_plancher_haut_comble_perdu = qualite_isol(
165
+ UphComblesPerdues,
166
+ surfaceComblesPerdues,
167
+ 0.15,
168
+ 0.2,
169
+ 0.3
170
+ );
171
+ }
172
+
173
+ return ret;
174
+ }
package/3.1_b.js ADDED
@@ -0,0 +1,141 @@
1
+ import enums from './enums.js';
2
+ import { tv, requestInput, requestInputID, bug_for_bug_compat } from './utils.js';
3
+
4
+ function findRanges(inputNumber) {
5
+ const ranges = [0.25, 0.5, 0.75, 1, 1.25, 2, 2.5, 3, 3.5, 4, 6, 8, 10, 25, 50];
6
+ const result = [];
7
+
8
+ if (inputNumber < ranges[0]) {
9
+ result.push(null);
10
+ result.push(ranges[0]);
11
+ } else if (inputNumber > ranges[ranges.length - 1]) {
12
+ result.push(ranges[ranges.length - 1]);
13
+ result.push(null);
14
+ } else {
15
+ for (let i = 0; i < ranges.length; i++) {
16
+ if (inputNumber <= ranges[i]) {
17
+ if (i > 0) {
18
+ result.push(ranges[i - 1]);
19
+ }
20
+ result.push(ranges[i]);
21
+ break;
22
+ }
23
+ }
24
+ }
25
+ return result;
26
+ }
27
+
28
+ export default function b(di, de, du, zc_id) {
29
+ const zc = enums.zone_climatique[zc_id].slice(0, 2);
30
+
31
+ du.enum_type_adjacence_id = Object.keys(enums.type_adjacence);
32
+ const matcher = {
33
+ enum_type_adjacence_id: requestInputID(de, du, 'type_adjacence')
34
+ };
35
+
36
+ if (de.enum_type_adjacence_id === '10') {
37
+ matcher.zone_climatique = zc;
38
+ matcher.enum_cfg_isolation_lnc_id = requestInputID(de, du, 'cfg_isolation_lnc');
39
+ /* du.enum_cfg_isolation_lnc_id = ['6', '7', '8', '9', '10', '11'] */
40
+ } else if (
41
+ ['8', '9', '11', '12', '13', '14', '15', '16', '17', '18', '19', '21'].includes(
42
+ de.enum_type_adjacence_id.toString()
43
+ )
44
+ ) {
45
+ if (de.surface_aue === 0) {
46
+ // cf page 10
47
+ // NOTE: bizarre de regarder aue pour un local chauffé non accessible
48
+ // voir 2287E2336469P
49
+ di.b = 0;
50
+ return;
51
+ }
52
+ matcher.enum_cfg_isolation_lnc_id = requestInputID(de, du, 'cfg_isolation_lnc');
53
+ if (matcher.enum_cfg_isolation_lnc_id === '1') {
54
+ // local chauffé non accessible
55
+ // aiu/aue non connu
56
+ delete matcher.enum_type_adjacence_id;
57
+ } else {
58
+ requestInput(de, du, 'surface_aiu', 'float');
59
+ requestInput(de, du, 'surface_aue', 'float');
60
+
61
+ if (de.surface_aiu === de.surface_aue) {
62
+ const defaultAiuAueMin = '0,75 <';
63
+ const defaultAiuAueMax = '≤ 1,00';
64
+
65
+ matcher.aiu_aue_min = defaultAiuAueMin;
66
+ matcher.aiu_aue_max = defaultAiuAueMax;
67
+
68
+ /**
69
+ * Certains DPE utilisent seulement aiu_aue_max = '≤ 0,25' alors que le ratio surface_aiu / surface_aue est 1 et donc
70
+ * on devrait avoir aiu_aue_min: '0,75 <' et aiu_aue_max: '≤ 1,00',
71
+ */
72
+ if (bug_for_bug_compat && de.tv_coef_reduction_deperdition_id) {
73
+ const rowCoeffReductionpertes = tv('coef_reduction_deperdition', {
74
+ tv_coef_reduction_deperdition_id: de.tv_coef_reduction_deperdition_id
75
+ });
76
+
77
+ if (rowCoeffReductionpertes) {
78
+ matcher.aiu_aue_min = rowCoeffReductionpertes.aiu_aue_min || defaultAiuAueMin;
79
+ matcher.aiu_aue_max = rowCoeffReductionpertes.aiu_aue_max || defaultAiuAueMax;
80
+
81
+ if (
82
+ matcher.aiu_aue_min !== defaultAiuAueMin ||
83
+ matcher.aiu_aue_max !== defaultAiuAueMax
84
+ ) {
85
+ console.error(
86
+ `Le calcul de b pour ${de.description} devrait se faire avec aiu_aue_min: '0,75 <' et aiu_aue_max: '≤ 1,00'
87
+ car surface_aiu === surface_aue. aiu_aue_min = ${matcher.aiu_aue_min} et aiu_aue_max = ${matcher.aiu_aue_max}
88
+ sont cependant utilisés par le DPE. Prise en compte de ces valeurs pour la suite des calculs`
89
+ );
90
+ }
91
+ }
92
+ }
93
+ } else {
94
+ const ranges = findRanges(de.surface_aiu / de.surface_aue);
95
+ if (ranges[0]) {
96
+ // Si le rapport des surfaces est égale à la borne inférieure, utilisation de la borne supérieure
97
+ // et prise en compte de l'égalité
98
+ if (ranges[0] === de.surface_aiu / de.surface_aue) {
99
+ matcher.aiu_aue_max =
100
+ '≤ ' +
101
+ ranges[0]
102
+ .toLocaleString(undefined, {
103
+ minimumFractionDigits: 2,
104
+ maximumFractionDigits: 2,
105
+ useGrouping: false
106
+ })
107
+ .replace('.', ',');
108
+ } else {
109
+ matcher.aiu_aue_min =
110
+ ranges[0]
111
+ .toLocaleString(undefined, {
112
+ minimumFractionDigits: 2,
113
+ maximumFractionDigits: 2,
114
+ useGrouping: false
115
+ })
116
+ .replace('.', ',') + ' <';
117
+ }
118
+ }
119
+ if (ranges[1]) {
120
+ matcher.aiu_aue_max =
121
+ '≤ ' +
122
+ ranges[1]
123
+ .toLocaleString(undefined, {
124
+ minimumFractionDigits: 2,
125
+ maximumFractionDigits: 2,
126
+ useGrouping: false
127
+ })
128
+ .replace('.', ',');
129
+ }
130
+ }
131
+ }
132
+ }
133
+
134
+ const row = tv('coef_reduction_deperdition', matcher);
135
+ if (row) {
136
+ di.b = Number(row.b);
137
+ de.tv_coef_reduction_deperdition_id = Number(row.tv_coef_reduction_deperdition_id);
138
+ } else {
139
+ console.error('!! pas de valeur forfaitaire trouvée pour b !!');
140
+ }
141
+ }