@open3cl/engine 1.0.7 → 1.0.9

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 (24) hide show
  1. package/features/dpe/domain/models/baie-vitree.model.ts +8 -6
  2. package/features/dpe/domain/models/dpe.model.ts +7 -3
  3. package/features/dpe/domain/models/{plancher-bas.model.ts → plancher.model.ts} +31 -7
  4. package/features/dpe/infrastructure/baieVitreeTv.store.js +292 -0
  5. package/features/dpe/infrastructure/baieVitreeTv.store.spec.js +352 -0
  6. package/features/dpe/infrastructure/pontThermiqueTv.store.js +112 -0
  7. package/features/dpe/infrastructure/pontThermiqueTv.store.spec.js +134 -0
  8. package/features/dpe/infrastructure/tv.store.js +0 -33
  9. package/features/dpe/infrastructure/tv.store.spec.js +0 -83
  10. package/features/engine/domain/engine.service.js +2 -1
  11. package/features/engine/domain/enveloppe/baie_vitree/deperdition-baie-vitree.service.js +292 -0
  12. package/features/engine/domain/enveloppe/baie_vitree/deperdition-baie-vitree.service.spec.js +484 -0
  13. package/features/engine/domain/enveloppe/deperdition-enveloppe.service.js +38 -0
  14. package/features/engine/domain/enveloppe/mur/deperdition-mur.service.js +28 -0
  15. package/features/engine/domain/enveloppe/mur/deperdition-mur.service.spec.js +61 -0
  16. package/features/engine/domain/enveloppe/plancher_bas/deperdition-plancher-bas.service.js +46 -0
  17. package/features/engine/domain/enveloppe/plancher_bas/deperdition-plancher-bas.service.spec.js +85 -0
  18. package/features/engine/domain/enveloppe/plancher_haut/deperdition-plancher-haut.service.js +33 -0
  19. package/features/engine/domain/enveloppe/plancher_haut/deperdition-plancher-haut.service.spec.js +61 -0
  20. package/features/engine/domain/enveloppe/pont_thermique/deperdition-pont-thermique.service.js +439 -0
  21. package/features/engine/domain/enveloppe/pont_thermique/deperdition-pont-thermique.service.spec.js +636 -0
  22. package/features/engine/domain/enveloppe/ventilation/deperdition-ventilation.service.spec.js +49 -0
  23. package/package.json +1 -1
  24. package/features/dpe/domain/models/plancher-haut.model.ts +0 -33
