Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(feat-75): new values for classe_emission_ges and classe_bilan_dpe for surface <= 40m2 #76

Merged
merged 1 commit into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
272 changes: 37 additions & 235 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"3cl"
],
"dependencies": {
"@jest/globals": "^29.7.0",
"fast-xml-parser": "^4.3.3",
"lodash": "^4.17.21"
},
Expand All @@ -42,8 +43,8 @@
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"@semantic-release/github": "^10.0.2",
"@types/node": "^20.12.4",
"@types/jest": "^29.5.12",
"@types/node": "^20.12.4",
"deep-object-diff": "^1.1.9",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
Expand Down
6 changes: 6 additions & 0 deletions scripts/synchronize_assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@ import { FileStore } from '../src/core/file/infrastructure/adapter/file.store.js
import { SynchronizeValeurTables } from '../src/core/assets/domain/synchronize-valeur-tables.js';
import { SynchronizeSolicitationsTables } from '../src/core/assets/domain/synchronize-solicitations-tables.js';
import { SynchronizeC1Tables } from '../src/core/assets/domain/synchronize-c1-tables.js';
import { SynchronizeDpeGesLimitValuesTables } from '../src/core/assets/domain/synchronize-dpe-ges-limit-values-tables.js';

const fileStore = new FileStore();
const appConfig = new ApplicationConfig();
const synchronizeEnumTables = new SynchronizeEnumTables(fileStore, appConfig);
const synchronizeSolicitationsTables = new SynchronizeSolicitationsTables(fileStore, appConfig);
const synchronizeDpeGesLimitValuesTables = new SynchronizeDpeGesLimitValuesTables(
fileStore,
appConfig
);
const synchronizeC1Tables = new SynchronizeC1Tables(fileStore, appConfig);
const synchronizeValeurTables = new SynchronizeValeurTables(
fileStore,
appConfig,
synchronizeSolicitationsTables,
synchronizeDpeGesLimitValuesTables,
synchronizeC1Tables
);
const synchronizeAssets = new SynchronizeAssets(synchronizeEnumTables, synchronizeValeurTables);
Expand Down
57 changes: 35 additions & 22 deletions src/conso.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import enums from './enums.js';
import calc_conso_eclairage from './16_conso_eclairage.js';
import tvs from './tv.js';

