Beispiel #1
0
def perform_move(game_id, player_id, move_dto):
    """Performs a move operation on the game."""
    location = mapper.dto_to_move_action(move_dto)
    _ = interactors.OverduePlayerInteractor(game_repository())
    interactor = interactors.PlayerActionInteractor(game_repository())
    _try(lambda: interactor.perform_move(game_id, player_id, location))
    DatabaseGateway.get_instance().commit()
Beispiel #2
0
def remove_unobserved_games(unobserved_period):
    """ Uses UnobservedGamesInteractor to remove games which have not been observed for the given period """
    interactor = interactors.UnobservedGamesInteractor(game_repository(), logging.get_logger())
    removed_ids = _try(lambda: interactor.remove_unobserved_games(unobserved_period))
    for game_id in removed_ids:
        logging.get_logger().remove_game(game_id)
    DatabaseGateway.get_instance().commit()
Beispiel #3
0
def add_player(game_id, player_request_dto):
    """ Adds a player to a game.
    Creates the game if it does not exist.
    After adding the player, the game is started.

    :param game_id: specifies the game
    :param player_request_dto: if this parameter is given, it contains information about the type of player to add
    :return: the added player
    """
    _ = interactors.OverduePlayerInteractor(game_repository(), logging.get_logger())
    _ = interactors.UpdateOnTurnChangeInteractor(game_repository())
    game = _get_or_create_game(game_id)
    is_bot, computation_method = mapper.dto_to_type(player_request_dto)
    player_name = mapper.dto_to_player_name(player_request_dto)
    player_id = _try(game.unused_player_id)
    player = None
    if not is_bot:
        player = Player(player_id, player_name=player_name)
    else:
        player = _try(lambda: bots.create_bot(compute_method=computation_method,
                                              url_supplier=URLSupplier(), player_id=player_id,
                                              player_name=player_name))
    _try(lambda: game.add_player(player))
    DatabaseGateway.get_instance().update_game(game_id, game)
    DatabaseGateway.get_instance().commit()
    logging.get_logger().add_player(player_id, game_id=game_id, is_bot=is_bot, num_players=len(game.players))
    return mapper.player_to_dto(player)
Beispiel #4
0
def get_game_state(game_id):
    """ Returns the game state """
    _ = interactors.OverduePlayerInteractor(game_repository())
    interactor = interactors.ObserveGameInteractor(game_repository())
    game = _try(lambda: interactor.retrieve_game(game_id))
    game_state = mapper.game_state_to_dto(game)
    DatabaseGateway.get_instance().commit()
    return game_state
Beispiel #5
0
def perform_shift(game_id, player_id, shift_dto):
    """Performs a shift operation on the game."""
    location, rotation = mapper.dto_to_shift_action(shift_dto)
    _ = interactors.OverduePlayerInteractor(game_repository(), logging.get_logger())
    _ = interactors.UpdateOnTurnChangeInteractor(game_repository())
    interactor = interactors.PlayerActionInteractor(game_repository())
    _try(lambda: interactor.perform_shift(game_id, player_id, location, rotation))
    DatabaseGateway.get_instance().commit()
Beispiel #6
0
def change_player_name(game_id, player_id, player_name_dto):
    """ Renames a player

    :param game_id: specifies the game
    :param player_id: specifies the player to remove
    :param player_name_dto: contains the new player name."""
    new_name = mapper.dto_to_player_name(player_name_dto)
    interactors.PlayerInteractor(game_repository()).change_name(game_id, player_id, new_name)
    DatabaseGateway.get_instance().commit()
Beispiel #7
0
def get_game_state(game_id):
    """ Returns the game state """
    _ = interactors.OverduePlayerInteractor(game_repository(), logging.get_logger())
    _ = interactors.UpdateOnTurnChangeInteractor(game_repository())
    action_timeout = timedelta(seconds=int(current_app.config["OVERDUE_PLAYER_TIMEDELTA_S"]))
    interactor = interactors.ObserveGameInteractor(game_repository(), action_timeout=action_timeout)
    game, remaining_timedelta = _try(lambda: interactor.retrieve_game(game_id))
    game_state = mapper.game_state_to_dto(game, remaining_timedelta)
    DatabaseGateway.get_instance().commit()
    return game_state
