import requests import requests_cache import json import csv import pandas from hanabi.database import global_db_connection_manager from hanabi.live.site_api import get from bdr import describe_game from endgames import analyze_game_cached, full_analyze_game_cached # Init db connection global_db_connection_manager.read_config() global_db_connection_manager.connect() session = requests_cache.CachedSession('.hanab-live.cache',expire_after=30000) player_mapping = { 'RamaNoVarjan': 'Ramanujan', 'purplejoe2': 'PurpleJoe', 'PurpleJoeVar': 'PurpleJoe', 'yagami_blank': 'Yagami', 'yagami_black': 'Yagami', 'MarkusKahlsen': 'Markus', 'NoVarkusKahlsen': 'Markus', 'spring': 'spring', 'str8tsknacker': 'str8tsknacker', 'novarknacker': 'str8tsknacker', 'StKildaFan': 'Kilda', 'noarv': 'Arv', 'arv': 'Arv', 'ElenaDhynho': 'Elena', 'ElenaDhynh0': 'Elena', 'Elenanovar': 'Elena', 'TimeHoodie': 'Hoodie', 'Hoodie': 'Hoodie', 'newduke': 'Duke', } allowed_team_members = ['Carunty', 'HelanaAshryvr', 'rz'] allowed_players = [s.lower() for s in player_mapping.keys()] + [s.lower() for s in allowed_team_members] excluded_games = [1056958, 1044951] player_cols = set() for _, p in player_mapping.items(): player_cols.add(p) class Entry: def __init__(self, game_id, seed, score, players, bdr=0): self.game_id = game_id self.seed = seed self.num_players = len(players) self.won = 1 if score == 25 else 0 self.players = players self.bdr = bdr def get_player_games(player: str): r = session.get('https://hanab.live/api/v1/history-full/{}?start={}'.format(player, 1044446)) if r.status_code == 200: return json.loads(r.text) def collect_player_games(): global_games = {} for player in player_mapping.keys(): print('Parsing games for player {}'.format(player)) games = get_player_games(player) for game in games: if game['options'].get('variantName', 'No Variant') != 'No Variant': continue game_id = game['id'] players = game['playerNames'] score = game['score'] seed = game['seed'] if len(players) not in [3,4,5]: continue if game_id in excluded_games: continue ok = True for player in players: if player.lower() not in allowed_players: ok = False if ok: global_games[game_id] = Entry(game_id, seed, score, players) return global_games def analyze_games(games): retval = {} for game_id in games.keys(): game = get("export/" + str(game_id)) bdrs, termination = describe_game(game) retval[game_id] = bdrs, termination return retval def analyze_endgames(games): retval = {} for game_id in games.keys(): print('Analysing endgames of game {}'.format(game_id)) result = analyze_game_cached(game_id) retval[game_id] = result return retval def full_analyze_endgames(games): retval = {} for game_id in games.keys(): print('Analysing all endgames of game {}'.format(game_id)) result = full_analyze_game_cached(game_id) retval[game_id] = result return retval def sort_players_by_num_games(games_dict): nums = {} for _, entry in games_dict.items(): for player in entry.players: col = player_mapping.get(player, None) if col is not None: num = nums.get(col, 0) nums[col] = num + 1 return sorted(player_cols, key = lambda col: -nums[col]) def lookup_val(endgame_dict, clue_modifier) -> str: if clue_modifier > 0: for lookup in range(clue_modifier, 0, -1): val = endgame_dict.get('+' + str(lookup), None) if val is not None: return val if clue_modifier < 0: for lookup in range(clue_modifier, 0): val = endgame_dict.get(str(lookup)) if val is not None: return val retval = endgame_dict.get('+0', None) return retval if __name__ == "__main__": games = collect_player_games() analysis = analyze_games(games) endgames = analyze_endgames(games) streaks = {} fieldnames = ['Game ID', 'Seed', 'Player #', 'Result', 'BDR'] fieldnames += sort_players_by_num_games(games) fieldnames += ['Other'] with open('out/games.csv', 'w', newline='') as f: f.writelines([','.join(fieldnames), "\n"]) with open('out/games.csv', 'a', newline='') as f: writer = csv.DictWriter(f, fieldnames=fieldnames) for game_id, entry in sorted(games.items()): bdrs, termination = analysis[game_id] row = { 'Game ID': "{}".format(entry.game_id, entry.game_id), 'Seed': "{}".format(entry.seed, entry.seed), 'Player #': entry.num_players, 'Result': 'Win' if entry.won else termination, 'BDR': len(bdrs), } for player in entry.players: col = player_mapping.get(player, None) if col is not None: if entry.won: streak = streaks.get(col, 0) streak += 1 streaks[col] = streak row[col] = streak else: streaks[col] = 0 row[col] = 0 else: num_others = row.get('Other', 0) row['Other'] = num_others + 1 writer.writerow(row) fieldnames = ['Game ID'] + [str(i) for i in range(1, 16)] with open('out/endgames.csv', 'w', newline='') as f: f.writelines([','.join(fieldnames), "\n"]) with open('out/endgames.csv', 'a', newline='') as f: writer = csv.DictWriter(f, fieldnames=fieldnames) for game_id, endgame in sorted(endgames.items()): endgame['Game ID'] = "{}".format(game_id, game_id) writer.writerow(endgame) all_endgames = full_analyze_endgames(games) fieldnames = ['Game ID'] + [str(i) for i in range(1, 11)] for clue_modifier in range(-2, 3): filename = 'endgames{}.csv'.format(clue_modifier) with open('out/' + filename, 'w') as f: f.writelines([','.join(fieldnames), "\n"]) with open('out/' + filename, 'a') as f: writer = csv.DictWriter(f, fieldnames=fieldnames) for game_id, endgame in sorted(all_endgames.items()): # print(endgame) row = {'Game ID': game_id} for deck_size in range(1, 11): val = lookup_val(endgame.get(str(deck_size), {}), clue_modifier) if val is not None: row[str(deck_size)] = val else: print("WARN: No results found for game {} and deck size {}: {}".format(game_id, deck_size, endgame.get(str(deck_size)))) writer.writerow(row) print('processed file {}'.format(filename)) x = pandas.read_csv('out/' + filename) x.to_html('out/endgames_{}.html'.format(clue_modifier), escape=False) a = pandas.read_csv("out/games.csv") a.to_html("out/games.html", escape=False) b = pandas.read_csv('out/endgames.csv') b.to_html("out/endgames.html", escape=False)