Skip to content

Commit f027531

Browse files
committed
Finish GameMetadata rework
1 parent b24eba6 commit f027531

File tree

13 files changed

+114
-112
lines changed

13 files changed

+114
-112
lines changed

src/cli_chess/core/game/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
from .game_presenter_base import GamePresenterBase, PlayableGamePresenterBase
44
from .online_game.online_game_presenter import start_online_game
55
from .offline_game.offline_game_presenter import start_offline_game
6-
from .game_metadata import GameMetadata, Player
6+
from .game_metadata import GameMetadata, PlayerMetadata, ClockMetadata
Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,41 @@
11
from dataclasses import dataclass
2+
from chess import Color
3+
from typing import Optional
24

35

46
@dataclass
5-
class Player:
6-
title: str = None
7-
name: str = None
8-
rating: str = None
9-
ai_level: str = None # only used online
10-
rating_diff: int = None
11-
is_provisional_rating: bool = False # only used online
7+
class PlayerMetadata:
8+
title: Optional[str] = None
9+
name: Optional[str] = None
10+
rating: Optional[str] = None
11+
rating_diff: Optional[int] = None
12+
is_provisional_rating: bool = False
13+
ai_level: Optional[str] = None
1214

1315

1416
@dataclass
15-
class Clock:
17+
class ClockMetadata:
1618
units: str = "ms"
17-
time: int = 0
18-
increment: int = 0
19+
time: Optional[int] = None
20+
increment: Optional[int] = None
1921

2022

2123
@dataclass
22-
class GameStatus:
23-
status: str = None
24-
winner: str = None
24+
class GameStatusMetadata:
25+
status: Optional[str] = None
26+
winner: Optional[str] = None
2527

2628

27-
@dataclass
2829
class GameMetadata:
29-
players = [Player(), Player()]
30-
clocks = [Clock(), Clock()]
31-
game_status = GameStatus()
32-
game_id: str = None
33-
variant: str = None
34-
my_color: str = None # TODO: Find a better solution
35-
rated: bool = False # only used online
36-
speed: str = None # only used online
30+
def __init__(self):
31+
self.players = [PlayerMetadata(), PlayerMetadata()]
32+
self.clocks = [ClockMetadata(), ClockMetadata()]
33+
self.game_status = GameStatusMetadata()
34+
self.game_id: Optional[str] = None
35+
self.variant: Optional[str] = None
36+
self.my_color: Optional[Color] = None
37+
self.rated: bool = False
38+
self.speed: Optional[str] = None
39+
40+
def reset(self):
41+
self.__init__()

src/cli_chess/core/game/game_presenter_base.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ def __init__(self, model: GameModelBase):
2020
self.move_list_presenter = MoveListPresenter(model.move_list_model)
2121
self.material_diff_presenter = MaterialDifferencePresenter(model.material_diff_model)
2222
self.player_info_presenter = PlayerInfoPresenter(model)
23-
# TODO: Revert this after testing
24-
# self.clock_presenter = ClockPresenter(model)
23+
self.clock_presenter = ClockPresenter(model)
2524
self.view = self._get_view()
2625

2726
self.model.e_game_model_updated.add_listener(self.update)

src/cli_chess/core/game/game_view_base.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ def __init__(self, presenter: GamePresenterBase) -> None:
2323
self.material_diff_lower_container = presenter.material_diff_presenter.view_lower
2424
self.player_info_upper_container = presenter.player_info_presenter.view_upper
2525
self.player_info_lower_container = presenter.player_info_presenter.view_lower
26-
# TODO: Revert this after testing
27-
# self.clock_upper = presenter.clock_presenter.view_upper
28-
# self.clock_lower = presenter.clock_presenter.view_lower
26+
self.clock_upper = presenter.clock_presenter.view_upper
27+
self.clock_lower = presenter.clock_presenter.view_lower
2928
self.alert = AlertContainer()
3029
self._container = self._create_container()
3130

