@open3cl/engine 1.0.10 → 1.0.11

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 (31) hide show
  1. package/features/dpe/infrastructure/ecs/ecsTv.store.js +22 -0
  2. package/features/dpe/infrastructure/ecs/ecsTv.store.spec.js +33 -0
  3. package/features/dpe/infrastructure/{baieVitreeTv.store.js → enveloppe/baieVitreeTv.store.js} +5 -5
  4. package/features/dpe/infrastructure/{pontThermiqueTv.store.js → enveloppe/pontThermiqueTv.store.js} +3 -3
  5. package/features/dpe/infrastructure/froid/frTv.store.js +36 -0
  6. package/features/dpe/infrastructure/froid/frTv.store.spec.js +52 -0
  7. package/features/engine/domain/apport_et_besoin/apport-et-besoin.service.js +74 -0
  8. package/features/engine/domain/apport_et_besoin/apport-et-besoin.service.spec.js +85 -0
  9. package/features/engine/domain/apport_et_besoin/apport_gratuit/apport-gratuit.service.js +134 -0
  10. package/features/engine/domain/apport_et_besoin/apport_gratuit/apport-gratuit.service.spec.js +167 -0
  11. package/features/engine/domain/apport_et_besoin/ecs/besoin-ecs.service.js +58 -0
  12. package/features/engine/domain/apport_et_besoin/ecs/besoin-ecs.service.spec.js +67 -0
  13. package/features/engine/domain/apport_et_besoin/froid/besoin-froid.service.js +131 -0
  14. package/features/engine/domain/apport_et_besoin/froid/besoin-froid.service.spec.js +229 -0
  15. package/features/engine/domain/{logement → apport_et_besoin}/surface-sud-equivalente.service.js +9 -10
  16. package/features/engine/domain/{logement → apport_et_besoin}/surface-sud-equivalente.service.spec.js +63 -43
  17. package/features/engine/domain/contexte.builder.js +48 -5
  18. package/features/engine/domain/contexte.builder.spec.js +59 -3
  19. package/features/engine/domain/engine.service.js +10 -13
  20. package/features/engine/domain/enveloppe/baie_vitree/deperdition-baie-vitree.service.js +1 -1
  21. package/features/engine/domain/enveloppe/baie_vitree/deperdition-baie-vitree.service.spec.js +1 -1
  22. package/features/engine/domain/enveloppe/espace_tampon/espace-tampon.service.js +1 -1
  23. package/features/engine/domain/enveloppe/espace_tampon/espace-tampon.service.spec.js +1 -1
  24. package/features/engine/domain/enveloppe/pont_thermique/deperdition-pont-thermique.service.js +1 -1
  25. package/features/engine/domain/enveloppe/pont_thermique/deperdition-pont-thermique.service.spec.js +1 -1
  26. package/features/engine/domain/logement/nadeq.service.js +8 -7
  27. package/features/engine/domain/logement/nadeq.service.spec.js +6 -16
  28. package/features/engine/domain/models/contexte.model.ts +9 -0
  29. package/package.json +1 -1
  30. /package/features/dpe/infrastructure/{baieVitreeTv.store.spec.js → enveloppe/baieVitreeTv.store.spec.js} +0 -0
  31. /package/features/dpe/infrastructure/{pontThermiqueTv.store.spec.js → enveloppe/pontThermiqueTv.store.spec.js} +0 -0
@@ -1,11 +1,23 @@
1
1
  import { TypeDpe, TypeHabitation } from '../../dpe/domain/models/type-habitation.model.js';
2
2
  import enums from '../../../enums.js';
3
+ import { NadeqService } from './logement/nadeq.service.js';
4
+ import { inject } from 'dioma';
3
5
 
4
6
  /**
5
7
  * Génère un contexte du logement à étudier avec des données persistées durant l'analyse
6
8
  */