@@ -28,7 +28,7 @@ export interface BaieVitreeDE extends DE {
28
28
  enum_type_materiaux_menuiserie_id?: string; // ENUM type_materiaux_menuiserie
29
29
  enum_type_baie_id?: string; // ENUM type_baie
30
30
  uw_saisi?: number;
31
- double_fenetre?: boolean;
31
+ double_fenetre?: number;
32
32
  uw_1?: number;
33
33
  sw_1?: number;
34
34
  uw_2?: number;
@@ -45,12 +45,10 @@ export interface BaieVitreeDE extends DE {
45
45
  sw_saisi?: number;
46
46
  enum_type_pose_id?: string; // ENUM type_pose
47
47
  enum_orientation_id?: string;
48
- tv_coef_masque_proche_id?: string;
49
- tv_coef_masque_lointain_homogene_id?: string;
48
+ tv_coef_masque_proche_id?: number;
49
+ tv_coef_masque_lointain_homogene_id?: number;
50
50
  masque_lointain_non_homogene_collection: {
51
- masque_lointain_non_homogene: {
52
- tv_coef_masque_lointain_non_homogene_id?: string; // TV
53
- };
51
+ masque_lointain_non_homogene: MasqueLointainNonHomogene;
54
52
  }[];
55
53
  }
56
54
 
@@ -93,3 +91,7 @@ export interface BaieVitreeDoubleFenetreDI {
93
91
  uw: number;
94
92
  sw: number;
95
93
  }
94
+
95
+ export interface MasqueLointainNonHomogene {
96
+ tv_coef_masque_lointain_non_homogene_id?: string;
97
+ }
@@ -4,8 +4,7 @@ import { Ets } from './ets.model';
4
4
  import { InstallationChauffage } from './installation-chauffage.model';
5
5
  import { InstallationEcs } from './installation-ecs.model';
6
6
  import { Mur } from './mur.model';
7
- import { PlancherBas } from './plancher-bas.model';
8
- import { PlancherHaut } from './plancher-haut.model';
7
+ import { PlancherBas, PlancherHaut } from './plancher.model';
9
8
  import { PontThermique } from './pont-thermique.model';
10
9
  import { Porte } from './porte.model';
11
10
  import { ProductionElecEnr } from './production-elec-enr.model';
@@ -187,7 +186,12 @@ export interface DE {
187
186
  reference?: string;
188
187
  }
189
188
 
190
- enum TypeHabitation {
189
+ export enum TypeHabitation {
190
+ MAISON = 'MAISON',
191
+ APPARTEMENT = 'APPARTEMENT',
192
+ IMMEUBLE = 'IMMEUBLE'
193
+ }
194
+ export enum TypeDpe {
191
195
  MAISON = 'MAISON',
192
196
  APPARTEMENT = 'APPARTEMENT',
193
197
  IMMEUBLE = 'IMMEUBLE'
@@ -5,7 +5,12 @@ export interface PlancherBas {
5
5
  donnee_intermediaire?: PlancherBasDI;
6
6
  }
7
7
 
8
- export interface PlancherBasDE extends DE {
8
+ export interface PlancherHaut {
9
+ donnee_entree?: PlancherHautDE;
10
+ donnee_intermediaire?: PlancherHautDI;
11
+ }
12
+
13
+ export interface PlancherDE extends DE {
9
14
  reference_lnc?: string;
10
15
  tv_coef_reduction_deperdition_id?: string; // TV
11
16
  surface_aiu?: number;
@@ -13,26 +18,45 @@ export interface PlancherBasDE extends DE {
13
18
  enum_cfg_isolation_lnc_id?: string; // ENUM cfg_isolation_lnc
14
19
  enum_type_adjacence_id?: string; // ENUM type_adjacence
15
20
  surface_paroi_opaque?: number;
16
- upb0_saisi?: number;
17
- tv_upb0_id?: string; // TV
18
- enum_type_plancher_bas_id?: string; // ENUM type_plancher_bas
19
21
  enum_methode_saisie_u0_id?: string; // ENUM methode_saisie_u0
20
- upb_saisi?: number;
22
+
21
23
  enum_type_isolation_id?: string; // ENUM type_isolation
22
24
  enum_periode_isolation_id?: string; // ENUM periode_isolation
23
25
  resistance_isolation?: number;
24
26
  epaisseur_isolation?: number;
25
- tv_upb_id?: string; // TV
26
27
  enum_methode_saisie_u_id?: string; // ENUM methode_saisie_u
28
+ }
29
+
30
+ export interface PlancherDI {
31
+ b: number;
32
+ }
33
+
34
+ export interface PlancherBasDE extends PlancherDE {
35
+ upb0_saisi?: number;
36
+ tv_upb0_id?: string; // TV
37
+ enum_type_plancher_bas_id?: string; // ENUM type_plancher_bas
38
+ upb_saisi?: number;
39
+ tv_upb_id?: string; // TV
27
40
  calcul_ue: number;
28
41
  perimetre_ue?: number;
29
42
  surface_ue?: number;
30
43
  ue?: number;
31
44
  }
32
45
 
33
- export interface PlancherBasDI {
46
+ export interface PlancherBasDI extends PlancherDI {
34
47
  upb: number;
35
48
  upb0: number;
36
49
  upb_final: number;
50
+ }
51
+
52
+ export interface PlancherHautDE extends PlancherDE {
53
+ uph0_saisi?: number;
54
+ tv_uph0_id?: string; // TV
55
+ enum_type_plancher_haut_id?: string; // ENUM type_plancher_bas
56
+ uph_saisi?: number;
57
+ tv_uph_id?: string; // TV
58
+ }
59
+
60
+ export interface PlancherHautDI extends PlancherDI {
37
61
  b: number;
38
62
  }
@@ -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
+ }