Example #1
0
def empty_collection(collection_name: str, db: StandardDatabase, edge: bool = False):
    try:
        db.delete_collection(collection_name)
        db.create_collection(collection_name, edge=edge)
    except CollectionDeleteError:
        print(
            f"couldn't remove collection: {collection_name}. It probably doesn't exist."
        )
    except CollectionCreateError:
        print(f"couldn't create collection: {collection_name}")
Example #2
0
def save(db: StandardDatabase, instance: GameInstance):
    """
    save a game instance
    :param db: connection
    :param instance: game
    """
    logger.info(f'save called for {instance.id} ({instance.game.title})')
    if not db.has_collection('instances'):
        logger.info('creating collection instances')
        db.create_collection('instances')
    col = db.collection('instances')
    txn_db = db.begin_transaction(read=col.name, write=col.name)
    txn_col = txn_db.collection('instances')
    txn_col.insert(json.dumps(instance, cls=MarugotoEncoder))
    txn_db.commit_transaction()
Example #3
0
def create(db: StandardDatabase, email, password, salt) -> Player:
    """
    create a new player
    :param db: connection
    :param email: mail
    :param password: plain text password
    :param salt: encryption salt
    :return: Player
    """
    if not db.has_collection('players'):
        logger.info('creating collection players')
        db.create_collection('players')
    player = Player(email, hash_password(password, salt))
    col = db.collection('players')
    col.insert({
        '_key': player.id.hex,
        'mail': player.email,
        'password': player.password,
        'tokens': []
    })
    return player
Example #4
0
def create_collection(db: StandardDatabase, name: str, unique_fields: Tuple,
                      _schema: Dict):
    if not db.has_collection(name):
        collection = db.create_collection(name=name, schema=_schema)
        collection.add_hash_index(fields=unique_fields, unique=True)