7
9
  export class ContexteBuilder {
8
- constructor() {}
10
+ /**
11
+ * @type {NadeqService}
12
+ */
13
+ #nadeqService;
14
+
15
+ /**
16
+ * @param nadeqService {NadeqService}
17
+ */
18
+ constructor(nadeqService = inject(NadeqService)) {
19
+ this.#nadeqService = nadeqService;
20
+ }
9
21
 
10
22
  /**
11
23
  * @param dpe {Dpe}
@@ -14,22 +26,40 @@ export class ContexteBuilder {
14
26
  fromDpe(dpe) {
15
27
  const caracteristiqueGenerale = dpe.logement.caracteristique_generale;
16
28
 
29
+ const typeDpe = this.#getTypeDpe(caracteristiqueGenerale);
30
+ const surfaceHabitable = this.#getSurfaceHabitable(caracteristiqueGenerale);
31
+ const inertieId = parseInt(dpe.logement.enveloppe?.inertie?.enum_classe_inertie_id);
32
+
17
33
  return {
18
34
  zoneClimatique: this.#zoneClimatique(dpe),
35
+ altitude: this.#altitude(dpe),
19
36
  typeHabitation: this.#getTypeHabitation(caracteristiqueGenerale),
20
- typeDpe: this.#getTypeDpe(caracteristiqueGenerale),
37
+ typeDpe: typeDpe,
21
38
  enumPeriodeConstructionId: caracteristiqueGenerale.enum_periode_construction_id?.toString(),
22
39
  effetJoule: this.#hasEffetJoule(dpe),
23
- surfaceHabitable: this.#getSurfaceHabitable(caracteristiqueGenerale),
40
+ surfaceHabitable: surfaceHabitable,
24
41
  hauteurSousPlafond: caracteristiqueGenerale.hsp,
25
- nombreAppartement: caracteristiqueGenerale.nombre_appartement
42
+ nombreAppartement: caracteristiqueGenerale.nombre_appartement,
43
+ nadeq: this.#nadeqService.execute(
44
+ typeDpe,
45
+ surfaceHabitable,
46
+ caracteristiqueGenerale.nombre_appartement
47
+ ),
48
+ inertie: {
49
+ id: inertieId,
50
+ ilpa:
51
+ parseInt(dpe.logement.meteo?.batiment_materiaux_anciens) === 1 &&
52
+ [1, 2].includes(inertieId)
53
+ ? 1
54
+ : 0
55
+ }
26
56
  };
27
57
  }
28
58
 
29
59
  /**
30
60
  * La zone climatique à partir du type de DPE
31
61
  * @param dpe {Dpe}
32
- * @return {{id: number, value: string}}
62
+ * @return {{id: string, value: string}}
33
63
  */
34
64
  #zoneClimatique(dpe) {
35
65
  const zoneClimatiqueId = parseInt(dpe.logement.meteo?.enum_zone_climatique_id);
@@ -39,6 +69,19 @@ export class ContexteBuilder {
39
69
  };
40
70
  }
41
71
 
72
+ /**
73
+ * La classe d'altitude à partir du type de DPE
74
+ * @param dpe {Dpe}
75
+ * @return {{id: string, value: string}}
76
+ */
77
+ #altitude(dpe) {
78
+ const altitudeId = parseInt(dpe.logement.meteo?.enum_classe_altitude_id);
79
+ return {
80
+ id: altitudeId.toString(),
81
+ value: enums.classe_altitude[altitudeId]
82
+ };
83
+ }
84
+
42
85
  /**
43
86
  * Si un générateur de chauffage par résistance électrique existe, alors effet joule vaut vrai
44
87
  * @param dpe {Dpe}
@@ -1,13 +1,18 @@
1
1
  import { ContexteBuilder } from './contexte.builder.js';
2
- import { beforeEach, describe, expect, test } from 'vitest';
2
+ import { beforeEach, describe, expect, test, vi } from 'vitest';
3
3
  import { TypeDpe, TypeHabitation } from '../../dpe/domain/models/type-habitation.model.js';
4
+ import { NadeqService } from './logement/nadeq.service.js';
5
+
6
+ /** @type {NadeqService} **/
7
+ let nadeqService;
4
8
 
