= Spcécification des règles de calcul de G4IT
:toc:
:toclevels: 4 
:sectnums:

== Historique des modifications
|===
|type de changement|date|type de modification
|majeur|28/06/2022|Création du document
|majeur|Avril 2023|Ouverture en Open Source
|===

[#_documents_de_reference]
== Documents de référence

|===
|identifiant|intitulé du document|source
|1|G4IT|Sopra Steria
|2|Référentiel services numériques_v1.0_FR|ADEME|Principes généraux pour
l’affichage environnemental des produits de grande consommation
|3|WeNR Methodology Note|weNR - https://wenr.isit-europe.org/wenr-methodology-note/|méthode de calcul
|4|BOAVIZTA|https://boavizta.org/
|===

== Introduction

NumEcoEval est une solution permettant, à partir de données de dimensionnement du SI et de données de références, de calculer l’empreinte environnementale d'un système d'information.
Cet outil open source a été initialisé à partir des travaux de Sopra Steria [1], de l’ADEME [2],  de l’INR [3], de BOAVIZTA [4] (cf.Documents de référence), avec la contribution d'IJO. 
Cet outil vise à déployer massivement le calcul de l'empreinte environnementale d'un système d'information au sein d'une organisation, en connectant NumEcoEval directement aux sources de données standard de celle-ci (notamment ses CMDB).
Le volume de données pouvant être important, une attention particlière a donc été apportée à la performance de l'outil et explique certains choix d'architecture (notamment l'utilisation de l'asynchronisme).

== Description des principaux concepts

[#_analyse_de_cycle_de_vie]
=== Analyse de cycle de vie
Notre approche s’inspire des méthodes d'Analyse de Cycle de Vie (ACV), cadrées par les normes ISO 14040 et 14044. Ces normes structurent l’analyse d’impact tout au long du cycle de vie d’un produit ou d'un service.L’application de ces normes à un service numérique est encore jeune mais est à ce jour l’approche la plus poussée et celle retenue par les groupes de travail liés à la règlementation (AGEC).
NumEcoEval a été conçu pour pouvoir intégrer d'autres étapes du cycle de vie des produits selon les besoins des organisations, sous réserve que les donnéées disponilbles et/ou les standards évoluent dans ce sens.

4 étapes du cycle de vie d'un produit sont retenues actuellement :

image::cycle_de_vie.jpg[]

|===
|Étape du cycle de vie |Traduction anglaise |description
|Fabrication|Build|Phase de fabrication d'un composant de l'extraction des matières premières à la fin de sa phase de fabrication.
|Utilisation|Use|Phase d'utilisation d'un équipement
|Fin de vie|End Of Life (EOL)| Phase de fin de vie et de recyclage d'un équipement
|Distribution|Dist| Phase d'acheminement du produit et des matières
|===

[#_criteres_dimpacts_environnementaux]
=== Critères d'impacts environnementaux
Les critères d'impact correspondent aux types d'impact environnementaux suivis par l'outil.
Sont retenus actuellement les critères décris dans la PCR Service Numérique ([1] des <<_documents_de_reference>>) comme obligatoire :

* Épuisement des ressources naturelles (minérales et métaux)
* Changement climatique
* Acidification
* Émissions de particules fines
* Radiations ionisantes
* Consommation d’énergie primaire (indicateur de flux - complémentaire)

Le raisonnement multicritère est important car il permet d'éviter les transferts d'impact lors de la planifaction du plan d'action suivant l'acte de mesure de l'empreinte.
Comme pour les étapes ACV, ce moteur de calcul permet nativement l'ajout d'autres critères d'impact environnementaux.

[#_Organisation]
=== L'Organisation
L'organisation regroupe l'ensemble des tiers utilisant NumEcoEval appartenant à une même structure. Une organisation peut contenir différentes entités.

.Exemple
Le Ministère de la Transition Écologique et de la Cohésion des Territoires est une organisation qui sollicite NumEcoEval pour calculer l'empreinte environnementale de son SI.

[#_architecture_fonctionnelle]
== Architecture fonctionnelle de la solution

image::architecture_fonctionnelle_simplifiee_V1.png[]

Comme indiqué dans le schéma d'architecture fonctionnel simplifié ci-dessus, il convient de distinguer différents types de données :

* Les *données brutes* : ce sont les données stockées sans transformation, sous des formes très différentes, dans les outils d'une organisation. Ces données peuvent être statiques (elles ne varient pas ou peu et sont valables à l'échelle d'un an) ou dynamiques (elles varient souvent et doivent être mesurées régulièrement). Elle sont fournies par des sondes, des API... et ne sont pas structurées au format G4IT.
* Les *données d'entrées* :  ce sont les données normalisées (format NumEcoEval), capables d'être comprises par G4IT et peuvent être interprétées par l'outil pour faire ses calculs. Ces données sont donc généralement issues de la transformation des données brutes (traduction, redressement, nettoyage...).
* Les *indicateurs* : ce sont les données pouvant être affichées dans les dashboards SuperSet. Elles sont généralement calculées via les règles présentes dans ce document (exemple : impact en CO2 eq d'un équipement) ou sont issues des données brutes (exemple : nombre d'équipements). Ces indicateurs sont de deux types :

	** Stratégiques : ils permettent au DSI ou aux sponsors des domaines d'avoir l'état de lieux et de fixer les objectifs
    ** Opérationnels : ils permettent au responsable de secteur et AMOE de mettre en place les actions sur leur périmètre.

* Les *références* : ce sont les données normalisées (format NumEcoEval), qui servent de base aux calculs des impacts pour les différentes phases du cycle de vie d'un équipement (cf. <<_analyse_de_cycle_de_vie>>) et pour les différents critères (cf. <<_criteres_dimpacts_environnementaux>>). Ces données peuvent provenir de base de référence externes (NegaOCtet, Base Impact de l'ADEME, base BOAVIZTA...), ou peuvent être calculées par le client (exemple : calcul de la consommation électrique moyenne annuelle d'un équipement).

== Description des Modules

=== Bloc Références
[#_donnees_de_reference]
==== Données de référence

Les données de références correspondent aux données qui ne proviennent pas directement de l'organisation (<<_Organisation>>)souhaitant utiliser NumEcoEval. Ces données peuvent être issue de la littérature scientifique, de bases de données de références externes et reconnues (NegaOctet, Base IMPACT de l'ADEME, bases de données BOAVIZTA...), ou issue de travaux empiriques. Ces données doivent nécesairement être sourcées pour assurer la traçabilité des calculs.

Le tableau suivant permet de connaitre les données de référence utilisées dans les différentes règles de calcul.Ces données seront précédées du préfixe "ref_" suivi d'une suite de lettre permettant d'identifier la table concernée.

exemple :
|===
|Identifiant|Description des données
|ref_Critere|Précise les critères pris en charges par l'outil, leur unité et d'autres informations qui leurs sont associées.
|ref_Etape|Précise les étapes du cycle de vie prises en charge par l'outil.
|ref_Hypothese |Précise les hypothèses nécessaires à certains calculs des indicateurs (par exemple les données par défaut)
|ref_TypeEquipement |Précise les types d'équipements autorisés et leur durée de vie par defaut
|ref_CorrespondanceRefEqP|Donne la correspondance entre les équipements présents dans les données d'entrées et les équipements de références présents dans la table ref_impactEquipement
|ref_ImpactEquipement |Donne pour chaque type équipement référencé, son impact environnemental selon le critère (<<_criteres_dimpacts_environnementaux>>) et le cycle de vie (<<_analyse_de_cycle_de_vie>>) regardé.
|ref_MixElec|Donne pour chaque pays référencé, l'impact environnemental d'un kWh d'électricité produit, selon les différents critères d'impact.
|ref_ImpactReseau|Donne l'impact lié à l'utilisation du réseau selon les différents critères et l'étapes dans le cycle de vie.
|===

**Pour chaque type d'objet, des endpoints de CRUD (Create/Read/Update/Delete) sont disponibles**

le format de ces références est contraint pour garantir la capacité du moteur de calul (cf.<<_moteur_de_calcul>>) à produire les indicateurs.

link:./References.plantuml[Diagramme de classe des référentiels]

Toutes ces données sont nécessaires au calcul des règles d'impact. Elles doivent être chargées par un administrateur NumEcoEval avant d'intégrer les données d'entrée.
===== Précisions sur l'import CSV de certains référentiels

*Référentiels dépendants d'une organisation* :

Le référentiel est lié à une organisation donnée. L'import se fait avec 2 paramètres :

* Le nom d'organisation pour laquelle les données sont établies
* Le fichier CSV du référentiel

Lors de l'import, les données précédentes de l'organisation pour le référentiel sont supprimées.

_Concerne_: ref_CorrespondanceRefEqP

*Référentiels généraux* :

Le référentiel est global à tout le système. L'import se fait uniquement avec le fichier CSV du référentiel.

Lors de l'import, les données précédentes sont supprimées.

_Concerne_: ref_Critere, ref_Etape, ref_ImpactEquipement, ref_MixElec, ref_ImpactReseau

==== Exposition du bloc

Les données de ce bloc sont exposées via les points suivants :
|===
|Endpoint API REST|Description|Paramètres|Sortie
|[[GET_Etapes]]GET /referentiels/etapes|Renvoie la liste des étapes de ref_EtapeACV|Aucuns| Liste d'objet ref_EtapeACV
|[[GET_Criteres]]GET /referentiels/criteres|Renvoie la liste des Critères de ref_Critere|Aucuns| Liste d'objet ref_Critere
|[[GET_ImpactsReseaux]]GET /referentiels/impactreseaux?etape=+{etape}+&critere=+{critere}+&reseau=+{refReseau}+|Renvoie l'impact d'un équipement sur le réseau selon les paramètres|Le nom du critère, le code de l'étape de cycle de vie et la référence de l'équipement|Un objet ref_ImpactReseau
|[[GET_Hypotheses]]GET /referentiels/hypotheses?cle=+{cle}+|Renvoie l'objet ref_Hypothese correspondant à la clé|La clé unique de l'hypothèse|Un objet ref_Hypothese
|[[GET_typeEquipement]]GET /referentiels/typeEquipement?type=+{type}+|Renvoie l'objet typeEquipement correspondant au type d'équipement|Le type d'équipement|Un objet ref_TypeEquipement
|[[GET_impactMessagerie]]GET /referentiels/impactMessagerie?critere=+{critere}+|Renvoie l'objet ref_ImpactMessagerie correspondant au critère|La référence d'impact messagerie|Un objet ref_ImpactMessagerie
|===

**Pour chaque type d'objet, des endpoints de CRUD (Create/Read/Update/Delete) sont disponibles**

_Tableau des endpoints CRUD en attente des retours sur Spring Data REST_
_TODO Ajouter le tableau une fois les endpoints stabilisés_

Pour certains référentiels compatibles, un endpoint d'import par fichier CSV est disponible
pour permettre un chargement en masse.
|===
|Exemple d'endpoint d'import par CSV|Description|Paramètres|Sortie
|POST /referentiels/<objet_ref>/import/csv|Importer plusieurs références. L'import fonctionne en annule-et-remplace (suppression de toutes les données avant import).|Le fichier CSV avec les données à insérer|Rapport du fichier CSV (nombre de lignes totales, nombre de lignes en erreur, nombre de lignes traitées, liste des erreurs par lignes).
|===

Ce endpoint est actuellement disponible pour les référentiels suivants :
ref_Critere, ref_EtapeACV, ref_Hypothese, ref_TypeEquipement, ref_ImpactEquipement,
ref_MixElec, ref_ImpactReseau, ref_ImpactMessagerie.

**Points d'attention **

- Par construction, une suppression sur le référentiel ref_EtapeACV supprime les référentiels référençant cette étape : ref_ImpactEquipement, ref_ImpactReseau et ref_ImpactMessagerie.
- Par construction, un import CSV sur le référentiel ref_EtapeACV supprime les référentiels référençant les étapes : ref_ImpactEquipement, ref_ImpactReseau et ref_ImpactMessagerie.
- Par construction, une suppression sur le référentiel ref_Critere supprime les référentiels référençant le critère : ref_ImpactEquipement, ref_ImpactReseau, ref_ImpactMessagerie et ref_MixElec.
- Par construction, un import CSV sur le référentiel ref_Critere supprime les référentiels référençant les critères : ref_ImpactEquipement, ref_ImpactReseau, ref_ImpactMessagerie et ref_MixElec.

==== Précision sur les hypothèses
Les hypothèses de travail se trouvent dans la table "Hypothèses".
Elles sont uniques pour une clé donnée.
À l'usage dans la suite du document, une hypothèse peut être retrouvée via la formule :
`ref_Hypothese(<clé d'hypothèse>)`

.Exemple d'hypothèses :
|===
|clé|valeur|source
|dureeVieParDefaut|1| dans le cas où la durée de vie d'un type d'équipement  ne serait pas renseigner on considère une hypothèse majorante d'une mise a rebut de l'équipement au bout de 1 an.
|===

[#_api_donnees_dentrees]
=== API pour les données d'entrées

L'API pour les données d'entrées permet d'importer des données dans le système NumEcoEval via des endpoints REST.

Toutes les informations reçues sont envoyés simultanément :
- Au bloc Données d'entrées pour historisation des données reçues si le module est activé
- Au bloc Calcul afin de produire les indicateurs issus des règles de calculs décrites dans ce document.

==== Endpoints de l'API

Les données de ce bloc sont exposées via les points suivants :
|===
|Endpoint API REST|Description|Paramètres|Sortie
|POST /entrees/csv|Envoi d'un objet en_DonneesEntree aux blocs Calculs (et enregistre ces Données Entrées si ce bloc "donnée d'entrée) est activé) | Les fichiers CSV correspondant aux différentes classes présentes dans les données d'entrée (équipement physiques, virtuels, datacenter...) 
|Rapports par fichier CSV contenant le nombre de lignes en erreur, le nombre d'objets intégrés, la liste des erreurs par lignes).
|===

=== Bloc Données d'entrées (optionnel)
Ce bloc est optionnel, il n'est pas nécessaire au calcul des indicateurs mais il permet d'historiser les données de dimensionnement de l'organisation, permettant de réaliser des rejeux de calculs et de connaitre les valeurs utilisé à un instant t.

[#_donnees_dentrees]
==== Données d'entrées

Les données d'entrée du sytème se trouvent dans la base "Entree".
Dans la spécification, les objets représentant des données d'entrées sont précédées du préfixe "en_"
et sont classées en 4 catégories :

* en_EqP: liste des équipements physiques (type, d'équipement)
* en_EqV : liste des équipements virtuels (vCPU, équipement physique sous jacent...)
* en_DC : liste des datacenters (identification, PUE)
* en_App : liste des applications

Tous ces objets sont groupées dans un objet en_DonneesEntree avant d'être envoyé dans l'outil.
Dans un premier temps, il est possible d'envoyer les objets par groupes.

le format de ces données d'entrée est contraint pour garantir la capacité du moteur de calul (cf.<<_moteur_de_calcul>>) à produire les indicateurs/
link:./DonneeEntree.plantuml[Diagramme de classe des entrées]

[#_bloc_calcul]
=== Bloc Calcul
Ce bloc représente le coeur de métier de la solution NumEcoEval.
Il permet de produire des indicateurs en se basant sur :

* Les référentiels exposés par le bloc Références (comprenant les critères, les étapes AVC, les hypothèses,... cf. <<_donnees_de_reference>>)
* Les données d'entrées reçues via un objet en_DonneesEntree : cf <<_donnees_dentrees>>

Le moteur de calcul permet d'intégrer toutes les règles de calcul (<<_regles_de_calcul>>) qui se basent sur les données de références et les données d'entrées.
Il permet de calculer des indicateurs qui pourront ensuite être utilisés unitairement ou associés entre eux pour fournir une vision de l'empreinte environnementale d'un périmètre et aider les utilisateurs à piloter leurs plans d'action.

cf.<<_moteur_de_calcul>>

[#_bloc_indicateurs]
=== Bloc Indicateurs
==== Historisation des indicateurs

Ce module permet d'historiser les indicateurs produits par le bloc de calcul.
Les indicateurs sont stockés dans des tables dédiées.

Tous les indicateurs sont autoporteurs, c'est-à-dire qu'ils sont compréhensibles et apportent de la valeur unitairement : ils font référence à un seul critère et une seule étape ACV, et la valeur de l'indicateur est toujours couplée avec une unité.

link:./Indicateurs.plantuml[Diagramme de classes des indicateurs]

==== Exposition du bloc

Le bloc Indicateurs expose les points suivants :
|===
|Méthode d'exposition dans la spécification|Description|Paramètres|Sortie
|[[sauvegarder_impact]]sauvegarder_impact(ind_Impact)|Persiste un objet ind_Impact (ou une des classes filles) en base de données|L'objet ind_Impact à sauvegarder en base de données| Aucunes
|===


[#_cles_de_lecture]
== Clés de lectures du pseudocode

* Pour faciliter la lecture des règles de calcul, chaque donnée est préfixée selon le module à laquelle elle appartient :
** Les données en entrée du système sont préfixées par en_
** Les données de référence sont préfixées par ref_ 

* Les objects manipulés ont la forme suivante  `nomDeClasse nomObjet`
** Exemple : `en_EqP EqP` indique qu'un objet `EqP` de classe `en_EqP` est disponible

* Pour les référentiels et les hypothèses : les éléments entre `()` correspondent aux clés uniques de lecture
** Exemples:
*** `ref_Hypothese(dureeVieParDefaut)` correspond à utiliser l'API GET /referentiels/hypotheses?cle={cle} avec la clé `dureeVieParDefaut` (cf.<<GET_Hypotheses>>)
pour obtenir l'objet ref_Hypothese correspondant
*** `ref_ImpactReseau(etape,critere,refReseau)` (cf.<<GET_ImpactsReseaux>>) correspond à utiliser l'API GET /referentiels/impactreseaux?etape={etape}&critere={critere}&reseau={refReseau} avec les paramètres `Etape`,`Critere` et `refReseau` correspondant

* Le "." derrière un objet (déclaré ou obtenu après une méthode d'exposition) indique l'accès à un attribut de l'objet.
** Exemples :
*** `ref_Hypothese(dureeVieParDefaut).valeur` correspond au champ valeur de l'objet ref_Hypothese de clé `dureeVieParDefaut`
*** `ref_ImpactReseau(Etape,Critere,refReseau).valeur` correspond au champ valeur de l'objet ref_ImpactReseau correspondant à `Etape`,`Critere` et `refReseau`

* Toutes les règles qui calculent des indicateurs l'enregistre en base de donnée grâce à la methode sauvegarder_impact(ImpactUnitaireReseau) : cf.<<sauvegarder_impact>>


[#_moteur_de_calcul]
== Moteur de calcul

Le déclenchement des règles présentes dans le Bloc Calcul se réalise à la soumission des calculs sur un lot donné via le endpoint POST /entrees/calculs/soumission.
NumEcoEval lance alors les calculs des indicateurs et les sauvegarde dans la base correspondante.

La cinématique globale est décrite ci-dessous :

image::cinématique.png[]

Voici l'algorithme général permettant le caclul des indicateurs

pseudocode
----
CalculDesIndicateurs(en_DonneesEntree) {
	List<ref_EtapeACV> etapes = GET /referentiels/etapes;
	SI en_DonneesEntree.etapesDemandees est renseigné
		ALORS mettre à jour la liste etapes pour ne contenir que les étapes demandées
	FIN SI

	List<ref_Critere> criteres = GET /referentiels/criteres;
	SI en_DonneesEntree.criteresDemandees est renseigné
		ALORS mettre à jour la liste criteres pour ne contenir que les critères demandés
	FIN SI

    BOUCLE SUR CHAQUE etape DE LA LISTE ref_EtapeACV
        BOUCLE SUR CHAQUE criteres DE LA LISTE ref_Critere

			initialisation d'un compteur d'impact applicatif

			BOUCLE SUR CHAQUE en_EqP DE en_DonneesEntree
				// Exécutions des règles sur les équipements physiques
				calculIndicateurImpactEquipementPhysique(etape, critere, en_DonneesEntree.nomOrganisation, en_EqP, en_DC, ind_ImpactEquipementPhysique)

				SI en_EqP.type est un serveur (ref_TypeEquipement.serveur est vrai)
					ALORS initialisation de la variable NbvCPU correspondant à la SOMME des vCPU de tous les équipements virtuels de l'équipement physique si ce dernier est renseigné ou à l'équipement physique dans le cas contraire
					ET initialisation de la variable stockageTotalVirtuel correspondant à la SOMME des capaciteStockage de tous les équipements virtuels de l'équipement physique si ce dernier est renseigné ou à l'équipement physique dans le cas contraire
					ET initialisation de la variable nbEqV correspondant au nombre de équipements virtuels de l'équipement physique si ce dernier est renseigné ou à l'équipement physique dans le cas contraire
					ET initialisation du bouléen vCPUoK indiquant que l'ensemble des équipements virtuels de l'équipement physique (si ce dernier est renseigné ou à l'équipement physique dans le cas contraire) possède un vCPU renseigné, entier et > à 0
					ET initialisation du bouléen stockoK indiquant que l'ensemble des équipements virtuels de l'équipement physique (si ce dernier est renseigné ou à l'équipement physique dans le cas contraire) possède un vCPU renseigné, entier et > à 0

					Soit ImpactEqP = ind_ImpactEquipementPhysique.ImpactUnitaire/ind_ImpactEquipementPhysique.quantite calculé dans cette boucle
					Soit ConsoElecEqP = ind_ImpactEquipementPhysique.consoElecMoyenne/ind_ImpactEquipementPhysique.quantite calculé dans cette boucle calculée dans cette boucle

					BOUCLE SUR CHAQUE en_EqV DE en_DonneesEntree dont l'équipement physique (en_EqV.nomEquipementPhysique) correspond à celui traité dans cette boucle
						
						ind_ImpactEquipementVirtuel = calculIndicateurImpactEquipementVirtuel(etape, critere, en_EqV, ImpactEqP, ConsoElecEqP, NbvCPU, nbEqV, vCPUoK, stockageTotalVirtuel, stockoK, ind_ImpactEquipement)
						
						// Calcul des impacts applicatifs : ils correspondent, pour l'impact unitaire, à la somme des impacts unitaires des équipements virtuels d'une application pour un type d'environnement, un critere et une étape ACV, et, pour la consommation electrique, à la somme des consommations électriques des équipements virtuels sous jacent.
						BOUCLE SUR CHAQUE en_App  DE en_DonneesEntree pour en_App.nomEquipementVirtuel = en_EqV.nomEquipementVirtuel
							SI AUCUN impact applicatif n'a été enregistré pour en_App.nomApplication, en_App.typEnvironnement, en_App.critere et en_App.etapeACV
								ALORS ENREGISRER l'impact applicatif
							SINON 
								AJOUTER ind_ImpactEquipementVirtuel à l'impact applicatif précedemment enregirsté 
							FIN SI

						FIN BOUCLE
					FIN BOUCLE			
				FIN SI

				// Calcul de l'impact réseau associé à ces équipements
				CalculImpactReseau(en_EqP, etape, critere, ind_ImpactReseau)
			
			FIN BOUCLE

        FIN BOUCLE

    FIN BOUCLE

    // Messagerie
	BOUCLE SUR CHAQUE critere DE LA LISTE ref_Critere
		SI ref_ImpactMessagerie.critere EXISTE pour le ref_Critere en cours
			BOUCLE SUR CHAQUE en_Messagerie DE LA LISTE en_DonneesEntree.messageries
				calculImpactMessagerie(en_Messagerie, critere, ref_ImpactMessagerie, ind_ImpactMessagerie)
			FIN BOUCLE
		FIN SI
	FIN BOUCLE

	SAUVERGARDER les indicateurs d'impact applicatif une fois l'ensemble des boucles terminées.
}
----

Liens vers les principaux éléments de cet algorithme

* <<GET_Etapes>>
* <<GET_Criteres>>
* <<_regles_de_calcul>>
** <<_calcul_impact_EqP_unitaire>>
** <<_calcul_impact_EqV_unitaire>>
** <<_calculImpactReseau>>
** <<_calculImpactMessagerie>>




[#_regles_de_calcul]
== Règles de calcul

=== Règles Générales

[#_rg_transfertdonnees]
==== Transfert de données

Certaines données reçues via les données d'entrées sont des données transmises
en mode "passe-plat" de l'entrée jusqu'aux indicateurs.
Ces données servent divers objectifs tels que :

- Le regroupement des indicateurs par lot
- La recherche dans les indicateurs
- Permettre d'agréger les données qui concernent une même catégorie (Organisation, entité, type d'équipement...)
- Les traces

Les champs de même nom dans les objets d'entrées (en_*) et les objets indicateurs (ind_*)
doivent être transmis à l'identique sans traitement particulier par le moteur de calcul.

Les champs concernés sont les suivants :

|===
|Nom du champ|Obligatoire|Objet Source|Objet de Sortie|Description et usage
|dateLot|Obligatoire|en_DonneesEntree|Tous les objets indicateurs|Date du lot de rattachement des données, permet de regrouper les données d'indicateurs. Définit une seule fois pour tous les objets.
|nomOrganisation|Obligatoire|en_DonneesEntree|Tous les objets indicateurs|Nom de l'organisation rattachée aux données, permet de regrouper les données d'indicateurs. Définit une seule fois pour tous les objets.
|nomEntite|Facultatif|Tous les objets d'entrées|Objets indicateurs du même niveau|Nom de l'entité responsable pouvant agir sur l'objet. Elle est définie dans les données d'entrées et alimente les indicateurs associés.
|===



[#_rg_traceCalcul]
==== RG_TraceCalcul

Pour chaque calcul produisant un indicateur (classe héritant de ind_Impact),
le moteur de calcul produit une trace représentée par un objet d'une des classes suivantes :

- TraceCalculImpactEquipementPhysique : la trace du calcul d'impact d'équipement physique cf. <<_calcul_impact_EqP_unitaire>>
- TraceCalculImpactEquipementVirtuel : la trace du calcul d'impact d'équipement virtuel cf. <<_calcul_impact_EqV_unitaire>>
- TraceCalculImpactMessagerie : la trace du calcul d'impact de la messagerie cf. <<_calculImpactMessagerie>>
- TraceCalculImpactReseau : la trace du calcul d'impact du réseau cf. <<_calculImpactReseau>>

Tous les objets de trace de calcul possèdent un champ "formule" permettant de vérifier le calcul de l'impact.
La formule se présente comme un calcul mathématique avec le nom des variables et leurs valeurs entre parenthèses.

_Exemple de valeur pour le champ formule :_
`ImpactEquipementPhysique = (Quantité(1.0) * ConsoElecAnMoyenne(29.198638586342973) * MixElectrique(0.0813225) * NbJourUtiliseAn(365.0) * tauxUtilisation(1.0)) / 365`

_Les formules originales (sans variable) sont visibles dans les différentes règles de calcul._

En fonction des règles concernées, des champs supplémentaires sont alimentés pour faciliter la vérification.

link:./Traces.plantuml[Diagramme de classes des objets relatifs aux traces]


[#_rg_dureevieeqp]
==== RG_DureeVieEqP : durée de vie d'un équipement physique

|===
|Version|Type de changement|Description
|V1|création|Initialisation de la règle à dire d'expert
|===

La durée de vie d'un équipement détermine la manière dont est amortie l'impact de sa fabrication.
Elle est exprimée en année et autorise les décimales.


|===
|parametre|entree/sortie|Description
|equipementPhysique|entrée|L'équipement physique dont on cherche à calculer la durée de Vie
|dureeVieEqP|sortie|La durée de vie de l'équipement physique
|===

[pseudocode]
----
Règle RG_DureeVieEqP(equipementPhysique,dureeVieEqP) {
	
	'dans le cas où il est possible de calculer l'age réel de l'équipement, ce dernier fait foi
	SI equipementPhysique.DateAchat est correcte et renseignée ET equipementPhysique.DateRetrait est correcte et renseignée
	ALORS
		SI (equipementPhysique.DateRetrait - equipementPhysique.DateAchat) < 1
		ALORS RENVOYER 1
		SINON RENVOYER ((equipementPhysique.DateRetrait - equipementPhysique.DateAchat) / 365)
	
	'dans le cas où seul la date d'achat est disponible, la règle du "Pseudo-amortissement" prévaut (impact de 100% sur l'année d'achat, 50% l'année 2, 33% l'année 3, etc... )
	SINON SI equipementPhysique.DateAchat est correcte et equipementPhysique.DateRetrait non reseignée
		ALORS RENVOYER ((equipementPhysique.DateAchat - date du jour) / 365)
	
	'dans les autres cas, une durée de vie moyenne de l'équipement est déduite
	SINON
			RENVOYER RG_DureeVieEqP_Defaut(equipementPhysique)
	FIN SI
}
----

cf.<<_rg_dureevieeqp_defaut>>

[#_rg_dureevieeqp_defaut]
==== RG_DureeVieEqP_Defaut : durée de vie des équipements par défaut

|===
|Version|Type de changement|Description
|V1|création|Initialisation de la règle à dire d'expert
|===

La durée de vie des équipements peut être déterminée par défaut dans le cas où la date d'acquisition ne serait pas renseignée. Elle est alors calculée sur la base suivante

|===
|paramètre|entree/sortie|Description
|equipementPhysique|entrée|L'équipement physique dont on cherche à calculer la durée de Vie par défaut
|dureeVieEqP_Defaut|sortie|La durée de vie par défaut de l'équipement physique
|===

[pseudocode]
----
Règle RG_DureeVieEqP_Defaut(equipementPhysique, dureeVieEqP_Defaut) {
		'la durée de vie par défaut des équipements est celle renseignée dans la table des types d'équipements
		SI l'équipement physique en entrée est présent dans la table des références d'équipement (ref_TypeEquipement.type) 
			ALORS dureeVieEqP_Defaut = ref_TypeEquipement.dureeVieDefaut
		'on retient l hypothèse d'une durée de vie par défaut des équipements égale à la durée de vie des équipements enregistrée dans les hypothèses
		SINON SI ref_Hypothese(dureeVieParDefaut) existe
			ALORS dureeVieEqP_Defaut = ref_Hypothese(dureeVieParDefaut).valeur
		SINON
			ErrCalcul("la durée de vie par défaut de l'équipement n'a pas pu être déterminée")
		FIN SI
}
----

[#_rg_correspondance_RefEquipement]
==== RG Correspondance entre les équipements et leur références :

|===
|Version|Type de changement|Description
|V1|création|Initialisation de la règle
|===

Cette règle permet de retrouver l'équipement de référence, c'est à dire celui dont les facteurs d'impact seront utilisés afin d'évaluer l'impact de l'équipement en court de traitement.

|===
|paramètre|entree/sortie|Description
|organisation|entrée|l'organisation en cours de traitement
|equipement|entrée|l'équipement dont on cherche la référence
|refEquipementretenu|sortie|l'équipement dont l'impact servira de référence
|===

[pseudocode]
----
Règle RG_correspondanceRefEquipement(nomOrganisation, equipement, refEquipementretenu) { 
	
		SI ref_CorrespondanceRefEqP(nomOrganisation, equipement.modele) existe 
			RENVOYER refEquipementretenu = ref_CorrespondanceRefEqP(nomOrganisation, equipement.modele).refEquipementCible
		SINON SI ref_TypeEquipement(equipement.type).refEquipementParDefaut existe 
			RENVOYER refEquipementretenu = ref_TypeEquipement(equipement.type).refEquipementParDefaut 
		SINON
			ErrCalcul("aucune correspondance avec un équipement de référence n'a pu être déterminée")
		FIN SI

}
----

=== Calculs d'impacts unitaires



[#_calcul_impact_EqP_unitaire]
==== Calcul impact unitaire équipement physique

|===
|Version|Type de changement|Description
|V1|création|Initialisation de la règle à dire d'expert
|===

Cette règle permet le calcul de l'impact moyen d'un équipement physique sur une année. Elle possède 3 paramètres : l'équipement dont on cherche à déterminer l'impact, l'étapeACV qui permet de déterminer quelle étape du cycle de vie de l'équipement est regardée et le critère d'impact que l'on souhaite extraire.

|===
|parametre|entree/sortie|Description
|critere|entrée|le critere dont on cherche à calculer la durée de Vie par défaut
|etapeACV|entrée|l'étape ACV dont on cherche à calculer la durée de Vie par défaut
|nomOrganisation|entrée|le nom de l'organisation en cours de traitement, récupéré de en_DonneesEntrees.nomOrganisation
|equipementPhysique|entrée|l'équipement physique dont on cherche à calculer l'impact environnemental
|en_DC|entrée|le PUE du datacenter lié à l'équipement physique.
|ind_ImpactEquipementPhysique.nomEquipement|sortie|le nom de l'équipement physique calculé
|ind_ImpactEquipementPhysique.critere|sortie|le critere calculé
|ind_ImpactEquipementPhysique.etapeACV|sortie|l'étape ACV calculé
|ind_ImpactEquipementPhysique.type|sortie|en_EqP.type
|ind_ImpactEquipementPhysique.impactUnitaire|sortie|L'impact calculé pour le critère et l'étape ACV, vaut null en cas d'erreur
|ind_ImpactEquipementPhysique.quantite|sortie|la quantité d'équipement physique
|ind_ImpactEquipementPhysique.tauxUtilisation|sortie|le taux d'utilisation de l'équipement physique
|ind_ImpactEquipementPhysique.modeUtilisation|sortie|le mode d'utilisation de l'équipement, il n'est utilisé que si le taux d'utilisation n'est pas renseigné. Les deux modes possibles sont (COPE & BYOD), les taux d'utilisation correspondants son enregistrés dans la table ref_hypotheses
|ind_ImpactEquipementPhysique.unite|sortie|l'unité présente dans le référentiel correspondant au critère en cours
|ind_ImpactEquipementPhysique.consoElecMoyenne|sortie|la consommation électrique déterminée par la règle suivante
|===

[pseudocode]
----
soit en_EqP(Equipement) = EqP

Règle calculIndicateurImpactEquipementPhysique(critere, etape, nomOrganisation, EqP, en_DC, ind_ImpactEquipementPhysique) {
'Récupération de la correspondance de refEquipement
refEquipementRetenu = RG_correspondanceRefEquipement(nomOrganisation, equipementPhysique)

	ind_ImpactEquipementPhysique(Equipement, EtapeACV, Critere) =
	
	SI EtapeACV.code = "UTILISATION"

		EqP.quantité

		SI EqP.consoElecAnnuelle est renseigné      
			x EqP.consoElecAnnuelle
			'enregistrement de la consommation electrique retenue
			ind_ImpactEquipementPhysique.consoElecMoyenne = EqP.consoElecAnnuelle
		SINON SI
			'récupération de la consommation électrique de la référence de l'équipement retenue
			x Ref_ImpactEquipement(refEquipementRetenu, EtapeACV, Critere).consoElecAnMoyenne
			'enregistrement de la consommation electrique retenue
			ind_ImpactEquipementPhysique.consoElecMoyenne = Ref_ImpactEquipement(refEquipementRetenu, EtapeACV, Critere).consoElecAnMoyenne
		SINON 
			ErrCalcFonc("donnée de consommation electrique manquante") 
			Arret du calcul
		FIN SI

		SI EqP.NomCourtDatacenter est renseigné

			SI n_DC(EqP.NomCourtDatacenter).PUE existe
				x en_DC(EqP.NomCourtDatacenter).PUE
			SINON SI ref_Hypothese(PUEParDefaut)
				x ref_Hypothese(PUEParDefaut)
			SINON 
				ErrCalcFonc("le PUE est manquant et ne permet le calcul de l'impact à l'usage de l'équipement") 
				Arret du calcul
			FIN SI

			x ref_MixElec(PaysDUtilisation = en_DC(NomCourtDatacenter).localisation).valeur
		SINON
			x ref_MixElec(PaysDUtilisation = EqP.PaysDUtilisation).valeur
		FIN SI

		SI EqP.tauxUtilisation est renseigné
			x EqP.tauxUtilisation
		SINON SI EqP.modeUtilisation est renseigné
			SI ref_Hypothese(EqP.modeUtilisation) existe
				EqP.tauxUtilisation = ref_Hypothese(EqP.modeUtilisation)
				x EqP.tauxUtilisation
			SINON 
				EqP.tauxUtilisation = 1.0
				x EqP.tauxUtilisation
		SINON 
			EqP.tauxUtilisation = 1.0
			x EqP.tauxUtilisation
		FIN SI

	SINON
		
		EqP.quantité

		SI EqP.tauxUtilisation est renseigné
			x EqP.tauxUtilisation
		SINON SI EqP.modeUtilisation est renseigné
			SI ref_Hypothese(EqP.modeUtilisation) existe
				EqP.tauxUtilisation = ref_Hypothese(EqP.modeUtilisation)
				x EqP.tauxUtilisation
			SINON 
				EqP.tauxUtilisation = 1.0
				x EqP.tauxUtilisation
		SINON 
			EqP.tauxUtilisation = 1.0
			x EqP.tauxUtilisation
		FIN SI

		'récupération de l'impact pour le critère et l'étape ACV en cours, de la référence de l'équipement retenue
		x Ref_ImpactEquipement(refEquipementretenu, EtapeACV, Critere).value
		
		/ RG_DureeVieEqP

		'conso electrique retenue est null
		ind_ImpactEquipementPhysique.consoElecMoyenne = null

	FIN SI
}
----

.Calcul de l'impact "moyen" en CO2 lié à l'utilisation d'un serveur sur 1 an
====
Equipement = exemple d'un serveur d'un client, sur une DataCenter possédant un PUE de 1.13

EqP.quantité = 1
x en_EqP.ConsoElecAnMoyenne= 1000 kWh
x en_EqP.tauxUtilisation = 0,85
x en_DC(NomCourtDatacenter = "googleCloud").PUE = 1,13
x ref_MixElec("France","Changement Climatique").valeur = 0,0813225

ImpactUnitaireEqP = 78,11 kg CO2eq /an
====


[#_calcul_impact_EqV_unitaire]
==== Calcul d'impact d'une machine virtuel

|===
|Version|Type de changement|Description
|V1|création|Initialisation de la règle à dire d'expert
|===

Cette règle permet le calcul de l'impact moyen d'un équipement virtuel sur une année.
L'impact alloué à la machine virtuelle correspond à une part de l'impact de l'équipement physique sous-jacent (décrit ici <<_calcul_impact_EqP_unitaire>>)

|===
|parametre|entree/sortie|Description
|critere|entrée|le critère dont on cherche à calculer la durée de Vie par défaut
|etapeACV|entrée|l'étape ACV dont on cherche à calculer la durée de Vie par défaut
|en_EqV|entrée|l'équipement virtuel dont on cherche à calculer l'impact environnemental
|ImpactEqP|entrée|l'équipement physique dont l'impact est en cours de calcul
|ConsoElecEqP|entrée|la consommation electrique retenue de l'équipement physique dont l'impact est en cours de calcul
|NbvCPU|entrée|le nombre de vCPU total de l'ensemble des machines virtuelles associées à l'équipement physique sous-jacent de l'équipement virtuel en cours de calcul
|nbEqV|entrée| le nombre total d'équipements virtuels associées à l'équipement physique sous-jacent de l'équipement virtuel en cours de calcul
|vCPUoK|entrée| le booléen indiquant que l'ensemble des VM du serveur possèdent un vCPU correctement renseigné
|ind_ImpactEquipementVirtuel.nomEquipement|sortie|le nom de l'équipement virtuel calculé
|ind_ImpactEquipementVirtuel.critere|sortie|le critère calculé
|ind_ImpactEquipementVirtuel.etapeACV|sortie|l'étape ACV calculée
|ind_ImpactEquipementVirtuel.cluster|sortie|le cluster présent dans les données d'entrée pour cette équipements virtuels
|ind_ImpactEquipementVirtuel.impactUnitaire|sortie|l'impact calculé pour le critère et l'étape ACV
|ind_ImpactEquipementVirtuel.unite|sortie|l'unité présente dans le référentiel correspondant au critère en cours
|ind_ImpactEquipementVirtuel.consoElecMoyenne|sortie|la consommation électrique renseignée en entrée 
|===


[pseudocode]
----
soit en_EqV(nomEquipementVirtuel) = EqV

Règle calculIndicateurImpactEquipementVirtuel(critere, etape, en_EqV, ImpactEqP, ConsoElecEqP, NbvCPU, nbEqV, vCPUoK, stockageTotalVirtuel, ind_ImpactEquipementVirtuel) {

	SI EqV.cleRepartition est renseigné
		ind_ImpactEquipementVirtuel.ImpactUnitaire = ImpactEqP x EqV.cleRepartition 
		ind_ImpactEquipementVirtuel.consoElecMoyenne = ConsoElecEqP x EqV.cleRepartition

	SINON SI EqV.typeEqV = "calcul" et vCPUoK est vrai
		ind_ImpactEquipementVirtuel.ImpactUnitaire = ImpactEqP x EqV.vCPU / NbvCPU
		ind_ImpactEquipementVirtuel.consoElecMoyenne = ConsoElecEqP x EqV.vCPU / NbvCPU

	SINON SI EqV.typeEqV = "stockage" et stockoK est vrai
		ind_ImpactEquipementVirtuel.ImpactUnitaire = ImpactEqP x EqV.capaciteStockage / stockageTotalVirtuel
		ind_ImpactEquipementVirtuel.consoElecMoyenne = ConsoElecEqP x EqV.capaciteStockage / stockageTotalVirtuel

	SINON
		'Si l'info des vCPU est manquante sur au moins un des équipement virtuel de l'équipement, on répartis l'impact à parts égale sur l'ensemble des équipements virtuels
		ind_ImpactEquipementVirtuel.ImpactUnitaire = ImpactEqP / nbEqV
		ind_ImpactEquipementVirtuel.consoElecMoyenne = ConsoElecEqP / nbEqV
	FIN SI

}
----


[#_calculIndicateurImpactApplicatif]
==== Calcul impact associé à une application 

|===
|Version|Type de changement|Description
|V1|création|Initialisation de la règle à dire d'expert
|===

Cet indicateur correspond l'impact moyen annuel d'une application. 
Il est calculé *directement dans le moteur de calcul* <<_moteur_de_calcul>> et part de l'hypothèse qu'un application tourne sur une ou plusieurs équipements virtuels dédiée(s). L'impact alloué à une application correspond alors l'impact des équipements virtuels sous-jacent (décrit ici <<_calcul_impact_EqV_unitaire>>).

|===
|parametre|entree/sortie|Description
|critere|entrée|le critère dont on cherche à calculer la durée de Vie par defaut
|etapeACV|entrée|l'étape ACV dont on cherche à calculer la durée de Vie par defaut
|nomApp|entrée|nom de l'applicaton 
|typeEnvironnement|entrée|type d'environnement sur lequel
|ind_ImpactApplicatif.nomApplication|sortie|en_App.nomApplication
|ind_ImpactApplicatif.critere|sortie|critère calculé
|ind_ImpactApplicatif.etapeACV|sortie|étape ACV calculée
|ind_ImpactApplicatif.typeEnvironnement|sortie|en_App.typeEnvironnement
|ind_ImpactApplicatif.domaine|sortie|en_App.domaine
|ind_ImpactApplicatif.sousDomaine|sortie|en_App.sousDomaine
|ind_ImpactApplicatif.unite|sortie|l'unité présente dans le référentiel correspondant au critère en cours
|ind_ImpactApplicatif.consoElecMoyenne|sortie|la consomation électrique calculée (correspondant à la somme des consommations éléctriques des équipements virtuels sous-jacentes)
|===


[#_calculImpactReseau]
==== Calcul impact lié à la sollicitation du réseau

|===
|version|type de changement|description 
|V1|création|Initialisation de la règle à dire d'expert
|===

*Note importante* : cette règle de calcul ne fait pas l'objet d'un consensus 
Cette règle permet le calcul de l'impact lié à la sollicitation des différents type de réseaux permettant l'interconnexion des utilisateurs et des équipements. Il peut s'agir de flux internet mais on peut aussi considérer les données transitant entre deux sites par exemple client via une liaison louée par exemple, ou même au sein d'un datacenter.

|===
|parametre|entree/sortie|Description
|equipementPhysique|entrée|l'équipement physique pour lequel l'impact réseau est calculé
|critere|entrée|le critere dont on cherche à calculer la durée de Vie par defaut
|etapeACV|entrée|l'étape ACV dont on cherche à calculer la durée de Vie par defaut
|ind_ImpactReseau.reference|sortie|type d'impact réseau
|ind_ImpactReseau.ImpactUnitaire|sortie|impact calculé
|ind_ImpactReseau.critere|sortie|critere calculé
|ind_ImpactReseau.etapeACV|sortie|etape ACV calculé
|ind_ImpactReseau.unite|sortie|l'unité présente dans le référentiel correspondant au critere en cours
|===

[pseudocode]
----
Règle calculImpactReseau(equipementPhysique, critere, etape, ind_ImpactReseau) {
	
	SI equipementPhysique.goTelecharge est renseigné ET ref_ImpactReseau(etape, critere, equipementPhysique) existe
	
	ALORS
		
		impactReseau = 
		equipementPhysique.goTelecharge 
		x ref_ImpactReseau(etape, critere, equipementPhysique).valeur

		RENVOYER ImpactUnitaireReseau
	
	SINON SI ref_ImpactReseau("impactReseauMobileMoyen") n'existe pas ou ref_ImpactReseau("impactReseauMobileMoyen").valeur n'est pas renseigné

		ErrCalcFonc("la référence impactReseauMobileMoyen n'existe pas")

	FIN SI
}
----

Références:

* ref_ImpactReseau(etape, critere, equipementPhysique) : cf.<<GET_ImpactsReseaux>>
* sauvegarder_impact(impact) : cf.<<sauvegarder_impact>>




[#_calculImpactMessagerie]
==== Calcul impact lié à la Messagerie

|===
|version|type de changement|description 
|V1|création|Initialisation de la règle à dire d'expert
|===

*Note importante* : cette règle de calcul ne fait pas l'objet d'un consensus 
Cette règle permet un calcul approximatif de l'impact lié à la messagerie. Il prend en compte l'impact moyen d'un mail établi à partir de différentes sources et en prenant en compte le poids des PJ (cf. sources)

|===
|parametre|entree/sortie|Description
|en_Messagerie|entrée|les données d'entrée liées à la messagerie
|ref_Critere|entrée|Critère d'impact en cours de travaux
|ref_Messagerie|entrée|Les paramètres associées à la fonction affine pour le critère en cours.
|ind_ImpactMessagerie.impactMensuel|sortie|l'impact calculé avec la fonction affine et les paramètre du référentiel
|ind_ImpactMessagerie.MoisAnnee|sortie|en_Messagerie.MoisAnnee
|ind_ImpactMessagerie.critere|sortie|ref_Critere.nomCritere
|ind_ImpactMessagerie|sortie|Autant d'indicateurs qu'il y a d'objet en_Messagerie en entrée
|===

[pseudocode]
----
Règle calculImpactMessagerie(en_Messagerie, ref_Critere, ref_ImpactMessagerie, ind_ImpactMessagerie) {

	'Production d'un indicateur ind_ImpactMessagerie par entrée en_Messagerie
		'calcul du poids moyen d'un mail en Go
		Double poidsMoyenMail = en_Messagerie.volumeTotalMailEmis/en_Messagerie.nombreMailEmis
		'on applique la fonction affine en utilisant les éléments du ref_ImpactMessagerie pour connaitre l'impact d'un mail en C02 selon son poids, et on le multiplie par le volume de mail envoyés
		ind_ImpactMessagerie.impactMensuel = (ref_ImpactMessagerie.constanteCoefficientDirecteur * poidsMoyenMail + ref_ImpactMessagerie.constanteOrdonneeOrigine) * en_Messagerie.nombreMailEmisXDestinataires
		ind_ImpactMessagerie.MoisAnnee = en_Messagerie.MoisAnnee
		ind_ImpactMessagerie.critere = ref_Critere.nomCritere

}
----

== Gestion des erreurs

=== ErrCalcFonc
Les erreurs fonctionnelles sont de la forme suivante : "ErrCalcFonc : [règle calculée et paramètres de la fonction associée] ; [message d'erreur]"
Au déclenchement de ce type d'erreur, une ligne s'affiche dans les logs, avec le nom de la règle où l'erreur s'est produite, les paramètres entrant de la règle et le message indiqués entre parenthèse.

.Erreur de calcul de l'impact réseau
====
 "ErrCalcFonc : ImpactUnitaireReseau(equipement, etapeACV, critere) ; la référence "impactReseauMobileMoyen" n'existe pas"
====

=== ErrCalcTech
Cette erreur se déclenche durant les calculs en cas d'erreurs non prévues et sont de la forme suivante : "ErrCalcTech : [règle calculée et paramètres de la fonction associée] ; [code de l'erreur technique]"


