class LogViewerTest(unittest.TestCase): FILENAME = 'filename' GAME0 = '{"moves": [{"to_move": "player1", "player1_cards": ["AS", "QS", "AH", "9D", "8D", "7H"], "moves_and_responds": ["7H", "TH"], "deck_count": 24, "player2_cards": ["JH", "TH", "QH", "6H", "8C", "TD"], "given_more": []}, {"to_move": "player2", "player1_cards": ["AS", "QC", "AH", "QS", "8D", "9D"], "moves_and_responds": ["6H"], "deck_count": 22, "player2_cards": ["6C", "QH", "6H", "8C", "TD", "JH"], "given_more": ["6C"]}], "ended_at": "2014-10-19T01:41:23.161425", "deck": ["QS", "8D", "AH", "AS", "7H", "9D", "TD", "JH", "QH", "TH", "8C", "6H", "QC", "6C", "JD", "9C", "9S", "KH", "AC", "8H", "KC", "8S", "TC", "7C", "TS", "9H", "6S", "6D", "7D", "JS", "KS", "AD", "KD", "JC", "QD", "7S"], "player2_name": "ENGINE", "result": "1-0", "player1_name": "HUMAN", "started_at": "2014-10-19T01:40:51.473966", "opened_trump": "7S"}' LOG_FILE_CONTENTS = '''\ ####2014-10-19T01:40:51, HUMAN - ENGINE (1-0)#### %s ####2014-11-19T01:40:51, VOVAN - KOLYAN (1-0)#### {"moves": [{"to_move": "player1", "player1_cards": ["AS", "QS", "AH", "9D", "8D", "7H"], "moves_and_responds": ["7H", "TH"], "deck_count": 24, "player2_cards": ["JH", "TH", "QH", "6H", "8C", "TD"], "given_more": []}], "ended_at": "2014-10-19T01:41:23.161425", "deck": ["QS", "8D", "AH", "AS", "7H", "9D", "TD", "JH", "QH", "TH", "8C", "6H", "QC", "7C", "JD", "9C", "9S", "KH", "AC", "8H", "KC", "8S", "TC", "6C", "TS", "9H", "6S", "6D", "7D", "JS", "KS", "AD", "KD", "JC", "QD", "7S"], "player2_name": "KOLYAN", "result": "1-0", "player1_name": "VOVAN", "started_at": "2014-10-19T01:40:51.473966", "opened_trump": "7S"} ''' % GAME0 def setUp(self): self.open_mock = MagicMock(spec=open) self._set_file_contents(self.LOG_FILE_CONTENTS) self.open_patcher = patch( '__builtin__.open', self.open_mock, create=True ) self.open_patcher.start() self.log_viewer = LogViewer(self.FILENAME) self.game0 = json.loads(self.GAME0) def tearDown(self): self.open_patcher.stop() def _set_file_contents(self, contents): self.open_mock.return_value.__enter__.return_value = StringIO(contents) def test_fill_game_index_parsing(self): self.assertEqual(self.log_viewer._game_index, [ { 'prev_end_offset': 0, 'start_offset': 50, 'title': '2014-10-19T01:40:51, HUMAN - ENGINE (1-0)' }, { 'prev_end_offset': 874, 'start_offset': 924, 'title': '2014-11-19T01:40:51, VOVAN - KOLYAN (1-0)' }, ]) def test_io_error_in_fill_game_index_is_invalid_log_format_error(self): self.open_mock.side_effect = IOError with self.assertRaises(InvalidLogFormat): self.log_viewer._fill_game_index() def test_no_games_in_file_is_invalid_log_format_error(self): self._set_file_contents('no games for you') with self.assertRaises(InvalidLogFormat): self.log_viewer._fill_game_index() def test_iterindex_returns_iterator_over_game_index(self): self.assertItemsEqual( self.log_viewer.iterindex(), iter(self.log_viewer._game_index) ) def test_load_game_loads_game_according_to_index(self): self.log_viewer.load_game(0) self.assertEqual(self.log_viewer.player1_name, 'HUMAN') self.log_viewer.load_game(1) self.assertEqual(self.log_viewer.player1_name, 'VOVAN') def test_io_error_in_load_game_is_invalid_log_format_error(self): self.open_mock.side_effect = IOError with self.assertRaises(InvalidLogFormat): self.log_viewer.load_game(0) def test_value_error_in_load_game_is_invalid_log_format_error(self): self._set_file_contents('no games for you') with self.assertRaises(InvalidLogFormat): self.log_viewer.load_game(0) def test_has_game_loaded_property(self): self.assertFalse(self.log_viewer.has_game_loaded) self.log_viewer.load_game(0) self.assertTrue(self.log_viewer.has_game_loaded) def test_get_new_move(self): self.log_viewer.load_game(0) move = self.game0['moves'][0] result = self.log_viewer._get_new_move(move) self.assertItemsEqual(result.keys(), move.keys() + ['event_type']) self.assertEqual(result['event_type'], self.log_viewer.NEW_MOVE) def test_opened_trump_property(self): self.log_viewer.load_game(0) self.assertEqual( self.log_viewer.opened_trump, DurakCard(self.game0['opened_trump']) ) def test_to_game_start(self): self.log_viewer.load_game(0) self.log_viewer._current_move = 666 self.log_viewer._current_table_index = 777 self.log_viewer.to_game_start() self.assertEqual( self.log_viewer._current_move, self.log_viewer.INITIAL_CURRENT_MOVE ) self.assertEqual( self.log_viewer._current_table_index, self.log_viewer.INITIAL_CURRENT_TABLE_INDEX ) def test_to_game_end(self): self.log_viewer.load_game(0) self.log_viewer._current_move = 666 self.log_viewer._current_table_index = 777 self.log_viewer.to_game_end() self.assertEqual( self.log_viewer._current_move, len(self.game0['moves']) ) self.assertEqual( self.log_viewer._current_table_index, self.log_viewer.INITIAL_CURRENT_TABLE_INDEX + 1 ) def test_player1_name_property(self): self.log_viewer.load_game(0) self.assertEqual( self.log_viewer.player1_name, self.game0['player1_name'] ) def test_player2_name_property(self): self.log_viewer.load_game(0) self.assertEqual( self.log_viewer.player2_name, self.game0['player2_name'] ) def test_get_opposite_player(self): self.assertEqual( self.log_viewer._get_opposite_player(self.log_viewer.PLAYER1), self.log_viewer.PLAYER2 ) self.assertEqual( self.log_viewer._get_opposite_player(self.log_viewer.PLAYER2), self.log_viewer.PLAYER1 ) def test_to_card_set(self): self.log_viewer.load_game(0) cards = ['AS', 'QS', 'AH', '9D', '8D', '7H'] result = self.log_viewer._to_card_set(cards) self.assertTrue(isinstance(result, CardSet)) self.assertItemsEqual(result, map(DurakCard, cards)) self.assertEqual(result._trump, DurakCard(self.game0['opened_trump'])) def test_has_next(self): self.log_viewer.load_game(0) self.assertTrue(self.log_viewer.has_next) self.log_viewer._current_move = 1 self.log_viewer._current_table_index = 1 self.assertTrue(self.log_viewer.has_next) self.log_viewer._current_table_index = 2 self.assertFalse(self.log_viewer.has_next) self.log_viewer._current_move = 3 self.log_viewer._current_table_index = ( self.log_viewer.INITIAL_CURRENT_TABLE_INDEX ) self.assertFalse(self.log_viewer.has_next) def test_has_prev(self): self.log_viewer._current_move = 666 self.log_viewer._current_table_index = 777 self.assertTrue(self.log_viewer.has_prev) self.log_viewer._current_move = self.log_viewer.INITIAL_CURRENT_MOVE self.assertTrue(self.log_viewer.has_prev) self.log_viewer._current_table_index = ( self.log_viewer.INITIAL_CURRENT_TABLE_INDEX ) self.assertFalse(self.log_viewer.has_prev) def test_get_next_and_get_prev(self): # проверяю оба метода в одном тесте, чтобы протестировать в условиях, # приближенных к реальным, а не городить моки EXPECTED_EVENTS = [ { 'to_move': self.log_viewer.PLAYER1, 'event_type': self.log_viewer.NEW_MOVE, 'moves_and_responds': [DurakCard('7H'), DurakCard('TH')], 'deck_count': 24, 'given_more': [], 'player2_cards': set(map(DurakCard, ( '6H', '8C', 'JH', 'TH', 'QH', 'TD' ))), 'player1_cards': set(map(DurakCard, ( 'QS', 'AH', '9D', '8D', '7H', 'AS' ))), }, { 'to_move': self.log_viewer.PLAYER1, 'event_type': self.log_viewer.MOVE, 'card': DurakCard('7H'), }, { 'to_move': self.log_viewer.PLAYER2, 'event_type': self.log_viewer.RESPOND, 'card': DurakCard('TH'), }, { 'to_move': self.log_viewer.PLAYER2, 'event_type': self.log_viewer.NEW_MOVE, 'moves_and_responds': [DurakCard('6H')], 'deck_count': 22, 'given_more': [DurakCard('6C')], 'player2_cards': set(map(DurakCard, ( '6H', '8C', 'JH', '6C', 'QH', 'TD' ))), 'player1_cards': set(map(DurakCard, ( 'QS', 'AH', '9D', '8D', 'QC', 'AS' ))), }, { 'to_move': self.log_viewer.PLAYER2, 'event_type': self.log_viewer.MOVE, 'card': DurakCard('6H'), }, { 'to_move': self.log_viewer.PLAYER2, 'event_type': self.log_viewer.GIVE_MORE, 'card': DurakCard('6C'), }, ] self.log_viewer.load_game(0) expected = iter(EXPECTED_EVENTS) while self.log_viewer.has_next: log_event = self.log_viewer.get_next() self.assertEqual(log_event, next(expected)) first_event = EXPECTED_EVENTS.pop(0) EXPECTED_EVENTS[2] = first_event expected = iter(reversed(EXPECTED_EVENTS)) while self.log_viewer.has_prev: log_event = self.log_viewer.get_prev() self.assertEqual(log_event, next(expected))
class ViewLogFrame(wx.Frame): WIDTH = 800 HEIGHT = 500 LAST_DIR_SETTING = 'last_log_dir' def __init__(self): super(ViewLogFrame, self).__init__(parent=None, title='Durak log viewer', size=(self.WIDTH, self.HEIGHT)) self._log_viever = None self._create_layout() def _create_layout(self): self.Bind(wx.EVT_CLOSE, self._on_close) self._panel = wx.Panel(parent=self) self._top_player_sizer = LabeledCardSizer( wx.HORIZONTAL, parent=self._panel, ) self._bottom_player_sizer = LabeledCardSizer( wx.HORIZONTAL, parent=self._panel, ) self._table_sizer = wx.FlexGridSizer(cols=2, rows=1) self._table_sizer.AddGrowableCol(0) self._table = TablePanel(parent=self._panel) self._table_sizer.Add(self._table, proportion=1) self._deck = DeckPanel(self._panel, size=(100, 130)) self._table_sizer.Add(self._deck) self._control_sizer = wx.BoxSizer(wx.HORIZONTAL) self._to_game_start_button = wx.Button(parent=self._panel, label=u'<<') self._to_game_start_button.Bind(wx.EVT_BUTTON, self._menu_on_to_game_start) self._prev_button = wx.Button(parent=self._panel, label=u'<') self._prev_button.Bind(wx.EVT_BUTTON, self._menu_on_prev) self._next_button = wx.Button(parent=self._panel, label=u'>') self._next_button.Bind(wx.EVT_BUTTON, self._menu_on_next) self._to_game_end_button = wx.Button(parent=self._panel, label=u'>>') self._to_game_end_button.Bind(wx.EVT_BUTTON, self._menu_on_to_game_end) self._control_sizer.AddMany([ self._to_game_start_button, self._prev_button, self._next_button, self._to_game_end_button ]) self._main_sizer = wx.FlexGridSizer(cols=1, rows=4) self._main_sizer.AddGrowableCol(0) self._main_sizer.AddGrowableRow(1) self._main_sizer.Add(self._top_player_sizer, flag=wx.EXPAND, proportion=1) self._main_sizer.Add(self._table_sizer, flag=wx.ALIGN_CENTER_VERTICAL, proportion=1) self._main_sizer.Add(self._control_sizer, flag=wx.EXPAND, proportion=1) self._main_sizer.Add(self._bottom_player_sizer, flag=wx.EXPAND, proportion=1) self._panel.SetSizer(self._main_sizer) self.CreateStatusBar() self._create_menu() self._panel.Layout() self.Refresh() self.Layout() self.PLAYER_SIZER_MAP = { LogViewer.PLAYER1: self._bottom_player_sizer, LogViewer.PLAYER2: self._top_player_sizer, } self._menu_on_open() def _create_menu(self): self.menu = wx.MenuBar() menu = wx.Menu() # Файл item = menu.Append(wx.ID_OPEN, u'Открыть файл лога...', u'Открыть файл лога') self.Bind(wx.EVT_MENU, self._menu_on_open, item) item = menu.Append(wx.ID_ANY, u'Список игр...\tCTRL+L', u'Просмотреть список игр в открытом файле') self.Bind(wx.EVT_MENU, self._menu_on_select_game, item) item = menu.Append(wx.ID_EXIT, u'Выход', u'Закрыть программу') self.Bind(wx.EVT_MENU, self._on_close, item) self.menu.Append(menu, u'Файл') menu = wx.Menu() # Текущая игра self._to_game_start_menu_item = menu.Append(wx.ID_ANY, u'В начало <<\tHOME', u'Перейти в начало игры') self.Bind(wx.EVT_MENU, self._menu_on_to_game_start, self._to_game_start_menu_item) self._prev_menu_item = menu.Append(wx.ID_ANY, u'Назад <\tCTRL+LEFT', u'Вернуться на ход назад') self.Bind(wx.EVT_MENU, self._menu_on_prev, self._prev_menu_item) self._next_menu_item = menu.Append(wx.ID_ANY, u'Вперед >\tCTRL+RIGHT', u'Перейти на ход вперед') self.Bind(wx.EVT_MENU, self._menu_on_next, self._next_menu_item) self._to_game_end_menu_item = menu.Append(wx.ID_ANY, u'В конец >>\tEND', u'Перейти в конец игры') self.Bind(wx.EVT_MENU, self._menu_on_to_game_end, self._to_game_end_menu_item) self.menu.Append(menu, u'Текущая игра') self.SetMenuBar(self.menu) def _on_close(self, event): if event.GetEventType() in wx.EVT_CLOSE.evtType: event.Skip() else: self.Close() def _menu_on_open(self, event=None): last_directory = get_setting(self.LAST_DIR_SETTING, os.path.expanduser('~')) dialog = wx.FileDialog(self, u'Выберите файл лога', last_directory, '', '*', wx.OPEN) if dialog.ShowModal() != wx.ID_OK: self.Close() filename = dialog.GetPath() dialog.Destroy() self._log_viever = LogViewer(filename) set_setting(self.LAST_DIR_SETTING, os.path.dirname(filename)) self._menu_on_select_game() def _menu_on_select_game(self, event=None): choices = [ '%d. %s' % (i, game['title']) for i, game in enumerate(self._log_viever.iterindex(), start=1) ] dialog = wx.SingleChoiceDialog( self, u'Выберите игру', u'Список игр', choices, wx.CHOICEDLG_STYLE, ) dialog.SetSize((500, 400)) dialog.Refresh() if dialog.ShowModal() == wx.ID_OK: self._log_viever.load_game(dialog.GetSelection()) self._bottom_player_sizer.set_label(self._log_viever.player1_name) self._top_player_sizer.set_label(self._log_viever.player2_name) self._menu_on_to_game_start() dialog.Destroy() def _menu_on_to_game_start(self, event=None): self._log_viever.to_game_start() if not self._log_viever.has_next: return self._deck.set_opened_trump(self._log_viever.opened_trump) for card_sizer in (self._bottom_player_sizer, self._top_player_sizer): card_sizer.trump = self._log_viever.opened_trump card_sizer.remove_all() log_event = self._log_viever.get_next() self._new_move(log_event) self._panel.Layout() self.Layout() self.Refresh() self._set_enabled_controls() def _menu_on_to_game_end(self, event=None): self._log_viever.to_game_end() if not self._log_viever.has_prev: return log_event = self._log_viever.get_prev() self._new_move(log_event, with_table=True) self._set_enabled_controls() def _menu_on_next(self, event): if not self._log_viever.has_next: return log_event = self._log_viever.get_next() if log_event['event_type'] == self._log_viever.NEW_MOVE: self._new_move(log_event) return card_sizer = self.PLAYER_SIZER_MAP[log_event['to_move']] table_method = getattr(self._table, log_event['event_type']) card = log_event['card'] table_method(card) card_sizer.remove_card(card, do_layout=True) self._set_enabled_controls() def _menu_on_prev(self, event): if not self._log_viever.has_prev: return log_event = self._log_viever.get_prev() if log_event['event_type'] == self._log_viever.NEW_MOVE: self._new_move(log_event, with_table=True) return card_sizer = self.PLAYER_SIZER_MAP[log_event['to_move']] card = log_event['card'] self._table.pop() card_sizer.add_card(card, do_layout=True) self._set_enabled_controls() def _new_move(self, log_event, with_table=False): assert log_event['event_type'] == self._log_viever.NEW_MOVE self._table.remove_all() self._deck.set_card_count(log_event['deck_count']) if with_table: for index, card in enumerate(log_event['moves_and_responds']): if index % 2: self._table.respond(card) else: self._table.move(card) for card in log_event['given_more']: self._table.give_more(card) card_sizers = (self._bottom_player_sizer, self._top_player_sizer) card_sets = (log_event['player1_cards'], log_event['player2_cards']) for card_sizer, card_set in zip(card_sizers, card_sets): if with_table: card_sizer.remove_all() cards_to_add = card_set - set(log_event['moves_and_responds'] + log_event['given_more']) else: cards_to_add = card_set - card_sizer.cards for card in cards_to_add: card_sizer.add_card(card) card_sizer.Layout() if log_event['to_move'] == self._log_viever.PLAYER1: self.SetStatusText(u'Атакует игрок снизу') else: self.SetStatusText(u'Атакует игрок сверху') self._set_enabled_controls() def _set_enabled_controls(self): all_controls = { self._to_game_start_button, self._to_game_end_button, self._next_button, self._prev_button, self._to_game_end_menu_item, self._to_game_start_menu_item, self._prev_menu_item, self._next_menu_item, } [control.Enable(False) for control in all_controls] if not self._log_viever or not self._log_viever.has_game_loaded: return if self._log_viever.has_prev: self._to_game_start_button.Enable() self._prev_button.Enable() self._to_game_start_menu_item.Enable() self._prev_menu_item.Enable() if self._log_viever.has_next: self._to_game_end_button.Enable() self._next_button.Enable() self._to_game_end_menu_item.Enable() self._next_menu_item.Enable()
class ViewLogFrame(wx.Frame): WIDTH = 800 HEIGHT = 500 LAST_DIR_SETTING = 'last_log_dir' def __init__(self): super(ViewLogFrame, self).__init__( parent=None, title='Durak log viewer', size=(self.WIDTH, self.HEIGHT) ) self._log_viever = None self._create_layout() def _create_layout(self): self.Bind(wx.EVT_CLOSE, self._on_close) self._panel = wx.Panel(parent=self) self._top_player_sizer = LabeledCardSizer( wx.HORIZONTAL, parent=self._panel, ) self._bottom_player_sizer = LabeledCardSizer( wx.HORIZONTAL, parent=self._panel, ) self._table_sizer = wx.FlexGridSizer(cols=2, rows=1) self._table_sizer.AddGrowableCol(0) self._table = TablePanel(parent=self._panel) self._table_sizer.Add(self._table, proportion=1) self._deck = DeckPanel(self._panel, size=(100, 130)) self._table_sizer.Add(self._deck) self._control_sizer = wx.BoxSizer(wx.HORIZONTAL) self._to_game_start_button = wx.Button(parent=self._panel, label=u'<<') self._to_game_start_button.Bind( wx.EVT_BUTTON, self._menu_on_to_game_start ) self._prev_button = wx.Button(parent=self._panel, label=u'<') self._prev_button.Bind(wx.EVT_BUTTON, self._menu_on_prev) self._next_button = wx.Button(parent=self._panel, label=u'>') self._next_button.Bind(wx.EVT_BUTTON, self._menu_on_next) self._to_game_end_button = wx.Button(parent=self._panel, label=u'>>') self._to_game_end_button.Bind(wx.EVT_BUTTON, self._menu_on_to_game_end) self._control_sizer.AddMany([ self._to_game_start_button, self._prev_button, self._next_button, self._to_game_end_button ]) self._main_sizer = wx.FlexGridSizer(cols=1, rows=4) self._main_sizer.AddGrowableCol(0) self._main_sizer.AddGrowableRow(1) self._main_sizer.Add( self._top_player_sizer, flag=wx.EXPAND, proportion=1 ) self._main_sizer.Add( self._table_sizer, flag=wx.ALIGN_CENTER_VERTICAL, proportion=1 ) self._main_sizer.Add(self._control_sizer, flag=wx.EXPAND, proportion=1) self._main_sizer.Add( self._bottom_player_sizer, flag=wx.EXPAND, proportion=1 ) self._panel.SetSizer(self._main_sizer) self.CreateStatusBar() self._create_menu() self._panel.Layout() self.Refresh() self.Layout() self.PLAYER_SIZER_MAP = { LogViewer.PLAYER1: self._bottom_player_sizer, LogViewer.PLAYER2: self._top_player_sizer, } self._menu_on_open() def _create_menu(self): self.menu = wx.MenuBar() menu = wx.Menu() # Файл item = menu.Append( wx.ID_OPEN, u'Открыть файл лога...', u'Открыть файл лога' ) self.Bind(wx.EVT_MENU, self._menu_on_open, item) item = menu.Append( wx.ID_ANY, u'Список игр...\tCTRL+L', u'Просмотреть список игр в открытом файле' ) self.Bind(wx.EVT_MENU, self._menu_on_select_game, item) item = menu.Append(wx.ID_EXIT, u'Выход', u'Закрыть программу') self.Bind(wx.EVT_MENU, self._on_close, item) self.menu.Append(menu, u'Файл') menu = wx.Menu() # Текущая игра self._to_game_start_menu_item = menu.Append( wx.ID_ANY, u'В начало <<\tHOME', u'Перейти в начало игры' ) self.Bind( wx.EVT_MENU, self._menu_on_to_game_start, self._to_game_start_menu_item ) self._prev_menu_item = menu.Append( wx.ID_ANY, u'Назад <\tCTRL+LEFT', u'Вернуться на ход назад' ) self.Bind(wx.EVT_MENU, self._menu_on_prev, self._prev_menu_item) self._next_menu_item = menu.Append( wx.ID_ANY, u'Вперед >\tCTRL+RIGHT', u'Перейти на ход вперед' ) self.Bind(wx.EVT_MENU, self._menu_on_next, self._next_menu_item) self._to_game_end_menu_item = menu.Append( wx.ID_ANY, u'В конец >>\tEND', u'Перейти в конец игры' ) self.Bind( wx.EVT_MENU, self._menu_on_to_game_end, self._to_game_end_menu_item ) self.menu.Append(menu, u'Текущая игра') self.SetMenuBar(self.menu) def _on_close(self, event): if event.GetEventType() in wx.EVT_CLOSE.evtType: event.Skip() else: self.Close() def _menu_on_open(self, event=None): last_directory = get_setting( self.LAST_DIR_SETTING, os.path.expanduser('~') ) dialog = wx.FileDialog( self, u'Выберите файл лога', last_directory, '', '*', wx.OPEN ) if dialog.ShowModal() != wx.ID_OK: self.Close() filename = dialog.GetPath() dialog.Destroy() self._log_viever = LogViewer(filename) set_setting(self.LAST_DIR_SETTING, os.path.dirname(filename)) self._menu_on_select_game() def _menu_on_select_game(self, event=None): choices = [ '%d. %s' % (i, game['title']) for i, game in enumerate(self._log_viever.iterindex(), start=1) ] dialog = wx.SingleChoiceDialog( self, u'Выберите игру', u'Список игр', choices, wx.CHOICEDLG_STYLE, ) dialog.SetSize((500, 400)) dialog.Refresh() if dialog.ShowModal() == wx.ID_OK: self._log_viever.load_game(dialog.GetSelection()) self._bottom_player_sizer.set_label(self._log_viever.player1_name) self._top_player_sizer.set_label(self._log_viever.player2_name) self._menu_on_to_game_start() dialog.Destroy() def _menu_on_to_game_start(self, event=None): self._log_viever.to_game_start() if not self._log_viever.has_next: return self._deck.set_opened_trump(self._log_viever.opened_trump) for card_sizer in (self._bottom_player_sizer, self._top_player_sizer): card_sizer.trump = self._log_viever.opened_trump card_sizer.remove_all() log_event = self._log_viever.get_next() self._new_move(log_event) self._panel.Layout() self.Layout() self.Refresh() self._set_enabled_controls() def _menu_on_to_game_end(self, event=None): self._log_viever.to_game_end() if not self._log_viever.has_prev: return log_event = self._log_viever.get_prev() self._new_move(log_event, with_table=True) self._set_enabled_controls() def _menu_on_next(self, event): if not self._log_viever.has_next: return log_event = self._log_viever.get_next() if log_event['event_type'] == self._log_viever.NEW_MOVE: self._new_move(log_event) return card_sizer = self.PLAYER_SIZER_MAP[log_event['to_move']] table_method = getattr(self._table, log_event['event_type']) card = log_event['card'] table_method(card) card_sizer.remove_card(card, do_layout=True) self._set_enabled_controls() def _menu_on_prev(self, event): if not self._log_viever.has_prev: return log_event = self._log_viever.get_prev() if log_event['event_type'] == self._log_viever.NEW_MOVE: self._new_move(log_event, with_table=True) return card_sizer = self.PLAYER_SIZER_MAP[log_event['to_move']] card = log_event['card'] self._table.pop() card_sizer.add_card(card, do_layout=True) self._set_enabled_controls() def _new_move(self, log_event, with_table=False): assert log_event['event_type'] == self._log_viever.NEW_MOVE self._table.remove_all() self._deck.set_card_count(log_event['deck_count']) if with_table: for index, card in enumerate(log_event['moves_and_responds']): if index % 2: self._table.respond(card) else: self._table.move(card) for card in log_event['given_more']: self._table.give_more(card) card_sizers = (self._bottom_player_sizer, self._top_player_sizer) card_sets = (log_event['player1_cards'], log_event['player2_cards']) for card_sizer, card_set in zip(card_sizers, card_sets): if with_table: card_sizer.remove_all() cards_to_add = card_set - set( log_event['moves_and_responds'] + log_event['given_more'] ) else: cards_to_add = card_set - card_sizer.cards for card in cards_to_add: card_sizer.add_card(card) card_sizer.Layout() if log_event['to_move'] == self._log_viever.PLAYER1: self.SetStatusText(u'Атакует игрок снизу') else: self.SetStatusText(u'Атакует игрок сверху') self._set_enabled_controls() def _set_enabled_controls(self): all_controls = { self._to_game_start_button, self._to_game_end_button, self._next_button, self._prev_button, self._to_game_end_menu_item, self._to_game_start_menu_item, self._prev_menu_item, self._next_menu_item, } [control.Enable(False) for control in all_controls] if not self._log_viever or not self._log_viever.has_game_loaded: return if self._log_viever.has_prev: self._to_game_start_button.Enable() self._prev_button.Enable() self._to_game_start_menu_item.Enable() self._prev_menu_item.Enable() if self._log_viever.has_next: self._to_game_end_button.Enable() self._next_button.Enable() self._to_game_end_menu_item.Enable() self._next_menu_item.Enable()