5
9
  /** @type {ContexteBuilder} **/
6
10
  let contexteBuilder;
7
11
 
8
12
  describe('Generateur du contexte du calcul', () => {
9
13
  beforeEach(() => {
10
- contexteBuilder = new ContexteBuilder();
14
+ nadeqService = new NadeqService();
15
+ contexteBuilder = new ContexteBuilder(nadeqService);
11
16
  });
12
17
 
13
18
  test('Contexte avec effet joule', () => {
@@ -79,11 +84,26 @@ describe('Generateur du contexte du calcul', () => {
79
84
  });
80
85
  });
81
86
 
87
+ test('Contexte avec calcul du nadeq', () => {
88
+ vi.spyOn(nadeqService, 'execute').mockReturnValue(1.58);
89
+ const dpe = {
90
+ logement: {
91
+ caracteristique_generale: {},
92
+ installation_chauffage_collection: {}
93
+ }
94
+ };
95
+
96
+ expect(contexteBuilder.fromDpe(dpe)).toMatchObject({
97
+ nadeq: 1.58
98
+ });
99
+ });
100
+
82
101
  test('Récupération des informations du logement concerné par le DPE', () => {
83
102
  let dpe = {
84
103
  logement: {
85
104
  meteo: {
86
- enum_zone_climatique_id: 1
105
+ enum_zone_climatique_id: 1,
106
+ enum_classe_altitude_id: 2
87
107
  },
88
108
  caracteristique_generale: {
89
109
  enum_periode_construction_id: 4,
@@ -106,11 +126,16 @@ describe('Generateur du contexte du calcul', () => {
106
126
  zoneClimatique: {
107
127
  id: '1',
108
128
  value: 'h1a'
129
+ },
130
+ altitude: {
131
+ id: '2',
132
+ value: '400-800m'
109
133
  }
110
134
  });
111
135
 
112
136
  dpe.logement.caracteristique_generale.enum_methode_application_dpe_log_id = '5';
113
137
  dpe.logement.meteo.enum_zone_climatique_id = '4';
138
+ dpe.logement.meteo.enum_classe_altitude_id = '3';
114
139
  expect(contexteBuilder.fromDpe(dpe)).toMatchObject({
115
140
  surfaceHabitable: dpe.logement.caracteristique_generale.surface_habitable_logement,
116
141
  typeHabitation: TypeHabitation.APPARTEMENT,
@@ -118,6 +143,10 @@ describe('Generateur du contexte du calcul', () => {
118
143
  zoneClimatique: {
119
144
  id: '4',
120
145
  value: 'h2a'
146
+ },
147
+ altitude: {
148
+ id: '3',
149
+ value: 'supérieur à 800m'
121
150
  }
122
151
  });
123
152
 
@@ -128,4 +157,31 @@ describe('Generateur du contexte du calcul', () => {
128
157
  typeDpe: TypeDpe.IMMEUBLE
129
158
  });
130
159
  });
160
+
161
+ test('Contexte avec calcul ilpa', () => {
162
+ const dpe = {
163
+ logement: {
164
+ caracteristique_generale: {},
165
+ meteo: {
166
+ batiment_materiaux_anciens: 0
167
+ },
168
+ enveloppe: {
169
+ inertie: {
170
+ enum_classe_inertie_id: 4
171
+ }
172
+ }
173
+ }
174
+ };
175
+
176
+ expect(contexteBuilder.fromDpe(dpe)).toMatchObject({ inertie: { id: 4, ilpa: 0 } });
177
+
178
+ dpe.logement.enveloppe.inertie.enum_classe_inertie_id = 1;
179
+ expect(contexteBuilder.fromDpe(dpe)).toMatchObject({ inertie: { id: 1, ilpa: 0 } });
180
+
181
+ dpe.logement.meteo.batiment_materiaux_anciens = 1;
182
+ expect(contexteBuilder.fromDpe(dpe)).toMatchObject({ inertie: { id: 1, ilpa: 1 } });
183
+
184
+ dpe.logement.enveloppe.inertie.enum_classe_inertie_id = 2;
185
+ expect(contexteBuilder.fromDpe(dpe)).toMatchObject({ inertie: { id: 2, ilpa: 1 } });
186
+ });
131
187
  });
@@ -2,7 +2,7 @@ import { inject } from 'dioma';
2
2
  import { ContexteBuilder } from './contexte.builder.js';
3
3
  import { DeperditionEnveloppeService } from './enveloppe/deperdition-enveloppe.service.js';
4
4
  import { logger } from '../../../core/util/logger/log-service.js';
5
- import { SurfaceSudEquivalenteService } from './logement/surface-sud-equivalente.service.js';
5
+ import { ApportEtBesoinService } from './apport_et_besoin/apport-et-besoin.service.js';
6
6
 
7
7
  export class EngineService {
8
8
  /**
@@ -11,9 +11,9 @@ export class EngineService {
11
11
  #deperditionService;
12
12
 
13
13
  /**
14
- * @type {SurfaceSudEquivalenteService}
14
+ * @type {ApportEtBesoinService}
15
15
  */
16
- #surfaceSudEquivalenteService;
16
+ #apportEtBesoinService;
17
17
 
18
18
  /**
19
19
  * @type {ContexteBuilder}
@@ -22,16 +22,16 @@ export class EngineService {
22
22
 
23
23
  /**
24
24
  * @param deperditionService {DeperditionEnveloppeService}
25
- * @param surfaceSudEquivalenteService {SurfaceSudEquivalenteService}
25
+ * @param apportEtBesoinService {ApportEtBesoinService}
26
26
  * @param contextBuilder {ContexteBuilder}
27
27
  */
28
28
  constructor(
29
29
  deperditionService = inject(DeperditionEnveloppeService),
30
- surfaceSudEquivalenteService = inject(SurfaceSudEquivalenteService),
30
+ apportEtBesoinService = inject(ApportEtBesoinService),
31
31
  contextBuilder = inject(ContexteBuilder)
32
32
  ) {
33
33
  this.#deperditionService = deperditionService;
34
- this.#surfaceSudEquivalenteService = surfaceSudEquivalenteService;
34
+ this.#apportEtBesoinService = apportEtBesoinService;
35
35
  this.#contextBuilder = contextBuilder;
36
36
  }
37
37
 
@@ -68,12 +68,10 @@ export class EngineService {
68
68
  proceededDpe.logement
69
69
  );
70
70
 
71
- proceededDpe.logement.sortie.apport_et_besoin = {
72
- surface_sud_equivalente: this.#surfaceSudEquivalenteService.execute(
73
- ctx,
74
- proceededDpe.logement.enveloppe
75
- )
76
- };
71
+ proceededDpe.logement.sortie.apport_et_besoin = this.#apportEtBesoinService.execute(
72
+ ctx,
73
+ proceededDpe.logement
74
+ );
77
75
 
78
76
  // Calcul des déperditions par renouvellement de l'air
79
77
 
@@ -114,7 +112,6 @@ export class EngineService {
114
112
  */
115
113
  #removeComputedData(dpe) {
116
114
  delete dpe.logement.sortie;
117
- delete dpe.logement.enveloppe.inertie;
118
115
 
119
116
  dpe.logement.enveloppe.mur_collection.mur?.map((m) => delete m.donnee_intermediaire);
120
117
  dpe.logement.enveloppe.baie_vitree_collection.baie_vitree?.map((m) => {
@@ -1,6 +1,6 @@
1
1
  import { DeperditionService } from '../deperdition.service.js';
2
2
  import { inject } from 'dioma';
3
- import { BaieVitreeTvStore } from '../../../../dpe/infrastructure/baieVitreeTv.store.js';
3
+ import { BaieVitreeTvStore } from '../../../../dpe/infrastructure/enveloppe/baieVitreeTv.store.js';
4
4
 
5
5
  /**
6
6
  * Calcul des déperditions des baies vitrées
@@ -4,7 +4,7 @@ import { ContexteBuilder } from '../../contexte.builder.js';
4
4
  import { DpeNormalizerService } from '../../../../normalizer/domain/dpe-normalizer.service.js';
5
5
  import { DeperditionBaieVitreeService } from './deperdition-baie-vitree.service.js';
6
6
  import { beforeEach, describe, expect, test, vi } from 'vitest';
7
- import { BaieVitreeTvStore } from '../../../../dpe/infrastructure/baieVitreeTv.store.js';
7
+ import { BaieVitreeTvStore } from '../../../../dpe/infrastructure/enveloppe/baieVitreeTv.store.js';
8
8
 
9
9
  /** @type {DeperditionBaieVitreeService} **/
10
10
  let service;
@@ -1,6 +1,6 @@
1
1
  import { DeperditionService } from '../deperdition.service.js';
2
2
  import { inject } from 'dioma';
3
- import { BaieVitreeTvStore } from '../../../../dpe/infrastructure/baieVitreeTv.store.js';
3
+ import { BaieVitreeTvStore } from '../../../../dpe/infrastructure/enveloppe/baieVitreeTv.store.js';
4
4
 
5
5
  /**
6
6
  * Calcul des déperditions des baies vitrées
@@ -1,7 +1,7 @@
1
1
  import { ContexteBuilder } from '../../contexte.builder.js';
2
2
  import { DpeNormalizerService } from '../../../../normalizer/domain/dpe-normalizer.service.js';
3
3
  import { beforeEach, describe, expect, test, vi } from 'vitest';
4
- import { BaieVitreeTvStore } from '../../../../dpe/infrastructure/baieVitreeTv.store.js';
4
+ import { BaieVitreeTvStore } from '../../../../dpe/infrastructure/enveloppe/baieVitreeTv.store.js';
5
5
  import { EspaceTamponService } from './espace-tampon.service.js';
6
6
  import { getAdemeFileJson } from '../../../../../../test/test-helpers.js';
7
7
 
@@ -3,7 +3,7 @@ import { DeperditionService } from '../deperdition.service.js';
3
3
  import { logger } from '../../../../../core/util/logger/log-service.js';
4
4
  import { compareReferences } from '../../../../../utils.js';
5
5
  import { DeperditionMurService } from '../mur/deperdition-mur.service.js';
6
- import { PontThermiqueTvStore } from '../../../../dpe/infrastructure/pontThermiqueTv.store.js';
6
+ import { PontThermiqueTvStore } from '../../../../dpe/infrastructure/enveloppe/pontThermiqueTv.store.js';
7
7
  import enums from '../../../../../enums.js';
8
8
  import { DeperditionPlancherHautService } from '../plancher_haut/deperdition-plancher-haut.service.js';
9
9
  import { DeperditionPlancherBasService } from '../plancher_bas/deperdition-plancher-bas.service.js';
@@ -4,7 +4,7 @@ import { ContexteBuilder } from '../../contexte.builder.js';
4
4
  import { DpeNormalizerService } from '../../../../normalizer/domain/dpe-normalizer.service.js';
5
5
  import { beforeEach, describe, expect, test, vi } from 'vitest';
6
6
  import { DeperditionPontThermiqueService } from './deperdition-pont-thermique.service.js';
7
- import { PontThermiqueTvStore } from '../../../../dpe/infrastructure/pontThermiqueTv.store.js';
7
+ import { PontThermiqueTvStore } from '../../../../dpe/infrastructure/enveloppe/pontThermiqueTv.store.js';
8
8
  import { DeperditionMurService } from '../mur/deperdition-mur.service.js';
9
9
  import { DeperditionPlancherHautService } from '../plancher_haut/deperdition-plancher-haut.service.js';
10
10
  import { DeperditionPlancherBasService } from '../plancher_bas/deperdition-plancher-bas.service.js';
@@ -10,18 +10,19 @@ import { TypeDpe } from '../../../dpe/domain/models/type-habitation.model.js';
10
10
  */
11
11
  export class NadeqService {
12
12
  /**
13
- * @param ctx {Contexte}
14
- * @param bv {BaieVitree}
13
+ * @param typeDpe {TypeDpe}
14
+ * @param surfaceHabitable {number}
15
+ * @param nombreAppartement {number}
15
16
  * @return {number}
16
17
  */
17
- execute(ctx) {
18
- if (ctx.typeDpe === TypeDpe.MAISON) {
19
- return this.#calculateIndividualNadeq(ctx.surfaceHabitable);
18
+ execute(typeDpe, surfaceHabitable, nombreAppartement) {
19
+ if (typeDpe === TypeDpe.MAISON) {
20
+ return this.#calculateIndividualNadeq(surfaceHabitable);
20
21
  }
21
22
 
22
23
  return this.#calculateCollectiveNadeq(
23
- ctx.surfaceHabitable,
24
- ctx.typeDpe === TypeDpe.APPARTEMENT ? 1 : ctx.nombreAppartement
24
+ surfaceHabitable,
25
+ typeDpe === TypeDpe.APPARTEMENT ? 1 : nombreAppartement
25
26
  );
26
27
  }
27
28
 
@@ -18,11 +18,7 @@ describe('Nadeq unit tests', () => {
18
18
  ])(
19
19
  `Typologie MAISON : Nombre d'adultes équivalent $expectedNadeq pour une surface de logement $surfaceHabitable`,
20
20
  ({ expectedNadeq, surfaceHabitable }) => {
21
- const ctx = {
22
- surfaceHabitable: surfaceHabitable,
23
- typeDpe: TypeDpe.MAISON
24
- };
25
- expect(service.execute(ctx)).toBe(expectedNadeq);
21
+ expect(service.execute(TypeDpe.MAISON, surfaceHabitable)).toBe(expectedNadeq);
26
22
  }
27
23
  );
28
24
 
@@ -36,11 +32,7 @@ describe('Nadeq unit tests', () => {
36
32
  ])(
37
33
  `Typologie APPARTEMENT : Nombre d'adultes équivalent $expectedNadeq pour une surface de logement $surfaceHabitable`,
38
34
  ({ expectedNadeq, surfaceHabitable }) => {
39
- const ctx = {
40
- surfaceHabitable: surfaceHabitable,
41
- typeDpe: TypeDpe.APPARTEMENT
42
- };
43
- expect(service.execute(ctx)).toBeCloseTo(expectedNadeq, 2);
35
+ expect(service.execute(TypeDpe.APPARTEMENT, surfaceHabitable)).toBeCloseTo(expectedNadeq, 2);
44
36
  }
45
37
  );
46
38
 
@@ -60,12 +52,10 @@ describe('Nadeq unit tests', () => {
60
52
  ])(
61
53
  `Typologie IMMEUBLE : Nombre d'adultes équivalent $expectedNadeq pour une surface de logement $surfaceHabitable et un nombre d'apartement $nombreAppartement`,
62
54
  ({ expectedNadeq, surfaceHabitable, nombreAppartement }) => {
63
- const ctx = {
64
- surfaceHabitable: surfaceHabitable,
65
- nombreAppartement: nombreAppartement,
66
- typeDpe: TypeDpe.IMMEUBLE
67
- };
68
- expect(service.execute(ctx)).toBeCloseTo(expectedNadeq, 2);
55
+ expect(service.execute(TypeDpe.IMMEUBLE, surfaceHabitable, nombreAppartement)).toBeCloseTo(
56
+ expectedNadeq,
57
+ 2
58
+ );
69
59
  }
70
60
  );
71
61
  });
@@ -11,5 +11,14 @@ export interface Contexte {
11
11
  id: string;
12
12
  value: string;
13
13
  };
14
+ altitude: {
15
+ id: string;
16
+ value: string;
17
+ };
14
18
  effetJoule: boolean;
19
+ nadeq: number;
20
+ inertie: {
21
+ id: number;
22
+ ilpa: number;
23
+ };
15
24
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open3cl/engine",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "description": "Open Source 3CL-DPE engine",
5
5
  "main": "index.js",
6
6
  "directories": {