示例#1
0
 def test_getPlayers(self):
     """
     Test players.getPlayers
     """
     # setup the test data
     self.setUp()
     players = Players()
     vbar()
     print("Test players.getPlayers")
     vbar()
     vprint(
         "We collect the players from the DB structure, and compare with the"
     )
     vprint("reference test data:")
     test_players = players.getPlayers()
     ref_players = refPlayers(True)
     # check that there are the same number of players on DB and reference
     lref = len(ref_players)
     ltest = len(test_players)
     result = (lref == ltest)
     vprint("    - there are " + str(ltest) + " players in the DB: " +
            str(result))
     self.assertTrue(result)
     # check that the DB is the same as the reference
     for pp_ref in ref_players:
         result = (pp_ref in test_players)
         vprint("        " + pp_ref['nickname'] + ": " + str(result))
         self.assertTrue(result)
     # end of the test
     self.teardown(players)
示例#2
0
 def test_updateTotalScore(self):
     """
     Test players.updateTotalScore
     """
     # setup the test data
     self.setUp()
     players = Players()
     # runs the test
     vbar()
     print("Test players.updateTotalScore")
     vbar()
     vprint(
         "We check that we can properly update the 'totalScore' with more points"
     )
     vprint("(typically updating the 'totalScore' after a game ended).")
     # self.list_test_players(players.playersColl)
     pid = players.getPlayerID("Daisy")['playerID']
     self.assertTrue(players.updateTotalScore(pid, 5))
     self.assertEqual(
         players.playersColl.find_one({'nickname': "Daisy"})['totalScore'],
         50)
     for pp in players.playersColl.find({}):
         vprint("      " + pp['nickname'] + " - totalScore: " +
                str(pp['totalScore']))
     # end of the test
     self.teardown(players)
示例#3
0
 def test_deserialize(self):
     """
     Test players.deserialize
     """
     # setup the test data
     self.setUp()
     players = Players()
     # We copy in 'target' the reference players (as in 'refPlayersDict')
     # without the password
     target = {'__class__': 'SetPlayers', 'players': []}
     for pp in refPlayers_Dict():
         target['players'].append({
             'playerID': pp['playerID'],
             'nickname': pp['nickname'],
             'passwordHash': pp['passwordHash'],
             'totalScore': pp['totalScore'],
             'gameID': pp['gameID']
         })
     players.deserialize(target)
     # runs the test
     vbar()
     print("Test players.deserialize")
     vbar()
     vprint(
         "We erase and rebuilt the DB thanks to the 'deserialize' method, and we"
     )
     vprint(
         "then compare the 'serialized' image of this new DB with the target,"
     )
     vprint("which is:")
     vprint(target)
     result = players.serialize()
     self.assertTrue(playersDict_equality(target, result))
     # end of the test
     self.teardown(players)
示例#4
0
 def test_getHash(self):
     """
     Test players.getHash
     """
     # setup the test data
     self.setUp()
     players = Players()
     vbar()
     print("Test players.getHash")
     vbar()
     vprint("We collect the hash of the players in the DB and compare with")
     vprint("the reference test data:")
     # test valid players
     for pp in refPlayers():
         playerID = pp['playerID']
         hash_ref = pp['passwordHash']
         result = players.getHash(playerID)
         valid = (result['status'] == "ok") and (result['passwordHash']
                                                 == hash_ref)
         vprint("    " + pp['nickname'] + ": result = " + str(result))
         self.assertTrue(valid)
     # test unknown player
     result = players.getHash(ObjectId())
     valid = (result['status'] == "ko") and (result['reason']
                                             == "unknown playerID")
     vprint("    Unknown player: result = " + str(result))
     self.assertTrue(valid)
     # test invalid playerID
     result = players.getHash("invalid")
     valid = (result['status'] == "ko") and (result['reason']
                                             == "invalid playerID")
     vprint("    Invalid playerID: result = " + str(result))
     self.assertTrue(valid)
     # end of the test
     self.teardown(players)
示例#5
0
def gameSetup(test_data_index):
    """
        Initialize a game from test data: the 'test_data_index' (0 or 1) points
        at the data set to be used from 'test_utilities' for:
            - players
            - cardset
        We then use the reference 'set proposal history' (in 'test_utilities' in 
        order to go through the game and compare the progress against reference 
        data available from 'refSteps'.
        """
    # Connection to the MongoDB server
    # read the players, register them and initiate a game.
    players = refPlayers(True)
    temp_players = Players()
    for pp in players:
        temp_players.register(pp['nickname'], pp['passwordHash'])
    partie = Game(players)
    # overwrite the gameID with the reference test data
    partie.gameID = ObjectId(refGameHeader_start()[test_data_index]['gameID'])
    # Overwrite the cardset with reference test data
    cards_dict = refGames_Dict()[test_data_index]['cardset']
    partie.cards.deserialize(cards_dict)
    # Force 'Steps' to take into account this new cardset.
    partie.steps[0].start(partie.cards)
    # The game is ready to start.
    return partie
示例#6
0
 def test_getPlayerID(self):
     """
     Test players.getPlayerID
     """
     # setup the test data
     self.setUp()
     players = Players()
     vbar()
     print("Test players.getPlayerID")
     vbar()
     vprint(
         "We collect the playerID of the players in the DB and compare with"
     )
     vprint("the reference test data:")
     # test valid players
     for pp in refPlayers():
         playerID_ref = pp['playerID']
         result = players.getPlayerID(pp['nickname'])
         valid = (result['status'] == "ok") and (result['playerID']
                                                 == playerID_ref)
         vprint("    " + pp['nickname'] + ": result = " + str(result))
         self.assertTrue(valid)
     # test invalid players
     nickname = "inexistantplayer"
     result = players.getPlayerID(nickname)
     valid = (result['status'] == "ko") and (result['reason']
                                             == "unknown nickname")
     vprint("    " + nickname + ": result = " + str(result))
     self.assertTrue(valid)
     # end of the test
     self.teardown(players)
示例#7
0
 def __init__(self):
     """
     Initiates the backend by creating game-persistent data
     """
     # initiate the list of future games
     self.games = []
     # initiates the players and waiting list
     self.players = Players()
     self.playersWaitingList = []
     self.nextGameID = None
