import json import sys from majority_judgment import majority_judgment verbose=False def collect_votes(votes,candidats,default_mention,warnings): 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} return collect def arrange_votes_par_candidat(votes,candidats,default_mention): vpc={} for candidat in candidats: vpc[candidat]=[vote[candidat] if candidat in vote else default_mention for vote in votes] return vpc def jugement_majoritaire(poll): verbose=False crosscheck=True 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=[] collect=collect_votes(votes,list(candidats),default_mention,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={} votes_par_candidat=arrange_votes_par_candidat(votes,candidats,mentions-1) # 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]) # expanded=expand_collect(collect,list(candidats),mentions) if verbose: print(votes_par_candidat) result = {'resultat':{'mention':nom_mentions[mention],'candidats':found},'merite':merite,'profil':merite_pourcent,"warnings":warnings} if crosscheck: # cross check with a well known implementation result["crosscheck"]=majority_judgment(votes_par_candidat, reverse=True) return result