def test_interactor__when_game_notifies_turn_listeners__updates_player_action_timestamp(
):
    game, _ = setup_test()
    data_access = DatabaseGateway(settings={"DATABASE": "foo"})
    game_repository = interactors.GameRepository(data_access)
    game_repository.update_action_timestamp = Mock()
    _ = interactors.OverduePlayerInteractor(game_repository, logger)
    data_access._notify_listeners(game)
    game._notify_turn_listeners()

    game_repository.update_action_timestamp.assert_called_once_with(
        game, matchers.time_close_to(datetime.now()))
Beispiel #9
0
def delete_player(game_id, player_id):
    """ Removes a player from a game

    :param game_id: specifies the game
    :param player_id: specifies the player to remove
    """
    _ = interactors.OverduePlayerInteractor(game_repository())
    game = _load_game_or_throw(game_id, for_update=True)
    _try(lambda: game.remove_player(player_id))
    DatabaseGateway.get_instance().update_game(game_id, game)
    DatabaseGateway.get_instance().commit()
    return ""
Beispiel #10
0
def change_game(game_id, game_request_dto):
    """ Changes game setup.

    Currently, the only option is to change the maze size.
    This will restart the game.
    :param game_id: specifies the game. Has to exist.
    :param game_request_dto: contains the new maze size."""
    new_size = mapper.dto_to_maze_size(game_request_dto)
    _ = interactors.OverduePlayerInteractor(game_repository())
    game = _load_game_or_throw(game_id)
    new_board = _try(lambda: factory.create_board(maze_size=new_size))
    _try(lambda: game.replace_board(new_board))
    DatabaseGateway.get_instance().update_game(game_id, game)
    DatabaseGateway.get_instance().commit()
Beispiel #11
0
def create_app(test_config=None):
    """ basic Flask app setup. Creates the instance folder if not existing """
    app = Flask(__name__,
                instance_relative_config=True,
                static_folder="../static",
                static_url_path="")

    app.config.from_mapping(
        SECRET_KEY='dev',
        PROFILE=False,
        DATABASE=os.path.join(app.instance_path, 'labyrinth.sqlite'),
        LIBRARY_PATH=os.path.join(app.instance_path, 'lib'),
    )

    if test_config is None:
        app.config.from_pyfile('config.py', silent=True)
    else:
        app.config.from_mapping(test_config)

    if app.config["PROFILE"]:
        app.wsgi_app = ProfilerMiddleware(app.wsgi_app, profile_dir=os.path.join(app.instance_path),
                                          stream=None)

    try:
        os.makedirs(app.instance_path)
    except OSError:
        pass

    from . import api
    app.register_blueprint(api.API)

    from . import game_management
    app.register_blueprint(game_management.GAME_MANAGEMENT)

    from labyrinth.database import DatabaseGateway
    app.before_first_request(lambda: DatabaseGateway.init_database())
    app.teardown_request(lambda exc: DatabaseGateway.close_database())

    mimetypes.add_type('application/wasm', '.wasm')

    @app.route('/')
    def index():
        """ Serves the 'static' part, i.e. the Vue application """
        return app.send_static_file("index.html")

    return app
