Beispiel #1
0
class GameRoomWindow(QWidget):

    start_game_signal = pyqtSignal()

    def __init__(self, room_name, master_name, guest_name,\
        server_ip, is_master, hall_hook, login_hook, auth_headers):
        super().__init__()

        self.auth_headers = auth_headers

        self.start_game_signal.connect(self.start_game)

        self.hall_hook = hall_hook
        self.login_hook = login_hook

        self.layout = QHBoxLayout()
        self.room_name = room_name
        self.server_ip = server_ip
        #self.user_name = user_name
        self.is_master = is_master
        self.master_stone = 1

        self.master_name = master_name
        self.guest_name = guest_name

        self.title = "Game Hall"
        self.top = 100
        self.left = 100
        self.width = 600
        self.height = 200

        self.ready = False

        self.init_socket()
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.top, self.left, self.width, self.height)
        current_path = ':/'  # sys.path[0] + '/'
        self.setWindowIcon(
            QIcon(current_path +
                  'chessboard/gomoku_icon.png'))  # set window icon
        self.stone_color_label = QLabel("Creator will use:", self)
        self.stone_color_label.move(255, 14)

        self.colors = QComboBox(self)
        self.colors.addItems(["Black", "White"])
        self.colors.setGeometry(250, 40, 100, 20)
        self.colors.setEnabled(self.is_master)
        if self.is_master:
            self.colors.currentIndexChanged.connect(self.handle_color_change)

        self.start_button_label = QLabel("Start the game:", self)
        self.start_button_label.move(405, 14)

        self.start_button = QPushButton('Start', self)
        self.start_button.move(400, 34)
        self.start_button.clicked.connect(self.handle_start)
        self.start_button.setEnabled(False)

        self.leave_button_label = QLabel("Leave the game:", self)
        self.leave_button_label.move(255, 74)

        self.leave_button = QPushButton('  Leave  ', self)
        self.leave_button.move(250, 94)
        self.leave_button.clicked.connect(self.handle_leave)

        self.guest_status_label = QLabel("Guest is:", self)
        self.guest_status_label.move(405, 74)

        self.ready_button = QPushButton('Unready', self)
        self.ready_button.move(400, 94)
        self.ready_button.clicked.connect(self.handle_ready)
        self.ready_button.setEnabled(not self.is_master)

        self.start_button.resize(self.leave_button.sizeHint())
        self.ready_button.resize(self.leave_button.sizeHint())

        self.room_status_label = QLabel(self)
        self.room_status_label.move(255, 140)

        # id label
        self.id_label = QLabel(self)
        self.id_label.move(40, 14)

        self.role_label = QLabel(self)
        self.role_label.move(40, 44)

        if self.is_master:
            self.id_label.setText("Your id: " + self.master_name)
            self.role_label.setText("You're creator of this room.")
            self.room_status_label.setText("Waiting for player ...")
        else:
            self.id_label.setText("Your id: " + self.guest_name)
            self.role_label.setText("You're guest of this room.")
            self.room_status_label.setText("Creator id: " + self.master_name)

        self.show()

    def handle_message(self, message):
        print("Received: ", message)
        if message[0] == 'J':
            # join signal
            if self.is_master:
                self.guest_name = message[1:]
                self.room_status_label.setText("Guest id: " + self.guest_name)
                if self.colors.currentText() == 'Black':
                    self.master_stone = 1
                    self.web_socket.send(BLACK_STONE_SIGNAL_MESSAGE)
                else:
                    self.master_stone = 2
                    self.web_socket.send(WHITE_STONE_SIGNAL_MESSAGE)
        else:
            try:
                signal = int(message)
                print("signal", signal)
                if signal < 0:
                    # START_SIGNAL = -1
                    # GUEST_READY_SIGNAL = -2
                    # GUEST_UNREADY_SIGNAL = -3
                    # GUEST_LEAVE_SIGNAL = -4
                    # MASTER_DELETE_SIGNAL = -5
                    # END_SIGNAL = -6

                    if self.is_master:
                        if signal == GUEST_READY_SIGNAL:
                            print("ready")
                            self.ready = True
                            self.start_button.setEnabled(True)
                            self.ready_button.setText("Ready")
                        elif signal == GUEST_UNREADY_SIGNAL:
                            print("unready")
                            self.ready = False
                            self.start_button.setEnabled(False)
                            self.ready_button.setText("Unready")
                        elif signal == GUEST_LEAVE_SIGNAL:
                            self.ready = False
                            self.start_button.setEnabled(self.ready)
                            self.ready_button.setText("Unready")
                            self.guest_name = None
                            self.room_status_label.setText(
                                "Waiting for player ...")
                        elif signal == START_SIGNAL:
                            print("try to start")
                            self.start_game_signal.emit()
                        else:
                            print("Unvalid master control signal.")
                    else:
                        if signal == START_SIGNAL:
                            print("try to start")
                            self.start_game_signal.emit()
                        elif signal == MASTER_DELETE_SIGNAL:
                            self.hall_hook()
                            self.close()
                            # TODO: pop a message box
                        elif signal == BLACK_STONE_SIGNAL:
                            self.master_stone = 1
                            self.colors.setCurrentIndex(
                                self.colors.findText('Black'))
                        elif signal == WHITE_STONE_SIGNAL:
                            self.master_stone = 2
                            self.colors.setCurrentIndex(
                                self.colors.findText('White'))
                        else:
                            print("Unvalid guest control signal.")
                    # control signal
                else:
                    # should not be processed now
                    print("Moving signal, game does not start yet.")
            except:
                print("Unvalid message format.")

    @pyqtSlot()
    def start_game(self):
        # return to hall after the match
        # if return to room, must init socket, reset the to_influence by calling hook()
        #hall_hook = self.hall_hook

        self.game_board = Gomoku(self.is_master, self.room_name,\
                                self.master_name, self.guest_name,\
                                self.master_stone, self.server_ip,\
                                self.web_socket, self.hall_hook)
        self.game_board.show()
        self.close()

    def init_socket(self):
        # uri = 'ws://' + self.server_ip + ':8080/playing'
        # role can be: "m" for master, "g" for guest, "a" for audience
        # if master use balck stone, "master_stone:1", if white, "master_stone:2"

        # if self.colors.currentText() == 'Black':
        #     master_stone = '1'
        # else:
        #     master_stone = '2'

        self.uri = 'ws://' + self.server_ip + ':8080/playing'
        # self.uri = 'ws://' + self.server_ip + ':8080/test'

        if self.is_master:
            role = 'm'
            user_name = self.master_name
        else:
            role = 'g'
            user_name = self.guest_name

        self.headers = [("role", role),\
            ("roomName", self.room_name),\
            ("userName", user_name),\
            ("masterStone", self.master_stone)]
        self.web_socket = SocketCli(self.uri, headers=self.headers)
        self.web_socket.connect()
        self.web_socket.hook(self)

        if not self.is_master:
            print("before send join")
            self.web_socket.send('J' + self.guest_name)
            print("sent join")

    @pyqtSlot()
    def handle_color_change(self):
        if self.colors.currentText() == 'Black':
            self.master_stone = 1
            print("send: change to balck")
            self.web_socket.send(BLACK_STONE_SIGNAL_MESSAGE)
        else:
            self.master_stone = 2
            print("send: change to white")
            self.web_socket.send(WHITE_STONE_SIGNAL_MESSAGE)

    @pyqtSlot()
    def handle_start(self):
        # donot need to send info to redis,
        # done by server

        self.web_socket.send(START_SIGNAL_MESSAGE)

    @pyqtSlot()
    def handle_leave(self):
        # donot need to send info to redis,
        # done by server

        if self.is_master:
            response = requests.get('http://' + self.server_ip +\
                ':8080/room/delete/'+ self.room_name + '/' +\
                self.master_name, headers=self.auth_headers)
            # if response.text == 'Success':
            #     self.web_socket.send(MASTER_DELETE_SIGNAL_MESSAGE)
            #     self.hall_hook()
            #     self.close()
            # elif response.text == "Unauthorized or timeout.":
            #     pop_info_and_back(self, response.text, self.login_hook)
            # else:
            print('#### Info: master delete: ' + response.text)
            if response.text == 'Success':
                print("Success")
                self.web_socket.send(MASTER_DELETE_SIGNAL_MESSAGE)
                self.web_socket.close()
                self.hall_hook()
            else:
                print("Fail")
                self.web_socket.close()
                self.hall_hook(refresh=True)
            self.close()
        else:
            response = requests.get('http://' + self.server_ip +\
                ':8080/room/leave/'+ self.room_name + '/' +\
                self.guest_name, headers=self.auth_headers)
            # if response.text == 'Success':
            #     self.web_socket.send(GUEST_LEAVE_SIGNAL_MESSAGE)
            #     self.hall_hook()
            #     self.close()
            # elif response.text == "Unauthorized or timeout.":
            #     pop_info_and_back(self, response.text, self.login_hook)
            # else:
            #     print(response.text)
            print('#### Info: guest leave: ' + response.text)
            self.web_socket.send(GUEST_LEAVE_SIGNAL_MESSAGE)
            self.web_socket.close()
            self.hall_hook()
            self.close()
            if response.text == 'Success':
                print("Success")
                self.web_socket.close()
                self.hall_hook()
            else:
                print("Fail")
                self.web_socket.close()
                self.hall_hook(refresh=True)
            self.close()

    @pyqtSlot()
    def handle_ready(self):
        # donot need to send info to redis,
        # done by server

        if self.ready:
            self.ready = False
            self.web_socket.send(GUEST_UNREADY_SIGNAL_MESSAGE)
            self.ready_button.setText("Unready")
        else:
            self.ready = True
            self.web_socket.send(GUEST_READY_SIGNAL_MESSAGE)
            self.ready_button.setText("Ready")