示例#8
0
 def test__init__(self):
     """
     Test players.__init__
     """
     # setup the test data
     self.setUp()
     players = Players()
     vbar()
     vprint("Test data creation")
     vprint("    We create 6 players in the DB:")
     for pp in players.playersColl.find():
         vprint("      " + pp['nickname'])
     vprint("    These will be used as test data for the whole test suite.")
     # self.list_test_players(players.playersColl)
     # check the number of players read from the database
     vbar()
     print("Test players.__init__")
     vbar()
     # replaced 'count' (deprecated) with 'count_documents'
     self.assertEqual(players.playersColl.count_documents({}), 6)
     # test if the db was properly read
     vprint(
         "We test that the __init__ will properly read 6 players from the DB, and"
     )
     vprint("check few details.")
     pp = players.playersColl.find_one({'nickname': "Fifi"})
     self.assertEqual(pp['totalScore'], 0)
     pp = players.playersColl.find_one({'nickname': "Zorro"})
     self.assertEqual(pp, None)
     pp = players.playersColl.find_one({'totalScore': 45})
     self.assertEqual(pp['nickname'], "Daisy")
     # end of the test
     self.teardown(players)
示例#9
0
 def reset(self):
     """
     ths method is used for test purposes: it enables 'test_setserver' to 
     reset the server's variables and ensure that all tests will run in a
     clean context.
     It is an alternative to endlessly stopping and restarting the server.
     """
     # connect to the players collection, and empty it
     getPlayersColl().drop()
     # connect to the games collection and empty it
     getGamesColl().drop()
     # voluntarily, we do NOT empty the log collection
     # initialize again all generic variables
     self.games = []
     self.players = Players()
     self.playersWaitingList = []
     self.nextGameID = None
     # returns status update answer
     return {'status': "reset"}
示例#10
0
 def test_isNicknameAvailable(self):
     """
     Test players.isNicknameAvailable
     """
     # test that the new player is actually added both in memory and in DB
     vbar()
     print("Test players.isNicknameAvailable")
     vbar()
     vprint(
         "We register players and check that their nickname are not available anymore."
     )
     # empty the database
     playersColl = getPlayersColl()
     playersColl.drop()
     # setup the test data
     players = Players()
     for pp in refPlayers():
         # test that the nickname is available
         vprint("   > " + pp['nickname'] + ":")
         answer = players.isNicknameAvailable(pp['nickname'])
         self.assertEqual(answer['status'], "ok")
         vprint("         * nickname is available")
         # register the player and test that the nickname is not available anymore.
         players.register(pp['nickname'], pp['passwordHash'])
         vprint("         * register " + pp['nickname'])
         answer = players.isNicknameAvailable(pp['nickname'])
         self.assertEqual(answer['status'], "ko")
         vprint("         * nickname is not available anymore")
示例#11
0
 def test_getPlayer(self):
     """
     Test players.getPlayer
     """
     # setup the test data
     self.setUp()
     players = Players()
     vbar()
     print("Test players.getPlayer")
     vbar()
     vprint(
         "We collect several players from the DB structure, and compare with the"
     )
     vprint("reference test data:")
     # collect Donald and Daisy and check results
     ref_players = refPlayers(True)
     idDonald = players.getPlayerID("Donald")['playerID']
     print("BOGUS: ", idDonald)
     test_player = players.getPlayer(idDonald)
     vprint("    Donald: " + str(test_player))
     self.assertEqual(test_player['status'], "ok")
     self.assertEqual(test_player['playerID'], ref_players[0]['playerID'])
     self.assertEqual(test_player['nickname'], ref_players[0]['nickname'])
     self.assertEqual(test_player['passwordHash'],
                      ref_players[0]['passwordHash'])
     self.assertEqual(test_player['totalScore'],
                      ref_players[0]['totalScore'])
     self.assertEqual(test_player['gameID'], ref_players[0]['gameID'])
     idDaisy = players.getPlayerID("Daisy")['playerID']
     test_player = players.getPlayer(idDaisy)
     vprint("    Daisy:  " + str(test_player))
     self.assertEqual(test_player['status'], "ok")
     self.assertEqual(test_player['playerID'], ref_players[5]['playerID'])
     self.assertEqual(test_player['nickname'], ref_players[5]['nickname'])
     self.assertEqual(test_player['passwordHash'],
                      ref_players[5]['passwordHash'])
     self.assertEqual(test_player['totalScore'],
                      ref_players[5]['totalScore'])
     self.assertEqual(test_player['gameID'], ref_players[5]['gameID'])
     # try to get invalid and unknown playerIDs
     idUnknown = ObjectId()
     test_player = players.getPlayer(idUnknown)
     vprint("    Unkown playerID:  " + str(test_player))
     self.assertEqual(test_player['status'], "ko")
     self.assertEqual(test_player['reason'], "unknown playerID")
     idInvalid = "invalid"
     test_player = players.getPlayer(idInvalid)
     vprint("    Invalid playerID:  " + str(test_player))
     self.assertEqual(test_player['status'], "ko")
     self.assertEqual(test_player['reason'], "invalid playerID")
示例#12
0
 def test_register(self):
     """
     Test players.register
     """
     # test that the new player is actually added both in memory and in DB
     vbar()
     print("Test players.register")
     vbar()
     vprint(
         "We add a player and check that it is properly registered to the DB."
     )
     vprint(
         "We also check that duplicate registering a player will not work.")
     # setup the test data
     self.setUp()
     players = Players()
     new_hash = "lEyycZ2UYZV0bX6ChdtSA5MGCmN3BrF1xoZG4TMRzEmwmpp"
     playerID = players.register("Dingo", new_hash)['playerID']
     read_id = players.playersColl.find_one({'nickname': "Dingo"})['_id']
     self.assertEqual(playerID, read_id)
     # replaced 'count' (deprecated) with 'count_documents'
     self.assertEqual(players.playersColl.count_documents({}), 7)
     # check the various fields of registered players
     pp = players.playersColl.find_one({'nickname': "Dingo"})
     self.assertEqual(pp['_id'], playerID)
     self.assertEqual(pp['passwordHash'], new_hash)
     # check that it is impossible to register a duplicate nickname
     result = players.register("Daisy", new_hash)
     self.assertEqual(result['status'], "ko")
     self.assertEqual(result['reason'], "invalid nickname")
     # replaced 'count' (deprecated) with 'count_documents'
     self.assertEqual(players.playersColl.count_documents({}), 7)
     # summarize
     vprint("    We now have 7 players in the DB:")
     for pp in players.playersColl.find():
         vprint("      " + pp['nickname'])
     # end of the test
     self.teardown(players)
