def create_bot_summary(ld: LeagueDir): """ Create a json file with all information about the bots. Useful for casters. """ bots = load_all_bots(ld) rankings = RankingSystem.load(ld).ensure_all(list(bots.keys())) rank_list = rankings.as_sorted_list() def bot_data(bot_id): config = bots[bot_id] rank, mmr = [(i + 1, mrr) for i, (id, mrr, sigma) in enumerate(rank_list) if id == bot_id][0] return { "name": config.name, "developer": config.base_agent_config.get("Details", "developer"), "description": config.base_agent_config.get("Details", "description"), "fun_fact": config.base_agent_config.get("Details", "fun_fact"), "github": config.base_agent_config.get("Details", "github"), "language": config.base_agent_config.get("Details", "language"), "rank": rank, "mmr": mmr, } bot_summary = { defmt_bot_name(bot_id): bot_data(bot_id) for bot_id in bots.keys() } with open(ld.bot_summary, 'w') as f: json.dump(bot_summary, f, indent=4)
def make_overlay(ld: LeagueDir, match: MatchDetails, bots: Mapping[BotID, BotConfigBundle]): """ Make a `current_match.json` file which contains the details about the current match and its participants. """ retired = load_retired_bots(ld) rankings = RankingSystem.load(ld).ensure_all(list(bots.keys())) rank_list = rankings.as_sorted_list(exclude=retired) def bot_data(bot_id): config = bots[bot_id] rank, mmr = [(i + 1, mrr) for i, (id, mrr, sigma) in enumerate(rank_list) if id == bot_id][0] return { "name": config.name, "config_path": str(config.config_path), "logo_path": try_copy_logo(config), "developer": config.base_agent_config.get("Details", "developer"), "description": config.base_agent_config.get("Details", "description"), "fun_fact": config.base_agent_config.get("Details", "fun_fact"), "github": config.base_agent_config.get("Details", "github"), "language": config.base_agent_config.get("Details", "language"), "rank": rank, "mmr": mmr, } overlay = { "blue": [bot_data(bot_id) for bot_id in match.blue], "orange": [bot_data(bot_id) for bot_id in match.orange], "map": match.map } with open(PackageFiles.overlay_current_match, 'w') as f: json.dump(overlay, f, indent=4)
def parse_subcommand_rank(args: List[str]): assert args[0] == "rank" help_msg = """Usage: autoleague rank list Print list of the current leaderboard""" ld = require_league_dir() if len(args) == 1 or args[1] == "help": print(help_msg) elif args[1] == "list" and len(args) == 2: bots = load_all_bots(ld) rank_sys = RankingSystem.load(ld) rank_sys.ensure_all(list(bots.keys())) rank_sys.print_ranks_and_mmr() else: print(help_msg)
def parse_subcommand_rank(args: List[str]): assert args[0] == "rank" help_msg = """Usage: autoleague rank list [showRetired] Print list of the current leaderboard""" ld = require_league_dir() if len(args) == 1 or args[1] == "help": print(help_msg) elif args[1] == "list" and (len(args) == 2 or len(args) == 3): show_retired = len(args) == 3 and bool(args[2]) exclude = [] if show_retired else load_retired_bots(ld) bots = load_all_bots(ld) rank_sys = RankingSystem.load(ld) rank_sys.ensure_all(list(bots.keys())) rank_sys.print_ranks_and_mmr(exclude) else: print(help_msg)
def make_summary(ld: LeagueDir, count: int): """ Make a summary of the N latest matches and the resulting ranks and tickets. If N is 0 the summary will just contain the current ratings. """ summary = {} tickets = TicketSystem.load(ld) # ========== Matches ========== matches = [] bot_wins = defaultdict(list) # Maps bots to list of booleans, where true=win and false=loss if count > 0: latest_matches = MatchDetails.latest(ld, count) for i, match in enumerate(latest_matches): matches.append({ "index": i, "blue_names": [defmt_bot_name(bot_id) for bot_id in match.blue], "orange_names": [defmt_bot_name(bot_id) for bot_id in match.orange], "blue_goals": match.result.blue_goals, "orange_goals": match.result.orange_goals, }) for bot in match.blue: bot_wins[bot].append(match.result.blue_goals > match.result.orange_goals) for bot in match.orange: bot_wins[bot].append(match.result.blue_goals < match.result.orange_goals) summary["matches"] = matches # ========= Ranks/Ratings ========= bots = load_all_unretired_bots(ld) retired = load_retired_bots(ld) bots_by_rank = [] if count <= 0: # Old rankings and current rankings is the same, but make sure all bots have a rank currently old_rankings = RankingSystem.load(ld).as_sorted_list(exclude=retired) cur_rankings = RankingSystem.load(ld).ensure_all(list(bots.keys())).as_sorted_list(exclude=retired) else: # Determine current rank and their to N matches ago n_rankings = RankingSystem.latest(ld, count + 1) old_rankings = n_rankings[0].as_sorted_list(exclude=retired) cur_rankings = n_rankings[-1].ensure_all(list(bots.keys())).as_sorted_list(exclude=retired) for i, (bot, mrr, sigma) in enumerate(cur_rankings): cur_rank = i + 1 old_rank = None old_mmr = None for j, (other_bot, other_mrr, _) in enumerate(old_rankings): if bot == other_bot: old_rank = j + 1 old_mmr = other_mrr break bots_by_rank.append({ "bot_id": defmt_bot_name(bot), "mmr": mrr, "old_mmr": old_mmr, "sigma": sigma, "cur_rank": cur_rank, "old_rank": old_rank, "tickets": tickets.get(bot) or tickets.new_bot_ticket_count, "wins": bot_wins[bot], }) summary["bots_by_rank"] = bots_by_rank # =========== Write ============= with open(PackageFiles.overlay_summary, 'w') as f: json.dump(summary, f, indent=4) league_settings = LeagueSettings.load(ld) league_settings.last_summary = count league_settings.save(ld)
def parse_subcommand_bot(args: List[str]): assert args[0] == "bot" help_msg = """Usage: autoleague bot list Print list of all known bots autoleague bot test <bot_id> Run test match using a specific bot autoleague bot details <bot_id> Print details about the given bot autoleague bot unzip Unzip all bots in the bot directory autoleague bot summary Create json file with bot descriptions""" ld = require_league_dir() if len(args) == 1 or args[1] == "help": print(help_msg) elif args[1] == "list" and len(args) == 2: bot_configs = load_all_bots(ld) rank_sys = RankingSystem.load(ld) ticket_sys = TicketSystem.load(ld) bot_ids = list( set(bot_configs.keys()).union(set(rank_sys.ratings.keys())).union( set(ticket_sys.tickets.keys()))) print(f"{'': <22} c r t") for bot in sorted(bot_ids): c = "x" if bot in bot_configs else " " r = "x" if bot in rank_sys.ratings else " " t = "x" if bot in ticket_sys.tickets else " " print(f"{bot + ' ':.<22} {c} {r} {t}") elif args[1] == "test" and len(args) == 3: # Load bots = load_all_bots(ld) bot = args[2] if bot not in bots: print(f"Could not find the config file of '{bot}'") return # Run match = MatchMaker.make_test_match(bot) run_match(ld, match, bots, ReplayPreference.NONE) print(f"Test of '{bot}' complete") elif args[1] == "details" and len(args) == 3: bots = load_all_bots(ld) bot = args[2] if bot not in bots: print(f"Could not find the config file of '{bot}'") return print_details(bots[bot]) elif args[1] == "unzip" and len(args) == 2: print("Unzipping all bots:") unzip_all_bots(ld) elif args[1] == "summary" and len(args) == 2: create_bot_summary(ld) print("Bot summary created") else: print(help_msg)
def parse_subcommand_match(args: List[str]): assert args[0] == "match" help_msg = """Usage: autoleague match run Run a standard 3v3 soccer match autoleague match undo Undo the last match autoleague match list [n] Show the latest matches""" ld = require_league_dir() if len(args) == 1 or args[1] == "help": print(help_msg) elif args[1] == "run" and len(args) == 2: # Load bots = load_all_bots(ld) rank_sys = RankingSystem.load(ld) ticket_sys = TicketSystem.load(ld) # Run match = MatchMaker.make_next(bots, rank_sys, ticket_sys) result, replay = run_match(ld, match, bots, ReplayPreference.SAVE) rank_sys.update(match, result) match.result = result match.replay_id = replay.replay_id # Save match.save(ld) rank_sys.save(ld, match.time_stamp) ticket_sys.save(ld, match.time_stamp) # Print new ranks rank_sys.print_ranks_and_mmr() # Make summary league_settings = LeagueSettings.load(ld) make_summary(ld, league_settings.last_summary + 1) print( f"Created summary of the last {league_settings.last_summary + 1} matches." ) elif args[1] == "undo" and len(args) == 2: # Undo latest match ld = require_league_dir() latest_matches = MatchDetails.latest(ld, 1) if len(latest_matches) == 0: print("No matches to undo") else: latest_match = latest_matches[0] # Prompt user print(f"Latest match was {latest_match.name}") if prompt_yes_no( "Are you sure you want to undo the latest match?"): # Undo latest update to all systems RankingSystem.undo(ld) TicketSystem.undo(ld) MatchDetails.undo(ld) # New latest match new_latest_match = MatchDetails.latest(ld, 1) if new_latest_match: print(f"Reverted to {new_latest_match[0].name}") else: print("Reverted to beginning of league (no matches left)") elif args[1] == "list" and len(args) <= 3: count = 999999 if len(args) == 3: count = int(args[2]) # Show list of latest n matches played latest_matches = MatchDetails.latest(ld, count) if len(latest_matches) == 0: print("No matches have been played yet.") else: print(f"Match history (latest {len(latest_matches)} matches):") for match in latest_matches: print( f"{match.time_stamp}: {', '.join(match.blue) + ' ':.<46} {match.result.blue_goals} VS {match.result.orange_goals} {' ' + ', '.join(match.orange):.>46}" ) else: print(help_msg)
def parse_subcommand_retirement(args: List[str]): assert args[0] == "retirement" help_msg = """Usage: autoleague retirement list Print all bots in retirement autoleague retirement retire <bot> Retire a bot, removing it from play and the leaderboard autoleague retirement unretire <bot> Unretire a bot autoleague retirement retireall Retire all bots""" ld = require_league_dir() if len(args) == 1 or args[1] == "help": print(help_msg) elif args[1] == "list" and len(args) == 2: retired = load_retired_bots(ld) if len(retired) == 0: print("There are no bots in retirement") else: print("Retired bots:") for bot_id in sorted(retired): print(bot_id) elif args[1] == "retire" and len(args) == 3: bot = args[2] retired = load_retired_bots(ld) retired.add(bot) save_retired_bots(ld, retired) print(f"Retired {bot}") elif args[1] == "unretire" and len(args) == 3: bot = args[2] retired = load_retired_bots(ld) try: retired.remove(bot) save_retired_bots(ld, retired) print(f"Unretired {bot}") except KeyError: print(f"The bot {bot} is not in retirement") elif args[1] == "retireall" and len(args) == 2: bot_configs = load_all_bots(ld) rank_sys = RankingSystem.load(ld) ticket_sys = TicketSystem.load(ld) retired = load_retired_bots(ld) all_bots = set( bot_configs.keys()).union(set(rank_sys.ratings.keys())).union( set(ticket_sys.tickets.keys())).union(retired) save_retired_bots(ld, all_bots) count = len(all_bots) - len(retired) print(f"Retired {count} bots") else: print(help_msg)