src/cli_chess/core/game/offline_game/offline_game_model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def _update_game_metadata(self, **kwargs) -> None:
7979
try:
8080
if 'game_parameters' in kwargs:
8181
data = kwargs['game_parameters']
82-
self.game_metadata.my_color = COLOR_NAMES[self.my_color]
82+
self.game_metadata.my_color = self.my_color
8383

8484
self.game_metadata.variant = data[GameOption.VARIANT]
8585
self.game_metadata.players[self.my_color].name = player_info_config.get_value(player_info_config.Keys.OFFLINE_PLAYER_NAME) # noqa: E501

src/cli_chess/core/game/online_game/online_game_model.py

Lines changed: 48 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from cli_chess.core.game.game_options import GameOption
33
from cli_chess.core.api import GameStateDispatcher
44
from cli_chess.utils import log, threaded, RequestSuccessfullySent
5-
from chess import COLOR_NAMES, WHITE
5+
from chess import COLORS, COLOR_NAMES, WHITE, BLACK, Color
66
from typing import Optional
77

88

@@ -12,12 +12,11 @@ class OnlineGameModel(PlayableGameModelBase):
1212
"""
1313
def __init__(self, game_parameters: dict, is_vs_ai: bool):
1414
super().__init__(play_as_color=game_parameters[GameOption.COLOR], variant=game_parameters[GameOption.VARIANT], fen=None)
15-
self._update_game_metadata(game_parameters=game_parameters)
16-
17-
self.game_state_dispatcher = Optional[GameStateDispatcher]
15+
self.vs_ai = is_vs_ai
1816
self.playing_game_id = None
1917
self.searching = False
20-
self.vs_ai = is_vs_ai
18+
self._update_game_metadata(game_parameters=game_parameters)
19+
self.game_state_dispatcher = Optional[GameStateDispatcher]
2120

2221
try:
2322
from cli_chess.core.api.api_manager import api_client, api_iem
@@ -37,17 +36,17 @@ def create_game(self) -> None:
3736
self.searching = True
3837

3938
if self.vs_ai: # Challenge Lichess AI (stockfish)
40-
self.api_client.challenges.create_ai(level=self.game_metadata['ai_level'],
41-
clock_limit=self.game_metadata['clock']['white']['time'],
42-
clock_increment=self.game_metadata['clock']['white']['increment'],
43-
color=self.game_metadata['my_color_str'],
44-
variant=self.game_metadata['variant'])
39+
self.api_client.challenges.create_ai(level=self.game_metadata.players[not self.my_color].ai_level,
40+
clock_limit=self.game_metadata.clocks[WHITE].time * 60, # challenges need time in seconds
41+
clock_increment=self.game_metadata.clocks[WHITE].increment,
42+
color=COLOR_NAMES[self.game_metadata.my_color],
43+
variant=self.game_metadata.variant)
4544
else: # Find a random opponent
46-
self.api_client.board.seek(time=self.game_metadata['clock']['white']['time'], # Both players initially have the same time
47-
increment=self.game_metadata['clock']['white']['increment'],
48-
color=self.game_metadata['my_color_str'],
49-
variant=self.game_metadata['variant'],
50-
rated=self.game_metadata['rated'],
45+
self.api_client.board.seek(time=self.game_metadata.clocks[WHITE].time,
46+
increment=self.game_metadata.clocks[WHITE].increment,
47+
color=COLOR_NAMES[self.game_metadata.my_color],
48+
variant=self.game_metadata.variant,
49+
rated=self.game_metadata.rated,
5150
rating_range=None)
5251

5352
def _start_game(self, game_id: str) -> None:
@@ -92,7 +91,7 @@ def handle_game_state_dispatcher_event(self, **kwargs) -> None:
9291
if 'gameFull' in kwargs:
9392
event = kwargs['gameFull']
9493
self._update_game_metadata(gsd_gameFull=event)
95-
self.board_model.reinitialize_board(variant=self.game_metadata['variant'],
94+
self.board_model.reinitialize_board(variant=self.game_metadata.variant,
9695
orientation=(self.my_color if self.board_model.get_variant_name() != "racingkings" else WHITE),
9796
fen=event.get('initialFen', ""))
9897
self.board_model.make_moves_from_list(event.get('state', {}).get('moves', []).split())
@@ -219,56 +218,52 @@ def _update_game_metadata(self, **kwargs) -> None:
219218
try:
220219
if 'game_parameters' in kwargs: # This is the data that came from the menu selections
221220
data = kwargs['game_parameters']
222-
self.game_metadata['my_color_str'] = COLOR_NAMES[self.my_color]
223-
self.game_metadata['variant'] = data.get(GameOption.VARIANT)
224-
self.game_metadata['rated'] = data.get(GameOption.RATED, False) # Games against AI will not have this data
225-
self.game_metadata['ai_level'] = data.get(GameOption.COMPUTER_SKILL_LEVEL) # Only games against AI will have this data
226-
self.game_metadata['clock']['white']['time'] = data.get(GameOption.TIME_CONTROL)[0] # mins
227-
self.game_metadata['clock']['white']['increment'] = data.get(GameOption.TIME_CONTROL)[1] # secs
228-
self.game_metadata['clock']['black'] = self.game_metadata['clock']['white']
229-
230-
if self.game_metadata['ai_level']:
231-
self.game_metadata['clock']['white']['time'] = data.get(GameOption.TIME_CONTROL)[0] * 60 # challenges need time in seconds
232-
self.game_metadata['clock']['black'] = self.game_metadata['clock']['white']
221+
self.game_metadata.my_color = self.my_color
222+
self.game_metadata.variant = data.get(GameOption.VARIANT)
223+
self.game_metadata.rated = data.get(GameOption.RATED, False)
224+
self.game_metadata.players[not self.my_color].ai_level = data.get(GameOption.COMPUTER_SKILL_LEVEL) if self.vs_ai else None
225+
226+
for color in COLORS:
227+
self.game_metadata.clocks[color].time = data.get(GameOption.TIME_CONTROL)[0] # mins
228+
self.game_metadata.clocks[color].increment = data.get(GameOption.TIME_CONTROL)[1] # secs
233229

234230
elif 'iem_gameStart' in kwargs:
235-
# Reset game metadata
236-
# self.game_metadata = self._default_game_metadata()
231+
self.game_metadata.reset()
237232

238233
data = kwargs['iem_gameStart']
239-
self.game_metadata['gameId'] = data.get('gameId')
240-
self.game_metadata['my_color_str'] = data.get('color')
241-
self.game_metadata['rated'] = data.get('rated')
242-
self.game_metadata['variant'] = data.get('variant', {}).get('name')
243-
self.game_metadata['speed'] = data['speed']
234+
self.game_metadata.game_id = data.get('gameId')
235+
self.game_metadata.my_color = self.my_color
236+
self.game_metadata.rated = data.get('rated')
237+
self.game_metadata.variant = data.get('variant', {}).get('name')
238+
self.game_metadata.speed = data['speed']
244239

245240
elif 'iem_gameFinish' in kwargs:
246241
data = kwargs['iem_gameFinish']
247-
self.game_metadata['players'][COLOR_NAMES[self.my_color]]['rating_diff'] = data.get('ratingDiff', "")
248-
self.game_metadata['players'][COLOR_NAMES[not self.my_color]]['rating_diff'] = data.get('opponent', {}).get('ratingDiff', "")
242+
self.game_metadata.players[self.my_color].rating_diff = data.get('ratingDiff', "")
243+
self.game_metadata.players[not self.my_color].rating_diff = data.get('opponent', {}).get('ratingDiff', "")
249244

250245
elif 'gsd_gameFull' in kwargs:
251246
data = kwargs['gsd_gameFull']
252247

253248
for color in COLOR_NAMES:
254-
if data.get(color, {}).get('name'):
255-
self.game_metadata['players'][color]['title'] = data.get(color, {}).get('title')
256-
self.game_metadata['players'][color]['name'] = data.get(color, {}).get('name', "?")
257-
self.game_metadata['players'][color]['rating'] = data.get(color, {}).get('rating', "?")
258-
self.game_metadata['players'][color]['provisional'] = data.get(color, {}).get('provisional', False)
259-
elif data.get(color, {}).get('aiLevel'):
260-
self.game_metadata['players'][color]['name'] = f"Stockfish level {data.get(color, {}).get('aiLevel', '?')}"
261-
262-
self.game_metadata['clock']['units'] = "ms"
263-
self.game_metadata['clock']['white']['time'] = data.get('state', {}).get('wtime')
264-
self.game_metadata['clock']['white']['increment'] = data.get('state', {}).get('winc')
265-
self.game_metadata['clock']['black']['time'] = data.get('state', {}).get('btime')
266-
self.game_metadata['clock']['black']['increment'] = data.get('state', {}).get('binc')
249+
side_data = data.get(color, {})
250+
color_as_bool = Color(COLOR_NAMES.index(color))
251+
if side_data.get('name'):
252+
self.game_metadata.players[color_as_bool].title = side_data.get('title')
253+
self.game_metadata.players[color_as_bool].name = side_data.get('name', "?")
254+
self.game_metadata.players[color_as_bool].rating = side_data.get('rating', "?")
255+
self.game_metadata.players[color_as_bool].is_provisional_rating = side_data.get('provisional', False)
256+
elif self.vs_ai:
257+
self.game_metadata.players[color_as_bool].name = f"Stockfish level {side_data.get('aiLevel', '?')}"
258+
259+
self.game_metadata.clocks[color_as_bool].units = "ms"
260+
self.game_metadata.clocks[color_as_bool].time = data.get('state', {}).get('wtime' if color == "white" else 'btime')
261+
self.game_metadata.clocks[color_as_bool].increment = data.get('state', {}).get('winc' if color == "white" else 'binc')
267262

268263
elif 'gsd_gameState' in kwargs:
269264
data = kwargs['gsd_gameState']
270-
self.game_metadata['clock']['white']['time'] = data.get('wtime')
271-
self.game_metadata['clock']['black']['time'] = data.get('btime')
265+
self.game_metadata.clocks[WHITE].time = data.get('wtime')
266+
self.game_metadata.clocks[BLACK].time = data.get('btime')
272267

273268
self._notify_game_model_updated()
274269
except Exception as e:
@@ -280,8 +275,8 @@ def _report_game_over(self, status: str, winner: str) -> None:
280275
This should only ever be called if the game is confirmed to be over
281276
"""
282277
self._game_end()
283-
self.game_metadata['state']['status'] = status # status list can be found in lila status.ts
284-
self.game_metadata['state']['winner'] = winner
278+
self.game_metadata.game_status.status = status # status list can be found in lila status.ts
279+
self.game_metadata.game_status.winner = winner
285280
self._notify_game_model_updated(onlineGameOver=True)
286281

