Merci de l'intérêt que vous portez au projet ! Open3CL est un moteur de calcul réglementaire : chaque correction, même d'un dixième de pourcent sur une déperdition, rapproche la librairie des logiciels certifiés. Toutes les contributions comptent.
Retour au README
- Comment contribuer
- Mettre en place son environnement
- Comprendre le projet
- Le cycle d'une contribution
- Conventions de commit
- Règles de code
- Tests
- Corriger un écart de calcul, pas à pas
- Signaler un bug
- Proposer une fonctionnalité
- Questions
Il n'y a pas que le code.
| Vous pouvez… | Comment |
|---|---|
| 🐛 Signaler un écart | Ouvrir un bug avec le numéro du DPE concerné |
| 🔬 Documenter un cas limite | Un DPE réel qui met le moteur en défaut est une contribution à part entière |
| 🧪 Ajouter des tests | Chaque article de la méthode mérite ses tests unitaires |
| 📖 Améliorer la documentation | Une explication qui vous a manqué manquera à d'autres |
| 🛠️ Corriger un calcul | Voir Corriger un écart de calcul |
| ✨ Proposer une fonctionnalité | Ouvrir une feature |
| Outil | Version | Vérifier |
|---|---|---|
| Node.js | ≥ 24.14.1 | node --version |
| npm | ≥ 10 | npm --version |
| git | — | git --version |
La version utilisée en développement et en intégration continue est fixée dans .nvmrc :
nvm usegit clone https://github.com/Open3CL/engine.git
cd engine
npm cinpm ci installe également les hooks husky : le formatage des fichiers modifiés et
la validation du message de commit sont automatiques.
| Commande | Ce qu'elle fait |
|---|---|
npm run test:unit |
Tests unitaires (src/**/*.spec.js) |
npm run test:unit:ci |
Idem, avec le rapport de couverture et le seuil de 100 % |
npm run test:int |
Tests d'intégration sur DPE réels (test/**/*.spec.js) |
npm test |
Toute la suite |
npm run test:corpus |
Tests de corpus — voir docs/CORPUS.md |
npm run qa:lint |
ESLint |
npm run qa:lint:fix |
ESLint avec correction automatique |
npm run qa:format |
Prettier sur tout le projet |
npm run qa:duplication |
Détection de code dupliqué (jscpd) |
npm run reports:preview |
Ouvre le rapport de corpus dans le navigateur |
Important
Avant d'ouvrir une pull request, exécutez au minimum npm run qa:lint et npm run test:unit.
Les tests d'intégration téléchargent des DPE depuis l'API de l'ADEME lorsqu'ils ne sont pas déjà présents dans
test/fixtures/. Il faut alors :
export ADEME_CLIENT_ID=...
export ADEME_CLIENT_SECRET=...Les DPE déjà présents dans test/fixtures/ ne sont jamais retéléchargés : la plupart des tests fonctionnent donc sans
identifiants.
engine/
├── index.js Point d'entrée public de la librairie
├── src/
│ ├── engine.js Orchestrateur : enchaîne tous les modules de calcul
│ ├── 3_deperdition.js ─┐
│ ├── 9_chauffage.js │ Un module par article de la méthode 3CL-DPE 2021,
│ ├── 11_ecs.js │ le préfixe numérique reprenant la numérotation
│ ├── 15_conso_aux.js ─┘ de l'annexe 1 de l'arrêté
│ ├── conso.js Agrégation des consommations, coûts, émissions
│ ├── tv.js Tables de valeurs réglementaires
│ ├── enums.js Énumérations de l'ADEME
│ └── *.spec.js Tests unitaires, au plus près du code testé
├── test/
│ ├── fixtures/ DPE réels utilisés par les tests d'intégration
│ ├── corpus/ Runner des tests de corpus
│ └── *.spec.js Tests d'intégration
├── docs/ Documentation détaillée
└── dist/reports/corpus/ Rapports générés (JSON, CSV, tableau de bord HTML)
Le moteur reproduit la méthode réglementaire, article par article. Quand vous modifiez un calcul :
- Citez la source. Un commentaire renvoyant à la section de l'annexe 1 de l'arrêté du 31 mars 2021 vaut mieux qu'une longue explication.
- Nommez comme la méthode. Si l'arrêté parle de
Pcirb,j, la variable s'appellePcirb_j, paspumpPower. - Mesurez sur le corpus. Un calcul « plus juste » qui fait chuter le taux de réussite doit être discuté : c'est souvent le signe que les logiciels certifiés font autrement.
flowchart LR
A["🍴 Fork"] --> B["🌿 Branche"]
B --> C["✍️ Code + tests"]
C --> D["✅ lint & tests"]
D --> E["📤 Pull request"]
E --> F["👀 Revue"]
F --> G["🚀 Merge"]
- Forkez le dépôt et clonez votre fork.
- Créez une branche depuis
main, nommée d'après ce qu'elle fait :fix/issue-123-deperdition-mur,feat/photovoltaique,docs/corpus. - Codez, en ajoutant les tests correspondants.
- Vérifiez :
npm run qa:lint && npm run test:unit. - Commitez en respectant les conventions.
- Ouvrez une pull request vers
main, avec :- une description de ce qui change et pourquoi ;
- le numéro de l'issue liée (
Closes #123) ; - l'impact sur les corpus si vous avez modifié un calcul (avant / après).
- Répondez à la revue. Les mainteneurs sont là pour aider, pas pour juger.
Tip
Pour une modification importante, ouvrez d'abord une issue pour en discuter. Cela évite d'écrire du code qui ne sera pas retenu.
Les messages suivent la convention Conventional Commits, vérifiée automatiquement par commitlint.
<type>(<scope>): <sujet>
| Type | Quand l'utiliser | Effet sur la version |
|---|---|---|
feat |
Nouvelle fonctionnalité | minor |
fix |
Correction de bug | patch |
perf |
Amélioration de performance | patch |
refactor |
Réorganisation sans changement de comportement | — |
test |
Ajout ou modification de tests | — |
docs |
Documentation | — |
chore |
Outillage, dépendances, CI | — |
style |
Formatage uniquement | — |
Le sujet doit être en minuscules ou en début de phrase, sans point final.
# ✅ Bien
git commit -m "fix(fix-311): Proration des besoins de chauffage pour installations multiples"
git commit -m "feat: support du photovoltaïque en autoconsommation"
git commit -m "test(15_conso_aux): couverture des auxiliaires de distribution ECS"
# ❌ À éviter
git commit -m "correction bug"
git commit -m "WIP"Note
Les versions sont publiées automatiquement par semantic-release à partir des
messages de commit. Un fix: déclenche une version corrective, un feat: une version mineure. Ne modifiez jamais
la version dans package.json à la main.
Pensez à squasher les commits intermédiaires pour garder un historique lisible.
| Règle | Vérifiée par |
|---|---|
Style JavaScript Standard, configuré dans .eslintrc.json |
npm run qa:lint |
Formatage Prettier (.prettierrc) |
npm run qa:format, hook de pre-commit |
Indentation et fins de ligne selon .editorconfig |
votre éditeur |
Pas de duplication excessive (.jscpd.json) |
npm run qa:duplication |
| Toute correction ou fonctionnalité est couverte par au moins un test | la revue |
| Couverture unitaire à 100 % (statements, branches, functions, lines) | npm run test:unit:ci |
-
ESM uniquement (
import/export), le projet est en"type": "module". -
JSDoc sur les fonctions exportées : décrivez les paramètres avec leur unité physique.
/** * 15.2.3 Consommation des auxiliaires de distribution d'ECS * @param Sh_logement {number} surface habitable du logement (m²) * @param nadeq {number} nombre d'unités d'équivalence */
-
Commentaires en français, comme le reste du projet et comme la méthode qu'il implémente.
-
Pas de magie : une constante réglementaire porte un nom et un commentaire renvoyant à la méthode.
| Niveau | Où | Ce qu'il garantit | Dépendances |
|---|---|---|---|
| Unitaire | src/*.spec.js |
Chaque article de la méthode, branche par branche | Toutes mockées |
| Intégration | test/*.spec.js |
Le moteur complet sur un DPE réel, comparé au DPE publié | DPE en fixture |
| Corpus | test/corpus/ |
Le moteur sur ~90 000 DPE réels, avec un taux de conformité | API ADEME |
Les tests unitaires mockent toutes les dépendances pour piloter chaque branche :
vi.mock('./utils.js', () => ({
mois_liste: ['Janvier'],
Njj: { Janvier: 31 }
}));Privilégiez les valeurs attendues calculables à la main plutôt que des constantes opaques :
// ✅ On comprend d'où vient la valeur
const CONSO_PLANCHER_20W = (31 * 24 * 20) / 1000; // circulateur à 20 W, toutes les heures du mois
expect(di.conso_auxiliaire_distribution_ecs).toBeCloseTo(CONSO_PLANCHER_20W, 10);
// 🟡 Acceptable en régression, mais commentez l'origine du nombre
expect(di.conso_auxiliaire_distribution_ch).toBeCloseTo(215.1781621610199, 9);import { getAdemeFileJsonOrDownload } from './test-helpers.js';
const input = await getAdemeFileJsonOrDownload('2263E1261479X');
const output = calcul_3cl(structuredClone(input));Le DPE est téléchargé une fois puis mis en cache dans test/fixtures/. Commitez le fichier XML : les autres
contributeurs n'auront pas besoin d'identifiants ADEME.
C'est le type de contribution le plus fréquent. Voici la méthode qui fonctionne.
Dans le rapport de corpus, survolez un DPE au-dessus du seuil : le détail des propriétés en écart s'affiche, avec la valeur attendue, la valeur calculée et l'écart.
Le CSV détaillé donne, pour chaque grandeur, _input (le DPE publié), _output (Open3CL) et _diff (l'écart en %) :
grep "^2263E1261479X," dist/reports/corpus/corpus_dpe.csv/corpus_detailed_report_main.csvLisez les écarts dans l'ordre de la chaîne de calcul — enveloppe, besoins, systèmes, consommations. Le premier écart significatif est presque toujours la cause des suivants.
Avant de modifier le code, reproduisez le calcul attendu dans un petit script : c'est plus rapide, et cela prouve l'hypothèse. Vérifiez-la ensuite sur plusieurs DPE partageant la même configuration — une hypothèse qui ne tient que sur un cas n'en est pas une.
Le test doit échouer avant la correction et passer après. Visez la branche que vous ajoutez, pas seulement le cas nominal.
npm run test:corpus -- corpus-file-path=corpus_dpe.csv
npm run reports:previewLe rapport compare automatiquement votre branche à main et liste les DPE nouvellement en échec. Un gain global qui
casse des cas auparavant conformes mérite d'être examiné, et mentionné dans la pull request.
- Le numéro du DPE de référence.
- La règle de la méthode appliquée, avec la section de l'arrêté.
- L'impact corpus :
corpus_dpe.csv : 4 591 → 4 612 (+21).
Avant d'ouvrir une issue, cherchez dans les issues existantes : votre question a peut-être déjà une réponse.
Une bonne issue contient :
- Le numéro du DPE concerné — c'est l'information la plus utile, elle rend le cas reproductible ;
- La grandeur en écart : valeur attendue, valeur obtenue, écart ;
- La version de la librairie (
getVersion()) ; - Le contexte : les options passées à
calcul_3cl; - La trace d'erreur complète s'il y a une exception.
Warning
Les issues ouvertes sans ces informations sont difficiles à traiter et peuvent être fermées sans suite.
- Changement majeur : ouvrez d'abord une issue décrivant le besoin et l'objectif. L'équipe en discute avec vous avant que vous n'écriviez du code.
- Changement mineur : une issue puis directement une pull request conviennent.
Le bug tracker est réservé aux bugs et aux demandes de fonctionnalités. Pour une question d'utilisation :