def test_delete_user_multiple_entries(context): session_id = get_random_session_id() board = chess.Board() color = chess.WHITE create_user(session_id, board, color) # Create another user session_id2 = get_random_session_id() board2 = chess.Board() color2 = chess.BLACK board2.push_san("e4") board2.push_san("d5") create_user(session_id2, board2, color2) # Delete first user delete_user(session_id) assert exists_in_db(session_id) is False # Verify that no other changes were made assert UserModel.query.count() == 1 assert get_user(session_id2) == User(board2, color2)
def two_squares(req: Dict[str, Any]) -> Dict[str, Any]: """Given two squares and a piece, play a move""" params = get_params_by_req(req) # Extract params and take the lowercase of the square squares = [square.lower() for square in params["squares"]] piece = params["piece"] if len(squares) == 1: return piece_and_square(req) # Extract board session_id = get_session_by_req(req) # TODO: Handle case when `session_id not found' when migrating to db # Get user user = get_user(session_id) # Get LAN move lan = two_squares_and_piece_to_lan(board=user.board, squares=squares, piece=piece) # TODO: Store this reply somewhere if lan == "illegal move": return get_response_for_google(textToSpeech=RESPONSES["illegal_move"]) # Play move on board mediator.play_lan(session_id=session_id, lan=lan) kwargs = get_response_kwargs(session_id) return get_response_for_google(**kwargs)
def piece_and_square(req: Dict[str, Any]) -> Dict[str, Any]: """Intent handler for when only one piece and one square are given""" session_id = get_session_by_req(req) params = get_params_by_req(req) piece = params["piece"].lower() pawn = params["pawn"].lower() square = params["square"].lower() board = get_user(session_id).board if pawn: san = square if piece and (square[-1] == "1" or square[-1] == "8"): # Promotion move san = f"{square}={get_piece_symbol(piece, upper=True)}" kwargs = handle_san_and_get_response_kwargs(session_id, board, san) elif piece: san = f"{get_piece_symbol(piece, upper=True)}{square}" kwargs = handle_san_and_get_response_kwargs(session_id, board, san) else: kwargs = {"textToSpeech": "Sorry, can you say that again?"} return get_response_for_google(**kwargs)
def test_get_user(context): session_id = get_random_session_id() board = chess.Board() color = chess.BLACK create_user(session_id, board, color) assert get_user(session_id) == User(board, color)
def get_response_kwargs(session_id: str, lastmove_lan: Optional[str] = None): """ Gets the appropriate args for generating response from result and engine's move Note: Also plays engine's move on the board """ user = get_user(session_id) kwargs = {} game_result = get_result_comment(user=user) if game_result: card = save_board_as_png_and_get_image_card(session_id) # TODO: Archive the game instead of deleting delete_user(session_id) kwargs.update( textToSpeech=game_result, expectUserResponse=False, basicCard=card ) else: # Play engine's move output = mediator.play_engine_move_and_get_speech(session_id) user = get_user(session_id) game_result = get_result_comment(user=user) if game_result: output = f"{output}. {game_result}" card = save_board_as_png_and_get_image_card(session_id) delete_user(session_id) kwargs.update( textToSpeech=output, expectUserResponse=False, basicCard=card ) else: output = f"{output}. {get_prompt_phrase()}" kwargs["textToSpeech"] = output if lastmove_lan: kwargs[ "displayText" ] = f"Your last move was {lastmove_lan}.\n {output}" return kwargs
def play_lan(self, session_id: str, lan: str) -> bool: """Play move and return bool showing if move was successful""" user = get_user(session_id) try: user.board.push_san(lan) update_user(session_id, user.board) return True except ValueError: # Illegal, invalid or ambiguous move return False
def test_undo_users_last_move_on_move_one(self, context, mocker): board = chess.Board() color = chess.BLACK board.push_san("e4") fen = board.fen() create_user(self.session_id, board, color) value = undo_users_last_move(self.session_id) assert value == [] assert get_user(self.session_id).board.fen() == fen
def test_update_user(context): session_id = get_random_session_id() board = chess.Board() color = chess.BLACK create_user(session_id, board, color) # Now update it with some moves board.push_san("Nf3") board.push_san("d5") update_user(session_id, board) assert get_user(session_id) == User(board, color)
def test_update_user_multiple_entries(context): session_id = get_random_session_id() board = chess.Board() color = chess.WHITE create_user(session_id, board, color) # Create second user session_id2 = get_random_session_id() board2 = chess.Board() color2 = chess.BLACK board2.push_san("e4") board2.push_san("e5") create_user(session_id2, board2, color2) board.push_san("g4") update_user(session_id, board) assert get_user(session_id) == User(board, color) # Ensure that other entry has not been modified assert get_user(session_id2) == User(board2, color2)
def test_undo_users_last_move(self, context, mocker): board = chess.Board() color = chess.BLACK for san in ["e4", "e5", "Nf3", "Nc6", "Bc4"]: board.push_san(san) fen = board.fen() board.push_san("Bc5") board.push_san("b4") expected_undone = ["b4", "Bc5"] create_user(self.session_id, board, color) value = undo_users_last_move(self.session_id) assert value == expected_undone assert get_user(self.session_id).board.fen() == fen
def test_undo_users_last_move_game_ended_after_users_move( self, context, mocker): board = chess.Board() color = chess.WHITE for san in ["e4", "e5", "Qh5", "Nc6", "Bc4", "Nf6"]: board.push_san(san) fen = board.fen() board.push_san("Qxf7#") expected_undone = ["Qxf7#"] create_user(self.session_id, board, color) value = undo_users_last_move(self.session_id) assert value == expected_undone assert get_user(self.session_id).board.fen() == fen
def test_delete_user(context): session_id = get_random_session_id() board = chess.Board() color = chess.BLACK create_user(session_id, board, color) # Verify that the user has been created assert get_user(session_id) == User(board, color) delete_user(session_id) # Verify that deletion is successful assert exists_in_db(session_id) is False # Verify that no other operation has been performed assert UserModel.query.count() == 0
def test_undo_on_move_one(self, client): board = chess.Board() color = chess.BLACK board.push_san("e4") fen = board.fen() create_user(self.session_id, board, color) expected_text = "Nothing to undo!" req_data = get_dummy_webhook_request_for_google( session_id=self.session_id, action="undo", intent="undo") r = client.post(url_for("webhook_bp.webhook"), json=req_data) resp = GoogleWebhookResponse(r.json) assert get_user(self.session_id).board.fen() == fen assert expected_text in resp.simple_response.text_to_speech assert expected_text in resp.simple_response.display_text
def simply_san(req: Dict[str, Any]) -> Dict[str, Any]: """Intent handler for simply SAN moves Note: Accepts overspecified SAN (including LAN) """ session_id = get_session_by_req(req) san = get_params_by_req(req)["san"] # Convert pawn moves like E4, D5 to lowercase i.e. e4, d5 if re.match(r"^[A-Z][1-8]$", san): san = san.lower() user = get_user(session_id) board = user.board kwargs = handle_san_and_get_response_kwargs(session_id, board, san) return get_response_for_google(**kwargs)
def castle(req: Dict[str, Any]) -> Dict[str, Any]: """When asked to castle, try playing the castles move""" session_id = get_session_by_req(req) user = get_user(session_id) queryText = req["queryResult"]["queryText"] # Get lan of move lan = process_castle_by_querytext(board=user.board, queryText=queryText) if lan == "illegal move": return get_response_for_google(textToSpeech=RESPONSES["illegal_move"]) mediator.play_lan(session_id=session_id, lan=lan) kwargs = get_response_kwargs(session_id) return get_response_for_google(**kwargs)
def play_engine_move_and_get_speech(self, session_id: str) -> str: """Play engine's move and return the speech conversion of the move""" if not self.engine: self.activate_engine() user = get_user(session_id) # Doesn't actually play the move result = self.engine.play(user.board, chess.engine.Limit(time=0.100)) # Store LAN notation and push lan = user.board.lan(result.move) user.board.push(result.move) # Update DB update_user(session_id, user.board) return lan_to_speech(lan)
def test_get_user_when_multiple_entries_exist(context): session_id = get_random_session_id() board = chess.Board() color = chess.WHITE # Make some moves board.push_san("Nc3") board.push_san("d5") board.push_san("d4") create_user(session_id, board, color) # Another entry session_id2 = get_random_session_id() board2 = chess.Board() color2 = chess.WHITE create_user(session_id2, board2, color2) assert get_user(session_id) == User(board, color)
def test_undo_game_ended_after_users_move(self, client): board = chess.Board() color = chess.WHITE for san in ["e4", "e5", "Qh5", "Nc6", "Bc4", "Nf6"]: board.push_san(san) fen = board.fen() board.push_san("Qxf7#") undone_move = "Qxf7#" create_user(self.session_id, board, color) expected_text = f"OK! Undid the move {undone_move}" req_data = get_dummy_webhook_request_for_google( session_id=self.session_id, action="undo", intent="undo") r = client.post(url_for("webhook_bp.webhook"), json=req_data) resp = GoogleWebhookResponse(r.json) assert get_user(self.session_id).board.fen() == fen assert expected_text in resp.simple_response.text_to_speech assert expected_text in resp.simple_response.display_text
def test_undo(self, client): board = chess.Board() color = chess.BLACK for san in ["e4", "e5", "Nf3", "Nc6", "Bc4"]: board.push_san(san) fen = board.fen() board.push_san("Bc5") board.push_san("b4") engine_move, user_move = "b4", "Bc5" create_user(self.session_id, board, color) expected_text = ( f"Alright! The moves {user_move} and {engine_move} have been " "undone.") req_data = get_dummy_webhook_request_for_google( session_id=self.session_id, action="undo", intent="undo") r = client.post(url_for("webhook_bp.webhook"), json=req_data) resp = GoogleWebhookResponse(r.json) assert get_user(self.session_id).board.fen() == fen assert expected_text in resp.simple_response.text_to_speech assert expected_text in resp.simple_response.display_text
def test_get_user_entry_does_not_exist(context): session_id = get_random_session_id() # Skipping create_user() step with pytest.raises(Exception, match="Entry not found."): get_user(session_id)