def startup(**_kwargs): """Task to run on start of celery, schedules game start""" game_config = storage.game.get_current_global_config() logger.info(f'Received game config: {game_config}') with storage.get_redis_storage().pipeline(transaction=True) as pipeline: with locking.acquire_redis_lock(pipeline, 'game_starting_lock'): already_started = storage.game.get_game_running() if not already_started: logger.info("Game is not running, initializing...") start_game.apply_async(eta=game_config.start_time, ) game_state = storage.game.construct_game_state_from_db(round=0) if not game_state: logger.warning('Initial game_state missing') else: logger.info( f"Initializing game_state with {game_state.to_dict()}") pipeline.set('game_state', game_state.to_json()) pipeline.execute() storage.get_wro_sio_manager().emit( event='update_scoreboard', data={'data': game_state.to_json()}, namespace='/game_events', )
def start_game(): """Starts game Sets `game_running` in DB """ logger.info('Starting game') with storage.get_redis_storage().pipeline(transaction=True) as pipeline: with locking.acquire_redis_lock(pipeline, 'game_starting_lock'): already_started = storage.game.get_game_running() if already_started: logger.info('Game already started') return storage.game.set_round_start(round=0) storage.game.set_game_running(True) game_state = storage.game.construct_game_state_from_db(round=0) if not game_state: logger.warning('Initial game_state missing') else: logger.info(f"Initializing game_state with {game_state.to_dict()}") pipeline.set('game_state', game_state.to_json()) pipeline.execute() storage.get_wro_sio_manager().emit( event='update_scoreboard', data={'data': game_state.to_json()}, namespace='/game_events', )
def handle_attack(attacker_id: int, flag_str: str, round: int) -> float: """Check flag, lock team for update, call rating recalculation, then publish redis message about stolen flag :param attacker_id: id of the attacking team :param flag_str: flag to be checked :param round: round of the attack :raises FlagSubmitException: when flag check was failed :return: attacker rating change """ flag = flags.try_add_stolen_flag_by_str(flag_str=flag_str, attacker=attacker_id, round=round) with storage.db_cursor() as (conn, curs): curs.callproc("recalculate_rating", (attacker_id, flag.team_id, flag.task_id, flag.id)) attacker_delta, victim_delta = curs.fetchone() conn.commit() flag_data = { 'attacker_id': attacker_id, 'victim_id': flag.team_id, 'task_id': flag.task_id, 'attacker_delta': attacker_delta, 'victim_delta': victim_delta, } storage.get_wro_sio_manager().emit( event='flag_stolen', data={'data': json.dumps(flag_data)}, namespace='/game_events', ) return attacker_delta
def update_game_state(current_round): if not current_round: return game_state = storage.game.construct_latest_game_state( round=current_round) logger.info(f'Publishing scoreboard for round {current_round}') with storage.get_redis_storage().pipeline( transaction=True) as pipeline: pipeline.set('game_state', game_state.to_json()) pipeline.execute() storage.get_wro_sio_manager().emit( event='update_scoreboard', data={'data': game_state.to_json()}, namespace='/game_events', )
def run(): conf_path = os.path.join(CONFIG_DIR, CONFIG_FILENAME) with open(conf_path) as f: file_config = yaml.load(f, Loader=yaml.FullLoader) with storage.db_cursor() as (conn, curs): create_tables_path = os.path.join(SCRIPTS_DIR, 'create_tables.sql') with open(create_tables_path) as f: create_tables_query = f.read() curs.execute(create_tables_query) create_functions_path = os.path.join(SCRIPTS_DIR, 'create_functions.sql') with open(create_functions_path) as f: create_functions_query = f.read() curs.execute(create_functions_query) teams_config = file_config['teams'] teams = [] for team_conf in teams_config: team_token = secrets.token_hex(8) team = models.Team(id=None, **team_conf, token=team_token) curs.execute(_TEAM_INSERT_QUERY, (team.name, team.ip, team_token)) team.id, = curs.fetchone() teams.append(team) tasks_config = file_config['tasks'] tasks = [] global_defaults = { 'checkers_path': '/checkers/', 'env_path': '/checkers/bin/', 'default_score': 2000.0, 'game_hardness': 3000.0, 'inflation': True, 'flag_lifetime': 5, 'round_time': 60, 'timezone': 'UTC', 'game_mode': 'classic', } global_config = file_config['global'] for k, v in global_defaults.items(): if k not in global_config: global_defaults[k] = v task_defaults = { 'env_path': global_config['env_path'], 'default_score': global_config['default_score'], 'get_period': global_config.get('get_period', global_config['round_time']), 'checker_returns_flag_id': True, 'gevent_optimized': False, } for task_conf in tasks_config: for k, v in task_defaults.items(): if k not in task_conf: task_conf[k] = v task_conf['checker'] = os.path.join(global_config['checkers_path'], task_conf['checker']) task = models.Task(id=None, **task_conf) curs.execute(_TASK_INSERT_QUERY, ( task.name, task.checker, task.gets, task.puts, task.places, task.checker_timeout, task.env_path, task.checker_returns_flag_id, task.gevent_optimized, task.get_period, )) task.id, = curs.fetchone() tasks.append(task) data = [(task.id, team.id, task.default_score, -1) for team in teams for task in tasks] curs.executemany(_TEAMTASK_INSERT_QUERY, data) global_config.pop('env_path', None) global_config.pop('default_score', None) global_config.pop('checkers_path', None) global_config.pop('get_period', None) tz = pytz.timezone(global_config['timezone']) global_config['start_time'] = tz.localize(global_config['start_time']) keys = global_config.keys() columns = ','.join(keys) values = ','.join(f'%({key})s' for key in keys) curs.execute( _CONFIG_INITIALIZATION_QUERY.format(columns=columns, values=values), global_config, ) conn.commit() game_state = storage.game.construct_game_state_from_db(round=0) with storage.get_redis_storage().pipeline(transaction=True) as pipeline: pipeline.set('game_state', game_state.to_json()) pipeline.execute() storage.get_wro_sio_manager().emit( event='update_scoreboard', data={'data': game_state.to_json()}, namespace='/game_events', )