Beispiel #12
0
def create_app(test_config=None):
    """ basic Flask app setup. Creates the instance folder if not existing """

    # Imports inside here so the package can be imported without the dependency to Flask #
    import mimetypes
    import os

    from flask import Flask
    from werkzeug.middleware.profiler import ProfilerMiddleware

    import labyrinth.event_logging as logging

    app = Flask(__name__,
                instance_relative_config=True,
                static_folder="../../web-client/dist",
                static_url_path="")

    app.config.from_mapping(SECRET_KEY='dev',
                            PROFILE=False,
                            ENABLE_INFLUXDB_LOGGING=False,
                            JSON_SORT_KEYS=False,
                            DATABASE=os.path.join(app.instance_path,
                                                  'labyrinth.sqlite'),
                            LIBRARY_PATH=os.path.join(app.instance_path,
                                                      'lib'))

    if test_config is None:
        app.config.from_pyfile('config.py', silent=True)
    else:
        app.config.from_mapping(test_config)

    if app.config["ENABLE_INFLUXDB_LOGGING"]:
        app.before_request(lambda: logging.create_logger(
            app.config["INFLUXDB_URL"], app.config["INFLUXDB_TOKEN"]))

    if app.config["PROFILE"]:
        app.wsgi_app = ProfilerMiddleware(app.wsgi_app,
                                          profile_dir=os.path.join(
                                              app.instance_path),
                                          stream=None)

    if test_config is None:
        from labyrinth.scheduler import scheduler, schedule_remove_overdue_players, schedule_remove_unobserved_games
        scheduler.init_app(app)
        schedule_remove_overdue_players()
        schedule_remove_unobserved_games()
        scheduler.start()

    try:
        os.makedirs(app.instance_path)
    except OSError:
        pass

    from . import api
    app.register_blueprint(api.API)

    from . import analytics
    app.register_blueprint(analytics.API)

    from . import game_management
    app.register_blueprint(game_management.GAME_MANAGEMENT)

    from labyrinth.database import DatabaseGateway
    app.before_first_request(lambda: DatabaseGateway.init_database())
    app.teardown_request(lambda exc: DatabaseGateway.close_database())

    mimetypes.add_type('application/wasm', '.wasm')

    @app.route('/')
    def index():
        """ Serves the 'static' part, i.e. the Vue application """
        return app.send_static_file("index.html")

    @app.route('/version')
    def version():
        """ Returns version as 3-tuple """
        return version_info._asdict()

    return app
Beispiel #13
0
def remove_unobserved_games(unobserved_period):
    """ Uses UnobservedGamesInteractor to remove games which have not been observed for the given period """
    interactor = interactors.UnobservedGamesInteractor(game_repository())
    _try(lambda: interactor.remove_unobserved_games(unobserved_period))
    DatabaseGateway.get_instance().commit()
Beispiel #14
0
def _load_game_or_throw(game_id, for_update=False):
    game = DatabaseGateway.get_instance().load_game(game_id, for_update=for_update)
    if game is None:
        raise exceptions.GAME_NOT_FOUND_API_EXCEPTION
    return game
Beispiel #15
0
def _create_game(game_id):
    game = factory.create_game(game_id=game_id)
    DatabaseGateway.get_instance().create_game(game, game_id)
    logging.get_logger().add_game(game_id)
    return game
Beispiel #16
0
def _get_or_create_game(game_id):
    game = DatabaseGateway.get_instance().load_game(game_id)
    if game is None:
        game = _create_game(game_id)
    return game
Beispiel #17
0
def game_repository():
    return interactors.GameRepository(DatabaseGateway.get_instance())
Beispiel #18
0
def _create_game(game_id):
    game = factory.create_game(game_id=game_id)
    DatabaseGateway.get_instance().create_game(game, game_id)
    return game
Beispiel #19
0
def remove_overdue_players(overdue_timedelta):
    """ Uses OverduePlayerInteractor to remove players which block the game by not performing actions """
    interactor = interactors.OverduePlayerInteractor(game_repository(), logging.get_logger())
    _try(lambda: interactor.remove_overdue_players(overdue_timedelta))
    DatabaseGateway.get_instance().commit()
Beispiel #20
0
    def managed_gateway(self):
        """ Creates a database gateway as a context manager

        It should only be necessary to retrieve this in non-request contexts.
        """
        return DatabaseGateway(self._data_access.settings)