Beispiel #2
0
class GameHallWindow(QWidget):
    """Game hall window, create/ join/ watch a match"""

    def __init__(self, username, server_ip, auth_headers, login_hook, manual_hook):
        super().__init__()
        self.auth_headers = auth_headers
        self.login_hook = login_hook
        self.manual_hook = manual_hook

        self.server_ip = server_ip
        self.username = username

        self.current_page = -1

        self.title = "Game Hall"
        self.top = 100
        self.left = 100
        self.width = 700
        self.height = 500

        self.init_ui()

        self.refresh()

    def init_ui(self):
        """
        init the ui of game hall:
        table, buttons.
        And set the style of them
        """
        self.setWindowTitle(self.title)
        self.setWindowIcon(QIcon('chessboard/gomoku_icon.png')) # set window icon
        self.setGeometry(self.top, self.left, self.width, self.height)

        self.create_room_button = QPushButton('Create', self)
        self.create_room_button.move(580, 20)
        self.create_room_button.clicked.connect(self.handle_create_room)

        self.action_button = QPushButton('Action', self)
        self.action_button.move(580, 70)
        self.action_button.clicked.connect(self.handle_action)
        # disable the action button at first
        self.action_button.setEnabled(False)

        self.refresh_button = QPushButton('Refresh', self)
        self.refresh_button.move(580, 120)
        self.refresh_button.clicked.connect(self.refresh)

        self.back_button = QPushButton('Back', self)
        self.back_button.move(580, 340)
        self.back_button.clicked.connect(self.handle_back)

        self.exit_button = QPushButton('Exit', self)
        self.exit_button.move(580, 390)
        self.exit_button.clicked.connect(self.handle_exit)

        # room list, using table
        self.rooms_observed = QTableWidget(self)
        self.rooms_observed.setRowCount(10)
        self.rooms_observed.setColumnCount(2)
        # change the action button after selecting a room
        self.rooms_observed.clicked.connect(self.handle_click_room_observed)
        # set column name
        self.rooms_observed.setHorizontalHeaderLabels(['Room Name', 'Status'])
        self.rooms_observed.setGeometry(50, 20, 500, 400)

        # cannot edit
        self.rooms_observed.setEditTriggers(QAbstractItemView.NoEditTriggers)
        # choose whole row
        self.rooms_observed.setSelectionBehavior(QAbstractItemView.SelectRows)
        # at most select one row
        self.rooms_observed.setSelectionMode(QAbstractItemView.SingleSelection)
        # hide vertical header
        self.rooms_observed.verticalHeader().setVisible(False)
        # fix the table width
        self.rooms_observed.setColumnWidth(0, 400)
        self.rooms_observed.setColumnWidth(1, 99)
        # disable the scrol bar
        self.rooms_observed.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.rooms_observed.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        # disable resizing table
        self.rooms_observed.setCornerButtonEnabled(False)
        self.rooms_observed.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed)

        self.create_room_button.resize(self.refresh_button.sizeHint())
        self.action_button.resize(self.refresh_button.sizeHint())
        self.exit_button.resize(self.refresh_button.sizeHint())
        self.back_button.resize(self.refresh_button.sizeHint())

        self.show()

    @pyqtSlot()
    def refresh(self):
        """handle clicking refresh button, refresh the room info in the table"""
        response = requests.get('http://%s:8080/room/all'\
            % self.server_ip,\
            headers=self.auth_headers)
        try:
            self.room_list = response.json()
            print(self.room_list)

            self.max_page = int(len(self.room_list) / 10)
            self.current_page = -1
            self.browse(0)

            # refresh chane the room list, should init the action btn
            self.action_button.setEnabled(False)
            self.action_button.setText("Action")
        except:
            pop_info_and_back(self, response.text, self.login_hook)

            # info = response.text
            # button = QMessageBox.question(self, "Info",\
            #                           info,\
            #                           QMessageBox.Ok,\
            #                           QMessageBox.Ok)
            # if button == QMessageBox.Ok:
            #     self.login_hook()
            #     self.close()
            # else:
            #     self.close()
            #     raise SystemExit(0)

    def browse(self, page):
        """choose the page of rooms to browse"""
        if self.current_page != page:
            self.rooms_observed.clearContents()
            self.current_page = page
            for i in range(10):
                if self.current_page*10+i >= len(self.room_list):
                    break
                self.add_line(self.room_list[self.current_page*10 + i], i)

    def add_line(self, a_room, row_num):
        """add a room into the table, call by browse"""
        self.rooms_observed.setItem(row_num, 0, QTableWidgetItem(a_room['roomName']))
        self.rooms_observed.setItem(row_num, 1, QTableWidgetItem(a_room['roomStatus']))

    @pyqtSlot()
    def handle_create_room(self):
        """create a room, call create window"""
        self.create_room_page = CreateRoomWindow(master_name=self.username,\
            server_ip=self.server_ip,\
            hall_hook=self.hall_hook,\
            login_hook=self.login_hook,\
            auth_headers=self.auth_headers)

        self.create_room_page.show()
        self.close()

    @pyqtSlot()
    def handle_action(self):
        """watch or join or disable based on the room chosen"""
        # selected_row = self.rooms_observed.currentRow()
        action = self.action_button.text()
        print(action)
        if action == "Join":
            self.join_room()
        elif action == "Watch":
            # try to watch the game
            self.watch_game()

    def watch_game(self):
        """call by action_btn, watch a match in certain room"""
        selected_row = self.rooms_observed.currentRow()
        master_name = self.room_list[selected_row + self.current_page * 10]["master"]
        guest_name = self.room_list[selected_row + self.current_page * 10]["guest"]
        room_name = self.rooms_observed.item(selected_row, 0).text()

        uri = 'ws://' + self.server_ip + ':8080/playing'

        socket_headers = [("role", 'a'),\
            ("roomName", room_name),\
            ("userName", self.username),\
            ("masterStone", 1)]

        self.web_socket = SocketCli(uri, headers=socket_headers)
        # self.web_socket.hook(self)

        self.game_board = Gomoku(True, room_name, master_name,\
            guest_name, 1, self.server_ip, self.web_socket,\
            self.hall_hook, True)
        self.game_board.show()
        self.close()

    @pyqtSlot()
    def handle_exit(self):
        """exit the programm, pop a window to ensure"""
        reply = QMessageBox.question(self, 'Exit', 'You sure to exit?',
                                     QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            # TODO: other actions
            self.close()

    @pyqtSlot()
    def handle_back(self):
        self.manual_hook()
        self.close()

    @pyqtSlot()
    def handle_click_room_observed(self):
        """
        select a room in the table,
        change the action_btn based on the game status
        """
        selected_row = self.rooms_observed.currentRow()
        try:
            select_status = self.rooms_observed.item(selected_row, 1).text()
            self.action_button.setEnabled(True)
            if select_status == 'Open':
                self.action_button.setText("Join")
            elif select_status == 'Playing':
                self.action_button.setText("Watch")
            else:
                self.action_button.setEnabled(False)
                self.action_button.setText("Action")
        except:
            self.action_button.setEnabled(False)
            self.action_button.setText("Action")

    def join_room(self):
        """join the room as a guest"""
        selected_row = self.rooms_observed.currentRow()
        try:
            room_name = self.rooms_observed.item(selected_row, 0).text()

            uri = "http://%s:8080/room/join/%s/%s"\
                % (self.server_ip, room_name, self.username)

            result = requests.get(uri, headers=self.auth_headers)

            print('from server: '+ result.text)

            if result.text == "Success":
                master_name = self.room_list[selected_row + self.current_page * 10]["master"]
                self.game_room = GameRoomWindow(room_name, master_name,\
                    self.username, self.server_ip, False, self.hall_hook,\
                    self.login_hook, self.auth_headers)
                self.game_room.show()
                self.close()
            else:
                QMessageBox.warning(self, 'Error', result.text)
        except Exception as e:
            print(e)
            QMessageBox.warning(self, 'Error', "Try again.")

    def hall_hook(self, refresh=True):
        self.show()
        if refresh:
            self.refresh()