Ejemplo n.º 1
0
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',
                    )
Ejemplo n.º 2
0
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',
            )
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
    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',
        )
Ejemplo n.º 5
0
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',
    )