示例#13
0
 def test_deRegister(self):
     """
     Test players.deRegister
     """
     # setup the test data
     self.setUp()
     players = Players()
     # removes a player
     vbar()
     print("Test players.deRegister")
     vbar()
     vprint("We first register all 6 reference test players.")
     pp = players.playersColl.find_one({'nickname': "Donald"})
     self.assertTrue(players.deRegister(pp['_id']))
     # replaced 'count' (deprecated) with 'count_documents'
     self.assertEqual(players.playersColl.count_documents({}), 5)
     pp = players.playersColl.find_one({'nickname': "Donald"})
     self.assertEqual(pp, None)
     vprint("We removed Donald and check that we have 5 players left.")
     for pp in players.playersColl.find():
         vprint("      " + pp['nickname'])
     # end of the test
     self.teardown(players)
示例#14
0
 def test_changeHash(self):
     """
     Test players.changeHash
     """
     # setup the test data
     vbar()
     print("Test players.changeHash")
     vbar()
     vprint(
         "We change the hash of the players in the DB and compare the result with"
     )
     vprint("the expected test data:")
     # test valid players
     self.setUp()
     players = Players()
     new_hash = "lEyycZ2UYZV0bX6ChdtSA5MGCmN3BrF1xoZG4TMRzEmwmpp"
     for pp in refPlayers():
         playerID = pp['playerID']
         result = players.changeHash(playerID, new_hash)
         valid = (result['status'] == "ok") and (result['passwordHash']
                                                 == new_hash)
         vprint("    " + pp['nickname'] + ": result = " + str(result))
         self.assertTrue(valid)
     # test unknown player
     result = players.getHash(ObjectId())
     valid = (result['status'] == "ko") and (result['reason']
                                             == "unknown playerID")
     vprint("    Unknown player: result = " + str(result))
     self.assertTrue(valid)
     # test invalid playerID
     result = players.getHash("invalid")
     valid = (result['status'] == "ko") and (result['reason']
                                             == "invalid playerID")
     vprint("    Invalid playerID: result = " + str(result))
     self.assertTrue(valid)
     # end of the test
     self.teardown(players)
