Not logged inCSS-Forum
Forum CSS-Online Help Search Login
CSS-Shop Impressum Datenschutz
Up Topic Hauptforen / CSS-Forum / Elo Berechnung
- By Lothar Jung Date 2023-05-03 09:05 Edited 2023-05-03 09:15 Upvotes 1
Direkter Discord Link:

https://discord.com/channels/425419482568196106/539960268982059008/1103213528531337246

Text:

<@311675903480692737> the version 1.0
```idealized_UHO_Elo --help``` prints
```
usage: idealized_UHO_Elo [-h] [-v] [-s [SYNONYM ...]] [-p [PLAYER ...]]
                         [-m MAX_PAIRS] [-V]
                         F [F ...]

Calculate the idealized UHO Elo from pair of games

positional arguments:
  F                     PGN file name to process

options:
  -h, --help            show this help message and exit
  -v, --version         show program's version number and exit
  -s [SYNONYM ...], --synonym [SYNONYM ...]
                        equivalent player names (ex: 'SF'='SF 15')
  -p [PLAYER ...], --player [PLAYER ...]
                        restrict the processing to players in list
  -m MAX_PAIRS, --max-pairs MAX_PAIRS
                        restrict the processing to the MAX_PAIRS first pairs
                        of games for each couple of players (default:
                        1000000000)
  -V, --verbose         output detailled statistics

    Games must be ordered by pairs, i.e. after finding a game between player1 and
    player2 the next game found with the same players must be the revenge game with
    color reversed.
   
    Formulas:
    wins = WD + DW + 2 * WW
    losses = LD + DL + 2 * LL
    draws = WL + LW + DD
   
    Elo = 100 * log_10(wins / losses)
    2 sigma error bar = 200 / ln(10) * sqrt(1 / wins + 1 / losses))
   
    Bugs:
    Skip undefined results
   
    Example:
    idealized_UHO_Elo --synonym 'SF'='SF 15' 'Kasparov'='Kasparov, Garry' --player lc0.net.808335 SF -- foo.pgn bar.pgn   
```

and a run example produced by ```idealized_UHO_Elo match-t81-swa-11061K_TC_240_4.pgn match-808335_TC_240_4.pgn``` prints
```
-----------------------------------------------------------------
  #  NAME                   |     1           2           3     
-----------------------------------------------------------------
  1  lc0.net.784968         |     0+-0      -14+-24       3+-35 
  2  lc0.net.t81-swa-11061K |    14+-24       0+-0      nan+-nan
  3  lc0.net.808335         |    -3+-35     nan+-nan      0+-0  
-----------------------------------------------------------------
```