Example #5
0
def create(db: StandardDatabase, game: Game, creator=None):
    """
    save a game to the database
    :param db: connection
    :param game: target
    :param creator: creator of the game
    """
    logger.info(f'create called for {game.title}')
    if not db.has_collection('games'):
        logger.info(f'games collection does not exist, creating it.')
        db.create_collection('games')
    db_games = db.collection('games')
    if db_games.find({'key': game.title}):
        logger.warning(f'{game.title} already in metadata')
        raise GameStateException(f'{game.title} already in metadata')
    if db.has_graph(game.title):
        logger.warning(f'{game.title} already defined')
        raise GameStateException(f'{game.title} already defined')
    if not nx.is_directed_acyclic_graph(game.graph):
        logger.warning(f'{game.title} is not acyclic')
        raise GameStateException(f'{game.title} is not acyclic')
    if not game.start_is_set():
        logger.warning(f'{game.title} has no starting point')
        raise GameStateException(f'{game.title} has no starting point')
    db_game_graph = db.create_graph(f'game_{game.title}')
    if not db_game_graph.has_vertex_collection('waypoints'):
        logger.info(f'waypoints vertex collection does not exist, creating it.')
        db_game_graph.create_vertex_collection('waypoints')
    path = db_game_graph.create_edge_definition(
        edge_collection='path',
        from_vertex_collections=['waypoints'],
        to_vertex_collections=['waypoints']
    )
    # add all game nodes
    for waypoint_vertex in set(game.start.all_path_nodes()):
        logger.debug(f'inserting waypoint vertex {repr(waypoint_vertex)}')
        db_game_graph.insert_vertex('waypoints', json.dumps(waypoint_vertex, cls=MarugotoEncoder))

    # tasks as documents
    if not db.has_collection('tasks'):
        logger.info(f'tasks collection does not exist, creating it.')
        db.create_collection('tasks')
    tasks = db.collection('tasks')

    # dialogs metadata
    if not db.has_collection('dialogs'):
        logger.info(f'dialogs does not exist, creating it.')
        db.create_collection('dialogs')
    db_dialogs = db.collection('dialogs')

    # npc dialog metadata
    if not db.has_collection('npcs'):
        logger.info(f'npcs collection does not exist, creating it.')
        db.create_collection('npcs')
    db_npcs = db.collection('npcs')

    for npc in game.npcs:
        if db_npcs.find({'_key': f'{game.title}-{npc.first_name}-{npc.last_name}'}):
            logger.warning(f'dialog {game.title}-{npc.first_name}-{npc.last_name} already in metadata')
            raise GameStateException(f'dialog {game.title}-{npc.first_name}-{npc.last_name} already in metadata')
        logger.debug(f'inserting npc {game.title}-{npc.first_name}-{npc.last_name} with dialog {npc.dialog.id.hex}')
        db_npcs.insert({
            '_key': f'{game.title}-{npc.first_name}-{npc.last_name}',
            'game': f'game_{game.title}',
            'first_name': npc.first_name,
            'last_name': npc.last_name,
            'salutation': npc.salutation,
            'mail': npc.mail,
            'image': base64.encodebytes(npc.image) if npc.image else None,
            'dialog': npc.dialog.id.hex
        })

        if db_dialogs.find({'_key': npc.dialog.id.hex}):
            logger.warning(f'dialog {npc.dialog.id} already in metadata')
            raise GameStateException(f'dialog {npc.dialog.id} already in metadata')
        if db.has_graph(f'dialog_{npc.dialog.id.hex}'):
            logger.warning(f'dialog {npc.dialog.id} already defined')
            raise GameStateException(f'dialog {npc.dialog.id} already defined')
        if not nx.is_directed_acyclic_graph(npc.dialog.graph):
            logger.warning(f'dialog {npc.dialog.id} is not acyclic')
            raise GameStateException(f'dialog {npc.dialog.id} is not acyclic')
        if not npc.dialog.start_is_set():
            logger.warning(f'dialog {npc.dialog.id} has no starting point')
            raise GameStateException(f'dialog {npc.dialog.id} has no starting point')
        db_dialog_graph = db.create_graph(f'dialog_{npc.dialog.id.hex}')
        if not db_dialog_graph.has_vertex_collection('interactions'):
            logger.debug(f'interaction vertex collection does not exist, creating it.')
            db_dialog_graph.create_vertex_collection('interactions')
        conversation = db_dialog_graph.create_edge_definition(
            edge_collection='conversation',
            from_vertex_collections=['interactions'],
            to_vertex_collections=['interactions']
        )
        # add all dialog nodes
        for interaction_vertex in set(npc.dialog.start.all_path_nodes()):
            logger.debug(f'inserting interaction vertex {repr(interaction_vertex)}')
            db_dialog_graph.insert_vertex('interactions', json.dumps(interaction_vertex, cls=MarugotoEncoder))

        dia_visited = {}

        def dialog_traversal(s, i):
            """
            Walk through the game path from a starting source
            :param s: starting waypoint for traversal
            :param i: dict containing identified steps
            """
            for successor in npc.dialog.graph.successors(s):
                logger.debug(f'successor {repr(successor)} for {repr(s)}')
                if s not in i.keys():
                    logger.debug(f'{repr(s)} is new, adding it')
                    i[s] = []
                if successor not in i[s]:
                    if successor.task:
                        logger.debug(f'{repr(successor)} has {repr(successor.task)}, adding to tasks')
                        task_dump = json.loads(json.dumps(successor.task, cls=MarugotoEncoder))
                        task_dump['_key'] = successor.task.id.hex
                        task_dump['for'] = successor.id.hex
                        if not tasks.find(task_dump):
                            tasks.insert(json.dumps(task_dump))
                    logger.debug(f'inserting interaction edge {repr(s)} to {repr(successor)}')
                    conversation.insert({
                        '_key': f'{s.id.hex}-{successor.id.hex}',
                        '_from': f'interactions/{s.id.hex}',
                        '_to': f'interactions/{successor.id.hex}'
                    })
                    dia_visited[s].append(successor)
                    dialog_traversal(successor, i)

        logger.debug(f'traversing dialog graph for {npc.first_name} {npc.last_name}')
        dialog_traversal(npc.dialog.start, dia_visited)
        logger.debug(f'inserting dialog {npc.dialog.id.hex}')
        db_dialogs.insert({
            '_key': npc.dialog.id.hex,
            'start': npc.dialog.start.id.hex
        })

    wp_visited = {}

    def game_traversal(s, i):
        """
        Walk through the game path from a starting source
        :param s: starting waypoint for traversal
        :param i: dict containing identified steps
        """
        for successor in game.graph.successors(s):
            logger.debug(f'successor {repr(successor)} for {repr(s)}')
            if s not in i.keys():
                logger.debug(f'{repr(s)} is new, adding it.')
                i[s] = []
            if successor not in i[s]:
                for task in successor.tasks:
                    logger.debug(f'{repr(successor)} has {repr(task)}, adding to tasks')
                    task_dump = json.loads(json.dumps(task, cls=MarugotoEncoder))
                    task_dump['_key'] = task.id.hex
                    task_dump['for'] = successor.id.hex
                    if not tasks.find(task_dump):
                        tasks.insert(json.dumps(task_dump))
                logger.debug(f'waypoint interaction edge {repr(s)} to {repr(successor)}')
                weight = game.graph.edges[s, successor]['weight'] if 'weight' in game.graph.edges[s, successor] and game.graph.edges[s, successor]['weight'] else None
                path.insert({
                    '_key': f'{s.id.hex}-{successor.id.hex}',
                    '_from': f'waypoints/{s.id.hex}',
                    '_to': f'waypoints/{successor.id.hex}',
                    'weight': weight
                })
                wp_visited[s].append(successor)
                game_traversal(successor, i)

    logger.debug(f'traversing game graph for {game.title}')
    game_traversal(game.start, wp_visited)
    logger.debug(f'inserting game {game.title}')
    db_games.insert({
        '_key': game.title,
        'start': game.start.id.hex,
        'image': base64.encodebytes(game.image) if game.image else None,
        'creator': creator
    })