示例#15
0
class Backend():
    """
    This class 'runs' the backend, i.e. the business logics to power the web
    server described in 'setserver.py'. Its methods enabled to:
    - welcome the front requests for games and players (one called by the web 
        server)
    - initiate as per need new games (calling on the Game class)
    
    Typically:
    - it starts a new Game, with a unique gameID, when the players are 
        identified (per team or via a waiting list for isolated players)
    - it starts a new game when conditions are met
    - it can stop a game and store it when instructed
    """

    def __init__(self):
        """
        Initiates the backend by creating game-persistent data
        """
        # initiate the list of future games
        self.games = []
        # initiates the players and waiting list
        self.players = Players()
        self.playersWaitingList = []
        self.nextGameID = None

    def reset(self):
        """
        ths method is used for test purposes: it enables 'test_setserver' to 
        reset the server's variables and ensure that all tests will run in a
        clean context.
        It is an alternative to endlessly stopping and restarting the server.
        """
        # connect to the players collection, and empty it
        getPlayersColl().drop()
        # connect to the games collection and empty it
        getGamesColl().drop()
        # voluntarily, we do NOT empty the log collection
        # initialize again all generic variables
        self.games = []
        self.players = Players()
        self.playersWaitingList = []
        self.nextGameID = None
        # returns status update answer
        return {'status': "reset"}

    def isNicknameAvailable(self, nickname):
        """
        This method checks if a nickname is still available so that a new player 
        could register with this nickname.
        
        NB: there is no possible 'reservation' for a nickname, and they are 
        assigned on a "first ask first served" basis.

        The client need to request if a nickname is available: it will push a 
        "nickname" to the server who will - if available - return a positive
        answer:
        - 
            post: { "nickname": "str" }
            answer: { "playerID": str(ObjectId) }
                
        The client need to parse the returned message to read the (stringified) 
        playerID.
        """
        answer = self.players.isNicknameAvailable(nickname)
        if answer['status'] == "ok":
            result = {'status': "ok", 'nickname': answer['nickname']}
        else:
            result = {'status': "ko", 'reason': answer['reason']}
        return result

    def getPlayerLoginDetails(self, nickname):
        """
        This method returns the details enabling a local client to log-in a 
        player.
        To date (v100), the required details are a nickname, a playerID and a 
        password hash.

        The result can be:
        - if successful: {  'result': "ok", 'nickname': str,
                            'playerID': str(ObjectId), 'passwordHash': str }
        - if not successful: { 'result': "ko", 'reason': str }
        """
        answer = self.players.getPlayerID(nickname)
        if answer['status'] == "ok":
            playerID = answer['playerID']
            passwordHash = self.players.getHash(playerID)['passwordHash']
            result = {
                'status': "ok",
                'nickname': nickname,
                'playerID': str(playerID),
                'passwordHash': passwordHash
                }
        else:
            result = {'status': "ko", 'reason': answer['reason']}
        return result

    def registerPlayer(self, nickname, passwordHash):
        """
        This method registers new players so that they can play and connect 
        to a game with their nickname (must be unique) or playerID and then 
        enlist onto a game.
        The players are persistent: they are stored on the db, although the
        game will manipulate 'in memory' objects as long as it runs.
        
        The client need to request the creation of a player: it will push a 
        "nickname" to the server who will - if successful - return a player ID:
            { 'status': "ok", 'playerID': "str(ObjectId) }
            or
            { 'status': "ko", 'reason': error_msg }
                
        The client need to parse the returned message to read the (stringified) 
        playerID.
        """
        # It will try to register a new player via 'players.addPlayer'.
        #     - If the answer is True, it returns the playerID 
        #     - if the answer is False, it returns 'Failed'.
        answer = self.players.register(nickname, passwordHash)
        if answer['status'] == "ok":
            answer['playerID'] = str(answer['playerID'])
        return answer

    def deRegisterPlayer(self, playerID):
        """
        This method de-registers a player so that we remove it from the 
        database.
        
        It will also remove the player from any game it would be part of.
        
        If returns:
            { 'status': "ok" }
            or
            { 'status': "ko", 'reason': error_msg }
        """
        # remove the player from all the games
        for gg in self.games:
            gg.delistPlayer(playerID)
        # remove the player from the database.
        return self.players.deRegister(playerID)

    def enlistPlayer(self, playerID):
        """
        This method enlists one player on a "new-game-yet-to-start".

        The client places a GET with its 'playerID' and receives 3 possible 
        answers:
            - the player is set on the waiting list for the next game which will 
                be started. The returned message is 'wait'
            - the game is starting, and the server indicates the corresponding
                'gameID'.
            - the player is not available (because it is already part of another 
                game): the answer is the 'gameID' of the game the player is 
                being part of.
                This is the nominal way for a client to check the gameID for an
                active player.
            - the player is not recognized (because its 'playerID' is not in the
                DB or is invalid): the answer is 'invalid'

        The information needed to start a game is a list of 'players' 
        dictionaries as:
            { 'playerID': ObjectId, 'nickname': string }
        The list is assumed to be filled with 'valid' player's ID and we check 
        that there are enough players to start a game (and is so, actually start 
        it).
        """
        # We assume here that the client will push a value named 'playerID' 
        # which is a valid player's ID, or will go through the form 'enlist_tpl'
        # check if the playerID is valid
        if isPlayerIDValid(playerID):
            # check if the player is available to take part into a new game
            if self.players.isPlayerAvailableToPlay(playerID)['status'] == "ok":
                # check if the playerID  is in the waiting list
                if (playerID in self.playersWaitingList):
                    # the player already enlisted but the game is not yet
                    # starting (waiting for more players to enlist)
                    result = {'status': "wait", 
                              'nb_players': len(self.playersWaitingList)}
                else:
                    self.playersWaitingList.append(playerID)
                    # check if the minimum number of players has been reached
                    if len(self.playersWaitingList) < playersMin:
                        # not enough player: stay in wait mode
                        result = {'status': "wait", 
                                  'nb_players': len(self.playersWaitingList)}
                    else:
                        # there are enough player: we start a new game
                        # build the players list for the new game
                        game_players = []
                        for pID in self.playersWaitingList:
                            game_players.append({
                                'playerID': pID, 
                                'nickname': self.players.getNickname(pID)['nickname'],
                                'passwordHash': self.players.getHash(pID)['passwordHash']
                                })
                        # initiate the new game
                        game = Game(game_players)
                        gameID = game.getGameID()
                        self.games.append(game)
                        # registers the players in the DB
                        for pID in self.playersWaitingList:
                            self.players.enlist(pID, gameID)
                        # empty the waiting list
                        self.playersWaitingList = []
                        # returns a 'gameID' result
                        result = {'status': "ok", 'gameID': gameID}
            else:
                # the player is already part of a game and cannot enlist.
                # the server indicates which game (i.e. gameID) the player 
                # is part of.
                result = {'status': "ok", 
                          'gameID': self.players.getGameID(playerID)['gameID']}
        else:
            # the playerID does not exist:
            result = {'status': "ko", 'reason': "unknown playerID"}
        # in any case, the server returns 'result'
        return result

    def enlistTeam(self, list_playerID):
        """
        This function enable to enlist multiple players in one time into the 
        same game. The list must contain at least 'playersMin' players (usually
        4 players) and at max 'playersMax' players (usually 6 players).
        The list contains dictionaries like:
                { 'playerID': ObjectId }
        The list is assumed to be filled with 'valid' player's ID and we check 
        that:
            - the number of players of correct (from 4 to 6 usually),
            - the IDs are all unique in the list.
        """
        # remove the duplicates
        pID_list = []
        for pp in list_playerID:
            pID_list.append(pp['playerID'])
        pID_list = list(set(pID_list))
        list_playerID = []
        for pID in pID_list:
            list_playerID.append({'playerID': pID})
        # check the playerID : should be registered and be available to play
        j = len(list_playerID)-1
        while j >= 0:
            pID = list_playerID[j]['playerID']
            if isPlayerIDValid(pID):
                if self.players.isPlayerAvailableToPlay(pID)['status'] == "ko":
                    del(list_playerID[j])
            else:
                del(list_playerID[j])
            j -= 1
        # check the 'real' number of players
        l = len(list_playerID)
        if (l >= playersMin) and (l <= playersMax):
            # the players's list is ok (number ok and all are valid, unique and 
            # available)
            game_players = []
            for pp in list_playerID:
                pID = pp['playerID']
                game_players.append({'playerID': pID, 
                    'nickname': self.players.getNickname(pID)['nickname'],
                    'passwordHash': self.players.getHash(pID)['passwordHash'],
                    'points': 0})
            #initiate a game
            game = Game(game_players)
            gameID = game.getGameID()
            self.games.append(game)
            # registers the players in the DB
            for pp in list_playerID:
                pID = pp['playerID']
                self.players.enlist(pID, gameID)
            # returns the game info
            return {'status': "ok", 'gameID': gameID}
        else:
            return {'status': "ko"}

    def delistPlayer(self, playerID):
        """
        This function enable to delist a player from the database and also from
        the game he might be part of.
        
        The returned result can be:
            { 'status': "ok" }
        or
            {'status': "ko", 'reason': message }
        """
        # retrieve the player's detail
        answer = self.players.getPlayer(playerID)
        if answer['status'] == "ok":
            # remove the player from all possible games
            for game in self.games:
                game.delistPlayer(playerID)
            # delist the player from the players list
            result = self.players.delist(playerID)
        else:
            result = answer
        return result

    def getGameID(self, playerID):
        """
        This method returns the gameID if the player exist and is part of a 
        game. 
        
        Possible answers are:
            {'status': "ok", 'gameID': ObjectId }
        or:
            {'status': "ko", 'reason': "unknown playerID"}
            {'status': "ko", 'reason': "invalid playerID"}
        """
        if oidIsValid(playerID):
            result = self.players.getGameID(playerID)
        else:
            result = {'status': "ko", 'reason': "invalid playerID"}
        return result

    def getNicknames(self, playerID):
        """
        This function gives back the names of all the players which are part of
        the same game as the player who identifies itself via his playerID.

        NB: on purpose, the playerIDs of the other players are not shared 
            openly, and only nicknames are shared.
        """
        # I should find a way to catch errors in case the playerID/gameID are 
        # not valid ObjectId.
        list_names = []
        if isPlayerIDValid(playerID):
            gameID = self.players.getGameID(playerID)['gameID']
            if gameID != None:
                list_pID = self.players.inGame(gameID)['list']
                for pID in list_pID:
                    nickname = self.players.getNickname(pID)['nickname']
                    list_names.append({'nickname': nickname})
        return list_names

    def stopGame(self, gameID, hard = False):
        """
        This function stops a game and de-registers the players who were part of this
        game.
           - hard == True: it will kill the game irrespective of its status.
           - hard == False: it first checks that the game is finished. 
        """
        # check that gameID is valid and the corresponding game exists
        if oidIsValid(gameID):
            good_game = None
            for i in range(0, len(self.games)):
                if self.games[i].getGameID() == gameID:
                    good_game = self.games[i]
                    break
            if good_game == None:
                # gameID is valid but there is no corresponding game
                result = {'status': "ko", 'reason': "game does not exist"}
            else:
                if self.games[i].getGameFinished() or hard:
                    # gameID is valid and correspond to the game 'good_game'
                    # kill the game and delist the corresponding players
                    del(self.games[i])
                    self.players.delistGame(gameID)
                    result = {'status': "ok"}
                else:
                    # gameID is ok, but the game is not finished and the 'hard'
                    # flag is not set
                    result = {'status': "ko", 'reason': "game not finished"}
        else:
            # gameID is not a valid ObjectId
            result = {'status': "ko", 'reason': "invalid GameID"}
        # end of the 'stop' method
        return result

    def getDetails(self,gameID):
        """
        The server will answer the clients when they ask about the generic 
        details of the game: cardset, turncounter...
        It will answer with the data description (JSON):
            { 'status': "ok", 
            'gameID': str(ObjectId), 
            'gameFinished': str(gameFinished), 
            'cards': cardset.serialize,
            'turnCounter': str(turncounter),
            'players': list of {'playerID': str(playerID), 'nickname': nickname,
                'passwordHash': passwordHash, 'points': str(points) }
        If the request is not ok, it will return the dictionary:
            { 'status': "ko", 'reason': msg }
        """
        if oidIsValid(gameID):
            good_game = None
            for gg in self.games:
                if gg.gameID == gameID:
                    good_game = gg
                    break
            if good_game != None:
                result = {'status': "ok",
                    'gameID': str(gameID),
                    'turnCounter': str(good_game.turnCounter),
                    'gameFinished': str(good_game.gameFinished),
                    'cardset': good_game.cards.serialize()}
                # add the players (local vision from within the game)
                result["players"] = []
                for pp in good_game.players:
                    result["players"].append( { 
                        'playerID': str(pp['playerID']), 
                        'nickname': pp['nickname'], 
                        'passwordHash': pp['passwordHash'],
                        'points': str(pp['points'])})
            else:
                result = {'status': "ko", 'reason': "unknown gameID"}
        else:
            result = {'status': "ko", 'reason': "invalid gameID"}
        return result

    def getTurnCounter(self,gameID):
        """
        The server will return the turncounter of the game if it exist.

        It will answer with the data description (JSON):
            { 'status': "ok", 'turnCounter': str(turncounter) }
        If the request is not ok, it will return the dictionary:
            { 'status': "ko", 'reason': msg }
        """
        answer = self.getDetails(gameID)
        if answer['status'] == "ok":
            result = {
                      'status': "ok",
                      'turnCounter': answer['turnCounter']
                      }
        else:
            result = answer
        return result

    def getGameFinished(self, gameID):
        """
        The server will return the gameFinished flag of the game if it exist.

        It will answer with the data description (JSON):
            { 'status': "ok", 'turnCounter': str(gameFinished) }
        If the request is not ok, it will return the dictionary:
            { 'status': "ko", 'reason': msg }
        """
        answer = self.getDetails(gameID)
        if answer['status'] == "ok":
            result = {
                      'status': "ok",
                      'gameFinished': answer['gameFinished']
                      }
        else:
            result = answer
        return result

    def getStep(self,gameID):
        """
        The server will answer the clients when they ask about the status of the 
        game:
        - if the request is successful, it returns:
                { 'status': "ok", 'step': step.serialize }
        - if gameID is not a valid ObjectId, it return:
                {'status': "ko", 'reason': "invalid gameID" }
        - if gameID is a valid ObjectId but the game does not exist, it returns:
                {'status': "ko", 'reason': "game does not exist"}
        """
        # check that the gameID is a valid ID
        if oidIsValid(gameID):
            # check if the gameID exist
            good_game = None
            for gg in self.games:
                if str(gg.gameID) == str(gameID):
                    good_game = gg
                    break
            if good_game != None:
                # gameID is valid and the game exist
                step = good_game.steps[good_game.turnCounter]
                result = {'status': "ok", 'step': step.serialize()}
            else:
                result = {'status': "ko", 'reason': "game does not exist"}
        else:
            result = {'status': "ko", 'reason': "invalid gameID"}
        return result

    def getHistory(self,gameID):
        """
        The server will answer the clients when they ask about the full history
        of a game (active or finished): it will answer with the full description 
        (JSON):
        - collect the full details of the game:
            GET url/game/<gameid>/history/
            answer { serialized Game }
        """
        # check that the gameID is a valid ID
        if oidIsValid(gameID):
            # check if the gameID exist
            good_game = None
            for gg in self.games:
                if str(gg.gameID) == str(gameID):
                    good_game = gg
                    break
            if good_game != None:
                # gameID is valid and the game exist
                result = {'status': "ok", 'game': good_game.serialize()}
            else:
                result = {'status': "ko", 'reason': "game does not exist"}
        else:
            result = {'status': "ko", 'reason': "invalid gameID"}
        return result

    def proposeSet(self, playerID, setlist):
        """
        The method collects a Set proposal to be checked and played:
            - playerID (ObjectId) indicates the player
            - setlist ([int0, int1, int2] indicates the positions of the 3 cards
                on the table for the current step.
        If the setlist is valid, it is played and the game continues:
            - the 3 cards are moved to the 'used'
            - 3 new cards are taken from the 'pick' and put on the 'table'
            - turnCounter and points are incremented...
        the method returns:
            - if PlayerID is an invalid ObjectId:
                { 'status': "ko", 'reason': "invalid playerID"}
            - else if playerID is valid but the player does not exist:
                { 'status': "ko", 'reason': "unknown player" }
            - else if PlayerID is valid but the setlist syntax is invalid:
                { 'status': "ko", 'reason': "invalid set" }
            - else if the playerID is valid, the setlist syntax is valid but 
                does not form a valid set of 3 cards:
                { 'status': "ko", 'reason': "wrong set" }
            - else the setlist is valid:
                { 'status': "ok" }
        """
        
        def setSyntax(setlist):
            """
            Check that the syntax of the proposed set is ok:
            - list of integers (not sure we can test this efficiently
            """
            valid = (type(setlist) == list)
            valid = valid and (len(setlist) == 3)
            if valid:
                for i in range(0,3):
                    valid = valid and (type(setlist[i]) == int)
                if valid:
                    for i in range(0,3):
                        valid = valid and (setlist[i] >= 0) and (setlist[i] < tableMax)
                        valid = valid and (setlist[i] != setlist[(i+1)%3])
            return valid
            
        if oidIsValid(playerID):
            #check if playerID exist 
            if isPlayerIDValid(playerID):
                # check if the set syntax is valid (3 integers between 0 and 11)
                if setSyntax(setlist):
                    # find the game
                    gameID = self.players.getGameID(playerID)['gameID']
                    if gameID != None:
                        good_game = None
                        for gg in self.games:
                            if (str(gg.getGameID()) == str(gameID)):
                                good_game = gg
                                break
                        if good_game != None:
                            # push the set to the game
                            valid = good_game.receiveSetProposal(playerID, setlist)
                            if valid:
                                # the set is valid and was already processed
                                result = {'status': "ok"}
                            else:
                                result = {'status': "ko",
                                          'reason': "wrong set"}
                        else:
                            # this case should never happen, unless the DB is 
                            # corrupted and playerID are enlisted to wrong games
                            result = {'status': "ko", 
                                      'reason': "player not in game"}
                    else:
                        # the player is not enlisted: this should never happen
                        # unless the DB is corrupted.
                        result = {'status': "ko", 
                                  'reason': "player not in game"}
                else:
                    result = {'status': "ko", 'reason': "invalid set"}
            else:
                result = {'status': "ko", 'reason': "unknown playerID"}
        else:
            result = {'status': "ko", 'reason': "invalid playerID"}
        return result

    def ForTestOnly_RegisterRefPlayers(self):
        """
        FOR TEST PURPOSE ONLY.
        This method register 6 reference test players.
        """
        # connects straight to the Mongo database
        playersColl = getPlayersColl()
        playersColl.drop()
        # now register the reference players straight to the DB (bypassing the
        # normal process = call to the setserver 'register' API)
        for pp in refPlayers(True):
            playersColl.insert_one( {
                '_id': pp['playerID'], 
                'nickname': pp['nickname'],
                'passwordHash': pp['passwordHash'],
                'totalScore': 0,
                'gameID': None } )
        return {'status': "ok"}

    def ForTestOnly_EnlistRefPlayers(self):
        """
        FOR TEST PURPOSE ONLY.
        This method enlist 6 reference test players. It assumes that these 
        reference players were already registered.
        """
        # enlist a team of 6 players (in which 1 duplicate): it should succeed
        list_pid = []
        for pp in refPlayers(True):
            list_pid.append({'playerID': pp['playerID']})
        result = self.enlistTeam(list_pid)
        return result

    def ForTestOnly_DelistAllPlayers(self):
        """
        FOR TEST PURPOSE ONLY.
        This method delist all players from any on-going game. If used unwisely, 
        this may induce inconsistency within the server (especially since this
        will not stop the on-going games, but only delist the players).
        
        It returns the number of players which were actually delisted from a 
        game.
        """
        # delist all the players by overwriting the gameID field with 'None'.
        modified = self.playersColl.update_many({}, {'$set': {'gameID': None}})
        return modified.modified_count

    def ForTestOnly_LoadRefGame(self, test_data_index):
        """
        FOR TEST PURPOSE ONLY.
        This method initiate the reference test game corresponding to the index 
        passed as argument. The game is fully played and is finished.
        """
        # cleans the DB and registers the reference players
        if test_data_index in (0,1):
            # initiate a new game and overwrite it with reference test data
            self.reset()
            self.ForTestOnly_RegisterRefPlayers()
            # initialize a game (just to have a game object available
            self.games.append(Game(refPlayers(True)))
            # override this game with the reference test data
            self.games[0].deserialize(refGames_Dict()[test_data_index])
            gID = self.games[0].getGameID()
            for pp in self.players.getPlayers():
                self.players.delist(pp['playerID'])
                self.players.enlist(pp['playerID'], gID)
            result = {'status': "ok", 'gameID': gID}
        else:
            result = {'status': "ko", 'reason': "wrong test_data_index"}
        return result

    def ForTestOnly_GetBackToTurn(self, test_data_index, target_turn):
        """
        FOR TEST PURPOSE ONLY.
        This method enable to roll the reference played loaded with previous 
        method back to the turn N.
        """
        # rewind the game back to turn 'target_turn'
        # we know - since the backend was reseted, that the new game is 
        # backend.game[0] => we set the games index i at 0 
        i = 0
        nb_turn_max = self.games[i].turnCounter
        target_turn = min(target_turn, nb_turn_max)
        target_turn = max(0, target_turn)
        original_turn = self.games[i].turnCounter
        if (target_turn < original_turn):
            refGames = refGames_Dict()[test_data_index]
            # adapts the generic details
            self.games[i].gameFinished = False
            self.games[i].turnCounter = target_turn
            # removes the 'future' steps
            j = original_turn
            while j > target_turn:
                del(self.games[i].steps[j])
                j -= 1
            # resets the 'playerID', nickname' and 'set' to empty if the game is 
            # not finished
            self.games[i].steps[target_turn].playerID = None
            self.games[i].steps[target_turn].nickname = ""
            self.games[i].steps[target_turn].set = []
            # set the player's points as from the reference test data
            # The only way to do so is actually to replay the game and add points to
            # the players accordingly.
            for pp in self.games[0].players:
                pp['points'] = 0
            for j in range(0,target_turn):
                pID_str = refGames['steps'][j]['playerID']
                for pp in self.games[0].players:
                    if str(pp['playerID']) == pID_str:
                        pp['points'] += pointsPerStep
            result = {'status': "ok"}
        else:
            result = {'status': "ko"}
        return result
