def test_start_game(): create_test_game() room = get_room(TEST_GAME) assert room.game_round == 0 assert room.game_mode == GameModes.LOBBY start_game_action.start_game(TEST_GAME) room = get_room(TEST_GAME) assert room.game_round == 1 assert room.game_mode == GameModes.TURN_RECAP
def test_randomize_room(): create_test_game() room = get_room(TEST_GAME) team_2 = room.team_2_players team_1 = room.team_1_players # Using a seed here ensures the teams will change. random.seed(11) randomize_teams(TEST_GAME) room = get_room(TEST_GAME) assert team_2 != room.team_2_players assert team_1 != room.team_1_players
def test_next_mode_typical_case(): clear_rooms() create_test_game() start_game_action.start_game(TEST_GAME) # go to turn recap room = get_room(TEST_GAME) assert room.game_mode == GameModes.TURN_RECAP next_mode(room.name) room = get_room(TEST_GAME) assert room.game_mode == GameModes.CLUE_GIVING next_mode(room.name) room = get_room(TEST_GAME) assert room.game_mode == GameModes.TURN_RECAP
def unready_phrases(room_name, player_name) -> Dict[str, Any]: """Remove phrases for a player and mark them as unready. Args: room_name: The room that this update will impact. player_name: The player submitting the phrases. """ # get player from name room = get_room(room_name) player_found = False for player in room.all_players(): if player_name == player.name: player_found = True if not player_found: raise ValueError(f'Player {player_name} not in room {room_name}.') # check phrases # update player as ready, with phrases player_with_phrases = build_player(player_name, False, []) room.update_player(player_name, player_with_phrases) return {}
def test_room_created(): create_test_game() assert game_room_exists(TEST_GAME) room = get_room(TEST_GAME) assert build_player('Mick') in room.team_1_players assert build_player('Dvir') in room.team_2_players
def randomize_teams(room_name: str) -> Dict[str, str]: """Randomize the teams in a given room. If the room specified for randomization exists, the teams are randomized. The response message is empty. The new teams are always different. If the room does not exist or is not specified, a response message with an 'error' field is returned. Args: room_name: the room to randomize. """ if not game_room_exists(room_name): return {fields.ERROR: f'Room named {room_name} does not exist.'} room = get_room(room_name) players = list(room.team_2_players + room.team_1_players) num_players = len(players) shuffle(players) team_2_players = players[:num_players // 2] team_1_players = players[num_players // 2:] room = evolve( room, **dict(team_1_players=team_1_players, team_2_players=team_2_players)) update_room(room_name, room) return {}
def test_room_can_be_jsonified(): create_test_game() room = get_room(TEST_GAME) jsonified_room = convert_room_to_json(room) data = json.dumps(jsonified_room) assert data
def test_next_clue_giver_other_team_missing(): clear_rooms() create_test_game() start_game_action.start_game(TEST_GAME) room = get_room(TEST_GAME) assert room.clue_giver == room.team_1_players[0] assert room.last_clue_giver is None giver = room.clue_giver # remove players from team 2 update_room(room.name, evolve(room, team_2_players=[])) next_clue_giver(room.name) # next player now on same team as before room = get_room(TEST_GAME) assert room.clue_giver == room.team_1_players[1] assert room.last_clue_giver == giver
def test_next_clue_giver_typical_case(): clear_rooms() create_test_game() start_game_action.start_game(TEST_GAME) room = get_room(TEST_GAME) assert room.clue_giver == room.team_1_players[0] assert room.last_clue_giver is None giver = room.clue_giver next_clue_giver(room.name) room = get_room(TEST_GAME) assert room.clue_giver == room.team_2_players[0] assert room.last_clue_giver == giver giver = room.clue_giver next_clue_giver(room.name) room = get_room(TEST_GAME) assert room.clue_giver == room.team_1_players[1] assert room.last_clue_giver == giver
def test_create_then_join_one_player_per_team(setup): room_name = 'room' player = 'Mick' request = {PLAYER_NAME: player, ROOM_NAME: room_name} result = create_game(request) assert ERROR not in result player2 = 'Dvir' result = join_game({PLAYER_NAME: player2, ROOM_NAME: room_name}) assert ERROR not in result room = get_room(room_name) assert build_player(player) in room.team_1_players assert build_player(player2) in room.team_2_players
def force_room_update(room_name: str) -> None: """Update clients with new room information. Emits the following information: room: room name team1: Sequence of team 1 players team1_ready: Sequence of bools denoting which player is ready. icon1: Icon label for team 1 score1: Score of team1 (... equivalent data for team 2). """ room = get_room(room_name) emit('update_room', convert_room_to_json(room), room=room_name)
def join_game(join_request: Dict[str, str]) -> Dict[str, Any]: """Receive and respond to a join game request from a client. If the game room exists and the player name is not already in use, then the player is added to the game room. This is done by updating the game state in that room. The player is added to the team with fewest players. If the game room does not exist an error message is returned. If the player name is already taken an error message is returned. If a field is missing or blank in the request an error message is returned. Args: join_request: Dictionary containing a 'player name' and 'room name' fields. Returns: On success, an empty dictionary is returned and the updated game state is broadcast to all clients in the room. Otherwise returns a dictionary with an 'error' field. """ error = validate_fields(join_request, (fields.ROOM_NAME, fields.PLAYER_NAME), (fields.ROOM_NAME, fields.PLAYER_NAME)) if error: return {fields.ERROR: error} room_name = join_request[fields.ROOM_NAME] if not game_room_exists(room_name): return {fields.ERROR: f'Room {room_name} does not exist.'} # Get current teams and check player name not already in use room = get_room(room_name) player_name = join_request[fields.PLAYER_NAME] if any(plyr.name == player_name for plyr in room.all_players()): return {fields.ERROR: f'Player \'{player_name}\' already in game.'} # Add player to team with fewest members. if len(room.team_1_players) > len(room.team_2_players): room.team_2_players.append(build_player(player_name)) else: room.team_1_players.append(build_player(player_name)) update_room(room_name, room) return {}
def start_game(room_name: str) -> Dict[str, Any]: """Change a room from lobby mode to the first mode of the round. Args: room_name: Name of the room to start game for. Must correspond to a room in lobby mode. """ assert game_room_exists(room_name) room = get_room(room_name) assert room.game_mode == GameModes.LOBBY assert room.game_round == 0 new_room = evolve(room, game_mode=GameModes.TURN_RECAP, game_round=1) update_room(room_name, new_room) return {}
def next_clue_giver(room_name: str) -> {}: """Changes the clue giver in a room to the next one in the order. The clue giver is set to the next person on the other team. If the other team is empty the next player on the current team is chosen. Args: room_name: The room for which to iterate the clue giver. """ assert game_room_exists(room_name) room = get_room(room_name) next_giver = None prev_giver = room.last_clue_giver # the one before current teams = (room.team_1_players, room.team_2_players) # special processing to handle no previous giver. Pretend like the previous # giver for the other team is the last person on that team. if prev_giver is None: if room.clue_giver in teams[0]: other_team = teams[1] elif room.clue_giver in teams[1]: other_team = teams[0] else: other_team = [] if not other_team: # switch to next player on current player's team prev_giver = room.clue_giver else: prev_giver = other_team[-1] # next clue giver is one following last_clue_giver (same team) for team in teams: if prev_giver in team: ind = team.index(prev_giver) next_giver = team[(ind + 1) % len(team)] update_room( room.name, evolve(room, last_clue_giver=room.clue_giver, clue_giver=next_giver))
def next_mode(room_name: str) -> None: """Cause a room to change to its next mode in the cycle. The room must be in mode CLUE_GIVING or TURN_RECAP. The mode is iterated between the two modes. Args: room_name: The room to iterate. """ room = get_room(room_name) modes = (GameModes.TURN_RECAP, GameModes.CLUE_GIVING) current_mode = room.game_mode assert current_mode in modes, (f'Next mode not defined for ' f'{current_mode.name}') new_mode = modes[1 - modes.index(current_mode)] update_room(room_name, evolve(room, game_mode=new_mode))
def create_test_game() -> None: """Add a test game to the data model. The game has room name 'test' and is populated with random characters. If the game already exists then this function does nothing. """ room_name = fields.TEST_GAME if game_room_exists(room_name): return # initialize room initialize_game_room(room_name, 'Mick') # populate room with players room = get_room(room_name) team_1 = [build_player(p) for p in ['Mick', 'Liz', 'M\'Lickz']] team_2 = [build_player(p) for p in ['Dvir', 'Celeste', 'Boaz', 'Ronen']] room = evolve(room, **dict(team_1_players=team_1, team_2_players=team_2)) update_room(room_name, room)
def submit_phrases(room_name, player_name, submit_request: Dict[str, Any]) -> Dict[str, Any]: """Record phrases for a player and mark them as ready. If the submit request has a valid room, player name, and phrases, update the room with those phrases and mark the player as ready. Empty phrases are not added. Otherwise, an error is returned if a phrase is repeated (or has already been submitted). Args: room_name: The room that this update will impact. player_name: The player submitting the phrases. submit_request: Message with fields PLAYER_NAME and PHRASES. The PHRASES field should store a sequence of string phrases. """ # Validate message structure error = validate_fields(submit_request, (PHRASES, ), (PHRASES, )) if error: raise ValueError(error) # get player from name room = get_room(room_name) player_found = False for player in room.all_players(): if player_name == player.name: player_found = True if not player_found: raise ValueError(f'Player {player_name} not in room {room_name}.') # check phrases phrases = submit_request[PHRASES] # update player as ready, with phrases player_with_phrases = build_player(player_name, True, phrases) room.update_player(player_name, player_with_phrases)