diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f97349be..ef295975 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,7 @@ Changelog To be released -------------- +* Add ``client.explorer.get_otb_master_game`` * Add:: client.external_engine.get diff --git a/README.rst b/README.rst index 87ed49da..8c78cf86 100644 --- a/README.rst +++ b/README.rst @@ -123,6 +123,7 @@ Most of the API is available: client.explorer.get_masters_games client.explorer.get_player_games client.explorer.stream_player_games + client.explorer.get_otb_master_game client.external_engine.get client.external_engine.get_by_id diff --git a/berserk/clients/opening_explorer.py b/berserk/clients/opening_explorer.py index 89d4d8fd..885d9d6a 100644 --- a/berserk/clients/opening_explorer.py +++ b/berserk/clients/opening_explorer.py @@ -11,6 +11,7 @@ Speed, OpeningExplorerRating, ) +from ..formats import PGN from ..types.common import Color logger = logging.getLogger("berserk.client.opening_explorer") @@ -196,3 +197,12 @@ def stream_player_games( for response in self._r.get(path, params=params, stream=True): yield cast(OpeningStatistic, response) + + def get_otb_master_game(self, game_id: str) -> str: + """Get PGN representation of an over-the-board master game. + + :param game_id: game ID + :return: PGN of the game + """ + path = f"/master/pgn/{game_id}" + return self._r.get(path, fmt=PGN) diff --git a/tests/clients/cassettes/test_opening_explorer/TestMasterGames.test_export.yaml b/tests/clients/cassettes/test_opening_explorer/TestMasterGames.test_export.yaml new file mode 100644 index 00000000..da08415c --- /dev/null +++ b/tests/clients/cassettes/test_opening_explorer/TestMasterGames.test_export.yaml @@ -0,0 +1,71 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.31.0 + method: GET + uri: https://explorer.lichess.ovh/master/pgn/LSVO85Cp + response: + body: + string: '[Event "3rd Norway Chess 2015"] + + [Site "Stavanger NOR"] + + [Date "2015.06.17"] + + [Round "2.4"] + + [White "Caruana, F."] + + [Black "Carlsen, M."] + + [Result "1-0"] + + [WhiteElo "2805"] + + [BlackElo "2876"] + + + 1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O Nxe4 5. d4 Nd6 6. Bxc6 dxc6 7. dxe5 + Nf5 8. Qxd8+ Kxd8 9. h3 h6 10. Rd1+ Ke8 11. Nc3 Ne7 12. b3 Bf5 13. Nd4 Bh7 + 14. Bb2 Rd8 15. Nce2 Nd5 16. c4 Nb4 17. Nf4 Rg8 18. g4 Na6 19. Nf5 Nc5 20. + Rxd8+ Kxd8 21. Rd1+ Kc8 22. Ba3 Ne6 23. Nxe6 Bxa3 24. Nexg7 Bf8 25. e6 Bxf5 + 26. Nxf5 fxe6 27. Ng3 Be7 28. Kg2 Rf8 29. Rd3 Rf7 30. Nh5 Bd6 31. Rf3 Rh7 + 32. Re3 Re7 33. f4 Ba3 34. Kf3 Bb2 35. Re2 Bc3 36. g5 Kd7 37. Kg4 Re8 38. + Ng3 Rh8 39. h4 b6 40. h5 c5 41. g6 Re8 42. f5 exf5+ 43. Kf4 Rh8 44. Nxf5 Bf6 + 45. Rg2 1-0 + + ' + headers: + Access-Control-Allow-Headers: + - Accept,If-Modified-Since,Cache-Control,X-Requested-With + Access-Control-Allow-Methods: + - GET,OPTIONS + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=10800 + - public + Connection: + - keep-alive + Content-Length: + - '722' + Content-Type: + - application/x-chess-pgn + Date: + - Wed, 01 Nov 2023 07:49:11 GMT + Expires: + - Wed, 01 Nov 2023 10:49:11 GMT + Server: + - nginx + status: + code: 200 + message: OK +version: 1 diff --git a/tests/clients/test_opening_explorer.py b/tests/clients/test_opening_explorer.py index d7d46658..d019ea07 100644 --- a/tests/clients/test_opening_explorer.py +++ b/tests/clients/test_opening_explorer.py @@ -48,6 +48,25 @@ def test_result(self): assert res["black"] == 1300 assert res["draws"] == 4428 + @pytest.mark.vcr + def test_export(self): + res = Client().opening_explorer.get_otb_master_game("LSVO85Cp") + assert ( + res + == """[Event "3rd Norway Chess 2015"] +[Site "Stavanger NOR"] +[Date "2015.06.17"] +[Round "2.4"] +[White "Caruana, F."] +[Black "Carlsen, M."] +[Result "1-0"] +[WhiteElo "2805"] +[BlackElo "2876"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O Nxe4 5. d4 Nd6 6. Bxc6 dxc6 7. dxe5 Nf5 8. Qxd8+ Kxd8 9. h3 h6 10. Rd1+ Ke8 11. Nc3 Ne7 12. b3 Bf5 13. Nd4 Bh7 14. Bb2 Rd8 15. Nce2 Nd5 16. c4 Nb4 17. Nf4 Rg8 18. g4 Na6 19. Nf5 Nc5 20. Rxd8+ Kxd8 21. Rd1+ Kc8 22. Ba3 Ne6 23. Nxe6 Bxa3 24. Nexg7 Bf8 25. e6 Bxf5 26. Nxf5 fxe6 27. Ng3 Be7 28. Kg2 Rf8 29. Rd3 Rf7 30. Nh5 Bd6 31. Rf3 Rh7 32. Re3 Re7 33. f4 Ba3 34. Kf3 Bb2 35. Re2 Bc3 36. g5 Kd7 37. Kg4 Re8 38. Ng3 Rh8 39. h4 b6 40. h5 c5 41. g6 Re8 42. f5 exf5+ 43. Kf4 Rh8 44. Nxf5 Bf6 45. Rg2 1-0 +""" + ) + class TestPlayerGames: @pytest.mark.vcr