示例#16
0
    def test_isPlayerAvailableToPlay(self):
        """
        Test players.isPlayerAvailableToPlay
        """
        vbar()
        print("Test players.isPlayerAvailableToPlay")
        vbar()
        vprint(
            "We check which players are available to play and compare with the"
        )
        vprint("reference data :")
        # setup the test data
        self.setUp()
        players = Players()
        id_Donald = players.getPlayerID("Donald")['playerID']
        print("bogus: id_Donald =", id_Donald)
        id_Mickey = players.getPlayerID("Mickey")['playerID']
        id_Riri = players.getPlayerID("Riri")['playerID']
        id_Fifi = players.getPlayerID("Fifi")['playerID']
        id_Loulou = players.getPlayerID("Loulou")['playerID']
        id_Daisy = players.getPlayerID("Daisy")['playerID']
        gameID1 = ObjectId()
        gameID2 = ObjectId()
        # first round of test
        players.enlist(id_Riri, gameID2)
        players.enlist(id_Fifi, gameID2)
        players.enlist(id_Loulou, gameID2)
        vprint("  > First round, only kids are playing:")
        result = players.isPlayerAvailableToPlay(id_Donald)
        print("Bogus: ", result)
        vprint("      Donald: " + str(result))
        self.assertTrue(result['status'] == "ok")
        result = players.isPlayerAvailableToPlay(id_Mickey)
        vprint("      Mickey: " + str(result))
        self.assertTrue(result['status'] == "ok")
        result = players.isPlayerAvailableToPlay(id_Riri)
        vprint("      Riri  : " + str(result))
        self.assertTrue(result['status'] == "ko"
                        and result['reason'] == "player is not available")
        result = players.isPlayerAvailableToPlay(id_Fifi)
        vprint("      Fifi  : " + str(result))
        self.assertTrue(result['status'] == "ko"
                        and result['reason'] == "player is not available")
        result = players.isPlayerAvailableToPlay(id_Loulou)
        vprint("      Loulou: " + str(result))
        self.assertTrue(result['status'] == "ko"
                        and result['reason'] == "player is not available")
        result = players.isPlayerAvailableToPlay(id_Daisy)
        vprint("      Daisy : " + str(result))
        self.assertTrue(result['status'] == "ok")
        # second round of test
        players.enlist(id_Daisy, gameID1)
        players.enlist(id_Donald, gameID1)
        vprint("  > Second round, two parents are also playing:")
        result = players.isPlayerAvailableToPlay(id_Donald)
        vprint("      Donald: " + str(result))
        self.assertTrue(result['status'] == "ko"
                        and result['reason'] == "player is not available")
        result = players.isPlayerAvailableToPlay(id_Mickey)
        vprint("      Mickey: " + str(result))
        self.assertTrue(result['status'] == "ok")
        result = players.isPlayerAvailableToPlay(id_Riri)
        vprint("      Riri  : " + str(result))
        self.assertTrue(result['status'] == "ko"
                        and result['reason'] == "player is not available")
        result = players.isPlayerAvailableToPlay(id_Fifi)
        vprint("      Fifi  : " + str(result))
        self.assertTrue(result['status'] == "ko"
                        and result['reason'] == "player is not available")
        result = players.isPlayerAvailableToPlay(id_Loulou)
        vprint("      Loulou: " + str(result))
        self.assertTrue(result['status'] == "ko"
                        and result['reason'] == "player is not available")
        result = players.isPlayerAvailableToPlay(id_Daisy)
        vprint("      Daisy : " + str(result))
        self.assertTrue(result['status'] == "ko"
                        and result['reason'] == "player is not available")
        # test inexistant or invalid playerID
        vprint("  > Third round, with invalid or unknown playerIDs:")
        result = players.isPlayerAvailableToPlay(ObjectId())
        vprint("      Unknown player: " + str(result))
        self.assertTrue(result['status'] == "ko"
                        and result['reason'] == "unknown playerID")
        result = players.isPlayerAvailableToPlay("stupid")
        vprint("      Invalid playerID: " + str(result))
        self.assertTrue(result['status'] == "ko"
                        and result['reason'] == "invalid playerID")

        # end of the test
        self.teardown(players)
