@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/tvs.d.ts
ADDED
package/utils.js
ADDED
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
import enums from './enums.js';
|
|
2
|
+
import tvs from './tv.js';
|
|
3
|
+
import _ from 'lodash';
|
|
4
|
+
|
|
5
|
+
export let bug_for_bug_compat = false;
|
|
6
|
+
export function set_bug_for_bug_compat() {
|
|
7
|
+
bug_for_bug_compat = true;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export let tv_match_new_version = false;
|
|
11
|
+
export function set_tv_match_optimized_version() {
|
|
12
|
+
tv_match_new_version = true;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function unset_tv_match_optimized_version() {
|
|
16
|
+
tv_match_new_version = false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const Tbase = {
|
|
20
|
+
'inférieur à 400m': {
|
|
21
|
+
h1: -9.5,
|
|
22
|
+
h2: -6.5,
|
|
23
|
+
h3: -3.5
|
|
24
|
+
},
|
|
25
|
+
'400-800m': {
|
|
26
|
+
h1: -11.5,
|
|
27
|
+
h2: -8.5,
|
|
28
|
+
h3: -5.5
|
|
29
|
+
},
|
|
30
|
+
'supérieur à 800m': {
|
|
31
|
+
h1: -13.5,
|
|
32
|
+
h2: -10.5,
|
|
33
|
+
h3: -7.5
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const Njj = {
|
|
38
|
+
Janvier: 31,
|
|
39
|
+
Février: 28,
|
|
40
|
+
Mars: 31,
|
|
41
|
+
Avril: 30,
|
|
42
|
+
Mai: 31,
|
|
43
|
+
Juin: 30,
|
|
44
|
+
Juillet: 31,
|
|
45
|
+
Aout: 31,
|
|
46
|
+
Septembre: 30,
|
|
47
|
+
Octobre: 31,
|
|
48
|
+
Novembre: 30,
|
|
49
|
+
Décembre: 24
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// sum all Njj values
|
|
53
|
+
export const Njj_sum = Object.values(Njj).reduce((acc, val) => acc + val, 0);
|
|
54
|
+
|
|
55
|
+
export const mois_liste = [
|
|
56
|
+
'Janvier',
|
|
57
|
+
'Février',
|
|
58
|
+
'Mars',
|
|
59
|
+
'Avril',
|
|
60
|
+
'Mai',
|
|
61
|
+
'Juin',
|
|
62
|
+
'Juillet',
|
|
63
|
+
'Aout',
|
|
64
|
+
'Septembre',
|
|
65
|
+
'Octobre',
|
|
66
|
+
'Novembre',
|
|
67
|
+
'Décembre'
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
export function add_references(enveloppe) {
|
|
71
|
+
let i = 0;
|
|
72
|
+
for (const mur of enveloppe.mur_collection.mur || []) {
|
|
73
|
+
if (!mur.donnee_entree.reference) {
|
|
74
|
+
mur.donnee_entree.reference = `mur_${i}`;
|
|
75
|
+
}
|
|
76
|
+
i += 1;
|
|
77
|
+
}
|
|
78
|
+
i = 0;
|
|
79
|
+
for (const ph of enveloppe.plancher_haut_collection.plancher_haut || []) {
|
|
80
|
+
if (!ph.donnee_entree.reference) {
|
|
81
|
+
ph.donnee_entree.reference = `plancher_haut_${i}`;
|
|
82
|
+
}
|
|
83
|
+
i += 1;
|
|
84
|
+
}
|
|
85
|
+
i = 0;
|
|
86
|
+
for (const pb of enveloppe.plancher_bas_collection.plancher_bas || []) {
|
|
87
|
+
if (!pb.donnee_entree.reference) {
|
|
88
|
+
pb.donnee_entree.reference = `plancher_bas_${i}`;
|
|
89
|
+
}
|
|
90
|
+
i += 1;
|
|
91
|
+
}
|
|
92
|
+
i = 0;
|
|
93
|
+
for (const bv of enveloppe.baie_vitree_collection.baie_vitree || []) {
|
|
94
|
+
if (!bv.donnee_entree.reference) {
|
|
95
|
+
bv.donnee_entree.reference = `baie_vitree_${i}`;
|
|
96
|
+
}
|
|
97
|
+
i += 1;
|
|
98
|
+
}
|
|
99
|
+
i = 0;
|
|
100
|
+
for (const porte of enveloppe.porte_collection.porte || []) {
|
|
101
|
+
if (!porte.donnee_entree.reference) {
|
|
102
|
+
porte.donnee_entree.reference = `porte_${i}`;
|
|
103
|
+
}
|
|
104
|
+
i += 1;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function requestInputID(de, du, field, type) {
|
|
109
|
+
// enums
|
|
110
|
+
const enum_name = `enum_${field}_id`;
|
|
111
|
+
if (type) du[enum_name] = type;
|
|
112
|
+
else du[enum_name] = Object.keys(enums[field]);
|
|
113
|
+
return de[enum_name];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function requestInput(de, du, field, type) {
|
|
117
|
+
if (enums.hasOwnProperty(field)) {
|
|
118
|
+
// enums
|
|
119
|
+
const enum_name = `enum_${field}_id`;
|
|
120
|
+
if (type) du[enum_name] = type;
|
|
121
|
+
else du[enum_name] = Object.keys(enums[field]);
|
|
122
|
+
return enums[field][de[enum_name]];
|
|
123
|
+
} else {
|
|
124
|
+
// not enums
|
|
125
|
+
if (!type) {
|
|
126
|
+
console.error(`requestInput: type is not defined for ${field}`);
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
du[field] = type;
|
|
130
|
+
return de[field];
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function getKeyByValue(object, value) {
|
|
135
|
+
return Object.keys(object).find((key) => object[key] === value);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function tvColumnIDs(filePath, field) {
|
|
139
|
+
const list = tvs[filePath];
|
|
140
|
+
const enum_name = `enum_${field}_id`;
|
|
141
|
+
let ids = list.map((row) => row[enum_name]);
|
|
142
|
+
// remove undefineds
|
|
143
|
+
ids = ids.filter((id) => id);
|
|
144
|
+
// split each by | and get uniques
|
|
145
|
+
const unique_ids = [];
|
|
146
|
+
for (const id of ids) {
|
|
147
|
+
const values = id.split('|');
|
|
148
|
+
for (const value of values) {
|
|
149
|
+
if (!unique_ids.includes(value)) unique_ids.push(value);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// sort like numbers
|
|
153
|
+
return unique_ids;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function tvColumnLines(filePath, column, matcher) {
|
|
157
|
+
const list = tvs[filePath];
|
|
158
|
+
// find lines in list that match matcher
|
|
159
|
+
const lines = [];
|
|
160
|
+
for (const row of list) {
|
|
161
|
+
let match = true;
|
|
162
|
+
for (const key in matcher) {
|
|
163
|
+
if (tvMatch(row, key, matcher) === false) {
|
|
164
|
+
match = false;
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (match) lines.push(row[column]);
|
|
169
|
+
}
|
|
170
|
+
return lines;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function tvMatch(row, key, matcher) {
|
|
174
|
+
if (tv_match_new_version) {
|
|
175
|
+
return tvMatchOptimized(row, key, matcher);
|
|
176
|
+
}
|
|
177
|
+
if (!row.hasOwnProperty(key)) {
|
|
178
|
+
// for empty csv columns
|
|
179
|
+
// for q4pa_conv
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
let match_value = String(matcher[key]).toLowerCase();
|
|
184
|
+
|
|
185
|
+
// If the match value starts with ^, ends with $ and contains + then we escape the +
|
|
186
|
+
// Ex: ^iti+ite$ becomes ^iti\\+ite$
|
|
187
|
+
if (/^\^(.*)\+(.*)\$$/g.test(match_value)) {
|
|
188
|
+
match_value = match_value.replace('+', '\\+');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (key.startsWith('enum_')) match_value = `^${String(matcher[key]).toLowerCase()}$`;
|
|
192
|
+
|
|
193
|
+
if (row[key].includes('|')) {
|
|
194
|
+
const values = row[key].split('|');
|
|
195
|
+
if (!values.some((v) => v.toLowerCase().match(String(match_value)))) {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
} else if (Number.isInteger(matcher[key]) && ['≥', '≤'].some((char) => row[key].includes(char))) {
|
|
199
|
+
return eval(match_value + row[key].replace('≥', '>=').replace('≤', '<='));
|
|
200
|
+
} else if (!row[key].toLowerCase().match(String(match_value))) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function tvMatchOptimized(row, key, matcher) {
|
|
207
|
+
if (!row[key]) {
|
|
208
|
+
// for empty csv columns
|
|
209
|
+
// for q4pa_conv
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
let row_value = row[key].toLowerCase();
|
|
214
|
+
let match_value = String(matcher[key]).toLowerCase();
|
|
215
|
+
|
|
216
|
+
if (row_value === match_value) {
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (match_value.startsWith('^')) {
|
|
221
|
+
const match_value_no_regex = match_value.replace('^', '').replace('$', '');
|
|
222
|
+
if (row_value === match_value_no_regex) {
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (isNaN(matcher[key]) && row_value.includes(match_value)) {
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (row_value.includes('|')) {
|
|
232
|
+
return row_value.split('|').includes(match_value);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (Number.isInteger(matcher[key]) && ['≥', '≤'].some((char) => row[key].includes(char))) {
|
|
236
|
+
return eval(match_value + row[key].replace('≥', '>=').replace('≤', '<='));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return row_value.includes(match_value);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export function tv(filePath, matcher) {
|
|
243
|
+
const list = tvs[filePath];
|
|
244
|
+
let match_count = 0;
|
|
245
|
+
let max_match_count = 0;
|
|
246
|
+
let match = null;
|
|
247
|
+
|
|
248
|
+
for (const row of list) {
|
|
249
|
+
match_count = 0;
|
|
250
|
+
for (const key in matcher) {
|
|
251
|
+
if (tvMatch(row, key, matcher)) match_count += 1;
|
|
252
|
+
}
|
|
253
|
+
// if match_count is same as matcher, we are done
|
|
254
|
+
if (match_count === Object.keys(matcher).length) return row;
|
|
255
|
+
|
|
256
|
+
/* if (filePath === 'q4pa_conv') console.warn(match_count) */
|
|
257
|
+
if (match_count > max_match_count) {
|
|
258
|
+
max_match_count = match_count;
|
|
259
|
+
match = row;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/* if (filePath === 'pont_thermique') { */
|
|
263
|
+
/* console.warn(matcher) */
|
|
264
|
+
/* console.warn(match) */
|
|
265
|
+
/* } */
|
|
266
|
+
return match;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export function removeKeyFromJSON(jsonObj, keyToRemove, skipKeys) {
|
|
270
|
+
for (const key in jsonObj) {
|
|
271
|
+
if (skipKeys.includes(key)) continue;
|
|
272
|
+
if (jsonObj.hasOwnProperty(key)) {
|
|
273
|
+
if (key === keyToRemove) {
|
|
274
|
+
delete jsonObj[key];
|
|
275
|
+
} else if (typeof jsonObj[key] === 'object') {
|
|
276
|
+
removeKeyFromJSON(jsonObj[key], keyToRemove, skipKeys);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export function clean_dpe(dpe_in) {
|
|
283
|
+
// skip generateur_[ecs|chauffage] because some input data is contained in donnee_intermediaire (e.g. pn, qp0, ...)
|
|
284
|
+
removeKeyFromJSON(dpe_in, 'donnee_intermediaire', ['generateur_ecs', 'generateur_chauffage']);
|
|
285
|
+
_.set(dpe_in, 'logement.sortie', null);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export function sanitize_dpe(dpe_in) {
|
|
289
|
+
const collection_paths = [
|
|
290
|
+
'logement.enveloppe.plancher_bas_collection.plancher_bas',
|
|
291
|
+
'logement.enveloppe.plancher_haut_collection.plancher_haut',
|
|
292
|
+
'logement.ventilation_collection.ventilation',
|
|
293
|
+
'logement.climatisation_collection.climatisation',
|
|
294
|
+
'logement.enveloppe.baie_vitree_collection.baie_vitree',
|
|
295
|
+
'logement.enveloppe.porte_collection.porte',
|
|
296
|
+
'logement.enveloppe.pont_thermique_collection.pont_thermique'
|
|
297
|
+
];
|
|
298
|
+
for (const path of collection_paths) {
|
|
299
|
+
if (!_.has(dpe_in, path)) {
|
|
300
|
+
_.set(dpe_in, path, []);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Retrieve a number describing a thickness from the description
|
|
307
|
+
* @param description string in which to get the number
|
|
308
|
+
* @returns {number} if found, 0 otherwise
|
|
309
|
+
*/
|
|
310
|
+
export function getThicknessFromDescription(description) {
|
|
311
|
+
if (!description) {
|
|
312
|
+
return 0;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const matching = description.match(/(\d+) cm/);
|
|
316
|
+
return matching && matching.length > 1 ? Number.parseFloat(matching[1]) : 0;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Return true si la collection $type peut être vide
|
|
321
|
+
* - Pas de pont thermique ou pas de pont thermique de type enum_type_liaison_id
|
|
322
|
+
* - Déperdition pour $type === 0 (donne probablement sur un autre local chauffé)
|
|
323
|
+
* @param logement {Logement}
|
|
324
|
+
* @param type {string}
|
|
325
|
+
* @param enum_type_liaison_id {number}
|
|
326
|
+
* @returns {boolean}
|
|
327
|
+
*/
|
|
328
|
+
export function collectionCanBeEmpty(logement, type, enum_type_liaison_id) {
|
|
329
|
+
const pontsThermiques = logement.enveloppe.pont_thermique_collection.pont_thermique || [];
|
|
330
|
+
|
|
331
|
+
const pontsThermiquesWithLiaison = pontsThermiques.filter(
|
|
332
|
+
(pontThermique) => pontThermique.donnee_entree.enum_type_liaison_id === enum_type_liaison_id
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
const deperdition = logement.sortie.deperdition[`deperdition_${type}`];
|
|
336
|
+
|
|
337
|
+
return pontsThermiquesWithLiaison.length === 0 && deperdition === 0;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Retrieve a number describing a volume from the description
|
|
342
|
+
* @param description string in which to get the number
|
|
343
|
+
* @returns {number} if found, 0 otherwise
|
|
344
|
+
*/
|
|
345
|
+
export function getVolumeStockageFromDescription(description) {
|
|
346
|
+
if (!description) {
|
|
347
|
+
return 0;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const matching = description.split('contenance ballon ');
|
|
351
|
+
return matching && matching.length > 1 ? parseInt(matching[1], 10) : 0;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Remove space and accented characters
|
|
356
|
+
* @param reference {string}
|
|
357
|
+
* return {string}
|
|
358
|
+
*/
|
|
359
|
+
export function cleanReference(reference) {
|
|
360
|
+
if (reference) {
|
|
361
|
+
return reference
|
|
362
|
+
.toString()
|
|
363
|
+
.toLowerCase()
|
|
364
|
+
.normalize('NFD')
|
|
365
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
366
|
+
.replace(/\s+/g, '');
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return reference;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Return true if references are the same (without spaces and accented characters)
|
|
374
|
+
* @param reference1 {string}
|
|
375
|
+
* @param reference2 {string}
|
|
376
|
+
* return {boolean}
|
|
377
|
+
*/
|
|
378
|
+
export function compareReferences(reference1, reference2) {
|
|
379
|
+
return cleanReference(reference1) === cleanReference(reference2);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Vérification si le chauffage est par effet joule
|
|
384
|
+
* 3.2 Calcul des U des parois opaques
|
|
385
|
+
* On considère qu’un logement est chauffé par effet joule lorsque la chaleur est fournie par une résistance électrique.
|
|
386
|
+
* @param instal_ch {InstallationChauffageItem[]}
|
|
387
|
+
* @returns {string} 1 if effet joule, 0 otherwise
|
|
388
|
+
*/
|
|
389
|
+
export function isEffetJoule(instal_ch) {
|
|
390
|
+
const { surfaceEffetJoule, surfaceTotale } = instal_ch.reduce(
|
|
391
|
+
(acc, item) => {
|
|
392
|
+
const generatorIds = item.generateur_chauffage_collection.generateur_chauffage.reduce(
|
|
393
|
+
(acc, generateur) => {
|
|
394
|
+
return [...acc, generateur.donnee_entree.enum_type_generateur_ch_id];
|
|
395
|
+
},
|
|
396
|
+
[]
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* enum_type_generateur_ch_id
|
|
401
|
+
* 98 - convecteur électrique nfc, nf** et nf***
|
|
402
|
+
* 99 - panneau rayonnant électrique nfc, nf** et nf***
|
|
403
|
+
* 100 - radiateur électrique nfc, nf** et nf***
|
|
404
|
+
* 101 - autres émetteurs à effet joule
|
|
405
|
+
* 102 - plancher ou plafond rayonnant électrique avec régulation terminale
|
|
406
|
+
* 103 - plancher ou plafond rayonnant électrique sans régulation terminale
|
|
407
|
+
* 104 - radiateur électrique à accumulation
|
|
408
|
+
* 105 - convecteur bi-jonction
|
|
409
|
+
* 106 - chaudière électrique
|
|
410
|
+
* @type {boolean}
|
|
411
|
+
*/
|
|
412
|
+
const isEffetJoule =
|
|
413
|
+
generatorIds.filter((value) =>
|
|
414
|
+
['98', '99', '100', '101', '102', '103', '104', '105', '106'].includes(value)
|
|
415
|
+
).length > 0;
|
|
416
|
+
|
|
417
|
+
if (isEffetJoule) {
|
|
418
|
+
acc.surfaceEffetJoule += item.donnee_entree.surface_chauffee;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
acc.surfaceTotale += item.donnee_entree.surface_chauffee;
|
|
422
|
+
return acc;
|
|
423
|
+
},
|
|
424
|
+
{ surfaceEffetJoule: 0, surfaceTotale: 0 }
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
// Si la surface chauffée par une résistance électrique est majoritaire => effet_joule = 1
|
|
428
|
+
return surfaceEffetJoule / surfaceTotale >= 0.5 ? '1' : '0';
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Vérification si on trouve au moins une des chaînes de caractères substrings dans mainString
|
|
433
|
+
* @param mainString chaîne dans laquelle vérifier l'existence des substrings
|
|
434
|
+
* @param substrings chaîne à chercher dans la chaine principale
|
|
435
|
+
* @returns {boolean}
|
|
436
|
+
*/
|
|
437
|
+
export function containsAnySubstring(mainString, substrings) {
|
|
438
|
+
return substrings.some((substring) =>
|
|
439
|
+
mainString.toString().toLowerCase().includes(substring.toLowerCase())
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Conversion des expressions du type `70 < Pn <= 400` en (70 < Pn) && (Pn <= 400)
|
|
445
|
+
* @param expression {string}
|
|
446
|
+
* @returns {string}
|
|
447
|
+
*/
|
|
448
|
+
export function convertExpression(expression) {
|
|
449
|
+
if (!expression) {
|
|
450
|
+
return expression;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// Gère les expressions combinées comme `70 < Pn <= 400`
|
|
454
|
+
expression = expression.replace(
|
|
455
|
+
/(\d+)\s*<\s*([a-zA-Z_$][\w]*)\s*<=\s*(\d+)/g,
|
|
456
|
+
'($1 < $2) && ($2 <= $3)'
|
|
457
|
+
);
|
|
458
|
+
return expression;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Retourne les valeurs qui encadrent inputNumber dans ranges
|
|
463
|
+
* Si inputNumber est présent dans ranges, inputNumber est retourné comme borne 1 et borne 2
|
|
464
|
+
*
|
|
465
|
+
* @param inputNumber {float}
|
|
466
|
+
* @param ranges {number[]}
|
|
467
|
+
* @returns {*[]}
|
|
468
|
+
*/
|
|
469
|
+
export function getRange(inputNumber, ranges) {
|
|
470
|
+
const result = [];
|
|
471
|
+
|
|
472
|
+
ranges.sort();
|
|
473
|
+
|
|
474
|
+
if (inputNumber < ranges[0]) {
|
|
475
|
+
result.push(ranges[0]);
|
|
476
|
+
result.push(ranges[1]);
|
|
477
|
+
return result;
|
|
478
|
+
}
|
|
479
|
+
if (inputNumber > ranges[ranges.length - 1]) {
|
|
480
|
+
result.push(ranges[ranges.length - 2]);
|
|
481
|
+
result.push(ranges[ranges.length - 1]);
|
|
482
|
+
}
|
|
483
|
+
if (ranges.includes(inputNumber)) {
|
|
484
|
+
result.push(inputNumber);
|
|
485
|
+
result.push(inputNumber);
|
|
486
|
+
} else {
|
|
487
|
+
ranges.find((range, index) => {
|
|
488
|
+
if (inputNumber < range) {
|
|
489
|
+
if (index > 0) {
|
|
490
|
+
result.push(ranges[index - 1]);
|
|
491
|
+
} else {
|
|
492
|
+
result.push(ranges[index]);
|
|
493
|
+
}
|
|
494
|
+
result.push(ranges[index]);
|
|
495
|
+
return true;
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
return result;
|
|
500
|
+
}
|
package/utils.spec.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { convertExpression, getRange, getThicknessFromDescription } from './utils.js';
|
|
2
|
+
|
|
3
|
+
describe('Utils unit tests', () => {
|
|
4
|
+
it.each([
|
|
5
|
+
[0, null],
|
|
6
|
+
[0, undefined],
|
|
7
|
+
[0, ''],
|
|
8
|
+
[0, 'Mur en blocs de béton creux'],
|
|
9
|
+
[0, "Mur en blocs de béton creux d'épaisseur xxx cm non isolé"],
|
|
10
|
+
[4, "Mur en blocs de béton creux d'épaisseur 4 cm non isolé"],
|
|
11
|
+
[25, "Mur en blocs de béton creux d'''épaisseur ≥ 25 cm non isolé"]
|
|
12
|
+
])('should get thickness %s from description %s', (thickness, description) => {
|
|
13
|
+
expect(getThicknessFromDescription(description)).toBe(thickness);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it.each([
|
|
17
|
+
['70 < Pn <= 400', '(70 < Pn) && (Pn <= 400)'],
|
|
18
|
+
['70 < Pn', '70 < Pn'],
|
|
19
|
+
['Pn <= 400', 'Pn <= 400'],
|
|
20
|
+
['Pn == 400', 'Pn == 400'],
|
|
21
|
+
['Pn', 'Pn'],
|
|
22
|
+
[null, null],
|
|
23
|
+
[undefined, undefined]
|
|
24
|
+
])('should transform expression %s to %s', (expression, expected) => {
|
|
25
|
+
expect(convertExpression(expression)).toBe(expected);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it.each([
|
|
29
|
+
[[1, 1.2, 3.4, 5.6], 0.5, [1, 1.2]],
|
|
30
|
+
[[1, 1.2, 3.4, 5.6], 1, [1, 1]],
|
|
31
|
+
[[1, 1.2, 3.4, 5.6], 1.3, [1.2, 3.4]],
|
|
32
|
+
[[1, 1.2, 3.4, 5.6], 6.5, [3.4, 5.6]]
|
|
33
|
+
])('should for values %s and inputNumber %s return range %s', (ranges, inputNumber, expected) => {
|
|
34
|
+
expect(getRange(inputNumber, ranges)).toStrictEqual(expected);
|
|
35
|
+
});
|
|
36
|
+
});
|