import json, sys import _pydecimal # moteur decimal (moins d'overflows) #-------------------------------- decimal_context = _pydecimal.Context(Emax=10**18) def new_decimal(n): return decimal_context.create_decimal(n) #fonctions ELO #------------- K = 32 D = 400 def expected_scores(RA, RB): """Expected normalized scores a player A and B with ratings RA and RB.""" #print(">",RA,RB) #QA = new_decimal(10) ** (RA / D) # overflow #QB = new_decimal(10) ** (RB / D) # overflow #return (QA / (QA + QB), QB / (QA + QB)) # (QA + QB) / QA = 1 + QB/QA = 1 + new_decimal(10) ** ((RB - RA) / D) # (QA + QB) / QB = 1 + QA/QB = 1 + new_decimal(10) ** ((RA - RB) / D) RAB = RB - RA return 1 / (1 + new_decimal(10) ** (RAB / D)), 1 / (1 + new_decimal(10) ** (-RAB / D)) def update_ratings(RA, RB, EA, EB, SA, SB): """Update ratings RA/RB of players A and B, which were expected to score EA/EB and ended up scoring SA/SB.""" return (RA + K * (SA - EA), RB + K * (SB - EB)) #fonctions dictionnaire #---------------------- def sorted_dictionnary(d, reverse=False): sitems = sorted(d.items(), key=lambda item: item[1], reverse=reverse) sd = {} for key, value in sitems: sd[key] = value return sd #fonctions tournoi #----------------- nprogress = 202 def reorder_resultats(res): print("ordonnancement des {:d} duels...".format(len(res))) prev_p1, prev_p2 = "", "" rres = [] cont = True len0 = len(res) old_progress = -1 i_test = 0 while len(res): found = False for duel in res: p1, p2 = duel[:2] tests = ( p1 != prev_p1 and p1 != prev_p2 and p2 != prev_p2 and p2 != prev_p1, p1 != prev_p1 and p1 != prev_p2 and p2 != prev_p2 or p1 != prev_p1 and p2 != prev_p2 and p2 != prev_p1, p1 != prev_p1 and p2 != prev_p2, p1 != prev_p1 or p2 != prev_p2, True ) if tests[i_test]: #if i_test: print("new duel [{:d}] {:s} {:s} ({:d})".format(i_test, p1, p2, len(res))) i_test = 0 found = True rres.append(duel) res.remove(duel) cont = True prev_p1, prev_p2 = p1, p2 progress = round(nprogress*(1 - len(res)*(len(res) + 1)/len0/(len0 + 1))) if old_progress != progress: sys.stdout.write("[%-{:d}s] %d%%".format(nprogress) % ('='*progress, round(progress*100/nprogress))) sys.stdout.write('\r') sys.stdout.flush() old_progress = progress if not found: i_test += 1 return rres #chargement donnees #------------------ fparticipants = open('participants.json') participants = json.load(fparticipants) player_elo = {} player_ia = {} player_duels = {} player_infos = {} for p in ("TonioBG", "Paul emploi"): # IAs identiques player_infos[p] = "(2)" for p in ("Kaïs.Mt", "RC06", "Sylvain_b"): # IAs identiques player_infos[p] = "(3)" for p in ("Genesect", "ZetaMap", "David Hooker", "ptijoz", "M4x1m3", "GRIFFON", "DiMartino", "ggauny@live.fr", "Houd", "briac210", "V.d.c."): # default ia_random player_infos[p] = "ia_random (0)" for p in ("Raphaël R",): # default improved ia_random player_infos[p] = "ia_random# (1)" SCORE_DIVIDER = 54 for participant in participants: p = participant['nom'] player_elo[p] = new_decimal(0) player_duels[p] = [0, 0] player_ia[p] = participant['choixfinal'] resultats = [] for nomfic in sys.argv[1:]: fresultats = open(nomfic) resultats.extend(json.load(fresultats)) freq_by_top = {} stable_by_top = {} nprogress = 100 old_progress = -1 duels = 0 sorted_player_elo = {} print("Traitement des {:d} duels...".format(len(resultats))) for duel in resultats[::-1]: duels += 1 p1, p2 = duel[:2] s1, s2 = [new_decimal(duel[i])/SCORE_DIVIDER for i in range(2, 4)] e1, e2 = expected_scores(player_elo[p1], player_elo[p2]) r1, r2 = update_ratings(player_elo[p1], player_elo[p2], e1, e2, s1, s2) player_elo[p1], player_elo[p2] = r1, r2 player_duels[p1][0] += 1 player_duels[p2][1] += 1 prev_sorted_player_elo = sorted_player_elo.copy() sorted_player_elo = sorted_dictionnary(player_elo, reverse=True) for i in range(1, len(participants) + 1): top = tuple(sorted_player_elo)[:i] if not top in freq_by_top: freq_by_top[top] = 0 freq_by_top[top] += 1 if tuple(prev_sorted_player_elo)[:i] != tuple(sorted_player_elo)[:i]: if not top in stable_by_top: stable_by_top[top] = 0 stable_by_top[top] += 1 progress = round(nprogress*duels/len(resultats)) if old_progress != progress: sys.stdout.write("[%-{:d}s] %d%%".format(nprogress) % ('='*progress, round(progress*100/nprogress))) sys.stdout.write('\r') sys.stdout.flush() old_progress = progress print() show_freq = True print("RANG NOM GROUP IA INFOS (*) SCORE DUELS FREQUENCE") i = 1 for p in sorted_player_elo: duels1, duels2 = player_duels[p][0], player_duels[p][1] top = tuple(sorted_player_elo)[:i] freq = freq_by_top[top]*100/duels for participant in participants: if p == participant['nom']: break infos = p in player_infos and player_infos[p] or "" if infos != "": show_freq = False top_freq = show_freq and "{:05.2f}% top{:d}".format(freq, i) or "" print("{:02d} {:14s} {:17s} {:19s} {:14s} {:06.3f} {:d} + {:d} = {:d} {:s}".format(i, p, participant['choixgrp'], player_ia[p], infos, sorted_player_elo[p] / 10**7, duels1, duels2, duels1 + duels2, top_freq)) i += 1 print("(*) Infos sur les IAs :") print("chiffre = IA identique pour plusieurs participations") print("1 = \"ia_random\" founie avec l'amélioration précodée activée") print("0 = \"ia_random\" fournie")