示例#17
0
 def test_serialize(self):
     """
     Test players.serialize
     """
     # build the reference data (without the passwrds)
     target = {'__class__': 'SetPlayers', 'players': []}
     for pp in refPlayers_Dict():
         target['players'].append({
             'playerID': pp['playerID'],
             'nickname': pp['nickname'],
             'passwordHash': pp['passwordHash'],
             'totalScore': pp['totalScore'],
             'gameID': pp['gameID']
         })
     # setup the test data
     self.setUp()
     players = Players()
     gameID1 = ObjectId('57bf224df9a2f36dd206845a')
     gameID2 = ObjectId('57bf224df9a2f36dd206845b')
     players.enlist(players.getPlayerID("Daisy")['playerID'], gameID1)
     players.enlist(players.getPlayerID("Donald")['playerID'], gameID1)
     players.enlist(players.getPlayerID("Riri")['playerID'], gameID2)
     players.enlist(players.getPlayerID("Fifi")['playerID'], gameID2)
     players.enlist(players.getPlayerID("Loulou")['playerID'], gameID2)
     # runs the test
     vbar()
     print("Test players.serialize")
     vbar()
     vprint(
         "We compare the result of the 'serialize' method with the target which is:"
     )
     vprint(target)
     # check that the class is equal
     result = players.serialize()
     self.assertTrue(playersDict_equality(target, result))
     # end of the test
     self.teardown(players)