287282
def cleanup(self) -> None:

src/cli_chess/core/game/online_game/online_game_presenter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ def update(self, **kwargs) -> None:
3838
def _parse_and_present_game_over(self) -> None:
3939
"""Triages game over status for parsing and sending to the view for display"""
4040
if not self.is_game_in_progress():
41-
status: str = self.model.game_metadata['state']['status']
42-
winner_str = self.model.game_metadata['state']['winner']
41+
status = self.model.game_metadata.game_status.status
42+
winner_str = self.model.game_metadata.game_status.winner
4343

4444
if winner_str: # Handle win/loss output
4545
self._display_win_loss_output(status, winner_str)

src/cli_chess/core/game/online_game/online_game_view.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ def _create_container(self) -> Container:
1818
VSplit([
1919
self.board_output_container,
2020
HSplit([
21-
#self.clock_upper,
21+
self.clock_upper,
2222
self.player_info_upper_container,
2323
self.material_diff_upper_container,
2424
self.move_list_container,
2525
self.material_diff_lower_container,
2626
self.player_info_lower_container,
27-
#self.clock_lower
27+
self.clock_lower
2828
])
2929
]),
3030
self.input_field_container,

src/cli_chess/core/game/online_game/watch_tv/watch_tv_model.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
from cli_chess.core.game import GameModelBase, GameMetadata
1+
from cli_chess.core.game import GameModelBase
22
from cli_chess.menus.tv_channel_menu import TVChannelMenuOptions
33
from cli_chess.utils.event import Event
44
from cli_chess.utils.logging import log
5-
from chess import COLOR_NAMES, Color, WHITE, BLACK
5+
from chess import COLOR_NAMES, COLORS, Color, WHITE, BLACK
66
from berserk.exceptions import ResponseError
77
from time import sleep
88
import threading
@@ -30,7 +30,7 @@ def _update_game_metadata(self, **kwargs) -> None:
3030
if 'tv_descriptionEvent' in kwargs:
3131
data = kwargs['tv_descriptionEvent']
3232
if 'tv_startGameEvent' in kwargs:
33-
self.game_metadata = GameMetadata()
33+
self.game_metadata.reset()
3434