const coef_ep = {
'électricité ch': 2.3,
Expand Down Expand Up @@ -91,11 +92,17 @@ export default function calc_conso(Sh, zc_id, ca_id, vt, ch, ecs, fr) {
emission_ges: calc_conso_pond(Sh, zc_id, vt, gen_ch, gen_ecs, fr, 'emission_ges', coef_ges),
cout: calc_conso_pond(Sh, zc_id, vt, gen_ch, gen_ecs, fr, 'cout', coef_cout)
};
ret.ep_conso.classe_bilan_dpe = classe_bilan_dpe(ret.ep_conso.ep_conso_5_usages_m2, zc_id, ca_id);
ret.ep_conso.classe_bilan_dpe = classe_bilan_dpe(
ret.ep_conso.ep_conso_5_usages_m2,
zc_id,
ca_id,
Sh
);
ret.emission_ges.classe_emission_ges = classe_emission_ges(
ret.emission_ges.emission_ges_5_usages_m2,
zc_id,
ca_id
ca_id,
Sh
);

const energie_ids = [];
Expand Down Expand Up @@ -142,42 +149,48 @@ export default function calc_conso(Sh, zc_id, ca_id, vt, ch, ecs, fr) {
return ret;
}

function classe_bilan_dpe(ep_conso_5_usages_m2, zc_id, ca_id) {
function classe_bilan_dpe(ep_conso_5_usages_m2, zc_id, ca_id, Sh) {
const ca = enums.classe_altitude[ca_id];

const cut = tvs.dpe_class_limit[ca][Math.round(Sh)] ?? [];

if (!ep_conso_5_usages_m2) return null;
if (ep_conso_5_usages_m2 < 70) return 'A';
if (ep_conso_5_usages_m2 < 110) return 'B';
if (ep_conso_5_usages_m2 < 180) return 'C';
if (ep_conso_5_usages_m2 < 250) return 'D';
if (ep_conso_5_usages_m2 < (cut['A'] ?? 70)) return 'A';
if (ep_conso_5_usages_m2 < (cut['B'] ?? 110)) return 'B';
if (ep_conso_5_usages_m2 < (cut['C'] ?? 180)) return 'C';
if (ep_conso_5_usages_m2 < (cut['D'] ?? 250)) return 'D';

const zc = enums.zone_climatique[zc_id];
const ca = enums.classe_altitude[ca_id];

if (['h1b', 'h1c', 'h2d'].includes(zc) && ca === 'supérieur à 800m') {
if (ep_conso_5_usages_m2 < 390) return 'E';
if (ep_conso_5_usages_m2 < 500) return 'F';
if (ep_conso_5_usages_m2 < (cut['E'] ?? 390)) return 'E';
if (ep_conso_5_usages_m2 < (cut['F'] ?? 500)) return 'F';
} else {
if (ep_conso_5_usages_m2 < 330) return 'E';
if (ep_conso_5_usages_m2 < 420) return 'F';
if (ep_conso_5_usages_m2 < (cut['E'] ?? 330)) return 'E';
if (ep_conso_5_usages_m2 < (cut['F'] ?? 420)) return 'F';
}
return 'G';
}

function classe_emission_ges(emission_ges_5_usages_m2, zc_id, ca_id) {
function classe_emission_ges(emission_ges_5_usages_m2, zc_id, ca_id, Sh) {
const ca = enums.classe_altitude[ca_id];

const cut = tvs.ges_class_limit[ca][Math.round(Sh)] ?? [];

if (!emission_ges_5_usages_m2) return null;
if (emission_ges_5_usages_m2 < 6) return 'A';
if (emission_ges_5_usages_m2 < 11) return 'B';
if (emission_ges_5_usages_m2 < 30) return 'C';
if (emission_ges_5_usages_m2 < 50) return 'D';
if (emission_ges_5_usages_m2 < (cut['A'] ?? 6)) return 'A';
if (emission_ges_5_usages_m2 < (cut['B'] ?? 11)) return 'B';
if (emission_ges_5_usages_m2 < (cut['C'] ?? 30)) return 'C';
if (emission_ges_5_usages_m2 < (cut['D'] ?? 50)) return 'D';

const zc = enums.zone_climatique[zc_id];
const ca = enums.classe_altitude[ca_id];

if (['h1b', 'h1c', 'h2d'].includes(zc) && ca === 'supérieur à 800m') {
if (emission_ges_5_usages_m2 < 80) return 'E';
if (emission_ges_5_usages_m2 < 110) return 'F';
if (emission_ges_5_usages_m2 < (cut['E'] ?? 80)) return 'E';
if (emission_ges_5_usages_m2 < (cut['F'] ?? 110)) return 'F';
} else {
if (emission_ges_5_usages_m2 < 70) return 'E';
if (emission_ges_5_usages_m2 < 100) return 'F';
if (emission_ges_5_usages_m2 < (cut['E'] ?? 70)) return 'E';
if (emission_ges_5_usages_m2 < (cut['F'] ?? 100)) return 'F';
}
return 'G';
}
Expand Down
1 change: 1 addition & 0 deletions src/core/assets/domain/synchronize-assets.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { SynchronizeAssets } from './synchronize-assets.js';
import { SynchronizeEnumTables } from './synchronize-enum-tables.js';
import { SynchronizeValeurTables } from './synchronize-valeur-tables.js';
import { jest } from '@jest/globals';

describe('SynchronizeAssets unit tests', () => {
it('should synchronize xlsx and ods files', () => {
Expand Down
1 change: 1 addition & 0 deletions src/core/assets/domain/synchronize-c1-tables.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { SynchronizeC1Tables } from './synchronize-c1-tables.js';
import { FileStore } from '../../file/infrastructure/adapter/file.store.js';
import { ApplicationConfig } from '../../conf/infrastructure/application.config.js';
import { C1TablesFixture } from '../../../../test/fixtures/core/assets/c1-tables.fixture.js';
import { jest } from '@jest/globals';

describe('SynchronizeC1Tables unit tests', () => {
it('should read and parse 18.5_c1.ods file', () => {
Expand Down
73 changes: 73 additions & 0 deletions src/core/assets/domain/synchronize-dpe-ges-limit-values-tables.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { set } from 'lodash-es';

const CLASSE_ALTITUDE_PROPERTY = 'classe_altitude';
const SURFACE_PROPERTY = 'surface';
const EXCLUDED_PROPERTIES = [CLASSE_ALTITUDE_PROPERTY, SURFACE_PROPERTY];

/**
* Read the `dpe_ges_limit_values.ods` local file
* - Convert the file into a json object
* - Extract, format data and return data
*
* The file content is merged in the `tv.js` file generated in the {@link SynchronizeValeurTables} use case.
*/
export class SynchronizeDpeGesLimitValuesTables {
/**
* @type {FileStore}
*/
#fileStore;

/**
* @type {ApplicationConfig}
*/
#appConfig;

/**
* @param fileStore {FileStore}
* @param appConfig {ApplicationConfig}
*/
constructor(fileStore, appConfig) {
this.#fileStore = fileStore;
this.#appConfig = appConfig;
}

/**
* @return {Promise<any>}
*/
execute() {
return this.#fileStore
.readLocalOdsFileAndConvertToJson(this.#appConfig.dpeGesLimitValuesFilePath)
.then(
/** @param excelSheets {{[key: string]: {classe_altitude: string, surface: string}[]}} **/ (
excelSheets
) => {
const output = {};

// For each tab in Excel file
for (const sheetName in excelSheets) {
output[sheetName] = {};

excelSheets[sheetName].forEach((sheetValue) => {
// Group by "classe_altitude" an "surface"
let groupKey = sheetValue.classe_altitude;

if (!output[sheetName][groupKey]) {
output[sheetName][groupKey] = {};
}

output[sheetName][groupKey][parseFloat(sheetValue.surface)] = {};

for (const sheetValueKey in sheetValue) {
if (!EXCLUDED_PROPERTIES.includes(sheetValueKey)) {
const path = `${sheetName}.${groupKey}.${sheetValue.surface}.${sheetValueKey}`;
set(output, path, parseFloat(sheetValue[sheetValueKey]));
}
}
});
}

return output;
}
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { FileStore } from '../../file/infrastructure/adapter/file.store.js';
import { ApplicationConfig } from '../../conf/infrastructure/application.config.js';
import { DpeGesLimitValuesTablesFixture } from '../../../../test/fixtures/core/assets/dpe-ges-limit-values-tables.fixture.js';
import { SynchronizeDpeGesLimitValuesTables } from './synchronize-dpe-ges-limit-values-tables.js';
import { jest } from '@jest/globals';

describe('SynchronizeDpeGesLimitValuesTables unit tests', () => {
it('should read and parse dpe_ges_limit_values file', () => {
const fileStore = new FileStore();
const appConfig = new ApplicationConfig();
const synchronizeDpeGesLimitValuesTables = new SynchronizeDpeGesLimitValuesTables(
fileStore,
appConfig
);

const dpeGesLimitData = DpeGesLimitValuesTablesFixture.aDpeGesLimitExample();
jest.spyOn(fileStore, 'readLocalOdsFileAndConvertToJson').mockResolvedValue(dpeGesLimitData);
jest
.spyOn(ApplicationConfig.prototype, 'solicitationsExtFilePath', 'get')
.mockReturnValue('src/file.ods');

return synchronizeDpeGesLimitValuesTables.execute().then((output) => {
expect(fileStore.readLocalOdsFileAndConvertToJson).toHaveBeenCalled();
expect(output).toStrictEqual({
dpe_class_limit: {
'inférieur à 400m': {
3: {
A: 146,
B: 186,
C: 386,
D: 505,
E: 622,
F: 739
}
},
'400-800m': {
10: {
A: 124,
B: 164,
C: 329,
D: 428,
E: 533,
F: 640
}
}
},
ges_class_limit: {
'400-800m': {
10: {
A: 10,
B: 15,
C: 40,
D: 62,
E: 84,
F: 115
}
},
'inférieur à 400m': {
3: {
A: 11,
B: 16,
C: 44,
D: 68,
E: 90,
F: 122
}
}
}
});
});
});
});
1 change: 1 addition & 0 deletions src/core/assets/domain/synchronize-enum-tables.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { FileStore } from '../../file/infrastructure/adapter/file.store.js';
import { ApplicationConfig } from '../../conf/infrastructure/application.config.js';
import { EnumTablesFixture } from '../../../../test/fixtures/core/assets/enum-tables.fixture.js';
import { SynchronizeEnumTables } from './synchronize-enum-tables.js';
import { jest } from '@jest/globals';

describe('SynchronizeEnumTables', () => {
it('should download, parse and convert enum_tables.xlsx file', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { FileStore } from '../../file/infrastructure/adapter/file.store.js';
import { ApplicationConfig } from '../../conf/infrastructure/application.config.js';
import { SynchronizeSolicitationsTables } from './synchronize-solicitations-tables.js';
import { SolicitationsTablesFixture } from '../../../../test/fixtures/core/assets/solicitations-tables.fixture.js';
import { jest } from '@jest/globals';

describe('SynchronizeSolicitationsTables unit tests', () => {
it('should read and parse 18.2_sollicitations_ext.ods file', () => {
Expand Down
16 changes: 15 additions & 1 deletion src/core/assets/domain/synchronize-valeur-tables.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ export class SynchronizeValeurTables {
*/
#synchronizeSolicitationsTables;

/**
* @type {SynchronizeDpeGesLimitValuesTables}
*/
#synchronizeDpeGesLimitValuesTables;

/**
* @type {SynchronizeC1Tables}
*/
Expand All @@ -31,12 +36,20 @@ export class SynchronizeValeurTables {
* @param fileStore {FileStore}
* @param appConfig {ApplicationConfig}
* @param synchronizeSolicitationsTables {SynchronizeSolicitationsTables}
* @param synchronizeDpeGesLimitValuesTables {SynchronizeDpeGesLimitValuesTables}
* @param synchronizeC1Tables {SynchronizeC1Tables}
*/
constructor(fileStore, appConfig, synchronizeSolicitationsTables, synchronizeC1Tables) {
constructor(
fileStore,
appConfig,
synchronizeSolicitationsTables,
synchronizeDpeGesLimitValuesTables,
synchronizeC1Tables
) {
this.#fileStore = fileStore;
this.#appConfig = appConfig;
this.#synchronizeSolicitationsTables = synchronizeSolicitationsTables;
this.#synchronizeDpeGesLimitValuesTables = synchronizeDpeGesLimitValuesTables;
this.#synchronizeC1Tables = synchronizeC1Tables;
}

Expand Down Expand Up @@ -97,6 +110,7 @@ export class SynchronizeValeurTables {
.then((valeurTablesValues) => {
return Promise.all([
this.#synchronizeSolicitationsTables.execute(),
this.#synchronizeDpeGesLimitValuesTables.execute(),
this.#synchronizeC1Tables.execute()
]).then((tablesValues) => {
const solicitationsTablesValues = tablesValues[0];
Expand Down
5 changes: 5 additions & 0 deletions src/core/assets/domain/synchronize-valeur-tables.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ import { ApplicationConfig } from '../../conf/infrastructure/application.config.
import { SynchronizeC1Tables } from './synchronize-c1-tables.js';
import { SynchronizeSolicitationsTables } from './synchronize-solicitations-tables.js';
import { ValeurTablesFixture } from '../../../../test/fixtures/core/assets/valeur-tables.fixture.js';
import { jest } from '@jest/globals';
import { SynchronizeDpeGesLimitValuesTables } from './synchronize-dpe-ges-limit-values-tables.js';

describe('SynchronizeValeurTables unit tests', () => {
it('should download, parse and convert valeur_tables.xlsx file', () => {
const fileStore = new FileStore();
const appConfig = new ApplicationConfig();
const synchronizeC1Tables = new SynchronizeC1Tables(null, null);
const synchronizeSolicitationTables = new SynchronizeSolicitationsTables(null, null);
const synchronizeDpeGesLimitValuesTables = new SynchronizeDpeGesLimitValuesTables(null, null);
const synchronizeValeurTables = new SynchronizeValeurTables(
fileStore,
appConfig,
synchronizeSolicitationTables,
synchronizeDpeGesLimitValuesTables,
synchronizeC1Tables
);

Expand All @@ -30,6 +34,7 @@ describe('SynchronizeValeurTables unit tests', () => {
jest.spyOn(fileStore, 'writeFileToLocalSystem').mockResolvedValue(null);
jest.spyOn(synchronizeC1Tables, 'execute').mockResolvedValue({});
jest.spyOn(synchronizeSolicitationTables, 'execute').mockResolvedValue({});
jest.spyOn(synchronizeDpeGesLimitValuesTables, 'execute').mockResolvedValue({});

return synchronizeValeurTables.execute().then(() => {
expect(fileStore.downloadXlsxFileAndConvertToJson).toHaveBeenCalled();
Expand Down
4 changes: 4 additions & 0 deletions src/core/conf/infrastructure/application.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ export class ApplicationConfig {
return 'src/tv/18.5_c1.ods';
}

get dpeGesLimitValuesFilePath() {
return 'src/tv/dpe_ges_limit_values.ods';
}

get assetsOutputFolder() {
return 'scripts/assets';
}
Expand Down
Loading