示例#18
0
 def test_inGame(self):
     """
     Test players.inGame
     """
     # setup the test data
     self.setUp()
     players = Players()
     gameID1 = ObjectId()
     gameID2 = ObjectId()
     players.enlist(players.getPlayerID("Daisy")['playerID'], gameID1)
     players.enlist(players.getPlayerID("Donald")['playerID'], gameID1)
     players.enlist(players.getPlayerID("Riri")['playerID'], gameID2)
     players.enlist(players.getPlayerID("Fifi")['playerID'], gameID2)
     players.enlist(players.getPlayerID("Loulou")['playerID'], gameID2)
     vbar()
     print("Test players.inGame")
     vbar()
     vprint(
         "We gather a list of the players being part of the fist game and check"
     )
     vprint("against the reference data :")
     list_pid1 = players.inGame(gameID1)['list']
     list_pid2 = players.inGame(gameID2)['list']
     self.assertTrue(players.getPlayerID("Donald")['playerID'] in list_pid1)
     self.assertTrue(players.getPlayerID("Daisy")['playerID'] in list_pid1)
     self.assertEqual(len(list_pid1), 2)
     vprint("  > GameID 1:")
     for pid in list_pid1:
         name = players.getNickname(pid)['nickname']
         vprint("      " + name + " (" + str(pid) + ")")
     self.assertTrue(players.getPlayerID("Riri")['playerID'] in list_pid2)
     self.assertTrue(players.getPlayerID("Fifi")['playerID'] in list_pid2)
     self.assertTrue(players.getPlayerID("Loulou")['playerID'] in list_pid2)
     self.assertEqual(len(list_pid2), 3)
     vprint("  > GameID 2:")
     for pid in list_pid2:
         name = players.getNickname(pid)['nickname']
         vprint("      " + name + " (" + str(pid) + ")")
     # end of the test
     self.teardown(players)
