@open3cl/engine 1.0.6 → 1.0.8

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 (72) hide show
  1. package/11_nadeq.spec.js +3 -2
  2. package/16.2_production_enr.spec.js +1 -0
  3. package/3.2.1_mur.spec.js +1 -0
  4. package/3.2.2_plancher_bas.spec.js +1 -0
  5. package/3.3_baie_vitree.spec.js +1 -0
  6. package/6.1_apport_gratuit.spec.js +1 -0
  7. package/7_inertie.spec.js +4 -3
  8. package/9_chauffage.spec.js +1 -0
  9. package/9_conso_ch.spec.js +1 -0
  10. package/9_generateur_ch.spec.js +1 -0
  11. package/conso.spec.js +1 -0
  12. package/core/assets/domain/synchronize-assets.spec.js +9 -9
  13. package/core/assets/domain/synchronize-c1-tables.spec.js +4 -4
  14. package/core/assets/domain/synchronize-dpe-ges-limit-values-tables.spec.js +6 -6
  15. package/core/assets/domain/synchronize-enum-tables.spec.js +10 -10
  16. package/core/assets/domain/synchronize-solicitations-tables.spec.js +6 -6
  17. package/core/assets/domain/synchronize-valeur-tables.spec.js +14 -14
  18. package/core/file/infrastructure/adapter/file.store.spec.js +5 -4
  19. package/core/tv/infrastructure/tvs.store.spec.js +3 -2
  20. package/core/util/infrastructure/object-util.spec.js +2 -1
  21. package/core/util/logger/log-service.js +47 -0
  22. package/features/dpe/domain/models/baie-ets.model.ts +12 -0
  23. package/features/dpe/domain/models/baie-vitree.model.ts +97 -0
  24. package/features/dpe/domain/models/climatisation.model.ts +25 -0
  25. package/features/dpe/domain/models/dpe.model.ts +194 -0
  26. package/features/dpe/domain/models/ets.model.ts +19 -0
  27. package/features/dpe/domain/models/installation-chauffage.model.ts +101 -0
  28. package/features/dpe/domain/models/installation-ecs.model.ts +76 -0
  29. package/features/dpe/domain/models/mur.model.ts +37 -0
  30. package/features/dpe/domain/models/plancher-bas.model.ts +38 -0
  31. package/features/dpe/domain/models/plancher-haut.model.ts +33 -0
  32. package/features/dpe/domain/models/pont-thermique.model.ts +21 -0
  33. package/features/dpe/domain/models/porte.model.ts +31 -0
  34. package/features/dpe/domain/models/production-elec-enr.model.ts +27 -0
  35. package/features/dpe/domain/models/sortie.model.ts +178 -0
  36. package/features/dpe/domain/models/type-habitation.model.js +8 -0
  37. package/features/dpe/domain/models/type-ventilation.model.js +8 -0
  38. package/features/dpe/domain/models/ventilation.model.ts +33 -0
  39. package/features/dpe/infrastructure/baieVitreeTv.store.js +292 -0
  40. package/features/dpe/infrastructure/baieVitreeTv.store.spec.js +352 -0
  41. package/features/dpe/infrastructure/tv.store.js +356 -0
  42. package/features/dpe/infrastructure/tv.store.spec.js +607 -0
  43. package/features/engine/domain/constants.js +1 -0
  44. package/features/engine/domain/contexte.builder.js +140 -0
  45. package/features/engine/domain/contexte.builder.spec.js +152 -0
  46. package/features/engine/domain/engine.service.js +139 -0
  47. package/features/engine/domain/engine.service.spec.js +7 -0
  48. package/features/engine/domain/enveloppe/baie_vitree/deperdition-baie-vitree.service.js +292 -0
  49. package/features/engine/domain/enveloppe/baie_vitree/deperdition-baie-vitree.service.spec.js +484 -0
  50. package/features/engine/domain/enveloppe/deperdition-enveloppe.service.js +278 -0
  51. package/features/engine/domain/enveloppe/deperdition-enveloppe.service.spec.js +282 -0
  52. package/features/engine/domain/enveloppe/deperdition.service.js +101 -0
  53. package/features/engine/domain/enveloppe/mur/deperdition-mur.service.js +168 -0
  54. package/features/engine/domain/enveloppe/mur/deperdition-mur.service.spec.js +345 -0
  55. package/features/engine/domain/enveloppe/plancher_bas/deperdition-plancher-bas.service.js +169 -0
  56. package/features/engine/domain/enveloppe/plancher_bas/deperdition-plancher-bas.service.spec.js +200 -0
  57. package/features/engine/domain/enveloppe/plancher_haut/deperdition-plancher-haut.service.js +136 -0
  58. package/features/engine/domain/enveloppe/plancher_haut/deperdition-plancher-haut.service.spec.js +211 -0
  59. package/features/engine/domain/enveloppe/porte/deperdition-porte.service.js +56 -0
  60. package/features/engine/domain/enveloppe/porte/deperdition-porte.service.spec.js +116 -0
  61. package/features/engine/domain/enveloppe/ventilation/deperdition-ventilation.service.js +338 -0
  62. package/features/engine/domain/enveloppe/ventilation/deperdition-ventilation.service.spec.js +442 -0
  63. package/features/engine/domain/models/contexte.model.ts +10 -0
  64. package/features/engine/domain/models/deperdition.model.ts +8 -0
  65. package/features/normalizer/domain/dpe-normalizer.service.js +24 -0
  66. package/features/normalizer/domain/dpe-normalizer.service.spec.js +3 -0
  67. package/ficheTechnique.spec.js +4 -3
  68. package/output.js +1 -0
  69. package/package.json +9 -8
  70. package/tv-v2.js +79121 -0
  71. package/utils.js +2 -2
  72. package/utils.spec.js +4 -3