and a run example produced by ```idealized_UHO_Elo match-t81-swa-11061K_TC_240_4.pgn

Python script:

match from collections import Counter
from math import log10 as log_10, log as ln, sqrt
from numpy import nan, inf

MAX_PAIRS = 10**9

W, D, L, UNDEFINED = 0, 1, 2, 3
RESULTS = ["1-0", "1/2-1/2", "0-1", "*"]
RES_NAME = "WDL*"

players = dict()
player_ids = []

def add_player(player_name):
    if not player_name in players:
        player_id = len(players)
        players[player_name] = player_id
        player_ids.append(player_id)
        return player_id
    player_id = find(players[player_name])
    players[player_name] = player_id
    return player_id

def find(player_id):
    father_id = player_ids[player_id]
    if father_id != player_id:
        player_ids[player_id] = find(father_id)
    return player_ids[player_id]

def union(id1, id2):
    player_ids[id2] = find(id1)

def player_id(player_name):
    return find(players[player_name])

def result(string):
    return RESULTS.index(string)

def is_tag(line):
    return len(line) > 0 and line[0] == '['

def tag_value(line):
    tag, value, _ = line.split('"')
    return tag.strip('[ '), value

def warning(file, nb_games, description=""):
    print("Issue after reading", nb_games, "games in", file_name)
    print(description, "\n")

def init_results():
    return [[0 for _ in range(3)] for _ in range(3)]

def add_result(pairing, pair_results, nb_pairs, pending_games, res, file, nb_games):
    if pairing in pending_games:
        warning(file, nb_games, "Games are not organised in pairs")
        return
    rev_pairing = tuple(reversed(pairing))
    if not rev_pairing in pending_games:
        pending_games[pairing] = res
        return
    reversed_res = pending_games.pop(rev_pairing)
    if nb_pairs[pairing] == 0:
        pair_results[pairing] = init_results()
        pair_results[rev_pairing] = init_results()
    pair_results[pairing][res][2 - reversed_res] += 1
    pair_results[rev_pairing][reversed_res][2 - res] += 1
    nb_pairs[pairing] += 1
    nb_pairs[rev_pairing] += 1

def parse_file(file_name, pair_results, nb_pairs, max_pairs=MAX_PAIRS):
    try:
        with open(file_name, "r") as pgn_file:
            pending_games = dict()
            nb_games = 0
            for line in pgn_file:
                line = line.strip()
                if is_tag(line):
                    tag, value = tag_value(line)
                    if tag == "White":
                        white = add_player(value)
                    elif tag == "Black":
                        black = add_player(value)
                    elif tag == "Result":
                        res = result(value)
                        pairing = (white, black)
                        if res != UNDEFINED and nb_pairs[pairing] < max_pairs:
                            add_result(pairing, pair_results, nb_pairs, pending_games, res, file_name, nb_games)
                        nb_games += 1
    except:
        if 'nb_games' not in locals():
            print("Can not open", file_name, "\n")
        else:
            warning(file_name, nb_games)
        return

    if pending_games:
        warning(file_name, nb_games, "{} reversed game(s) not found".format(len(pending_games)))

def idealized_UHO_Elo(pairing, pair_results, player_names, verbose=True):
    (player1, player2) = pairing
    if player1 == player2:
        return 0, 0
    if not pairing in pair_results:
        return nan, nan
    results = pair_results[pairing]
    wins = results[W][D] + results[D][W] + 2 * results[W][W]
    losses = results[L][D] + results[D][L] + 2 * results[L][L]
    draws = results[L][W] + results[W][L] + results[D][D]
    if wins == 0 and losses == 0:
        elo = 0
        error = nan
    elif wins == 0:
        elo = -inf
        error = nan
    elif losses == 0:
        elo = +inf
        error = nan
    else:
        elo = round(100 * log_10(wins / losses))
        error = round(200 / ln(10) * sqrt(1 / wins + 1 / losses))

    if verbose:
        LIMIT = "-" * 40

        print(LIMIT)

        print(player_names[player1], "-", player_names[player2])
        print()

        for first, name1 in zip((W, D, L), RES_NAME):
            for second, name2 in zip((W, D, L), RES_NAME):
                print("{}{}: {}".format(name1, name2, results[first][second]))
        print()

        print("total:", sum(sum(line) for line in results))
        print()

        print("idealized UHO Elo:", elo)
        print("2 sigma error bar:", error)

        print(LIMIT)

    return elo, error

if __name__ == "__main__":
    from os.path import basename, splitext
    from argparse import ArgumentParser, RawDescriptionHelpFormatter

    VERSION = "1.0"

    script_name, *_ = splitext(basename(__file__))

    DESCRIPTION = "Calculate the idealized UHO Elo from pair of games"
    EPILOG = """\
    Games must be ordered by pairs, i.e. after finding a game between player1 and
    player2 the next game found with the same players must be the revenge game with
    color reversed.
   
    Formulas:
    wins = WD + DW + 2 * WW
    losses = LD + DL + 2 * LL
    draws = WL + LW + DD
   
    Elo = 100 * log_10(wins / losses)
    2 sigma error bar = 200 / ln(10) * sqrt(1 / wins + 1 / losses))
   
    Bugs:
    Skip undefined results
   
    Example:
    {} --synonym 'SF'='SF 15' 'Kasparov'='Kasparov, Garry' --player lc0.net.808335 SF -- foo.pgn bar.pgn\
    """.format(script_name)

    HELP_MAX_PAIRS = """
    restrict the processing to the MAX_PAIRS first pairs of games for each couple
    of players (default: {})
    """.format(MAX_PAIRS)

    try:
        with open("{}.cfg".format(script_name), "r") as file:
            args = file.readlines()
            args = list(map(str.strip, args))
        file.close()
    except:
        args = None

    parser = ArgumentParser(script_name, description=DESCRIPTION, epilog=EPILOG,
                            formatter_class=RawDescriptionHelpFormatter)

    parser.add_argument("pgn_files", metavar="F", nargs="+", type=str,
                        help="PGN file name to process")

    parser.add_argument("-v", "--version", action="version",
                        version="%(prog)s {}\n".format(VERSION))
    parser.add_argument("-s", "--synonym", type=str, nargs="*",
                        help="equivalent player names (ex: 'SF'='SF 15')")
    parser.add_argument("-p", "--player", type=str, nargs="*",
                        help="restrict the processing to players in list")
    parser.add_argument("-m", "--max-pairs", type=int,
                        default=MAX_PAIRS, help=HELP_MAX_PAIRS)
    parser.add_argument("-V", "--verbose", action='store_const', const=True,
                        default=False, help="output detailled statistics")

    options = parser.parse_args(args)

    if options.player:
        for player_name in options.player:
            add_player(player_name)
    if options.synonym:
        for synonyms in options.synonym:
            name1, name2 = synonyms.split('=')
            union(add_player(name1), add_player(name2))

    pair_results = dict()
    nb_pairs = Counter()

    for file_name in options.pgn_files:
        parse_file(file_name, pair_results, nb_pairs, options.max_pairs)

    player_names = list(players)
    elo_table = [[None for _ in range(len(players))] for _ in range(len(players))]

    for player1 in range(len(players)):
        for player2 in range(len(players)):
            pairing = (player1, player2)
            elo = idealized_UHO_Elo(pairing, pair_results, player_names, options.verbose)
            elo_table[player1][player2] = elo

    first_col_len = max(map(len, player_names))
    sep = " |"
    limit = "-" * (5 + len(sep) + first_col_len + 12 * len(players))

    print()
    print(limit)
    print("  #  NAME" + " " * (first_col_len - 4) + sep, end="")
    for nb, _ in enumerate(players, 1):
        print(f"{nb:6d}", end=" " * 6)
    print()
    print(limit)
    for nb, (name, line) in enumerate(zip(player_names, elo_table), 1):
        name_format = f"{nb:3d}" + "  {:" + str(first_col_len) + "s}"
        print(name_format.format(name), end=sep)
        for elo, error in line:
            print(f'{elo:>6}+-{error:<3}', end=" ")
        print()
    print(limit)
-808335_TC_240_4.pgn``` prints
```
-----------------------------------------------------------------
- - By Micha Wehrmann Date 2023-05-03 15:01 Upvotes 1
Was will uns der Dichter sagen?
Parent - By Kurt Utzinger Date 2023-05-04 08:05 Upvotes 1
Micha Wehrmann schrieb:

Was will uns der Dichter sagen?


Das habe ich mich soeben auch gefragt.
- - By Lothar Jung Date 2023-05-04 22:37
Scheint wohl keiner das PythonScript laden zu können und/oder EloWerte bei Engine/Engine Turniere zu ermitteln.Erbärmlich.
Parent - By Olaf Jenkner Date 2023-05-04 22:55 Upvotes 3
Die erbärmlichen Foristen haben dich auf "Ignorieren" gesetzt und bekommen von deinen aufmerksamkeitheischenden Hilferufen nichts mit.
Up Topic Hauptforen / CSS-Forum / Elo Berechnung

Powered by mwForum 2.29.3 © 1999-2014 Markus Wichitill