3535
self.game_metadata.game_id = data.get('id')
3636
self.game_metadata.rated = data.get('rated')
@@ -43,20 +43,21 @@ def _update_game_metadata(self, **kwargs) -> None:
4343
color_as_bool = Color(COLOR_NAMES.index(color))
4444
side_data = data.get('players', {}).get(color, {})
4545
player_data = side_data.get('user')
46-
ai_level = player_data.get('aiLevel')
47-
if side_data and player_data: # non-ai player data
48-
self.game_metadata.players[color_as_bool].name = player_data.get('name', "")
49-
self.game_metadata.players[color_as_bool].rating = side_data.get('rating', "")
46+
ai_level = side_data.get('aiLevel')
47+
if side_data and player_data:
48+
self.game_metadata.players[color_as_bool].title = player_data.get('title')
49+
self.game_metadata.players[color_as_bool].name = player_data.get('name', "?")
50+
self.game_metadata.players[color_as_bool].rating = side_data.get('rating', "?")
51+
self.game_metadata.players[color_as_bool].is_provisional_rating = side_data.get('provisional', False)
5052
self.game_metadata.players[color_as_bool].rating_diff = side_data.get('ratingDiff', "")
51-
elif ai_level: # ai data
53+
elif ai_level:
5254
self.game_metadata.players[color_as_bool].name = f"Stockfish level {ai_level}"
5355

