def _load(self): lock_path = update_lock_path(self.root_dir) with share_lock(lock_path): "grab a lock & reload" logging.info("Loading compstate from {0}".format(self.root_dir)) self.comp = SRComp(self.root_dir) self.update_time = time.time()
def command(settings): import os.path from collections import defaultdict from functools import partial from itertools import chain from sr.comp.comp import SRComp comp = SRComp(os.path.realpath(settings.compstate)) all_scores = (comp.scores.tiebreaker, comp.scores.knockout, comp.scores.league) all_points = dict(chain.from_iterable(s.game_points.items() for s in all_scores)) points_map = defaultdict(partial(defaultdict, list)) for match, points in all_points.items(): for tla, team_points in points.items(): points_map[team_points][tla].append(match) count = len(points_map) for idx, (points, team_info) in enumerate(sorted(points_map.items())): if idx + 2 < count: print(f"{len(team_info):>3} teams scored {points}") else: print() print(f"The following {len(team_info)} team(s) scored {points} points:") for tla, matches in team_info.items(): print(f"- {tla} in match(es): " + ", ".join( "{}{}".format(*x) for x in matches ))
def command(settings): import os.path from sr.comp.comp import SRComp from sr.comp.winners import Award comp = SRComp(os.path.realpath(settings.compstate)) def format_team(tla): team = comp.teams[tla] return u'{} ({}{})'.format(tla, team.name, ' [rookie]' if team.rookie else '') award_order = (Award.image, Award.web, Award.committee, Award.rookie, Award.movement, Award.third, Award.second, Award.first) missing = set(Award) - set(award_order) assert not missing, "Awards missed!: {0}".format(", ".join( map(str, missing))) for award in award_order: print('### {}'.format(award.value.upper())) recipients = comp.awards.get(award, None) if recipients is None: print(' Not yet awarded.') elif not recipients: print(' Awarded to nobody.') elif len(recipients) == 1: print(" ", format_team(recipients[0])) else: print(' Split between {} teams (a tie):'.format(len(recipients))) for recipient in recipients: print(" ", format_team(recipient)) print()
def _load(self): lock_path = update_lock_path(self.root_dir) with share_lock(lock_path): # Grab a lock & reload logging.info("Loading compstate from %s", self.root_dir) self._comp = SRComp(self.root_dir) self.update_time = time.time()
def command(args): import subprocess from sr.comp.comp import SRComp from .deploy import print_fail compstate = SRComp(args.compstate) if args.arena: if args.arena not in compstate.arenas: print("{} is not a valid arena, choose from {}".format( args.arena, ", ".join(compstate.arenas.keys()), )) for part in args.command: PlaceholderExpander.validate(part) try: for match_number in sorted(args.matches): for arena, match in compstate.schedule.matches[match_number].items( ): if args.arena not in (arena, None): continue command = replace_placeholders(match, args.command) subprocess.check_call(command) except subprocess.CalledProcessError as e: print_fail(str(e)) exit(1)
def command(args): from collections import Counter from sr.comp.comp import SRComp comp = SRComp(args.compstate) print("Number of arenas:", len(comp.arenas), \ "({0})".format(", ".join(comp.arenas.keys()))) print( "Number of teams:", len(comp.teams), "({0} rookies)".format(sum(1 for t in comp.teams.values() if t.rookie))) slots_by_type = Counter(first(slot.values()).type.value \ for slot in comp.schedule.matches) slots_by_type_str = counter_to_string(slots_by_type) assert sum(slots_by_type.values()) == len(comp.schedule.matches) print("Number of match slots:", len(comp.schedule.matches), "({0})".format(slots_by_type_str)) games_by_type = Counter(game.type.value \ for slot in comp.schedule.matches \ for game in slot.values()) games_by_type_str = counter_to_string(games_by_type) print("Number of games:", sum(games_by_type.values()), "({0})".format(games_by_type_str))
def command(args): from sr.comp.comp import SRComp comp = SRComp(args.compstate) matches = comp.schedule.matches remaining_teams = dict(comp.teams) for slot in matches: for arena, match in slot.items(): print("## Match #{} in Arena {} (at {:%H:%M})".format( match.num, arena, match.start_time, )) for tla in match.teams: team = remaining_teams.get(tla) if team: print(" - {tla}: {name}".format(**team._asdict())) remaining_teams.pop(tla) if remaining_teams: print() else: return if remaining_teams: print() else: return
def command(settings): import os.path from sr.comp.comp import SRComp from sr.comp.raw_compstate import RawCompstate comp = SRComp(os.path.realpath(settings.compstate)) raw_comp = RawCompstate( os.path.realpath(settings.compstate), local_only=True, ) generator = ScheduleGenerator( settings.output, arenas=comp.arenas, state=comp.state, ) generator.generate( comp, raw_comp, settings.periods, settings.shepherds, settings.locations, settings.plain, settings.shepherds_combined, ) generator.write()
def test_dummy_is_valid(): test_dir = os.path.dirname(os.path.abspath(__file__)) dummy_compstate = os.path.join(test_dir, 'dummy') fake_stderr = StringIO() with mock.patch("sys.stderr", fake_stderr): comp = SRComp(dummy_compstate) error_count = validate(comp) assert 0 == error_count, fake_stderr.getvalue()
def command(settings): import os.path from datetime import datetime, timedelta from sr.comp.comp import SRComp comp = SRComp(os.path.realpath(settings.compstate)) num_teams_per_arena = getattr(comp, 'num_teams_per_arena', len(comp.corners)) matches = comp.schedule.matches now = datetime.now(comp.timezone) current_matches = list(comp.schedule.matches_at(now)) if not settings.all: time = now - timedelta(minutes=10) matches = [ slot for slot in matches if first(slot.values()).start_time >= time ] matches = matches[:int(settings.limit)] def teams_str(teams): return ':'.join(tla.center(5) if tla else ' - ' for tla in teams) def print_col(text, last=False): print(text, end='|') empty_teams = teams_str(' ' * num_teams_per_arena) teams_len = len(empty_teams) print_col(' Num Time ') for a in comp.arenas.values(): print_col(a.display_name.center(teams_len)) print_col('Display Name'.center(DISPLAY_NAME_WIDTH)) print() arena_ids = comp.arenas.keys() for slot in matches: m = first(slot.values()) print_col(" {0:>3} {1:%H:%M} ".format(m.num, m.start_time)) for a_id in arena_ids: if a_id in slot: print_col(teams_str(slot[a_id].teams)) else: print_col(empty_teams) print_col(m.display_name.center(DISPLAY_NAME_WIDTH)) if m in current_matches: print(' *') else: print()
def get_current_match_start(compstate_path): from sr.comp.comp import SRComp compstate = SRComp(compstate_path) now = compstate.schedule.datetime_now current_matches = tuple(compstate.schedule.matches_at(now)) if not current_matches: raise Exception( "Not currently in a match, specify a valid time instead") return min(x.start_time for x in current_matches)
def command(settings): from sr.comp.comp import SRComp from sr.comp.validation import validate comp = SRComp(settings.compstate) if settings.lax: error_count = 0 else: error_count = validate(comp) exit(error_count)
def test_load(): "Test that loading the dummy state works" global instance instance = SRComp(DUMMY_PATH) assert instance.root assert instance.state assert instance.teams assert instance.schedule assert instance.scores assert instance.arenas assert instance.corners assert isinstance(instance.awards, dict)
def command(args): comp = SRComp(args.compstate) controller = None if args.dry_run: controller = LightingController(comp) elif args.midi: import mido output = mido.open_output(args.midi) controller = MidiLightingController(comp, output) assert controller controller.run()
def load_teams_areans(compstate_path): import os.path from sr.comp.comp import SRComp league_yaml = league_yaml_path(compstate_path) if not os.path.exists(league_yaml): # If nothing there yet create an empty schedule so the state can load # Assume that if it is there it's in the right format dump_league_yaml({}, league_yaml) comp = SRComp(compstate_path) team_ids = list(sorted(comp.teams.keys())) arena_ids = list(sorted(comp.arenas.keys())) return team_ids, arena_ids
def command(settings): from sr.comp.comp import SRComp import os.path comp = SRComp(os.path.realpath(settings.compstate)) teams_last_round = set() last_round_num = len(comp.schedule.knockout_rounds) - 1 for i, matches in enumerate(comp.schedule.knockout_rounds): teams_this_round = set() for game in matches: teams_this_round.update(game.teams) print("Teams not in round {} ({})".format(i, round_name(last_round_num - i))) out = teams_last_round - teams_this_round teams_out = [t for t in out if t is not None] for tla in teams_out: print(tla, comp.teams[tla].name) teams_last_round = teams_this_round print()
def main(args: argparse.Namespace) -> None: offset = datetime.timedelta(seconds=args.offset_seconds) match_number: int = args.match_number comp = SRComp(Path(__file__).parent) if len(comp.arenas) != 1: raise ValueError("Multiple arenas not supported") if len(comp.corners) != 2: raise ValueError("More than two corners not supported") arena, = comp.arenas.keys() slots = comp.schedule.matches[match_number:] matches = [x[arena] for x in slots] # Yes, this doesn't account for the game not aligning within the slot. # Happily we don't need to account for that explicitly as it's a fixed # offset which affects all matches equally and thus drops out. stream_start = matches[0].start_time - offset print(f"{format_time(datetime.timedelta())} Introduction") for match in matches: if None in match.teams: print( f"Match {match.display_name} contains unknown teams. Stopping.", file=sys.stderr, ) break match_steam_time = format_time(match.start_time - stream_start) teams = " vs ".join(match.teams) print(f"{match_steam_time} {match.display_name}: {teams}") print("Note: also add the outtro/wrapup!", file=sys.stderr)
#!/usr/bin/env python3 import argparse import itertools import math import matplotlib.pyplot as plt import numpy as np from colour import Color from sr.comp.comp import SRComp import plot_utils comp = SRComp('.') def game_point_by_period(tla, match_periods): for period in match_periods: total = 0 for slot in period.matches: for match in slot.values(): if tla in match.teams: scores = getattr(comp.scores, match.type.value) match_id = (match.arena, match.num) try: total += scores.game_points[match_id][tla] except KeyError: # not scored yet pass yield total
def load(self): """Load the state as an ``SRComp`` instance.""" return SRComp(self._path)
import argparse from pathlib import Path from collections import defaultdict from sr.comp.comp import SRComp import random import yaml parser = argparse.ArgumentParser(description='falsify scores for matches') parser.add_argument('compstate', type=Path, help='competition state repository') parser.add_argument('first', type=int, help='first match ID to falsify') parser.add_argument('last', type=int, help='last match ID to falsify') args = parser.parse_args() competition = SRComp(str(args.compstate)) SKILL_LEVELS = defaultdict(lambda: 0.5) def update_skill_table(match): learning_rate = 0.1 try: points = competition.scores.league.ranked_points[match.arena, match.num] except KeyError: return for team, point_assignment in points.items(): factor = (point_assignment - 4) / 4 SKILL_LEVELS[team] *= 1 + (factor * learning_rate)