@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,146 @@
1
+ import { ObjectUtil } from '../../util/infrastructure/object-util.js';
2
+
3
+ /**
4
+ * Download the `valeur_tables.xlsx` file from the official ademe repository and generates a new `enums.js` file
5
+ * Please see @link https://gitlab.com/observatoire-dpe/observatoire-dpe/-/tree/master
6
+ * - Convert the file into a json object
7
+ * - Extract, format data and then generate a new tv.js file
8
+ */
9
+ export class SynchronizeValeurTables {
10
+ /**
11
+ * @type {FileStore}
12
+ */
13
+ #fileStore;
14
+
15
+ /**
16
+ * @type {ApplicationConfig}
17
+ */
18
+ #appConfig;
19
+
20
+ /**
21
+ * @type {SynchronizeSolicitationsTables}
22
+ */
23
+ #synchronizeSolicitationsTables;
24
+
25
+ /**
26
+ * @type {SynchronizeDpeGesLimitValuesTables}
27
+ */
28
+ #synchronizeDpeGesLimitValuesTables;
29
+
30
+ /**
31
+ * @type {AddAdditionnalUeValuesTables}
32
+ */
33
+ #addAdditionnalUeValuesTables;
34
+
35
+ /**
36
+ * @type {SynchronizeC1Tables}
37
+ */
38
+ #synchronizeC1Tables;
39
+
40
+ /**
41
+ * @param fileStore {FileStore}
42
+ * @param appConfig {ApplicationConfig}
43
+ * @param synchronizeSolicitationsTables {SynchronizeSolicitationsTables}
44
+ * @param synchronizeDpeGesLimitValuesTables {SynchronizeDpeGesLimitValuesTables}
45
+ * @param addAdditionnalUeValuesTables {AddAdditionnalUeValuesTables}
46
+ * @param synchronizeC1Tables {SynchronizeC1Tables}
47
+ */
48
+ constructor(
49
+ fileStore,
50
+ appConfig,
51
+ synchronizeSolicitationsTables,
52
+ synchronizeDpeGesLimitValuesTables,
53
+ addAdditionnalUeValuesTables,
54
+ synchronizeC1Tables
55
+ ) {
56
+ this.#fileStore = fileStore;
57
+ this.#appConfig = appConfig;
58
+ this.#synchronizeSolicitationsTables = synchronizeSolicitationsTables;
59
+ this.#synchronizeDpeGesLimitValuesTables = synchronizeDpeGesLimitValuesTables;
60
+ this.#addAdditionnalUeValuesTables = addAdditionnalUeValuesTables;
61
+ this.#synchronizeC1Tables = synchronizeC1Tables;
62
+ }
63
+
64
+ /**
65
+ * @return {Promise<void>}
66
+ */
67
+ execute() {
68
+ return this.#fileStore
69
+ .downloadXlsxFileAndConvertToJson(this.#appConfig.ademeValeurTablesFileUrl)
70
+ .then(
71
+ /** @param excelSheets {any} xlsx content file grouped by tab */
72
+ (excelSheets) => {
73
+ // transform Excel sheets to match actual `tv.js` file
74
+ excelSheets = ObjectUtil.deepObjectTransform(
75
+ excelSheets,
76
+ (key) => {
77
+ if (key.includes('ditribution')) {
78
+ // Fix typo in xlsx file
79
+ return key.replace('ditribution', 'distribution');
80
+ }
81
+ return key;
82
+ },
83
+ (value, key) => {
84
+ if (typeof value === 'string') {
85
+ // Remove 'kW' to be compatible with the legacy `tv.js` file
86
+ if (value.endsWith('kW')) {
87
+ return value.replace(/kW/g, '').replace(/\s/g, '');
88
+ }
89
+ }
90
+
91
+ // By default, the Excel parsing ignore property with 0 value,
92
+ // so we force it to be compatible with the legacy `tv.js` file
93
+ if (key === 'q4pa_conv' && Array.isArray(value)) {
94
+ return value.map((v) => {
95
+ if (!v.isolation_surfaces) {
96
+ v.isolation_surfaces = '0';
97
+ }
98
+ return v;
99
+ });
100
+ }
101
+
102
+ // Reformat all number with only one decimal to be compatible with the legacy `tv.js` file
103
+ if (!isNaN(Number(value)) && value.endsWith('0') && value.includes('.')) {
104
+ return `${Math.round(value * 10) / 10}`;
105
+ }
106
+
107
+ return value;
108
+ }
109
+ );
110
+
111
+ return excelSheets;
112
+ }
113
+ )
114
+ .then((valeurTablesValues) => {
115
+ return Promise.all([
116
+ this.#synchronizeSolicitationsTables.execute(),
117
+ this.#synchronizeDpeGesLimitValuesTables.execute(),
118
+ this.#synchronizeC1Tables.execute()
119
+ ]).then((tablesValues) => {
120
+ const solicitationsTablesValues = tablesValues[0];
121
+ const dpeGesLimitTablesValues = tablesValues[1];
122
+ const c1TablesValues = tablesValues[2];
123
+
124
+ // Merge content from "valeur_tables.xlsx" file with "18.2_sollicitations_ext.ods" file
125
+ let tableValues = Object.assign(
126
+ {},
127
+ valeurTablesValues,
128
+ solicitationsTablesValues,
129
+ dpeGesLimitTablesValues,
130
+ c1TablesValues
131
+ );
132
+
133
+ // Ajout de valeurs supplémentaires pour le calcul du facteur Ue pour les déperditions plancher_bas
134
+ if (tableValues['ue']) {
135
+ tableValues = this.#addAdditionnalUeValuesTables.execute(tableValues);
136
+ }
137
+
138
+ // Overwrite the tv.js file in filesystem
139
+ return this.#fileStore.writeFileToLocalSystem(
140
+ `${this.#appConfig.assetsOutputFolder}/tv.js`,
141
+ `/** @type {TableValeur} **/\nexport const tvs = ${JSON.stringify(tableValues, null, 2)};\n export default tvs;`
142
+ );
143
+ });
144
+ });
145
+ }
146
+ }
@@ -0,0 +1,54 @@
1
+ import { SynchronizeValeurTables } from './synchronize-valeur-tables.js';
2
+ import { FileStore } from '../../file/infrastructure/adapter/file.store.js';
3
+ import { ApplicationConfig } from '../../conf/infrastructure/application.config.js';
4
+ import { SynchronizeC1Tables } from './synchronize-c1-tables.js';
5
+ import { SynchronizeSolicitationsTables } from './synchronize-solicitations-tables.js';
6
+ import { ValeurTablesFixture } from '../../../../test/fixtures/core/assets/valeur-tables.fixture.js';
7
+ import { jest } from '@jest/globals';
8
+ import { SynchronizeDpeGesLimitValuesTables } from './synchronize-dpe-ges-limit-values-tables.js';
9
+ import { AddAdditionnalUeValuesTables } from './add-additionnal-ue-values-tables.js';
10
+
11
+ describe('SynchronizeValeurTables unit tests', () => {
12
+ it('should download, parse and convert valeur_tables.xlsx file', () => {
13
+ const fileStore = new FileStore();
14
+ const appConfig = new ApplicationConfig();
15
+ const synchronizeC1Tables = new SynchronizeC1Tables(fileStore, appConfig);
16
+ const synchronizeSolicitationTables = new SynchronizeSolicitationsTables(fileStore, appConfig);
17
+ const synchronizeDpeGesLimitValuesTables = new SynchronizeDpeGesLimitValuesTables(
18
+ fileStore,
19
+ appConfig
20
+ );
21
+ const addAdditionnalUeValuesTables = new AddAdditionnalUeValuesTables(fileStore, appConfig);
22
+ const synchronizeValeurTables = new SynchronizeValeurTables(
23
+ fileStore,
24
+ appConfig,
25
+ synchronizeSolicitationTables,
26
+ synchronizeDpeGesLimitValuesTables,
27
+ addAdditionnalUeValuesTables,
28
+ synchronizeC1Tables
29
+ );
30
+
31
+ const valeurTablesData = ValeurTablesFixture.aValeurTableExample();
32
+ jest
33
+ .spyOn(ApplicationConfig.prototype, 'ademeValeurTablesFileUrl', 'get')
34
+ .mockReturnValue('http://localhost/file.xlsx');
35
+ jest
36
+ .spyOn(ApplicationConfig.prototype, 'assetsOutputFolder', 'get')
37
+ .mockReturnValue('src/assets');
38
+
39
+ jest.spyOn(fileStore, 'downloadXlsxFileAndConvertToJson').mockResolvedValue(valeurTablesData);
40
+ jest.spyOn(fileStore, 'writeFileToLocalSystem').mockResolvedValue(null);
41
+ jest.spyOn(synchronizeC1Tables, 'execute').mockResolvedValue({});
42
+ jest.spyOn(synchronizeSolicitationTables, 'execute').mockResolvedValue({});
43
+ jest.spyOn(synchronizeDpeGesLimitValuesTables, 'execute').mockResolvedValue({});
44
+ jest.spyOn(addAdditionnalUeValuesTables, 'execute').mockResolvedValue({});
45
+
46
+ return synchronizeValeurTables.execute().then(() => {
47
+ expect(fileStore.downloadXlsxFileAndConvertToJson).toHaveBeenCalled();
48
+ expect(fileStore.writeFileToLocalSystem).toHaveBeenCalledWith(
49
+ 'src/assets/tv.js',
50
+ expect.any(String)
51
+ );
52
+ });
53
+ });
54
+ });
@@ -0,0 +1,33 @@
1
+ export class ApplicationConfig {
2
+ get ademeRepositoryVersion() {
3
+ return 'dpe-mdd-v8.2.1-controle-1.21.8-audit-mdd-v4.4.0-controle-1.9.9-ajout-nom-organisme-qualification';
4
+ }
5
+
6
+ get ademeRepositoryUrl() {
7
+ return 'https://gitlab.com/observatoire-dpe/observatoire-dpe';
8
+ }
9
+
10
+ get ademeEnumTablesFileUrl() {
11
+ return `${this.ademeRepositoryUrl}/-/raw/${this.ademeRepositoryVersion}/modele_donnee/enum_tables.xlsx?ref_type=tags&inline=false`;
12
+ }
13
+
14
+ get ademeValeurTablesFileUrl() {
15
+ return `${this.ademeRepositoryUrl}/-/raw/${this.ademeRepositoryVersion}/modele_donnee/valeur_tables.xlsx?ref_type=tags&inline=false`;
16
+ }
17
+
18
+ get solicitationsExtFilePath() {
19
+ return 'src/tv/18.2_sollicitations_ext.ods';
20
+ }
21
+
22
+ get c1FilePath() {
23
+ return 'src/tv/18.5_c1.ods';
24
+ }
25
+
26
+ get dpeGesLimitValuesFilePath() {
27
+ return 'src/tv/dpe_ges_limit_values.ods';
28
+ }
29
+
30
+ get assetsOutputFolder() {
31
+ return 'src';
32
+ }
33
+ }
@@ -0,0 +1,75 @@
1
+ import { writeFile, readFile } from 'fs';
2
+ import * as XLSX from 'xlsx';
3
+
4
+ export class FileStore {
5
+ /**
6
+ * Download a xlsx file and convert it to json
7
+ *
8
+ * @param url {string} url of the xlsx file to download and convert
9
+ *
10
+ * @return {Promise<any>}
11
+ */
12
+ async downloadXlsxFileAndConvertToJson(url) {
13
+ return fetch(url)
14
+ .then((res) => res.arrayBuffer())
15
+ .then((buffer) =>
16
+ this.#excelWorkBookToJson(XLSX.read(buffer, { type: 'string', raw: false }))
17
+ );
18
+ }
19
+
20
+ readLocalOdsFileAndConvertToJson(filePath) {
21
+ return new Promise((resolve, reject) => {
22
+ readFile(filePath, (err, data) => {
23
+ if (err) {
24
+ reject(err);
25
+ } else {
26
+ resolve(data);
27
+ }
28
+ });
29
+ }).then((fileContent) =>
30
+ this.#excelWorkBookToJson(XLSX.read(fileContent, { type: 'buffer', raw: false }))
31
+ );
32
+ }
33
+
34
+ /**
35
+ * @param filePath {string}
36
+ * @param content {string}
37
+ * @return {Promise<void>}
38
+ */
39
+ writeFileToLocalSystem(filePath, content) {
40
+ return new Promise((resolve, reject) => {
41
+ writeFile(filePath, content, { encoding: 'utf-8' }, (err) => {
42
+ if (err) {
43
+ reject(err);
44
+ } else {
45
+ resolve();
46
+ }
47
+ });
48
+ });
49
+ }
50
+
51
+ #excelWorkBookToJson(workBook) {
52
+ const jsonOutput = {};
53
+ workBook.SheetNames.forEach((sheetName) => {
54
+ /**
55
+ * @type {import('xlsx').WorkSheet}
56
+ */
57
+ const sheet = workBook.Sheets[sheetName];
58
+ if (sheet['!merges']) {
59
+ sheet['!merges'].forEach((merge) => {
60
+ const columnStart = XLSX.utils.encode_col(merge.s.c);
61
+ const rowStart = XLSX.utils.encode_row(merge.s.r);
62
+
63
+ const nbMergedRows = merge.e.r - merge.s.r;
64
+ const firstCell = sheet[`${columnStart}${rowStart}`];
65
+ for (let i = 0; i < nbMergedRows; i++) {
66
+ const newRowStart = XLSX.utils.encode_row(merge.s.r + i + 1);
67
+ sheet[`${columnStart}${newRowStart}`] = firstCell;
68
+ }
69
+ });
70
+ }
71
+ jsonOutput[sheetName] = XLSX.utils.sheet_to_json(sheet, { raw: false });
72
+ });
73
+ return jsonOutput;
74
+ }
75
+ }
@@ -0,0 +1,30 @@
1
+ import { FileStore } from './file.store.js';
2
+
3
+ global.fetch = jest.fn(() =>
4
+ Promise.resolve({
5
+ arrayBuffer: () => Promise.resolve(new ArrayBuffer(1))
6
+ })
7
+ );
8
+
9
+ describe('FileStore unit tests', () => {
10
+ it('should be able to download and parse an xlsx file', () => {
11
+ const fileStore = new FileStore();
12
+
13
+ return fileStore.downloadXlsxFileAndConvertToJson('http://localhost:8080').then((output) => {
14
+ expect(output).toEqual({ Sheet1: [] });
15
+ });
16
+ });
17
+
18
+ it('should be able to read and parse local ods file', () => {
19
+ const fileStore = new FileStore();
20
+
21
+ return fileStore.readLocalOdsFileAndConvertToJson('file.ods').then((output) => {
22
+ expect(output).toEqual({ Sheet1: [] });
23
+ });
24
+ });
25
+
26
+ it('should write file to local system', () => {
27
+ const fileStore = new FileStore();
28
+ return fileStore.writeFileToLocalSystem('src/output.js', 'filecontent');
29
+ });
30
+ });
@@ -0,0 +1,69 @@
1
+ export const UPB_ADDITIONAL_VALUES = [
2
+ {
3
+ type_adjacence_plancher: 'terre plein bâtiment construit avant 2001',
4
+ enum_periode_construction_id: '1|2|3|4|5|6',
5
+ periode_construction: '<2001',
6
+ type_adjacence: 'terre-plein',
7
+ enum_type_adjacence_id: '5',
8
+ values: [
9
+ { '2s_p': '1', upb: '3.4', ue: '0.98' },
10
+ { '2s_p': '1', upb: '1.5', ue: '0.66' },
11
+ { '2s_p': '1', upb: '0.85', ue: '0.49' },
12
+ { '2s_p': '1', upb: '0.59', ue: '0.39' },
13
+ { '2s_p': '1', upb: '0.46', ue: '0.34' },
14
+ { '2s_p': '2', upb: '3.4', ue: '0.88' },
15
+ { '2s_p': '2', upb: '1.5', ue: '0.61' },
16
+ { '2s_p': '2', upb: '0.85', ue: '0.46' },
17
+ { '2s_p': '2', upb: '0.59', ue: '0.37' },
18
+ { '2s_p': '2', upb: '0.46', ue: '0.32' }
19
+ ]
20
+ },
21
+ {
22
+ type_adjacence_plancher: 'terre plein bâtiment construit à partir de 2001',
23
+ enum_type_adjacence_id: '5',
24
+ type_adjacence: 'terre-plein',
25
+ enum_periode_construction_id: '7|8|9|10',
26
+ periode_construction: '>=2001',
27
+ values: [
28
+ { '2s_p': '1', upb: '3.4', ue: '0.8' },
29
+ { '2s_p': '1', upb: '1.5', ue: '0.7' },
30
+ { '2s_p': '1', upb: '0.85', ue: '0.57' },
31
+ { '2s_p': '1', upb: '0.6', ue: '0.45' },
32
+ { '2s_p': '1', upb: '0.46', ue: '0.37' },
33
+ { '2s_p': '1', upb: '0.37', ue: '0.32' },
34
+ { '2s_p': '1', upb: '0.31', ue: '0.29' },
35
+ { '2s_p': '2', upb: '3.4', ue: '0.75' },
36
+ { '2s_p': '2', upb: '1.5', ue: '0.65' },
37
+ { '2s_p': '2', upb: '0.85', ue: '0.53' },
38
+ { '2s_p': '2', upb: '0.6', ue: '0.42' },
39
+ { '2s_p': '2', upb: '0.46', ue: '0.35' },
40
+ { '2s_p': '2', upb: '0.37', ue: '0.3' },
41
+ { '2s_p': '2', upb: '0.31', ue: '0.27' }
42
+ ]
43
+ },
44
+ {
45
+ type_adjacence_plancher: 'plancher sur vide sanitaire ou sous-sol non chauffé',
46
+ enum_type_adjacence_id: '3|6',
47
+ type_adjacence: 'vide sanitaire ou sous-sol non chauffé',
48
+ enum_periode_construction_id: '1|2|3|4|5|6|7|8|9|10',
49
+ periode_construction: 'toutes',
50
+ values: [
51
+ { '2s_p': '1', upb: '3.33', ue: '0.49' },
52
+ { '2s_p': '1', upb: '1.43', ue: '0.46' },
53
+ { '2s_p': '1', upb: '0.83', ue: '0.43' },
54
+ { '2s_p': '1', upb: '0.45', ue: '0.4' },
55
+ { '2s_p': '1', upb: '0.41', ue: '0.37' },
56
+ { '2s_p': '1', upb: '0.37', ue: '0.32' },
57
+ { '2s_p': '1', upb: '0.34', ue: '0.3' },
58
+ { '2s_p': '1', upb: '0.31', ue: '0.28' },
59
+ { '2s_p': '2', upb: '3.33', ue: '0.47' },
60
+ { '2s_p': '2', upb: '1.43', ue: '0.44' },
61
+ { '2s_p': '2', upb: '0.83', ue: '0.41' },
62
+ { '2s_p': '2', upb: '0.45', ue: '0.38' },
63
+ { '2s_p': '2', upb: '0.41', ue: '0.35' },
64
+ { '2s_p': '2', upb: '0.37', ue: '0.31' },
65
+ { '2s_p': '2', upb: '0.34', ue: '0.29' },
66
+ { '2s_p': '2', upb: '0.31', ue: '0.27' }
67
+ ]
68
+ }
69
+ ];
@@ -0,0 +1,40 @@
1
+ import tvs from '../../../tv.js';
2
+
3
+ const TV_RENDEMENT_DISTRIBUTION_CH_PROPERTY = 'rendement_distribution_ch';
4
+
5
+ /**
6
+ * @type {RendementDistributionCh[]}
7
+ */
8
+ const RENDEMENT_DISTRIBUTION_CH_LIST = tvs[TV_RENDEMENT_DISTRIBUTION_CH_PROPERTY];
9
+
10
+ export class TvsStore {
11
+ /**
12
+ * @param enumTypeEmissionDistributionId {string}
13
+ * @param reseauDistributionIsole {number?}
14
+ * @return {RendementDistributionCh}
15
+ */
16
+ getRendementDistributionCh(enumTypeEmissionDistributionId, reseauDistributionIsole) {
17
+ return RENDEMENT_DISTRIBUTION_CH_LIST.find((rendement) => {
18
+ const hasTypeEmissionId = rendement.enum_type_emission_distribution_id
19
+ .split('|')
20
+ .includes(enumTypeEmissionDistributionId);
21
+
22
+ if (hasTypeEmissionId && reseauDistributionIsole !== undefined) {
23
+ return rendement.reseau_distribution_isole === reseauDistributionIsole.toString();
24
+ }
25
+
26
+ return hasTypeEmissionId;
27
+ });
28
+ }
29
+
30
+ /**
31
+ * @param tv_rendement_distribution_ch_id {number}
32
+ * @return {RendementDistributionCh}
33
+ */
34
+ getRendementDistributionChById(tv_rendement_distribution_ch_id) {
35
+ return RENDEMENT_DISTRIBUTION_CH_LIST.find(
36
+ (rendement) =>
37
+ rendement.tv_rendement_distribution_ch_id === tv_rendement_distribution_ch_id.toString()
38
+ );
39
+ }
40
+ }
@@ -0,0 +1,34 @@
1
+ import { TvsStore } from './tvs.store.js';
2
+
3
+ describe('TvsStore unit tests', () => {
4
+ it('should get rendement distribution ch id', () => {
5
+ const store = new TvsStore();
6
+
7
+ expect(store.getRendementDistributionCh('41', '0')).toMatchObject({
8
+ tv_rendement_distribution_ch_id: '2'
9
+ });
10
+
11
+ expect(store.getRendementDistributionCh('41', 0)).toMatchObject({
12
+ tv_rendement_distribution_ch_id: '2'
13
+ });
14
+
15
+ expect(store.getRendementDistributionCh('41')).toMatchObject({
16
+ tv_rendement_distribution_ch_id: '1'
17
+ });
18
+
19
+ expect(store.getRendementDistributionCh('15', 1)).toMatchObject({
20
+ tv_rendement_distribution_ch_id: '8'
21
+ });
22
+ expect(store.getRendementDistributionCh('42')).toMatchObject({
23
+ tv_rendement_distribution_ch_id: '12'
24
+ });
25
+ });
26
+
27
+ it('should get rendement distribution ch by id', () => {
28
+ const store = new TvsStore();
29
+
30
+ expect(store.getRendementDistributionChById('10')).toMatchObject({
31
+ tv_rendement_distribution_ch_id: '10'
32
+ });
33
+ });
34
+ });
@@ -0,0 +1,23 @@
1
+ export class ObjectUtil {
2
+ /**
3
+ * Apply transformation on object properties or nested properties
4
+ * @param obj {any}
5
+ * @param keyTransformFn {(key: string) => string}
6
+ * @param valueTransformFn {(value: any, key?: string) => string}
7
+ */
8
+ static deepObjectTransform(obj, keyTransformFn, valueTransformFn) {
9
+ return Array.isArray(obj)
10
+ ? obj.map((val) => ObjectUtil.deepObjectTransform(val, keyTransformFn, valueTransformFn))
11
+ : typeof obj === 'object'
12
+ ? Object.keys(obj).reduce((acc, current) => {
13
+ const key = keyTransformFn(current);
14
+ const val = valueTransformFn(obj[current], key);
15
+ acc[key] =
16
+ val !== null && typeof val === 'object'
17
+ ? ObjectUtil.deepObjectTransform(val, keyTransformFn, valueTransformFn)
18
+ : val;
19
+ return acc;
20
+ }, {})
21
+ : obj;
22
+ }
23
+ }
@@ -0,0 +1,25 @@
1
+ import { ObjectUtil } from './object-util.js';
2
+
3
+ describe('ObjectUtil unit tests', () => {
4
+ it('should be able to deeply transform an object keys and values', () => {
5
+ expect(
6
+ ObjectUtil.deepObjectTransform(
7
+ { key1: 'Value1', key2: 'Value2', nested: [{ key3: 'Value3' }] },
8
+ (key) => {
9
+ return key.toUpperCase();
10
+ },
11
+ (value) => {
12
+ return typeof value === 'string' ? value.toLowerCase() : value;
13
+ }
14
+ )
15
+ ).toEqual({
16
+ KEY1: 'value1',
17
+ KEY2: 'value2',
18
+ NESTED: [
19
+ {
20
+ KEY3: 'value3'
21
+ }
22
+ ]
23
+ });
24
+ });
25
+ });