def test_notation_only_root_default_status(): referentiel = Referentiel(root_action=make_action_referentiel()) notation = Notation(referentiel) scores = notation.compute_and_get_scores() assert_score_with_nomenclature_id_equals( scores, "", points=0.0, percentage=0.0, potentiel=defaut_referentiel_root_points_value, referentiel_points=defaut_referentiel_root_points_value, referentiel_percentage=1, )
def test_notation_only_root_default_status(): # todo, do we want to keep this ? referentiel = Referentiel(root_action=make_action_referentiel(points=42), mesure_depth=0) notation = Notation(referentiel) scores = notation.compute_and_get_scores() assert_score_with_nomenclature_id_equals( scores, "", points=0.0, percentage=0.0, potentiel=42, referentiel_points=42, referentiel_percentage=1, )
async def get_eci_scores(epci_id: str): query = ActionStatus.filter(epci_id=epci_id, latest=True) statuses: List[ActionStatus] = await ActionStatus_Pydantic.from_queryset( query) notation = Notation(referentiel_eci) for status in statuses: if status.action_id.startswith("economie_circulaire"): index = tuple(status.action_id.split("__")[-1].split(".")) # convert the avancement set by the user to a statut for the notation engine notation_statut = Status.from_action_status_avancement( status.avancement) # set the status in the epci notation so the scores can be computed. notation.set_status(index, notation_statut) return notation.compute_and_get_scores()
def test_redistribution_amongst_niveaux_on_eci(): """Set all taches of a niveaux of an orientation as non concernée test it changes the niveaux sibling potentiel up.""" from api.notation.referentiels import referentiel_eci notation = Notation(referentiel_eci) niveau_nc = ("1", "1", "1") orientation = ("1", "1") niveaux_faits = [ index for index in notation.referentiel.indices if index[:-1] == orientation and index != niveau_nc ] for niveau in niveaux_faits: taches = [ index for index in notation.referentiel.indices if index[:-1] == niveau ] for tache in taches: notation.set_status(tache, Status.faite) taches_nc = [ index for index in notation.referentiel.indices if index[:-1] == niveau_nc ] for tache_nc in taches_nc: notation.set_status(tache_nc, Status.non_concernee) notation.compute() # assert that niveau non concerné is worth 0 assert notation.potentiels[niveau_nc] == 0 for tache_nc in taches_nc: assert notation.potentiels[tache_nc] == 0 # assert the niveaux faits are worth more because 1.1.1 is non concerné for niveau in niveaux_faits: assert notation.potentiels[niveau] > notation.referentiel.points[niveau] taches = [ index for index in notation.referentiel.indices if index[:-1] == niveau ] for tache in taches: assert notation.potentiels[tache] > notation.referentiel.points[ tache] # check totals orientation_taches_potentiel = sum([ notation.potentiels[index] for index in notation.referentiel.indices if index[:-2] == orientation ]) assert math.isclose(orientation_taches_potentiel, notation.referentiel.points[orientation])
async def get_cae_scores(epci_id: str) -> List[ActionReferentielScore]: query = ActionStatus.filter(epci_id=epci_id, latest=True) statuses: List[ActionStatus] = await ActionStatus_Pydantic.from_queryset( query) notation = Notation(referentiel_cae) for status in statuses: if get_referentiel_from_status(status) == "cae": index = tuple(status.action_id.split("__")[-1].split(".")) # convert the avancement set by the user to a statut for the notation engine notation_statut = Status.from_action_status_avancement( status.avancement) # set the status in the epci notation so the scores can be computed. try: notation.set_status(index, notation_statut) except UnknownActionIndex: print(f"Warning - UnknownActionIndex {index}") return notation.compute_and_get_scores()
def test_notation_redistribution(notation: Notation): """In orientation 1.1.1 mark everything 'non_concernee' except 1st niveau So that 1st niveau is worth all the points of its parent orientation """ niveaux_of_1_1_1 = notation.referentiel.children(("1", "1", "1")) for niveau in niveaux_of_1_1_1: notation.statuses[niveau] = Status.non_concernee notation.statuses[niveaux_of_1_1_1[0]] = Status.faite point_of_1_1_1 = notation.referentiel.points[("1", "1", "1")] notation.compute() # test that orientation 1.1.1 have score 100% of the points assert math.isclose(notation.points[("1", "1", "1")], point_of_1_1_1) # test that niveau 1.1.1.1 is worth the total its parent orientation. assert math.isclose(notation.points[("1", "1")], point_of_1_1_1) # test that tache 1.1.1.1 is worth the total its parent orientation. assert math.isclose(notation.points[("1", "1", "1", "1")], point_of_1_1_1)
def test_potentiel_non_redistribution_on_eci(): """Set all taches of every niveaux of an orientation as non concernée test it change the orientation potentiel to 0 and remove orientation points from ancestors potentiels.""" from api.notation.referentiels import referentiel_eci notation = Notation(referentiel_eci) orientation = ("1", "1") axe = ("1", ) root = () niveaux = [ index for index in notation.referentiel.indices if index[:-1] == orientation ] for niveau in niveaux: taches = [ index for index in notation.referentiel.indices if index[:-1] == niveau ] for tache in taches: notation.set_status(tache, Status.non_concernee) notation.compute() for niveau in niveaux: assert notation.potentiels[niveau] == 0.0 assert notation.potentiels[orientation] == 0.0 assert (notation.potentiels[axe] == notation.referentiel.points[axe] - notation.referentiel.points[orientation]) assert (notation.potentiels[root] == notation.referentiel.points[root] - notation.referentiel.points[orientation])
def test_potentiel_redistribution_on_eci(): """Set all taches of a niveau as non concernée, test it doesn't change potentiels of orientation but redistribute potentiel amongst niveaux""" from api.notation.referentiels import referentiel_eci notation = Notation(referentiel_eci) niveau = ("1", "1", "1") orientation = ("1", "1") axe = ("1", ) root = () taches = [ index for index in notation.referentiel.indices if index[:-1] == niveau ] for tache in taches: notation.set_status(tache, Status.non_concernee) notation.compute() assert notation.potentiels[niveau] == 0.0 siblings = [ n for n in notation.referentiel.children(orientation) if n != niveau ] for sibling in siblings: assert math.isclose( notation.potentiels[sibling], notation.referentiel.points[orientation] / len(siblings), ) assert notation.potentiels[orientation] == notation.referentiel.points[ orientation] assert notation.potentiels[axe] == notation.referentiel.points[axe] assert notation.potentiels[root] == notation.referentiel.points[root]
def test_notation(notation: Notation): """In orientation 1.1.1 mark everything 'fait' So that the grand total is the same as the orientation 1.1.1 points from référentiel """ niveaux_of_1_1_1 = notation.referentiel.children(("1", "1", "1")) for niveau in niveaux_of_1_1_1: notation.statuses[niveau] = Status.faite point_of_1_1_1 = notation.referentiel.points[("1", "1", "1")] notation.compute() # test that orientation 1.1.1 have score 100% of the points assert math.isclose(notation.points[("1", "1", "1")], point_of_1_1_1) # test that orientation 1.1.2 points is 0 assert notation.points[("1", "1", "2")] == 0 # test that the point of root (that is the grand total) is equal to orientation 1.1.1 assert math.isclose(notation.points[tuple()], point_of_1_1_1) # everything is marked as fait in orientation so the percentatge should be 100% assert math.isclose(notation.percentages[("1", "1", "1")], 1.0)
def test_potentiel_non_propagation_on_eci(): """Set some taches of a niveau as non concernée test it doesn't change potentiels of ancestors""" from api.notation.referentiels import referentiel_eci notation = Notation(referentiel_eci) niveau = ("1", "1", "1") orientation = ("1", "1") axe = ("1", ) root = () taches = [ index for index in notation.referentiel.indices if index[:-1] == niveau ] for tache in taches[1:]: notation.set_status(tache, Status.non_concernee) notation.compute() assert notation.potentiels[niveau] == notation.referentiel.points[niveau] assert notation.potentiels[orientation] == notation.referentiel.points[ orientation] assert notation.potentiels[axe] == notation.referentiel.points[axe] assert notation.potentiels[root] == notation.referentiel.points[root]
def notation(referentiel) -> Notation: return Notation(referentiel)
def test_notation_non_concernee_changes_parents_potentiels(): """ A l'intérieur d'une mesure/orientation : - Si une action a un statut "Non concernée", alors cette action n'est pas prise en compte pour calculer le score. *Exemple : Orientation 1.2. = 30 points Si niveau 1.2.1 dont le poids est 20% est "Non concerné" alors l'orientation 1.2 reste évaluée sur 30 points et le poids est reventilé sur les autres niveaux en augmentant de façon proportionnelle - 1.2.2 = 20% + 1/3 x 20% - 1.2.3 = 20% + 1/3 x 20% - 1.2.4 = 40% + 1/3 x 40% - Si toutes les actions sœurs ont un statut "Non concernée" (en dehors des mesures/orientations), alors le niveau parent est "Non concerné" et l'action n'est pas prise en compte pour calculer le score. *Exemple : Niveau 1.2.1. Si 1.2.1.1/2/3/4/5 sont "Non concernée" alors 1.2.1 = Non concernée* - Cas particulier : Si tous les enfants d'une mesure/orientation sont "Non concernée" alors la mesure/orientation a bien un statut "Non concernée" MAIS son nombre de points passe à "0" sans être reventilé sur les autres mesures/orientations. *Exemple : Orientation 1.2 = 30 points Si 1.2.1/2/3/4 = "Non concernée" alors 1.2 = "Non concernée" et "0/0 points" et la collectivité n'est plus évaluée sur 500 points mais sur 470 points.* """ action_1_2_1 = make_action_referentiel(id_nomenclature="1.2.1", actions=[], points=25) action_1_2_2 = make_action_referentiel(id_nomenclature="1.2.2", actions=[], points=25) action_1_2_3 = make_action_referentiel(id_nomenclature="1.2.3", actions=[], points=25) action_1_2_4 = make_action_referentiel(id_nomenclature="1.2.4", actions=[], points=25) action_1_2 = make_action_referentiel( id_nomenclature="1.2", actions=[action_1_2_1, action_1_2_2, action_1_2_3, action_1_2_4], points=30, ) action_1 = make_action_referentiel(id_nomenclature="1", actions=[action_1_2]) action_2_2 = make_action_referentiel( id_nomenclature="2.2", actions=[], points=470, ) action_2 = make_action_referentiel(id_nomenclature="2", actions=[action_2_2]) root_action = make_action_referentiel(actions=[action_1, action_2]) referentiel = Referentiel(root_action, mesure_depth=2) notation = Notation(referentiel) notation.set_status(index=("1", "2", "1"), status=Status.non_concernee) notation.set_status(index=("1", "2", "2"), status=Status.non_concernee) notation.set_status(index=("1", "2", "3"), status=Status.non_concernee) notation.set_status(index=("1", "2", "4"), status=Status.non_concernee) scores = notation.compute_and_get_scores() assert_score_with_nomenclature_id_equals( scores, "", points=0.0, percentage=0.0, potentiel=470, referentiel_points=500, referentiel_percentage=1, ) assert_score_with_nomenclature_id_equals( scores, "1", points=0, percentage=0.0, potentiel=0, referentiel_points=30, referentiel_percentage=30 / 500, ) assert_score_with_nomenclature_id_equals( scores, "1.2", points=0, percentage=0.0, potentiel=0, referentiel_points=30, referentiel_percentage=1, ) assert_score_with_nomenclature_id_equals( scores, "1.2.1", points=0, percentage=0.0, potentiel=0, referentiel_points=30 / 4, referentiel_percentage=1 / 4, ) assert_score_with_nomenclature_id_equals( scores, "2", points=0, percentage=0.0, potentiel=470, referentiel_points=470, referentiel_percentage=0.94, )