示例#19
0
 def test_delistGame(self):
     """
     Test players.delistGame
     """
     # setup the test data
     self.setUp()
     players = Players()
     ref_players = []
     for pp in refPlayers():
         ref_players.append(player_format_DB(pp))
     gameID1 = ref_players[0]['gameID']
     gameID2 = ref_players[2]['gameID']
     players.enlist(players.getPlayerID("Daisy")['playerID'], gameID1)
     players.enlist(players.getPlayerID("Donald")['playerID'], gameID1)
     players.enlist(players.getPlayerID("Riri")['playerID'], gameID2)
     players.enlist(players.getPlayerID("Fifi")['playerID'], gameID2)
     players.enlist(players.getPlayerID("Loulou")['playerID'], gameID2)
     # will delist few players
     vbar()
     print("Test players.delistGame")
     vbar()
     vprint("Test registering several players on two games:")
     vprint("    - Riri, Fifi and Loulou are part of a first game.")
     vprint("    - Daisy and Donald are part of another game.")
     vprint("    - Mickey does not play a game.")
     vprint("  Here are the players after we deregister the second game:")
     gid = players.getGameID(
         players.getPlayerID("Riri")['playerID'])['gameID']
     players.delistGame(gid)
     riri_gid = players.getGameID(
         players.getPlayerID("Riri")['playerID'])['gameID']
     fifi_gid = players.getGameID(
         players.getPlayerID("Fifi")['playerID'])['gameID']
     loulou_gid = players.getGameID(
         players.getPlayerID("Loulou")['playerID'])['gameID']
     self.assertTrue(riri_gid == fifi_gid == loulou_gid == None)
     for pp in players.playersColl.find({}):
         vprint("      " + pp['nickname'] + " - gameID: " +
                str(pp['gameID']))
     # end of the test
     self.teardown(players)
示例#20
0
 def test_delistPlayer(self):
     """
     Test players.delistPlayer
     """
     # setup the test data
     self.setUp()
     players = Players()
     ref_players = []
     for pp in refPlayers():
         ref_players.append(player_format_DB(pp))
     gameID1 = ref_players[0]['gameID']
     gameID2 = ref_players[2]['gameID']
     players.enlist(players.getPlayerID("Daisy")['playerID'], gameID1)
     players.enlist(players.getPlayerID("Donald")['playerID'], gameID1)
     players.enlist(players.getPlayerID("Riri")['playerID'], gameID2)
     players.enlist(players.getPlayerID("Fifi")['playerID'], gameID2)
     players.enlist(players.getPlayerID("Loulou")['playerID'], gameID2)
     donald = players.playersColl.find_one({'nickname': "Donald"})
     riri = players.playersColl.find_one({'nickname': "Riri"})
     fifi = players.playersColl.find_one({'nickname': "Fifi"})
     loulou = players.playersColl.find_one({'nickname': "Loulou"})
     daisy = players.playersColl.find_one({'nickname': "Daisy"})
     # will deregister few players
     vbar()
     print("Test players.delistPlayer")
     vbar()
     vprint("Test registering several players on two games:")
     vprint("    - Riri, Fifi and Loulou are part of a first game.")
     vprint("    - Daisy and Donald are part of another game.")
     vprint("    - Mickey does not play a game.")
     vprint("  Here are the players after we deregister them:")
     DonaldID = players.getPlayerID("Donald")['playerID']
     players.delist(DonaldID)
     DaisyID = players.getPlayerID("Daisy")['playerID']
     players.delist(DaisyID)
     donald_gid = players.getGameID(donald['_id'])['gameID']
     daisy_gid = players.getGameID(daisy['_id'])['gameID']
     self.assertTrue(donald_gid == daisy_gid == None)
     players.delist(players.getPlayerID("Riri")['playerID'])
     players.delist(players.getPlayerID("Fifi")['playerID'])
     players.delist(players.getPlayerID("Loulou")['playerID'])
     riri_gid = players.getGameID(riri['_id'])['gameID']
     fifi_gid = players.getGameID(fifi['_id'])['gameID']
     loulou_gid = players.getGameID(loulou['_id'])['gameID']
     self.assertTrue(riri_gid == fifi_gid == loulou_gid == None)
     for pp in players.playersColl.find({}):
         vprint("      " + pp['nickname'] + " - gameID: " +
                str(pp['gameID']))
     # end of the test
     self.teardown(players)
示例#21
0
 def test_enlist(self):
     """
     Test players.enlist
     """
     # setup the test data
     self.setUp()
     players = Players()
     ref_players = []
     for pp in refPlayers():
         ref_players.append(player_format_DB(pp))
     gameID1 = ref_players[0]['gameID']
     gameID2 = ref_players[2]['gameID']
     print("Bogus: ", ref_players[0])
     print("Bogus: ", ref_players[2])
     # modifies few gameID values
     vbar()
     print("Test players.enlist")
     vbar()
     vprint("Test registering several players on two games:")
     vprint("    - Riri, Fifi and Loulou are part of a first game.")
     vprint("    - Daisy and Donald are part of another game.")
     vprint("    - Mickey does not play a game.")
     vprint("  Here are the players:")
     playerID = players.getPlayerID("Daisy")['playerID']
     result = players.enlist(playerID, gameID1)
     self.assertEqual(result['status'], "ok")
     playerID = players.getPlayerID("Donald")['playerID']
     result = players.enlist(playerID, gameID1)
     self.assertEqual(result['status'], "ok")
     playerID = players.getPlayerID("Riri")['playerID']
     result = players.enlist(playerID, gameID2)
     self.assertEqual(result['status'], "ok")
     playerID = players.getPlayerID("Fifi")['playerID']
     result = players.enlist(playerID, gameID2)
     self.assertEqual(result['status'], "ok")
     playerID = players.getPlayerID("Loulou")['playerID']
     result = players.enlist(playerID, gameID2)
     self.assertEqual(result['status'], "ok")
     # self.list_test_players(players.playersColl)
     pp = []
     for p in players.playersColl.find({'gameID': gameID1}):
         pp.append(p)
     result = (ref_players[0] in pp) and (ref_players[5] in pp) and (len(pp)
                                                                     == 2)
     self.assertTrue(result)
     pp = []
     for p in players.playersColl.find({'gameID': gameID2}):
         pp.append(p)
     result = (ref_players[2] in pp) and (ref_players[3] in pp) and (
         ref_players[4] in pp) and (len(pp) == 3)
     self.assertTrue(result)
     for pp in players.playersColl.find({}):
         vprint("      " + pp['nickname'] + " - gameID: " +
                str(pp['gameID']))
     # end of the test
     self.teardown(players)