5456
if 'tv_coreGameEvent' in kwargs:
5557
data = kwargs['tv_coreGameEvent']
56-
self.game_metadata.clocks[WHITE].units = "sec"
57-
self.game_metadata.clocks[BLACK].units = "sec"
58-
self.game_metadata.clocks[WHITE].time = data.get('wc')
59-
self.game_metadata.clocks[BLACK].time = data.get('bc')
58+
for color in COLORS:
59+
self.game_metadata.clocks[color].units = "sec"
60+
self.game_metadata.clocks[color].time = data.get('wc' if color == WHITE else 'bc')
6061

6162
self.e_game_model_updated.notify()
6263
except Exception as e:
@@ -77,7 +78,7 @@ def stream_event_received(self, **kwargs):
7778
variant = event.get('variant', {}).get('key')
7879
white_rating = int(event.get('players', {}).get('white', {}).get('rating') or 0)
7980
black_rating = int(event.get('players', {}).get('black', {}).get('rating') or 0)
80-
orientation = True if ((white_rating >= black_rating) or self.channel.key == "racingKings") else False
81+
orientation = WHITE if ((white_rating >= black_rating) or self.channel.key == "racingKings") else BLACK
8182

8283
self._update_game_metadata(tv_descriptionEvent=event, tv_startGameEvent=True)
8384
last_move = event.get('lastMove', "")

0 commit comments

Comments
 (0)