@@ -0,0 +1,178 @@
1
+ export interface Sortie {
2
+ deperdition: Deperdition;
3
+ apport_et_besoin: ApportEtBesoin;
4
+ ef_conso: EfConso;
5
+ ep_conso: EpConso;
6
+ emission_ges: EmissionGes;
7
+ cout: Cout;
8
+ production_electricite: ProductionElectricite;
9
+ sortie_par_energie_collection: { sortie_par_energie: SortieParEnergie[] };
10
+ confort_ete?: ConfortEte;
11
+ qualite_isolation: QualiteIsolation;
12
+ }
13
+
14
+ export interface Deperdition {
15
+ hvent: number;
16
+ hperm: number;
17
+ deperdition_renouvellement_air: number;
18
+ deperdition_mur: number;
19
+ deperdition_plancher_bas: number;
20
+ deperdition_plancher_haut: number;
21
+ deperdition_baie_vitree: number;
22
+ deperdition_porte: number;
23
+ deperdition_pont_thermique: number;
24
+ deperdition_enveloppe: number;
25
+ }
26
+
27
+ export interface ApportEtBesoin {
28
+ surface_sud_equivalente: number;
29
+ apport_solaire_fr: number;
30
+ apport_interne_fr: number;
31
+ apport_solaire_ch: number;
32
+ apport_interne_ch: number;
33
+ fraction_apport_gratuit_ch: number;
34
+ fraction_apport_gratuit_depensier_ch: number;
35
+ pertes_distribution_ecs_recup: number;
36
+ pertes_distribution_ecs_recup_depensier: number;
37
+ pertes_stockage_ecs_recup: number;
38
+ pertes_generateur_ch_recup: number;
39
+ pertes_generateur_ch_recup_depensier: number;
40
+ nadeq: number;
41
+ v40_ecs_journalier: number;
42
+ v40_ecs_journalier_depensier: number;
43
+ besoin_ch: number;
44
+ besoin_ch_depensier: number;
45
+ besoin_ecs: number;
46
+ besoin_ecs_depensier: number;
47
+ besoin_fr: number;
48
+ besoin_fr_depensier: number;
49
+ }
50
+
51
+ export interface EfConso {
52
+ conso_ch: number;
53
+ conso_ch_depensier: number;
54
+ conso_ecs: number;
55
+ conso_ecs_depensier: number;
56
+ conso_eclairage: number;
57
+ conso_auxiliaire_generation_ch: number;
58
+ conso_auxiliaire_generation_ch_depensier: number;
59
+ conso_auxiliaire_distribution_ch: number;
60
+ conso_auxiliaire_generation_ecs: number;
61
+ conso_auxiliaire_generation_ecs_depensier: number;
62
+ conso_auxiliaire_distribution_ecs: number;
63
+ conso_auxiliaire_distribution_fr?: number;
64
+ conso_auxiliaire_ventilation: number;
65
+ conso_totale_auxiliaire: number;
66
+ conso_fr: number;
67
+ conso_fr_depensier: number;
68
+ conso_5_usages: number;
69
+ conso_5_usages_m2: number;
70
+ }
71
+
72
+ export interface EpConso {
73
+ ep_conso_ch: number;
74
+ ep_conso_ch_depensier: number;
75
+ ep_conso_ecs: number;
76
+ ep_conso_ecs_depensier: number;
77
+ ep_conso_eclairage: number;
78
+ ep_conso_auxiliaire_generation_ch: number;
79
+ ep_conso_auxiliaire_generation_ch_depensier: number;
80
+ ep_conso_auxiliaire_distribution_ch: number;
81
+ ep_conso_auxiliaire_generation_ecs: number;
82
+ ep_conso_auxiliaire_generation_ecs_depensier: number;
83
+ ep_conso_auxiliaire_distribution_ecs: number;
84
+ ep_conso_auxiliaire_distribution_fr?: number;
85
+ ep_conso_auxiliaire_ventilation: number;
86
+ ep_conso_totale_auxiliaire: number;
87
+ ep_conso_fr: number;
88
+ ep_conso_fr_depensier: number;
89
+ ep_conso_5_usages: number;
90
+ ep_conso_5_usages_m2: number;
91
+ classe_bilan_dpe: string;
92
+ }
93
+
94
+ export interface EmissionGes {
95
+ emission_ges_ch: number;
96
+ emission_ges_ch_depensier: number;
97
+ emission_ges_ecs: number;
98
+ emission_ges_ecs_depensier: number;
99
+ emission_ges_eclairage: number;
100
+ emission_ges_auxiliaire_generation_ch: number;
101
+ emission_ges_auxiliaire_generation_ch_depensier: number;
102
+ emission_ges_auxiliaire_distribution_ch: number;
103
+ emission_ges_auxiliaire_generation_ecs: number;
104
+ emission_ges_auxiliaire_generation_ecs_depensier: number;
105
+ emission_ges_auxiliaire_distribution_ecs: number;
106
+ emission_ges_auxiliaire_distribution_fr?: number;
107
+ emission_ges_auxiliaire_ventilation: number;
108
+ emission_ges_totale_auxiliaire: number;
109
+ emission_ges_fr: number;
110
+ emission_ges_fr_depensier: number;
111
+ emission_ges_5_usages: number;
112
+ emission_ges_5_usages_m2: number;
113
+ classe_emission_ges: string;
114
+ }
115
+
116
+ export interface Cout {
117
+ cout_ch: number;
118
+ cout_ch_depensier: number;
119
+ cout_ecs: number;
120
+ cout_ecs_depensier: number;
121
+ cout_eclairage: number;
122
+ cout_auxiliaire_generation_ch: number;
123
+ cout_auxiliaire_generation_ch_depensier: number;
124
+ cout_auxiliaire_distribution_ch: number;
125
+ cout_auxiliaire_generation_ecs: number;
126
+ cout_auxiliaire_generation_ecs_depensier: number;
127
+ cout_auxiliaire_distribution_ecs: number;
128
+ cout_auxiliaire_distribution_fr?: number;
129
+ cout_auxiliaire_ventilation: number;
130
+ cout_total_auxiliaire: number;
131
+ cout_fr: number;
132
+ cout_fr_depensier: number;
133
+ cout_5_usages: number;
134
+ }
135
+
136
+ export interface ProductionElectricite {
137
+ production_pv: number;
138
+ conso_elec_ac: number;
139
+ conso_elec_ac_ch: number;
140
+ conso_elec_ac_ecs: number;
141
+ conso_elec_ac_fr: number;
142
+ conso_elec_ac_eclairage: number;
143
+ conso_elec_ac_auxiliaire: number;
144
+ conso_elec_ac_autre_usage: number;
145
+ }
146
+
147
+ export interface SortieParEnergie {
148
+ enum_type_energie_id: number;
149
+ conso_ch: number;
150
+ conso_ecs: number;
151
+ conso_5_usages: number;
152
+ emission_ges_ch: number;
153
+ emission_ges_ecs: number;
154
+ emission_ges_5_usages: number;
155
+ cout_ch: number;
156
+ cout_ecs: number;
157
+ cout_5_usages: number;
158
+ }
159
+
160
+ export interface ConfortEte {
161
+ isolation_toiture?: boolean;
162
+ protection_solaire_exterieure: boolean;
163
+ aspect_traversant?: boolean;
164
+ brasseur_air?: boolean;
165
+ inertie_lourde: boolean;
166
+ enum_indicateur_confort_ete_id: number;
167
+ }
168
+
169
+ export interface QualiteIsolation {
170
+ ubat: number;
171
+ qualite_isol_enveloppe: number;
172
+ qualite_isol_mur?: number;
173
+ qualite_isol_plancher_haut_toit_terrasse?: number;
174
+ qualite_isol_plancher_haut_comble_perdu?: number;
175
+ qualite_isol_plancher_haut_comble_amenage?: number;
176
+ qualite_isol_plancher_bas?: number;
177
+ qualite_isol_menuiserie: number;
178
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @type {{[key: string]: string}}
3
+ */
4
+ export const TypeHabitation = {
5
+ MAISON: 'MAISON',
6
+ APPARTEMENT: 'APPARTEMENT',
7
+ IMMEUBLE: 'IMMEUBLE'
8
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @type {{[key: string]: string}}
3
+ */
4
+ export const TypeVentilation = {
5
+ SIMPLE_FLUX_AUTO: 'SIMPLE_FLUX_AUTO',
6
+ SIMPLE_FLUX_HYGRO: 'SIMPLE_FLUX_HYGRO',
7
+ DOUBLE_FLUX: 'DOUBLE_FLUX'
8
+ };
@@ -0,0 +1,33 @@
1
+ import { DE } from './dpe.model';
2
+
3
+ export interface Ventilation {
4
+ donnee_entree?: VentilationDE;
5
+ donnee_intermediaire?: VentilationDI;
6
+ }
7
+
8
+ export interface VentilationDE extends DE {
9
+ enum_type_ventilation_id: number;
10
+ surface_ventile: number;
11
+ plusieurs_facade_exposee: boolean;
12
+ tv_q4pa_conv_id?: number;
13
+ q4pa_conv_saisi?: number;
14
+ enum_methode_saisie_q4pa_conv_id: number;
15
+ tv_debits_ventilation_id: number;
16
+ ventilation_post_2012: boolean;
17
+ ref_produit_ventilation?: number;
18
+ cle_repartition_ventilation?: number;
19
+ }
20
+
21
+ export interface VentilationDI {
22
+ pvent_moy?: number;
23
+ q4pa_conv: number;
24
+ conso_auxiliaire_ventilation: number;
25
+ hperm: number;
26
+ hvent: number;
27
+ }
28
+
29
+ enum TypeVentilation {
30
+ SIMPLE_FLUX_AUTO = 'SIMPLE_FLUX_AUTO',
31
+ SIMPLE_FLUX_HYGRO = 'SIMPLE_FLUX_HYGRO',
32
+ DOUBLE_FLUX = 'DOUBLE_FLUX'
33
+ }
@@ -0,0 +1,292 @@
1
+ import { tvs as tv } from '../../../tv-v2.js';
2
+ import { getRange } from '../../../utils.js';
3
+ import { logger } from '../../../core/util/logger/log-service.js';
4
+ import { TvStore } from './tv.store.js';
5
+
6
+ /**
7
+ * Accès aux données des tables de valeurs pour les baies vitrées
8
+ */
9
+ export class BaieVitreeTvStore extends TvStore {
10
+ /**
11
+ * Coefficient de transmission thermique du vitrage (W/(m².K))
12
+ *
13
+ * @param enumTypeVitrageId {string}
14
+ * @param enumTypeGazLameId {string|undefined}
15
+ * @param enumInclinaisonVitrageId {string|undefined}
16
+ * @param vitrageVir {number|undefined}
17
+ * @param epaisseurLame {number|undefined}
18
+ * @return {number|undefined}
19
+ */
20
+ getUg(enumTypeVitrageId, enumTypeGazLameId, enumInclinaisonVitrageId, vitrageVir, epaisseurLame) {
21
+ const ug = tv['ug'].find(
22
+ (v) =>
23
+ v.enum_type_vitrage_id.split('|').includes(enumTypeVitrageId) &&
24
+ (!enumTypeGazLameId || v.enum_type_gaz_lame_id?.split('|').includes(enumTypeGazLameId)) &&
25
+ (!enumInclinaisonVitrageId ||
26
+ v.enum_inclinaison_vitrage_id?.split('|').includes(enumInclinaisonVitrageId)) &&
27
+ (!vitrageVir || parseInt(vitrageVir) === parseInt(v.vitrage_vir)) &&
28
+ (!epaisseurLame || parseFloat(v.epaisseur_lame) === epaisseurLame)
29
+ )?.ug;
30
+
31
+ if (!ug) {
32
+ logger.error(
33
+ `Pas de valeur forfaitaire ug pour enumTypeVitrageId:${enumTypeVitrageId}, enumTypeGazLameId:${enumTypeGazLameId}, enumInclinaisonVitrageId:${enumInclinaisonVitrageId}, vitrageVir:${vitrageVir}, epaisseurLame:${epaisseurLame}`
34
+ );
35
+ return;
36
+ }
37
+
38
+ return parseFloat(ug);
39
+ }
40
+
41
+ /**
42
+ * Épaisseurs disponibles pour les coefficients de transmission thermique du vitrage (W/(m².K))
43
+ *
44
+ * @return {number[]}
45
+ */
46
+ getEpaisseurAvailableForUg() {
47
+ return [
48
+ ...new Set(tv['ug'].map((value) => parseInt(value.epaisseur_lame) || 0).sort((a, b) => a - b))
49
+ ];
50
+ }
51
+
52
+ /**
53
+ * Proportion d’énergie solaire incidente qui pénètre dans le logement par la paroi vitrée
54
+ *
55
+ * @param enumTypeVitrageId {string}
56
+ * @param enumTypeBaieId {string}
57
+ * @param enumTypeMateriauxMenuiserieId {string}
58
+ * @param vitrageVir {number|undefined}
59
+ * @param enumTypePoseId {string|undefined}
60
+ * @return {number|undefined}
61
+ */
62
+ getSw(
63
+ enumTypeVitrageId,
64
+ enumTypeBaieId,
65
+ enumTypeMateriauxMenuiserieId,
66
+ vitrageVir,
67
+ enumTypePoseId
68
+ ) {
69
+ const sw = tv['sw'].find(
70
+ (v) =>
71
+ (!v.enum_type_vitrage_id ||
72
+ v.enum_type_vitrage_id.split('|').includes(enumTypeVitrageId)) &&
73
+ v.enum_type_baie_id.split('|').includes(enumTypeBaieId) &&
74
+ v.enum_type_materiaux_menuiserie_id.split('|').includes(enumTypeMateriauxMenuiserieId) &&
75
+ (!vitrageVir || parseInt(vitrageVir) === parseInt(v.vitrage_vir)) &&
76
+ (!enumTypePoseId || v.enum_type_pose_id.split('|').includes(enumTypePoseId))
77
+ )?.sw;
78
+
79
+ if (!sw) {
80
+ logger.error(
81
+ `Pas de valeur forfaitaire sw pour enumTypeVitrageId:${enumTypeVitrageId}, enumTypeBaieId:${enumTypeBaieId}, enumTypeMateriauxMenuiserieId:${enumTypeMateriauxMenuiserieId}, vitrageVir:${vitrageVir}, enumTypePoseId:${enumTypePoseId}`
82
+ );
83
+ return;
84
+ }
85
+
86
+ return parseFloat(sw);
87
+ }
88
+
89
+ /**
90
+ * Coefficient de transmission thermique des fenêtres
91
+ *
92
+ * @param enumTypeVitrageId {string}
93
+ * @param enumTypeBaieId {string}
94
+ * @param enumTypeMateriauxMenuiserieId {string}
95
+ * @param ug {number|undefined}
96
+ * @return {number|undefined}
97
+ */
98
+ getUw(enumTypeBaieId, enumTypeMateriauxMenuiserieId, ug) {
99
+ let uw;
100
+
101
+ /**
102
+ * Pas de notion de ug pour les parois polycarbonate ou verre
103
+ * enum_type_baie_id
104
+ * 1 - paroi en brique de verre pleine
105
+ * 2 - paroi en brique de verre creuse
106
+ * 3 - paroi en polycarbonnate
107
+ */
108
+ if (['1', '2', '3'].includes(enumTypeBaieId)) {
109
+ uw = tv['uw'].find((v) => v.enum_type_baie_id.split('|').includes(enumTypeBaieId))?.uw;
110
+ } else {
111
+ /**
112
+ * 3.3.2 Coefficients Uw des fenêtres / portes-fenêtres
113
+ * Les Uw associés à des Ug non présents dans les tableaux peuvent être obtenus par interpolation ou
114
+ * extrapolation avec les deux Ug tabulés les plus proches.
115
+ */
116
+ const ugValues =
117
+ tv['uw'].filter(
118
+ (v) =>
119
+ v.enum_type_baie_id.split('|').includes(enumTypeBaieId) &&
120
+ v.enum_type_materiaux_menuiserie_id.split('|').includes(enumTypeMateriauxMenuiserieId)
121
+ ) || [];
122
+
123
+ let ug1, ug2;
124
+
125
+ if (ugValues.length) {
126
+ [ug1, ug2] = getRange(ug, [...new Set(ugValues.map((value) => value.ug).sort())]);
127
+
128
+ const uw1 = ugValues.find((value) => value.ug === ug1)?.uw || 0;
129
+ const uw2 = ugValues.find((value) => value.ug === ug2)?.uw || 0;
130
+
131
+ const delta_uw = Number(uw2) - Number(uw1);
132
+ const delta_ug = ug2 - ug1 || 0;
133
+
134
+ if (delta_ug === 0) {
135
+ uw = Number(uw1);
136
+ } else {
137
+ // Interpolation linéaire si upb n'est pas une valeur connue
138
+ uw = Number(uw1) + (delta_uw * (ug - ug1)) / delta_ug;
139
+ }
140
+ }
141
+ }
142
+
143
+ if (!uw) {
144
+ logger.error(
145
+ `Pas de valeur forfaitaire uw pour enumTypeBaieId:${enumTypeBaieId}, enumTypeMateriauxMenuiserieId:${enumTypeMateriauxMenuiserieId}, ug:${ug}`
146
+ );
147
+ return;
148
+ }
149
+
150
+ return parseFloat(uw);
151
+ }
152
+
153
+ /**
154
+ * La présence de volets aux fenêtres et portes-fenêtres leur apporte un supplément d’isolation avec une résistance
155
+ * additionnelle ΔR
156
+ *
157
+ * @param enumTypeFermetureId {string}
158
+ * @return {number|undefined}
159
+ */
160
+ getDeltar(enumTypeFermetureId) {
161
+ const deltar = tv['deltar'].find((v) =>
162
+ v.enum_type_fermeture_id.split('|').includes(enumTypeFermetureId)
163
+ )?.deltar;
164
+
165
+ if (!deltar) {
166
+ logger.error(
167
+ `Pas de valeur forfaitaire deltar pour enumTypeFermetureId:${enumTypeFermetureId}`
168
+ );
169
+ return;
170
+ }
171
+
172
+ return parseFloat(deltar);
173
+ }
174
+
175
+ /**
176
+ * La présence de volets aux fenêtres et portes-fenêtres leur apporte un supplément d’isolation avec une résistance
177
+ * additionnelle ΔR
178
+ *
179
+ * @param enumTypeFermetureId {string}
180
+ * @param uw {number}
181
+ *
182
+ * @return {number|undefined}
183
+ */
184
+ getUjn(enumTypeFermetureId, uw) {
185
+ let ujn;
186
+ /**
187
+ * 3.3.3 Coefficients Ujn des fenêtres/portes-fenêtres
188
+ * Dans la suite, les Ujn associés à des Uw non présents dans les tableaux peuvent être obtenus par interpolation ou
189
+ * extrapolation avec les deux Uw tabulés les plus proches.
190
+ */
191
+ const deltar = this.getDeltar(enumTypeFermetureId);
192
+ const uwValues =
193
+ tv['ujn'].filter((v) => Number(v.deltar).toPrecision(2) === Number(deltar).toPrecision(2)) ||
194
+ [];
195
+
196
+ let uw1, uw2;
197
+
198
+ if (uwValues.length) {
199
+ [uw1, uw2] = getRange(uw, [...new Set(uwValues.map((value) => value.uw).sort())]);
200
+
201
+ const ujn1 =
202
+ uwValues.find((value) => Number(value.uw).toPrecision(2) === Number(uw1).toPrecision(2))
203
+ ?.ujn || 0;
204
+ const ujn2 =
205
+ uwValues.find((value) => Number(value.uw).toPrecision(2) === Number(uw2).toPrecision(2))
206
+ ?.ujn || 0;
207
+
208
+ const delta_ujn = Number(ujn2) - Number(ujn1);
209
+ const delta_uw = uw2 - uw1 || 0;
210
+
211
+ if (delta_uw === 0) {
212
+ ujn = Number(ujn1);
213
+ } else {
214
+ // Interpolation linéaire si uw n'est pas une valeur connue
215
+ ujn = Number(ujn1) + (delta_ujn * (uw - uw1)) / delta_uw;
216
+ }
217
+
218
+ if (!ujn) {
219
+ logger.error(
220
+ `Pas de valeur forfaitaire ujn pour enumTypeFermetureId:${enumTypeFermetureId}, uw:${uw}`
221
+ );
222
+ return;
223
+ }
224
+
225
+ return parseFloat(ujn);
226
+ }
227
+ }
228
+
229
+ /**
230
+ * Calcul de l’ombrage créé par un obstacle sur une paroi
231
+ *
232
+ * @param tvCoeffMasqueLointainNonHomogeneId {number}
233
+ * @return {number|undefined}
234
+ */
235
+ getOmbre(tvCoeffMasqueLointainNonHomogeneId) {
236
+ const ombre = tv['coef_masque_lointain_non_homoge'].find(
237
+ (v) =>
238
+ parseInt(v.tv_coef_masque_lointain_non_homogene_id) ===
239
+ parseInt(tvCoeffMasqueLointainNonHomogeneId)
240
+ )?.omb;
241
+
242
+ if (!ombre) {
243
+ logger.error(
244
+ `Pas de valeur forfaitaire ombre pour tvCoeffMasqueLointainNonHomogeneId:${tvCoeffMasqueLointainNonHomogeneId}`
245
+ );
246
+ return;
247
+ }
248
+
249
+ return parseFloat(ombre);
250
+ }
251
+
252
+ /**
253
+ * Calcul de l'incidence d'un masque proche sur une paroi
254
+ *
255
+ * @param tvCoefMasqueProcheId {number}
256
+ * @return {number|undefined}
257
+ */
258
+ getMasqueProche(tvCoefMasqueProcheId) {
259
+ const fe1 = tv['coef_masque_proche'].find(
260
+ (v) => parseInt(v.tv_coef_masque_proche_id) === parseInt(tvCoefMasqueProcheId)
261
+ )?.fe1;
262
+
263
+ if (!fe1) {
264
+ logger.error(`Pas de valeur fe1 pour tvCoefMasqueProcheId:${tvCoefMasqueProcheId}`);
265
+ return;
266
+ }
267
+
268
+ return parseFloat(fe1);
269
+ }
270
+
271
+ /**
272
+ * Calcul de l'incidence d'un masque lointain homogène sur une paroi
273
+ *
274
+ * @param tvCoefMasqueLointainHomogeneId {number}
275
+ * @return {number|undefined}
276
+ */
277
+ getMasqueLointainHomogene(tvCoefMasqueLointainHomogeneId) {
278
+ const fe2 = tv['coef_masque_lointain_homogene'].find(
279
+ (v) =>
280
+ parseInt(v.tv_coef_masque_lointain_homogene_id) === parseInt(tvCoefMasqueLointainHomogeneId)
281
+ )?.fe2;
282
+
283
+ if (!fe2) {
284
+ logger.error(
285
+ `Pas de valeur fe2 pour tvCoefMasqueLointainHomogeneId:${tvCoefMasqueLointainHomogeneId}`
286
+ );
287
+ return;
288
+ }
289
+
290
+ return parseFloat(fe2);
291
+ }
292
+ }