librairie jugmenet_majoritaire python locale
- pour préparer une comparaison avec https://github.com/MieuxVoter/majority-judgment-library-python
This commit is contained in:
@@ -1,5 +1,14 @@
|
||||
# Libraire de calcul Jugement majoritaire
|
||||
|
||||
## Etude
|
||||
|
||||
Une étude de l'existant est dans le répertoire étude.
|
||||
|
||||
Ce projet est plutot un jouet comparé à l'existant.
|
||||
L'idée ici serait d'avoir une API commune ou à minima des formats d'échanges communs.
|
||||
|
||||
## Cette Librairie
|
||||
|
||||
Le fonctionnement actuel est de fournir un fichier json contenant la votation.
|
||||
Ce fichier n'a pas de connaissance des votants, juste de leur vote.
|
||||
|
||||
|
||||
104
code/jugement_majoritaire/__init__.py
Normal file
104
code/jugement_majoritaire/__init__.py
Normal file
@@ -0,0 +1,104 @@
|
||||
import json
|
||||
import sys
|
||||
|
||||
verbose=False
|
||||
|
||||
def collect_votes(votes,candidats,mentions,warnings):
|
||||
collect={}
|
||||
default_mention=mentions-1
|
||||
for vote in votes:
|
||||
# missing candidat in vote picks the worse one
|
||||
for candidat in candidats:
|
||||
if not candidat in vote:
|
||||
vote[candidat]=default_mention
|
||||
|
||||
for candidat,mention in vote.items():
|
||||
if mention > default_mention or mention < 0:
|
||||
mention = default_mention
|
||||
warnings.append("index de mention invalide, soit la liste des mentions est erronnée soit la mention dans le vote est erronée")
|
||||
if candidat in collect:
|
||||
if mention in collect[candidat]:
|
||||
collect[candidat][mention]=collect[candidat][mention]+1
|
||||
else:
|
||||
collect[candidat][mention]=1
|
||||
else:
|
||||
collect[candidat]={mention:1}
|
||||
return collect
|
||||
|
||||
def jugement_majoritaire(poll):
|
||||
|
||||
votants=poll['votants']['decompte']
|
||||
candidats=poll['candidats']
|
||||
nombre_candidats=len(candidats)
|
||||
|
||||
# l'ordre des mentions est de la meilleure à la pire (reject)
|
||||
nom_mentions=poll['mentions']
|
||||
mentions=len(nom_mentions)
|
||||
|
||||
votes=poll["votation"]["votes"]
|
||||
if verbose:
|
||||
print('candidats:' + str(candidats))
|
||||
print(votes)
|
||||
|
||||
warnings=[]
|
||||
|
||||
collect=collect_votes(votes,list(candidats),mentions,warnings)
|
||||
if verbose:
|
||||
print(collect)
|
||||
|
||||
votant_median_check= votants / 2 if votants % 2 == 0 else ((votants-1) / 2) +1
|
||||
|
||||
votant_median=votants // 2 + votants % 2
|
||||
|
||||
if votant_median_check != votant_median:
|
||||
print('[ERROR] le nombre median de votants semble erroné. contactez le developpeur de ce code.' + str(votant_median_check))
|
||||
|
||||
merite={}
|
||||
mention_mediane={}
|
||||
merite_pourcent={}
|
||||
|
||||
# cumul : du meilleur au pire
|
||||
# range_mentions = range(len(mentions))
|
||||
# cumul du pire au meilleur
|
||||
range_mentions = range(mentions-1,-1,-1)
|
||||
|
||||
for candidat in list(candidats):
|
||||
vote=collect[candidat]
|
||||
cumul=0
|
||||
m=[0 for i in range(mentions)]
|
||||
mention_m=None
|
||||
pourcent=[0 for i in range(mentions)]
|
||||
for mention in range_mentions:
|
||||
if mention in vote:
|
||||
cumul=cumul+vote[mention]
|
||||
pourcent[mention]= ( 100 * vote[mention] ) / votants
|
||||
if cumul >= votant_median and mention_m is None:
|
||||
mention_m=mention
|
||||
m[mention]=cumul
|
||||
if cumul < votants:
|
||||
print('[ERROR] le cumul des votes doit correspondre au nombre de votants. contactez le developpeur de ce code.')
|
||||
mention_mediane[candidat]=mention_m
|
||||
merite[candidat]=m
|
||||
merite_pourcent[candidat]=pourcent
|
||||
|
||||
if verbose:
|
||||
print(merite)
|
||||
print(mention_mediane)
|
||||
|
||||
# les gagnants sont ceux qui ont la mention mediane minimale ( la meilleure )
|
||||
found=[]
|
||||
for mention in range(0,mentions):
|
||||
for candidat,merite_median in mention_mediane.items():
|
||||
if merite_median == mention:
|
||||
found.append({candidat:candidats[candidat]})
|
||||
if len(found) > 0:
|
||||
break
|
||||
|
||||
if verbose:
|
||||
print(found)
|
||||
print(nom_mentions[mention])
|
||||
|
||||
result = {'resultat':{'mention':nom_mentions[mention],'candidats':found},'merite':merite,'profil':merite_pourcent,"warnings":warnings}
|
||||
|
||||
return result
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import json
|
||||
import sys
|
||||
from jugement_majoritaire import jugement_majoritaire
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
poll_file=sys.argv[1]
|
||||
@@ -15,101 +16,6 @@ with open(poll_file,'r') as poll_fd:
|
||||
if verbose:
|
||||
print(poll)
|
||||
|
||||
votants=poll['votants']['decompte']
|
||||
candidats=poll['candidats']
|
||||
nombre_candidats=len(candidats)
|
||||
|
||||
# l'ordre des mentions est de la meilleure à la pire (reject)
|
||||
nom_mentions=poll['mentions']
|
||||
mentions=len(nom_mentions)
|
||||
|
||||
default_mention=mentions-1
|
||||
|
||||
votes=poll["votation"]["votes"]
|
||||
if verbose:
|
||||
print('candidats:' + str(candidats))
|
||||
print(votes)
|
||||
|
||||
warnings=[]
|
||||
default_vote={}
|
||||
for candidat in candidats:
|
||||
default_vote[candidat]=default_mention
|
||||
|
||||
collect={}
|
||||
for vote in votes:
|
||||
|
||||
# missing candidat in vote picks the worse one
|
||||
for candidat in candidats:
|
||||
if not candidat in vote:
|
||||
vote[candidat]=default_mention
|
||||
|
||||
for candidat,mention in vote.items():
|
||||
if mention > default_mention or mention < 0:
|
||||
mention = default_mention
|
||||
warnings.append("index de mention invalide, soit la liste des mentions est erronnée soit la mention dans le vote est erronée")
|
||||
if candidat in collect:
|
||||
if mention in collect[candidat]:
|
||||
collect[candidat][mention]=collect[candidat][mention]+1
|
||||
else:
|
||||
collect[candidat][mention]=1
|
||||
else:
|
||||
collect[candidat]={mention:1}
|
||||
|
||||
if verbose:
|
||||
print(collect)
|
||||
|
||||
votant_median_check= votants / 2 if votants % 2 == 0 else ((votants-1) / 2) +1
|
||||
|
||||
votant_median=votants // 2 + votants % 2
|
||||
|
||||
if votant_median_check != votant_median:
|
||||
print('[ERROR] le nombre median de votants semble erroné. contactez le developpeur de ce code.' + str(votant_median_check))
|
||||
|
||||
merite={}
|
||||
mention_mediane={}
|
||||
merite_pourcent={}
|
||||
|
||||
# cumul : du meilleur au pire
|
||||
# range_mentions = range(len(mentions))
|
||||
# cumul du pire au meilleur
|
||||
range_mentions = range(mentions-1,-1,-1)
|
||||
|
||||
for candidat in candidats:
|
||||
vote=collect[candidat]
|
||||
cumul=0
|
||||
m=[0 for i in range(mentions)]
|
||||
mention_m=None
|
||||
pourcent=[0 for i in range(mentions)]
|
||||
for mention in range_mentions:
|
||||
if mention in vote:
|
||||
cumul=cumul+vote[mention]
|
||||
pourcent[mention]= ( 100 * vote[mention] ) / votants
|
||||
if cumul >= votant_median and mention_m is None:
|
||||
mention_m=mention
|
||||
m[mention]=cumul
|
||||
if cumul < votants:
|
||||
print('[ERROR] le cumul des votes doit correspondre au nombre de votants. contactez le developpeur de ce code.')
|
||||
mention_mediane[candidat]=mention_m
|
||||
merite[candidat]=m
|
||||
merite_pourcent[candidat]=pourcent
|
||||
|
||||
if verbose:
|
||||
print(merite)
|
||||
print(mention_mediane)
|
||||
|
||||
# les gagnants sont ceux qui ont la mention mediane minimale ( la meilleure )
|
||||
found=[]
|
||||
for mention in range(0,mentions):
|
||||
for candidat,merite_median in mention_mediane.items():
|
||||
if merite_median == mention:
|
||||
found.append({candidat:candidats[candidat]})
|
||||
if len(found) > 0:
|
||||
break
|
||||
|
||||
if verbose:
|
||||
print(found)
|
||||
print(nom_mentions[mention])
|
||||
|
||||
result = {'resultat':{'mention':nom_mentions[mention],'candidats':found},'merite':merite,'profil':merite_pourcent,"warnings":warnings}
|
||||
result = jugement_majoritaire(poll)
|
||||
|
||||
print(json.dumps(result))
|
||||
|
||||
@@ -22,15 +22,85 @@ https://en.wikipedia.org/wiki/Jugement_majoritaire
|
||||
|
||||
|source|info|interet|
|
||||
|------------------|-----------------------------|-------------|
|
||||
|https://github.com/AlexJade23/JugementMajoritaire|RAS VIDE|1/20|
|
||||
|https://github.com/ostix360/JugementMajoritaire|Où est l'algo ?|2/20|
|
||||
|https://github.com/MieuxVoter/mieuxvoter.fr||18/20|
|
||||
|https://github.com/CitoyensDeDemain/JugementMajoritaire|Il y a un algo, mais pas de format de donnée, données hardcodées / API et pas de procédure d'install|11/20|
|
||||
|https://github.com/ostix360/JugementMajoritaire|Où est l'algo ?|2/20|
|
||||
|https://github.com/AlexJade23/JugementMajoritaire|RAS VIDE|1/20|
|
||||
|
|
||||
|
||||
|
||||
# https://mieuxvoter.fr/en
|
||||
|
||||
C'est la référence, les théoriciens du vote majoritaire ont été invités à participer à l'élaboration de ce site.
|
||||
|
||||
Par contre pour trouver la librairie de base...
|
||||
|
||||
https://github.com/MieuxVoter/mieuxvoter.fr
|
||||
|
||||
image docker
|
||||
|
||||
|
||||
https://app.mieuxvoter.fr/en/votes/ult-kxm-vzcr
|
||||
|
||||
https://app.mieuxvoter.fr/en/results/ult-kxm-vzcr
|
||||
|
||||
https://app.mieuxvoter.fr/en/admin/ult-kxm-vzcr/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6dHJ1ZSwiZWxlY3Rpb24iOiJ1bHRreG12emNyIn0.TzkM380pk0eVo8_iHJGYANxlapVbp5Z3jxLQSzqLpRM
|
||||
|
||||
|
||||
https://app.mieuxvoter.fr/fr/votes/ult-kxm-vzcr : même en français 'Very good' ...
|
||||
|
||||
Obligation de noter tous les participants.
|
||||
|
||||
## Librairie python
|
||||
|
||||
https://github.com/MieuxVoter/majority-judgment-library-python
|
||||
|
||||
Très courte ( ./majority_judgment/__init__.py 145 lignes )
|
||||
|
||||
```
|
||||
>>> from majority_judgment import majority_judgment
|
||||
>>> data = {
|
||||
... 'Pizza': [!, 0, 3, 0, 2, 0, 3, 1, 2, 3],
|
||||
... 'Chips': [0, 1, 0, 2, 1, 2, 2, 3, 2, 3],
|
||||
... 'Pasta': [0, 1, 0, 1, 2, 1, 3, 2, 3, 3],
|
||||
... 'Bread': [0, 1, 2, 1, 1, 2, 1, 2, 2, 3],
|
||||
... }
|
||||
>>> majority_judgment(data, reverse=False)
|
||||
{'Chips': 0, 'Pasta': 1, 'Pizza': 2, 'Bread': 3}
|
||||
|
||||
```
|
||||
|
||||
(!) ?
|
||||
|
||||
## API REST python
|
||||
|
||||
https://github.com/MieuxVoter/majority-judgment-api-python
|
||||
|
||||
License: GNU aGPLV3 / CECILL variant affero compliant
|
||||
|
||||
|postgres||
|
||||
|python| >= 3.11 |
|
||||
|
||||
serveur uvicorn
|
||||
|
||||
```
|
||||
uvicorn app.main:app --reload --env-file .env.local
|
||||
```
|
||||
|
||||
profiles :
|
||||
|
||||
|core| if you only need the backend and database|
|
||||
|dashboard| if you only need Metabase|
|
||||
|image| if you only need to store images|
|
||||
|backup| for restic|
|
||||
|
||||
Election Candidat Grade Vote
|
||||
|
||||
# david chavalarias
|
||||
|
||||
https://github.com/davidchavalarias/jugement-majoritaire
|
||||
|
||||
Dans le cadre d'une soutenance en 2014 le porjet n'a pas été maintenu ni forké.
|
||||
Dans le cadre d'une soutenance en 2014 le projet n'a pas été maintenu ni forké.
|
||||
|
||||
Une application sous symfony2 ( php Doctrine )
|
||||
|
||||
@@ -443,22 +513,3 @@ langage for smart contracts : blockchain donc.
|
||||
# https://github.com/jeromeschwaederle/Vote_Jugement_Majoritaire
|
||||
|
||||
python simple
|
||||
|
||||
# https://mieuxvoter.fr/en
|
||||
|
||||
|
||||
https://github.com/MieuxVoter/mieuxvoter.fr
|
||||
|
||||
image docker
|
||||
|
||||
|
||||
https://app.mieuxvoter.fr/en/votes/ult-kxm-vzcr
|
||||
|
||||
https://app.mieuxvoter.fr/en/results/ult-kxm-vzcr
|
||||
|
||||
https://app.mieuxvoter.fr/en/admin/ult-kxm-vzcr/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6dHJ1ZSwiZWxlY3Rpb24iOiJ1bHRreG12emNyIn0.TzkM380pk0eVo8_iHJGYANxlapVbp5Z3jxLQSzqLpRM
|
||||
|
||||
|
||||
https://app.mieuxvoter.fr/fr/votes/ult-kxm-vzcr : même en français 'Very good' ...
|
||||
|
||||
Obligation de noter tous les participants.
|
||||
Reference in New Issue
Block a user