diff --git a/src/CheckUpdateGui.py b/src/CheckUpdateGui.py index 0804faa..171b2b2 100644 --- a/src/CheckUpdateGui.py +++ b/src/CheckUpdateGui.py @@ -89,8 +89,11 @@ def initUi(self): row1.addWidget(QLabel(self.release.tag_name)) row1.addItem(QSpacerItem( 20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)) - self.dateTimeLabel.setText(QDateTime.fromString( - self.release.assets_created_at, "yyyy-MM-ddThh:mm:ssZ").toString("yyyy-MM-dd hh:mm:ss")) + self.dateTimeLabel.hide() + if self.release.assets_created_at != "": + self.dateTimeLabel.setText(QDateTime.fromString( + self.release.assets_created_at, "yyyy-MM-ddThh:mm:ssZ").toString("yyyy-MM-dd hh:mm:ss")) + self.dateTimeLabel.show() row1.addWidget(self.dateTimeLabel) row1.addItem(QSpacerItem( 20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)) @@ -99,24 +102,29 @@ def initUi(self): self.titleWidget.setLayout(row1) self.titleWidget.setContentsMargins(0, 0, 0, 0) formLayout = QFormLayout() - urlLabel = QLabel() - urlLabel.setText("" + QObject.tr(self, "open external links") + "") - urlLabel.setOpenExternalLinks(True) - dataLayout = QVBoxLayout() formLayout.setLabelAlignment(Qt.AlignmentFlag.AlignLeft) - formLayout.addRow(QObject.tr(self, "html_url"), urlLabel) + dataLayout = QVBoxLayout() + if self.release.html_url != "": + urlLabel = QLabel() + urlLabel.setText("" + QObject.tr(self, "open external links") + "") + urlLabel.setOpenExternalLinks(True) + formLayout.addRow(QObject.tr(self, "html_url"), urlLabel) formLayout.addRow(QObject.tr(self, "name"), QLabel(self.release.assets_name)) - formLayout.addRow(QObject.tr(self, "content_type"), - QLabel(self.release.assets_content_type)) - formLayout.addRow(QObject.tr(self, "size"), QLabel( - str(f"{self.release.assets_size / 1000000:.2f} MB"))) - formLayout.addRow(QObject.tr(self, "download_count"), - QLabel(str(self.release.assets_download_count))) - formLayout.addRow(QObject.tr(self, "created_at"), - QLabel(QDateTime.fromString(self.release.assets_created_at, "yyyy-MM-ddThh:mm:ssZ").toString( - "yyyy-MM-dd hh:mm:ss"))) + if self.release.assets_content_type != "": + formLayout.addRow(QObject.tr(self, "content_type"), + QLabel(self.release.assets_content_type)) + if self.release.assets_size > 0: + formLayout.addRow(QObject.tr(self, "size"), QLabel( + str(f"{self.release.assets_size / 1000000:.2f} MB"))) + if self.release.assets_download_count != "": + formLayout.addRow(QObject.tr(self, "download_count"), + QLabel(str(self.release.assets_download_count))) + if self.release.assets_created_at != "": + formLayout.addRow(QObject.tr(self, "created_at"), + QLabel(QDateTime.fromString(self.release.assets_created_at, "yyyy-MM-ddThh:mm:ssZ").toString( + "yyyy-MM-dd hh:mm:ss"))) downloadUrlLabel = QLabel() downloadUrlLabel.setText("" + QObject.tr(self, "open download links") + "") @@ -237,7 +245,7 @@ def __init__(self, github: GitHub, parent=None): self.setWindowTitle(QObject.tr(self, "CheckUpdate")) # 去掉问号 self.setWindowFlags(self.windowFlags() & ~ - Qt.WindowContextHelpButtonHint) + Qt.WindowContextHelpButtonHint) self.r_path = parent.r_path self.github: GitHub = github self.github.setParent(self) @@ -309,7 +317,7 @@ def initConnect(self): def changeSource(self, source: str): self.pingThread = PingThread( - source, self.github.sourceManager.sources[source]) + source, self.github.sourceManager.sources[source]['url']) self.sourceSpeedLabel.setText("---ms") self.pingThread.pingSignal.connect( lambda x, y: self.sourceSpeedLabel.setText(f"{int(y)}ms")) diff --git a/src/githubApi.py b/src/githubApi.py index f1b685d..75d4e34 100644 --- a/src/githubApi.py +++ b/src/githubApi.py @@ -47,7 +47,7 @@ def run(self) -> None: class SourceManager(QObject): quickSource = pyqtSignal(str, float) - def __init__(self, sources: dict, current: any = None, parent=None): + def __init__(self, sources: dict, current: str = None, parent=None): super().__init__(parent) if not isinstance(sources, dict): raise TypeError @@ -55,7 +55,8 @@ def __init__(self, sources: dict, current: any = None, parent=None): raise ValueError self.sources = sources # 第一个的key - self.currentSource = list(sources.keys())[0] if current is None else current + self.currentSource = list(sources.keys())[ + 0] if current is None else current self.speedData = {} self.threads = [] @@ -70,7 +71,7 @@ def sources(self, sources: dict): if not sources: raise ValueError for key in sources: - sources[key] = sources[key].strip('/') + sources[key]['url'] = sources[key]['url'].strip('/') self.__sources = sources self.currentSource = list(sources.keys())[0] @@ -81,6 +82,17 @@ def currentSource(self): """ return self.__currentSource + @property + def token(self) -> str: + return self.__sources[self.currentSource]['t'] + + @property + def tokenUrl(self) -> str: + if self.currentSource == "gitee": + return f'?access_token={self.token}' + else: + return "" + @currentSource.setter def currentSource(self, currentSource: str): """ @@ -98,7 +110,7 @@ def currentSource(self, currentSource: str): @property def currentSourceUrl(self): - return self.sources[self.currentSource] + return self.sources[self.currentSource]['url'] def checkSourceSpeed(self): """ @@ -107,7 +119,7 @@ def checkSourceSpeed(self): self.threads.clear() self.speedData = {} for source in self.sources: - thread = PingThread(source, self.sources[source]) + thread = PingThread(source, self.sources[source]['url']) thread.pingSignal.connect(self.__pingSignal) self.threads.append(thread) thread.start() @@ -129,13 +141,13 @@ def __init__(self, dataJson: dict, versionReStr: str) -> None: self.tag_name = dataJson['tag_name'] if re.search( versionReStr, dataJson['tag_name']) else dataJson['name'] self.body = dataJson['body'] - self.html_url = dataJson['html_url'] + self.html_url = dataJson['html_url'] if 'html_url' in dataJson else "" m_assert = dataJson['assets'][0] self.assets_name = m_assert['name'] - self.assets_content_type = m_assert['content_type'] - self.assets_size = m_assert['size'] - self.assets_download_count = m_assert['download_count'] - self.assets_created_at = m_assert['created_at'] + self.assets_content_type = m_assert['content_type'] if 'content_type' in m_assert else "" + self.assets_size = m_assert['size'] if 'size' in m_assert else 0 + self.assets_download_count = m_assert['download_count'] if 'download_count' in m_assert else "" + self.assets_created_at = m_assert['created_at'] if 'created_at' in m_assert else "" self.assets_browser_download_url = m_assert['browser_download_url'] @@ -148,20 +160,16 @@ class GitHub(QObject): downloadReleaseAsyncFinishSignal = pyqtSignal(str) errorSignal = pyqtSignal(str) - def __init__(self, sourceManager: SourceManager, owner: str, repo: str, version: str, versionReStr: str, + def __init__(self, sourceManager: SourceManager, version: str, versionReStr: str, parent=None): """ :param sourceManager: 一个SourceManager实例,提供了多个github api的url - :param owner: github的owner - :param repo: github的仓库名 :param version: 当前的版本号 :param versionReStr: 一个正则表达式串,用于从github的release中,提取版本号 :param parent: 一个QObject实例,父对象 """ super().__init__(parent) self.__sourceManager = sourceManager - self.__owner = owner - self.__repo = repo self.__version = version self.__versionReStr = versionReStr self.__replyDict = {} @@ -177,22 +185,6 @@ def sourceManager(self, sourceManager: SourceManager) -> None: self.__sourceManager = sourceManager self.__sourceManager.setParent(self) - @property - def owner(self) -> str: - return self.__owner - - @owner.setter - def owner(self, owner: str) -> None: - self.__owner = owner - - @property - def repo(self) -> str: - return self.__repo - - @repo.setter - def repo(self, repo: str) -> None: - self.__repo = repo - @property def version(self) -> str: return self.__version @@ -214,14 +206,14 @@ def latestReleaseUrl(self) -> str: """ 获取最新的release的url """ - return f'{self.sourceManager.currentSourceUrl}/{self.__owner}/{self.__repo}/releases/latest' + return f'{self.sourceManager.currentSourceUrl}/releases/latest{self.sourceManager.tokenUrl}' @property def releasesUrl(self) -> str: """ 获取所有release的url """ - return f'{self.sourceManager.currentSourceUrl}/{self.__owner}/{self.__repo}/releases' + return f'{self.sourceManager.currentSourceUrl}/releases{self.sourceManager.tokenUrl}' def isNeedUpdate(self, isAsync: bool = True) -> bool | str | None: """ @@ -354,7 +346,8 @@ def downloadRelease(self, release: ReleaseInfo) -> str: :return: 一个当前请求的唯一标识 """ self.downloadReleaseAsyncStartSignal.emit(release) - nam, request = self.__createRequest(release.assets_browser_download_url) + nam, request = self.__createRequest( + release.assets_browser_download_url) reply = nam.get(request) reply.setObjectName(str(uuid.uuid1())) self.__replyDict[reply.objectName()] = reply @@ -474,14 +467,14 @@ def removeDownloadFile(self): """删除下载的文件""" GitHub.removeAllTempFile(f".*{self.__repo}.*") + if __name__ == '__main__': app = QCoreApplication([]) data = { - "Github": "https://api.github.com/repos/", - "gitee": "https://api.gitee.com/repos/", + "Github": "https://api.github.com/repos/eee555/Metasweeper", + "gitee": "https://api.gitee.com/repos/ee55/Metasweeper", } - github = GitHub(SourceManager(data), "eee555", - "Solvable-Minesweeper", "3.1.9", "(\d+\.\d+\.\d+)") + github = GitHub(SourceManager(data, "gitee"), "3.1.9", "(\d+\.\d+\.\d+)") github.releasesAsyncSignal.connect(lambda x: print(x)) github.releases() # manager = SourceManager(data) diff --git a/src/main.py b/src/main.py index 400e6e8..9d7f27d 100644 --- a/src/main.py +++ b/src/main.py @@ -2,22 +2,44 @@ import time from PyQt5 import QtWidgets from PyQt5 import QtCore -from PyQt5.QtWidgets import QApplication -from PyQt5.QtNetwork import QLocalSocket,QLocalServer -import sys, os +from PyQt5.QtWidgets import QApplication, QMessageBox +from PyQt5.QtNetwork import QLocalSocket, QLocalServer +import sys +import os import mainWindowGUI as mainWindowGUI import mineSweeperGUI as mineSweeperGUI import ctypes from ctypes import wintypes os.environ["QT_FONT_DPI"] = "96" -def on_new_connection(localServer:QLocalServer): + +def on_new_connection(localServer: QLocalServer): + """当新连接进来时,接受连接并将文件路径传递给主窗口""" + socket = localServer.nextPendingConnection() + if socket: + socket.readyRead.connect(lambda: on_ready_read(socket)) + + +def on_ready_read(socket: QLocalSocket): + """从socket读取文件路径并传递给主窗口""" + if socket and socket.state() == QLocalSocket.ConnectedState: + # 读取文件路径并调用打开文件 + socket.waitForReadyRead(500) + file_path = socket.readAll().data().decode() + for win in QApplication.topLevelWidgets(): + if isinstance(win, mainWindowGUI.MainWindow): + win.dropFileSignal.emit(file_path) + socket.disconnectFromServer() # 断开连接 + + +def on_new_connection(localServer: QLocalServer): """当新连接进来时,接受连接并将文件路径传递给主窗口""" socket = localServer.nextPendingConnection() if socket: socket.readyRead.connect(lambda: on_ready_read(socket)) -def on_ready_read(socket:QLocalSocket): + +def on_ready_read(socket: QLocalSocket): """从socket读取文件路径并传递给主窗口""" if socket and socket.state() == QLocalSocket.ConnectedState: # 读取文件路径并调用打开文件 @@ -29,21 +51,43 @@ def on_ready_read(socket:QLocalSocket): socket.disconnectFromServer() # 断开连接 +def on_new_connection(localServer: QLocalServer): + """当新连接进来时,接受连接并将文件路径传递给主窗口""" + socket = localServer.nextPendingConnection() + if socket: + socket.readyRead.connect(lambda: on_ready_read(socket)) + + +def on_ready_read(socket: QLocalSocket): + """从socket读取文件路径并传递给主窗口""" + if socket and socket.state() == QLocalSocket.ConnectedState: + # 读取文件路径并调用打开文件 + socket.waitForReadyRead(500) + file_path = socket.readAll().data().decode() + for win in QApplication.topLevelWidgets(): + if isinstance(win, mainWindowGUI.MainWindow): + win.dropFileSignal.emit(file_path) + socket.disconnectFromServer() # 断开连接 + def find_window(class_name, window_name): """ 查找指定窗口的句柄。 - + + Args: class_name (str): 要查找的窗口的类名。 window_name (str): 要查找的窗口的标题。 - + + Returns: int: 查找到的窗口的句柄。如果未找到窗口,则抛出异常。 - + + Raises: ctypes.WinError: 如果未找到指定窗口,则抛出此异常。 - + + """ user32 = ctypes.WinDLL('user32', use_last_error=True) user32.FindWindowW.argtypes = [wintypes.LPCWSTR, wintypes.LPCWSTR] @@ -58,7 +102,7 @@ def find_window(class_name, window_name): if __name__ == "__main__": # QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling) try: - app = QtWidgets.QApplication (sys.argv) + app = QtWidgets.QApplication(sys.argv) serverName = "MineSweeperServer" socket = QLocalSocket() socket.connectToServer(serverName) @@ -72,7 +116,8 @@ def find_window(class_name, window_name): else: localServer = QLocalServer() localServer.listen(serverName) - localServer.newConnection.connect(lambda: on_new_connection(localServer=localServer)) + localServer.newConnection.connect( + lambda: on_new_connection(localServer=localServer)) mainWindow = mainWindowGUI.MainWindow() ui = mineSweeperGUI.MineSweeperGUI(mainWindow, sys.argv) ui.mainWindow.show() @@ -82,8 +127,14 @@ def find_window(class_name, window_name): hwnd = find_window(None, _translate("MainWindow", "元扫雷")) SetWindowDisplayAffinity = ctypes.windll.user32.SetWindowDisplayAffinity - ui.disable_screenshot = lambda: ... if SetWindowDisplayAffinity(hwnd, 0x00000011) else 1/0 - ui.enable_screenshot = lambda: ... if SetWindowDisplayAffinity(hwnd, 0x00000000) else 1/0 + ui.disable_screenshot = lambda: ... if SetWindowDisplayAffinity( + hwnd, 0x00000011) else 1/0 + ui.enable_screenshot = lambda: ... if SetWindowDisplayAffinity( + hwnd, 0x00000000) else 1/0 + ui.disable_screenshot = lambda: ... if SetWindowDisplayAffinity( + hwnd, 0x00000011) else 1/0 + ui.enable_screenshot = lambda: ... if SetWindowDisplayAffinity( + hwnd, 0x00000000) else 1/0 sys.exit(app.exec_()) ... @@ -157,4 +208,3 @@ def find_window(class_name, window_name): # MouseState::ChordingNotFlag => Ok(6), # MouseState::DownUpAfterChording => Ok(7), # MouseState::Undefined => Ok(8), - diff --git a/src/mineSweeperGUI.py b/src/mineSweeperGUI.py index 67bb848..5ed0a8e 100644 --- a/src/mineSweeperGUI.py +++ b/src/mineSweeperGUI.py @@ -4,7 +4,11 @@ # from PyQt5.QtWidgets import QLineEdit, QInputDialog, QShortcut from PyQt5.QtWidgets import QApplication, QFileDialog, QWidget import gameDefinedParameter -import superGUI, gameAbout, gameSettings, gameSettingShortcuts,\ +import superGUI +import gameAbout +import gameSettings +import gameSettingShortcuts +import \ captureScreen, mine_num_bar, videoControl, gameRecordPop from CheckUpdateGui import CheckUpdateGui from githubApi import GitHub, SourceManager @@ -15,23 +19,24 @@ # import time import os import ctypes -import hashlib, uuid +import hashlib +import uuid # from PyQt5.QtWidgets import QApplication from country_name import country_name import metaminesweeper_checksum from mainWindowGUI import MainWindow + class MineSweeperGUI(superGUI.Ui_MainWindow): def __init__(self, MainWindow: MainWindow, args): self.mainWindow = MainWindow self.checksum_guard = metaminesweeper_checksum.ChecksumGuard() super(MineSweeperGUI, self).__init__(MainWindow, args) - - + # MineSweeperGUI父类的init中读.ini、读图片、设置字体、局面初始化等 - self.time_10ms: int = 0 # 已毫秒为单位的游戏时间,全局统一的 + self.time_10ms: int = 0 # 已毫秒为单位的游戏时间,全局统一的 self.showTime(self.time_10ms // 100) self.timer_10ms = QTimer() self.timer_10ms.setInterval(10) # 10毫秒回调一次的定时器 @@ -48,6 +53,7 @@ def __init__(self, MainWindow: MainWindow, args): self.actiongao_ji.triggered.connect(lambda: self.predefined_Board(3)) self.actionzi_ding_yi.triggered.connect(self.action_CEvent) self.actiongao_ji.triggered.connect(lambda: self.predefined_Board(3)) + def save_evf_file_integrated(): if self.game_state != "ready" and self.game_state != "playing" and\ self.game_state != "show" and self.game_state != "study" and\ @@ -63,10 +69,14 @@ def save_evf_file_integrated(): self.actiongaun_yv.triggered.connect(self.action_AEvent) self.actionauto_update.triggered.connect(self.auto_Update) self.actionopen.triggered.connect(self.action_OpenFile) - self.english_action.triggered.connect(lambda: self.trans_language("en_US")) - self.chinese_action.triggered.connect(lambda: self.trans_language("zh_CN")) - self.polish_action.triggered.connect(lambda: self.trans_language("pl_PL")) - self.german_action.triggered.connect(lambda: self.trans_language("de_DE")) + self.english_action.triggered.connect( + lambda: self.trans_language("en_US")) + self.chinese_action.triggered.connect( + lambda: self.trans_language("zh_CN")) + self.polish_action.triggered.connect( + lambda: self.trans_language("pl_PL")) + self.german_action.triggered.connect( + lambda: self.trans_language("de_DE")) # config = configparser.ConfigParser() # config.read(self.game_setting_path, encoding='utf-8') @@ -89,7 +99,8 @@ def save_evf_file_integrated(): self.frameShortcut7.activated.connect(lambda: self.predefined_Board(6)) self.frameShortcut8.activated.connect(self.showScores) self.frameShortcut9.activated.connect(self.screenShot) - self.shortcut_hidden_score_board.activated.connect(self.hidden_score_board) + self.shortcut_hidden_score_board.activated.connect( + self.hidden_score_board) self._game_state = self.game_state = 'ready' # 用状态机控制局面状态。 @@ -102,14 +113,12 @@ def save_evf_file_integrated(): # 'fail':游戏失败,踩雷了。 # 'win':游戏成功。 - - # 相对路径 self.relative_path = args[0] # 用本软件打开录像 if len(args) == 2: self.action_OpenFile(openfile_name=args[1]) - + self.trans_language() self.score_board_manager.with_namespace({ "race_identifier": self.race_identifier, @@ -117,17 +126,17 @@ def save_evf_file_integrated(): "checksum_ok": "--", "is_official": "--", "is_fair": "--" - }) - self.score_board_manager.reshow(self.label.ms_board, index_type = 1) + }) + self.score_board_manager.reshow(self.label.ms_board, index_type=1) self.score_board_manager.visible() self.mainWindow.closeEvent_.connect(self.closeEvent_) self.mainWindow.dropFileSignal.connect(self.action_OpenFile) - + @property def pixSize(self): return self._pixSize - + @pixSize.setter def pixSize(self, pixSize): pixSize = max(5, pixSize) @@ -147,11 +156,13 @@ def pixSize(self, pixSize): else: self.predefinedBoardPara[0]['pixsize'] = pixSize - self.label.setMinimumSize(QtCore.QSize(pixSize * self.column + 8, pixSize * self.row + 8)) - self.label.setMaximumSize(QtCore.QSize(pixSize * self.column + 8, pixSize * self.row + 8)) + self.label.setMinimumSize(QtCore.QSize( + pixSize * self.column + 8, pixSize * self.row + 8)) + self.label.setMaximumSize(QtCore.QSize( + pixSize * self.column + 8, pixSize * self.row + 8)) # self.label.setFixedSize(QtCore.QSize(self.pixSize*self.column + 8, self.pixSize*self.row + 8)) - self.reimportLEDPic(pixSize) # 重新导入图片,无磁盘io + self.reimportLEDPic(pixSize) # 重新导入图片,无磁盘io self.label_2.reloadFace(pixSize) self.set_face(14) self.showMineNum(self.mineUnFlagedNum) @@ -180,11 +191,11 @@ def game_state(self): def game_state(self, game_state: str): # print(self._game_state, " -> " ,game_state) if self._game_state in ("playing", "show", "joking") and\ - game_state not in ("playing", "show", "joking"): + game_state not in ("playing", "show", "joking"): self.timer_10ms.stop() self.unlimit_cursor() elif self._game_state in ("display", "showdisplay") and\ - game_state not in ("display", "showdisplay"): + game_state not in ("display", "showdisplay"): self.timer_video.stop() self.ui_video_control.QWidget.close() self.label.paint_cursor = False @@ -194,14 +205,13 @@ def game_state(self, game_state: str): "is_official": "--", "is_fair": "--", "mode": self.gameMode, - }) - self.score_board_manager.show(self.label.ms_board, index_type = 1) + }) + self.score_board_manager.show(self.label.ms_board, index_type=1) elif self._game_state == 'study': self.num_bar_ui.QWidget.close() self._game_state = game_state - def layMine(self, i, j): xx = self.row yy = self.column @@ -231,7 +241,7 @@ def timeCount(self): since_time_unix_2 = QtCore.QDateTime.currentDateTime().\ toMSecsSinceEpoch() - self.start_time_unix_2 if abs(t * 1000 - since_time_unix_2) > 10 and\ - (self.game_state == "playing" or self.game_state == "joking"): + (self.game_state == "playing" or self.game_state == "joking"): # 防CE作弊 self.gameRestart() @@ -240,7 +250,7 @@ def timeCount(self): # self.score_board_manager.with_namespace({ # "rtime": self.time_ms / 1000, # }) - self.score_board_manager.show(self.label.ms_board, index_type = 1) + self.score_board_manager.show(self.label.ms_board, index_type=1) def ai(self, i, j): # 0,4, 5, 6, 7, 8, 9, 10代表:标准、win7、 @@ -251,13 +261,14 @@ def ai(self, i, j): return elif self.gameMode == 6: if self.label.ms_board.board[i][j] >= 0 and \ - not ms.is_able_to_solve(self.label.ms_board.game_board, (i, j)): + not ms.is_able_to_solve(self.label.ms_board.game_board, (i, j)): board = self.label.ms_board.board.into_vec_vec() board[i][j] = -1 self.label.ms_board.board = board return elif self.gameMode == 7: - code = ms.is_guess_while_needless(self.label.ms_board.game_board, (i, j)) + code = ms.is_guess_while_needless( + self.label.ms_board.game_board, (i, j)) if code == 3: board = self.label.ms_board.board.into_vec_vec() board[i][j] = -1 @@ -268,7 +279,8 @@ def ai(self, i, j): self.label.ms_board.board = board return elif self.gameMode == 8: - code = ms.is_guess_while_needless(self.label.ms_board.game_board, (i, j)) + code = ms.is_guess_while_needless( + self.label.ms_board.game_board, (i, j)) if code == 2: board, flag = mm.enumerateChangeBoard(self.label.ms_board.board, self.label.ms_board.game_board, [(i, j)]) @@ -280,10 +292,9 @@ def ai(self, i, j): board, flag = mm.enumerateChangeBoard(self.label.ms_board.board, self.label.ms_board.game_board, [(i, j)]) - self.label.ms_board.board = board return - + # 双击时进入,可以双击猜雷 # 此处架构可以改进,放到工具箱里 def chording_ai(self, i, j): @@ -295,16 +306,16 @@ def chording_ai(self, i, j): if self.label.ms_board.mouse_state != 5 and self.label.ms_board.mouse_state != 6: return if self.label.ms_board.game_board[i][j] >= 10 or\ - self.label.ms_board.game_board[i][j] == 0: + self.label.ms_board.game_board[i][j] == 0: return if self.gameMode == 0 or self.gameMode == 4 or self.gameMode == 5: return - not_mine_round = [] # 没有标雷,且非雷 - is_mine_round = [] # 没有标雷,且是雷 - flag_not_mine_round = [] # 标雷,且非雷 - flag_is_mine_round = [] # 标雷,且是雷 - for ii in range(max(0,i-1), min(self.row,i+2)): - for jj in range(max(0,j-1), min(self.column,j+2)): + not_mine_round = [] # 没有标雷,且非雷 + is_mine_round = [] # 没有标雷,且是雷 + flag_not_mine_round = [] # 标雷,且非雷 + flag_is_mine_round = [] # 标雷,且是雷 + for ii in range(max(0, i-1), min(self.row, i+2)): + for jj in range(max(0, j-1), min(self.column, j+2)): if (ii, jj) != (i, j): if self.label.ms_board.game_board[ii][jj] == 10: if self.label.ms_board.board[ii][jj] == -1: @@ -317,7 +328,7 @@ def chording_ai(self, i, j): else: flag_not_mine_round.append((ii, jj)) if len(flag_is_mine_round) + len(flag_not_mine_round) !=\ - self.label.ms_board.board[i][j]: + self.label.ms_board.board[i][j]: # 不满足双击条件 return board = self.label.ms_board.board.into_vec_vec() @@ -330,7 +341,8 @@ def chording_ai(self, i, j): elif self.gameMode == 7: must_guess = True for (x, y) in is_mine_round + not_mine_round: - code = ms.is_guess_while_needless(self.label.ms_board.game_board, (x, y)) + code = ms.is_guess_while_needless( + self.label.ms_board.game_board, (x, y)) if code == 3: must_guess = False break @@ -346,7 +358,8 @@ def chording_ai(self, i, j): elif self.gameMode == 8: must_guess = True for (x, y) in is_mine_round + not_mine_round: - code = ms.is_guess_while_needless(self.label.ms_board.game_board, (x, y)) + code = ms.is_guess_while_needless( + self.label.ms_board.game_board, (x, y)) if code == 3: must_guess = False break @@ -360,11 +373,10 @@ def chording_ai(self, i, j): self.label.ms_board.game_board, not_mine_round + is_mine_round) self.label.ms_board.board = board - def mineAreaLeftPressed(self, i, j): if self.game_state == 'ready' or self.game_state == 'playing' or\ - self.game_state == 'joking': + self.game_state == 'joking': self.label.ms_board.step('lc', (i, j)) self.label.update() @@ -372,7 +384,8 @@ def mineAreaLeftPressed(self, i, j): elif self.game_state == 'show': # 看概率时,所有操作都移出局面外 - self.label.ms_board.step('lc', (self.row * self.pixSize, self.column * self.pixSize)) + self.label.ms_board.step( + 'lc', (self.row * self.pixSize, self.column * self.pixSize)) self.set_face(15) def mineAreaLeftRelease(self, i, j): @@ -381,10 +394,10 @@ def mineAreaLeftRelease(self, i, j): self.label.ms_board.step('lr', (i, j)) else: if self.label.ms_board.mouse_state == 4 and\ - self.label.ms_board.game_board[i// self.pixSize][j// self.pixSize] == 10: + self.label.ms_board.game_board[i // self.pixSize][j // self.pixSize] == 10: # 正式埋雷开始 self.layMine(i // self.pixSize, j // self.pixSize) - + if self.board_constraint: self.game_state = 'joking' else: @@ -398,14 +411,13 @@ def mineAreaLeftRelease(self, i, j): if self.cursor_limit: self.limit_cursor() - # 核实用的时间,防变速齿轮 self.start_time_unix_2 = QtCore.QDateTime.currentDateTime().\ - toMSecsSinceEpoch() + toMSecsSinceEpoch() self.timer_10ms.start() # 禁用双击修改指标名称公式 self.score_board_manager.editing_row = -2 - + self.label.ms_board.step('lr', (i, j)) if self.label.ms_board.game_board_state == 3: @@ -424,11 +436,11 @@ def mineAreaLeftRelease(self, i, j): elif self.game_state == 'playing' or self.game_state == 'joking': # 如果是游戏中,且是左键抬起(不是双击),且是在10上,且在局面内,则用ai劫持、处理下 if self.pos_is_in_board(i, j): - if self.label.ms_board.game_board[i// self.pixSize][j// self.pixSize] == 10 \ - and self.label.ms_board.mouse_state == 4: + if self.label.ms_board.game_board[i // self.pixSize][j // self.pixSize] == 10 \ + and self.label.ms_board.mouse_state == 4: self.ai(i // self.pixSize, j // self.pixSize) - self.chording_ai(i// self.pixSize, j// self.pixSize) - + self.chording_ai(i // self.pixSize, j // self.pixSize) + self.label.ms_board.step('lr', (i, j)) if self.label.ms_board.game_board_state == 3: @@ -444,7 +456,8 @@ def mineAreaLeftRelease(self, i, j): elif self.game_state == 'show': # 看概率时,所有操作都移出局面外 - self.label.ms_board.step('lr', (self.row * self.pixSize, self.column * self.pixSize)) + self.label.ms_board.step( + 'lr', (self.row * self.pixSize, self.column * self.pixSize)) self.set_face(14) def mineAreaRightPressed(self, i, j): @@ -454,11 +467,11 @@ def mineAreaRightPressed(self, i, j): # 假如按下左键,再切屏(比如快捷键截图),再左键抬起,再切回来,再右键按下, # 就会导致DownUp状态下右键按下。此时不应该标雷,左上角雷数也应该不变 if self.label.ms_board.game_board[i//self.pixSize][j//self.pixSize] == 11 and\ - self.label.ms_board.mouse_state == 1: + self.label.ms_board.mouse_state == 1: self.mineUnFlagedNum += 1 self.showMineNum(self.mineUnFlagedNum) elif self.label.ms_board.game_board[i//self.pixSize][j//self.pixSize] == 10 and\ - self.label.ms_board.mouse_state == 1: + self.label.ms_board.mouse_state == 1: self.mineUnFlagedNum -= 1 self.showMineNum(self.mineUnFlagedNum) self.label.ms_board.step('rc', (i, j)) @@ -467,24 +480,24 @@ def mineAreaRightPressed(self, i, j): def mineAreaRightRelease(self, i, j): if self.game_state == 'ready' or self.game_state == 'playing' or self.game_state == 'joking': - self.chording_ai(i// self.pixSize, j// self.pixSize) + self.chording_ai(i // self.pixSize, j // self.pixSize) self.label.ms_board.step('rr', (i, j)) self.label.update() self.set_face(14) elif self.game_state == 'show': # 看概率时,所有操作都移出局面外 - self.label.ms_board.step('rr', (self.row * self.pixSize, self.column * self.pixSize)) + self.label.ms_board.step( + 'rr', (self.row * self.pixSize, self.column * self.pixSize)) self.set_face(14) def mineAreaLeftAndRightPressed(self, i, j): if self.game_state == 'ready' or self.game_state == 'playing' or\ - self.game_state == 'joking': + self.game_state == 'joking': self.label.ms_board.step('cc', (i, j)) self.label.update() self.set_face(15) - def mineMouseMove(self, i, j): # 正常情况的鼠标移动事件,与高亮的显示有关 if self.game_state == 'playing' or self.game_state == 'joking' or self.game_state == 'ready': @@ -495,23 +508,24 @@ def mineMouseMove(self, i, j): if not self.pos_is_in_board(i, j): self.label_info.setText('(是雷的概率)') else: - text4 = '{:.3f}'.format(max(0, self.label.boardPossibility[i//self.pixSize][j//self.pixSize])) + text4 = '{:.3f}'.format( + max(0, self.label.boardPossibility[i//self.pixSize][j//self.pixSize])) self.label_info.setText(text4) # 播放录像时的鼠标移动事件 elif self.game_state == 'showdisplay': if not self.pos_is_in_board(i, j): self.label_info.setText('(是雷的概率)') else: - text4 = '{:.3f}'.format(max(0, self.label.ms_board.game_board_poss[i//self.pixSize][j//self.pixSize])) + text4 = '{:.3f}'.format( + max(0, self.label.ms_board.game_board_poss[i//self.pixSize][j//self.pixSize])) self.label_info.setText(text4) - def resizeWheel(self, i, x, y): # 按住ctrl滚轮,调整局面大小 # study状态下,滚轮修改局面 # 函数名要改了 if QApplication.keyboardModifiers() == Qt.ControlModifier and\ - self.game_state == 'ready' and self.label.ms_board.game_board_state == 1: + self.game_state == 'ready' and self.label.ms_board.game_board_state == 1: # 调整局面大小需要满足:ui端是ready且状态机是ready if i > 0: self.pixSize += 1 @@ -575,8 +589,10 @@ def gameStart(self): self.label.set_rcp(self.row, self.column, self.pixSize) self.game_state = 'ready' self.label.reloadCellPic(self.pixSize) - self.label.setMinimumSize(QtCore.QSize(self.pixSize*self.column + 8, self.pixSize*self.row + 8)) - self.label.setMaximumSize(QtCore.QSize(self.pixSize*self.column + 8, self.pixSize*self.row + 8)) + self.label.setMinimumSize(QtCore.QSize( + self.pixSize*self.column + 8, self.pixSize*self.row + 8)) + self.label.setMaximumSize(QtCore.QSize( + self.pixSize*self.column + 8, self.pixSize*self.row + 8)) # self.label.setMinimumSize(QtCore.QSize(8, 8)) self.label_2.reloadFace(self.pixSize) @@ -585,21 +601,23 @@ def gameStart(self): self.minimumWindow() # 点击脸时调用,或尺寸不变时重开 - def gameRestart(self, e = None): # 画界面,但是不埋雷,改数据而不是重新生成label + def gameRestart(self, e=None): # 画界面,但是不埋雷,改数据而不是重新生成label if e: - # 点脸周围时,会传入一个e参数 + # 点脸周围时,会传入一个e参数 if not (self.MinenumTimeWigdet.width() >= e.localPos().x() >= 0 and 0 <= e.localPos().y() <= self.MinenumTimeWigdet.height()): return # 此时self.label.ms_board是mm.abstract_game_board的实例 if self.game_state == 'display' or self.game_state == 'showdisplay': # self.timer_video.stop() # self.ui_video_control.QWidget.close() - self.label.ms_board = ms.BaseVideo([[0] * self.column for _ in range(self.row)], self.pixSize) + self.label.ms_board = ms.BaseVideo( + [[0] * self.column for _ in range(self.row)], self.pixSize) self.label.ms_board.mode = self.gameMode elif self.game_state == 'study': # self.num_bar_ui.QWidget.close() self.score_board_manager.visible() - self.label.ms_board = ms.BaseVideo([[0] * self.column for _ in range(self.row)], self.pixSize) + self.label.ms_board = ms.BaseVideo( + [[0] * self.column for _ in range(self.row)], self.pixSize) self.label.ms_board.mode = self.gameMode self.label_info.setText(self.player_identifier) self.game_state = 'ready' @@ -620,8 +638,8 @@ def gameRestart(self, e = None): # 画界面,但是不埋雷,改数据而 # self.label.paint_cursor = False # self.label.setMouseTracking(False) # 鼠标未按下时,组织移动事件回调 - # 游戏结束画残局,改状态 + def gameFinished(self): if self.label.ms_board.game_board_state == 3 and self.end_then_flag: self.label.ms_board.win_then_flag_all_mine() @@ -634,12 +652,11 @@ def gameFinished(self): self.score_board_manager.with_namespace({ "is_official": self.is_official(), "is_fair": self.is_fair() - }) - self.score_board_manager.show(self.label.ms_board, index_type = 2) + }) + self.score_board_manager.show(self.label.ms_board, index_type=2) self.enable_screenshot() self.unlimit_cursor() - def gameWin(self): # 成功后改脸和状态变量,停时间 self.timer_10ms.stop() self.score_board_manager.editing_row = -1 @@ -656,10 +673,8 @@ def gameWin(self): # 成功后改脸和状态变量,停时间 self.dump_evf_file_data() self.save_evf_file() - self.gameFinished() - # 尝试弹窗,没有破纪录则不弹 if self.auto_notification and self.is_fair(): self.try_record_pop() @@ -671,28 +686,31 @@ def checksum_module_ok(self): return hashlib.sha256(bytes(metaminesweeper_checksum.get_self_key())).hexdigest() ==\ '590028493bb58a25ffc76e2e2ad490df839a1f449435c35789d3119ca69e5d4f' - # 搜集数据,生成evf文件的二进制数据,但是不保存 + def dump_evf_file_data(self): if isinstance(self.label.ms_board, ms.BaseVideo): - self.label.ms_board.use_question = False # 禁用问号是共识 + self.label.ms_board.use_question = False # 禁用问号是共识 self.label.ms_board.use_cursor_pos_lim = self.cursor_limit self.label.ms_board.use_auto_replay = self.auto_replay > 0 - + self.label.ms_board.is_fair = self.is_fair() self.label.ms_board.is_official = self.is_official() - + self.label.ms_board.software = superGUI.version self.label.ms_board.mode = self.gameMode self.label.ms_board.player_identifier = self.player_identifier self.label.ms_board.race_identifier = self.race_identifier self.label.ms_board.uniqueness_identifier = self.unique_identifier - self.label.ms_board.country = "XX" if not self.country else country_name[self.country].upper() - self.label.ms_board.device_uuid = hashlib.md5(bytes(str(uuid.getnode()).encode())).hexdigest().encode( "UTF-8" ) - + self.label.ms_board.country = "XX" if not self.country else country_name[self.country].upper( + ) + self.label.ms_board.device_uuid = hashlib.md5( + bytes(str(uuid.getnode()).encode())).hexdigest().encode("UTF-8") + self.label.ms_board.generate_evf_v4_raw_data() # 补上校验值 - checksum = self.checksum_guard.get_checksum(self.label.ms_board.raw_data[:-1]) + checksum = self.checksum_guard.get_checksum( + self.label.ms_board.raw_data[:-1]) self.label.ms_board.checksum_evf_v4 = checksum return elif isinstance(self.label.ms_board, ms.EvfVideo): @@ -707,10 +725,10 @@ def dump_evf_file_data(self): self.label.ms_board.generate_evf_v4_raw_data() return - # 将evf数据存成evf文件 # 调试的时候不会自动存录像,见checksum_module_ok # 菜单保存的回调。以及游戏结束自动保存。 + def save_evf_file(self): if not os.path.exists(self.replay_path): os.mkdir(self.replay_path) @@ -726,12 +744,12 @@ def save_evf_file(self): if self.game_state == "display" or self.game_state == "showdisplay": self.label.ms_board.current_time = 999999.9 file_name = self.replay_path + '\\' + filename_level +\ - f'{self.label.ms_board.mode}' + '_' +\ - f'{self.label.ms_board.rtime:.3f}' +\ - '_' + f'{self.label.ms_board.bbbv}' +\ - '_' + f'{self.label.ms_board.bbbv_s:.3f}' +\ - '_' + self.label.ms_board.player_identifier - + f'{self.label.ms_board.mode}' + '_' +\ + f'{self.label.ms_board.rtime:.3f}' +\ + '_' + f'{self.label.ms_board.bbbv}' +\ + '_' + f'{self.label.ms_board.bbbv_s:.3f}' +\ + '_' + self.label.ms_board.player_identifier + if not self.label.ms_board.is_completed: file_name += "_fail" if not self.label.ms_board.is_fair: @@ -740,11 +758,10 @@ def save_evf_file(self): file_name += "_trans" elif not self.checksum_module_ok(): file_name += "_fake" - - self.label.ms_board.save_to_evf_file(file_name) + self.label.ms_board.save_to_evf_file(file_name) - def gameFailed(self): # 失败后改脸和状态变量 + def gameFailed(self): # 失败后改脸和状态变量 self.timer_10ms.stop() self.score_board_manager.editing_row = -1 @@ -816,7 +833,6 @@ def try_record_pop(self): else: raise RuntimeError() - if b.rtime < self.record_setting.value(f"{record_key}/rtime", None, float): if b.rce == 0 and self.gameMode == 0: self.record_setting.set_value(f"{record_key}/rtime", b.rtime) @@ -824,7 +840,7 @@ def try_record_pop(self): else: self.record_setting.set_value(f"{record_key}/rtime", b.rtime) elif b.rce == 0 and self.gameMode == 0 and\ - b.rtime < self.record_setting.value(f"{LNF}/rtime", None, float): + b.rtime < self.record_setting.value(f"{LNF}/rtime", None, float): self.record_setting.set_value(f"{LNF}/rtime", b.rtime) nf_items.append(1) else: @@ -836,7 +852,7 @@ def try_record_pop(self): else: self.record_setting.set_value(f"{record_key}/bbbv_s", b.bbbv_s) elif b.rce == 0 and self.gameMode == 0 and\ - b.bbbv_s > self.record_setting.value(f"{LNF}/bbbv_s", None, float): + b.bbbv_s > self.record_setting.value(f"{LNF}/bbbv_s", None, float): self.record_setting.set_value(f"{LNF}/bbbv_s", b.bbbv_s) nf_items.append(3) else: @@ -848,7 +864,7 @@ def try_record_pop(self): else: self.record_setting.set_value(f"{record_key}/stnb", b.stnb) elif b.rce == 0 and self.gameMode == 0 and\ - b.stnb > self.record_setting.value(f"{LNF}/stnb", None, float): + b.stnb > self.record_setting.value(f"{LNF}/stnb", None, float): self.record_setting.set_value(f"{LNF}/stnb", b.stnb) nf_items.append(5) else: @@ -860,7 +876,7 @@ def try_record_pop(self): else: self.record_setting.set_value(f"{record_key}/ioe", b.ioe) elif b.rce == 0 and self.gameMode == 0 and\ - b.ioe > self.record_setting.value(f"{LNF}/ioe", None, float): + b.ioe > self.record_setting.value(f"{LNF}/ioe", None, float): self.record_setting.set_value(f"{LNF}/ioe", b.ioe) nf_items.append(7) else: @@ -872,7 +888,7 @@ def try_record_pop(self): else: self.record_setting.set_value(f"{record_key}/path", b.path) elif b.rce == 0 and self.gameMode == 0 and\ - b.path < self.record_setting.value(f"{LNF}/path", None, float): + b.path < self.record_setting.value(f"{LNF}/path", None, float): self.record_setting.set_value(f"{LNF}/path", b.path) nf_items.append(9) else: @@ -884,7 +900,7 @@ def try_record_pop(self): else: self.record_setting.set_value(f"{record_key}/rqp", b.rqp) elif b.rce == 0 and self.gameMode == 0 and\ - b.rqp < self.record_setting.value(f"{LNF}/rqp", None, float): + b.rqp < self.record_setting.value(f"{LNF}/rqp", None, float): self.record_setting.set_value(f"{LNF}/rqp", b.rqp) nf_items.append(11) else: @@ -894,13 +910,15 @@ def try_record_pop(self): if self.gameMode == 0: if b.level == 3: if b.rtime < self.record_setting.value(f"BEGINNER/{b.bbbv}", None, float): - self.record_setting.set_value(f"BEGINNER/{b.bbbv}", b.rtime) + self.record_setting.set_value( + f"BEGINNER/{b.bbbv}", b.rtime) del_items += [14, 15] else: del_items += [13, 14, 15] elif b.level == 4: if b.rtime < self.record_setting.value(f"INTERMEDIATE/{b.bbbv}", None, float): - self.record_setting.set_value(f"INTERMEDIATE/{b.bbbv}", b.rtime) + self.record_setting.set_value( + f"INTERMEDIATE/{b.bbbv}", b.rtime) del_items += [13, 15] else: del_items += [13, 14, 15] @@ -916,7 +934,8 @@ def try_record_pop(self): del_items += [13, 14, 15] if len(del_items) < 9: - ui = gameRecordPop.ui_Form(self.r_path, del_items, b.bbbv, nf_items, self.mainWindow) + ui = gameRecordPop.ui_Form( + self.r_path, del_items, b.bbbv, nf_items, self.mainWindow) ui.Dialog.setModal(True) ui.label_16.setText(mode_text) ui.Dialog.show() @@ -928,8 +947,8 @@ def showMineNum(self, n): self.mineNumShow = n if n >= 0 and n <= 999: self.label_11.setPixmap(self.pixmapLEDNum[n//100]) - self.label_12.setPixmap(self.pixmapLEDNum[n//10%10]) - self.label_13.setPixmap(self.pixmapLEDNum[n%10]) + self.label_12.setPixmap(self.pixmapLEDNum[n//10 % 10]) + self.label_13.setPixmap(self.pixmapLEDNum[n % 10]) elif n < 0: self.label_11.setPixmap(self.pixmapLEDNum[0]) self.label_12.setPixmap(self.pixmapLEDNum[0]) @@ -943,8 +962,8 @@ def showTime(self, t): # 显示剩余时间,时间数大于等于0,小于等于999秒,整数 if t >= 0 and t <= 999: self.label_31.setPixmap(self.pixmapLEDNum[t//100]) - self.label_32.setPixmap(self.pixmapLEDNum[t//10%10]) - self.label_33.setPixmap(self.pixmapLEDNum[t%10]) + self.label_32.setPixmap(self.pixmapLEDNum[t//10 % 10]) + self.label_33.setPixmap(self.pixmapLEDNum[t % 10]) return elif t >= 1000: return @@ -975,17 +994,18 @@ def predefined_Board(self, k): self.label.ms_board.reset(row, column, self.pixSize) else: # 解决播放录像时快捷键切换难度报错 - self.label.ms_board = ms.BaseVideo([[0] * column for _ in range(row)], self.pixSize) + self.label.ms_board = ms.BaseVideo( + [[0] * column for _ in range(row)], self.pixSize) self.gameMode = self.predefinedBoardPara[k]['gamemode'] self.score_board_manager.with_namespace({ "mode": self.gameMode, - }) + }) self.score_board_manager.show(self.label.ms_board, index_type=1) self.board_constraint = self.predefinedBoardPara[k]['board_constraint'] self.attempt_times_limit = self.predefinedBoardPara[k]['attempt_times_limit'] - # 菜单回放的回调 + def replay_game(self): if not isinstance(self.label.ms_board, ms.BaseVideo): return @@ -993,15 +1013,14 @@ def replay_game(self): return self.dump_evf_file_data() raw_data = bytes(self.label.ms_board.raw_data) - + video = ms.EvfVideo("virtual.evf", raw_data) self.play_video(video) - def action_CEvent(self): # 点击菜单栏的自定义后回调 self.actionChecked('C') - ui = gameDefinedParameter.ui_Form(self.r_path, self.row, self.column, + ui = gameDefinedParameter.ui_Form(self.r_path, self.row, self.column, self.mineNum, self.mainWindow) ui.Dialog.setModal(True) ui.Dialog.show() @@ -1051,7 +1070,6 @@ def setBoard_and_start(self, row, column, mineNum): else: self.gameRestart() - def action_NEvent(self): # 游戏设置 self.actionChecked('N') @@ -1060,7 +1078,7 @@ def action_NEvent(self): ui.Dialog.show() ui.Dialog.exec_() if ui.alter: - + self.pixSize = ui.pixSize self.gameStart() self.gameMode = ui.gameMode @@ -1100,11 +1118,11 @@ def action_NEvent(self): for child in self.mainWindow.findChildren(QWidget): # 设置子窗口的透明度 child.setWindowOpacity(ui.transparency / 100) - + self.score_board_manager.with_namespace({ "race_identifier": ui.race_identifier, "mode": self.gameMode, - }) + }) self.score_board_manager.show(self.label.ms_board, index_type=1) def action_QEvent(self): @@ -1125,7 +1143,6 @@ def action_mouse_setting(self): os.system("start rundll32.exe shell32.dll,Control_RunDLL main.cpl,,2") except: ... - def action_AEvent(self): # 关于 @@ -1137,11 +1154,17 @@ def action_AEvent(self): def auto_Update(self): data = { - "Github": "https://api.github.com/repos/", - "Gitee": "https://api.gitee.com/repos/", + "Github": { + "url": "https://api.github.com/repos/eee555/Metasweeper", + "t": "" + }, + "gitee": { + "url": "https://gitee.com/api/v5/repos/ee55/Metasweeper", + "t": "02d95b894b8a5ccb3731a9464b2a6f2b" + } } - update_dialog = CheckUpdateGui(GitHub(SourceManager(data), "eee555", - "Metasweeper", superGUI.version, "(\d+\.\d+\.\d+)"), parent = self) + update_dialog = CheckUpdateGui(GitHub(SourceManager( + data, "Github"), superGUI.version, "(\d+\.\d+\.\d+)"), parent=self) update_dialog.setModal(True) update_dialog.show() update_dialog.exec_() @@ -1154,8 +1177,7 @@ def screenShot(self): if self.game_state == "display" or self.game_state == "showdisplay": self.video_playing = False self.timer_video.stop() - - + self.enable_screenshot() ui = captureScreen.CaptureScreen() @@ -1167,7 +1189,8 @@ def screenShot(self): # 会报两种runtimeerror,标记阶段无解的局面、枚举阶段无解的局面 try: - ans = ms.cal_possibility_onboard(ui.board, 0.20625 if len(ui.board[0]) >= 24 else 0.15625) + ans = ms.cal_possibility_onboard( + ui.board, 0.20625 if len(ui.board[0]) >= 24 else 0.15625) except: return @@ -1175,7 +1198,6 @@ def screenShot(self): # 概率矩阵为空就是出错了 return - # 连续截屏时 # if self.game_state == 'study': # self.num_bar_ui.QWidget.close() @@ -1196,32 +1218,34 @@ def screenShot(self): self.row = len(ui.board) self.column = len(ui.board[0]) - self.num_bar_ui = mine_num_bar.ui_Form(ans[1], self.pixSize * self.row, self.mainWindow) + self.num_bar_ui = mine_num_bar.ui_Form( + ans[1], self.pixSize * self.row, self.mainWindow) self.num_bar_ui.QWidget.barSetMineNum.connect(self.showMineNum) - self.num_bar_ui.QWidget.barSetMineNumCalPoss.connect(self.render_poss_on_board) + self.num_bar_ui.QWidget.barSetMineNumCalPoss.connect( + self.render_poss_on_board) self.num_bar_ui.setSignal() # self.mainWindow.closeEvent_.connect(self.num_bar_ui.QWidget.close) self.timer_close_bar = QTimer() - self.timer_close_bar.timeout.connect(lambda:self.num_bar_ui.QWidget.show()) + self.timer_close_bar.timeout.connect( + lambda: self.num_bar_ui.QWidget.show()) self.timer_close_bar.setSingleShot(True) self.timer_close_bar.start(1) # self.num_bar_ui.QWidget.show() # self.setBoard_and_start(len(ui.board), len(ui.board[0]), ans[1][1]) self.setBoard(self.row, self.column, ans[1][1]) - + self.label.paintPossibility = True self.label.set_rcp(self.row, self.column, self.pixSize) - + self.label.ms_board.game_board = ui.board self.label.ms_board.mouse_state = 1 self.label.ms_board.game_board_state = 1 self.mineNumShow = ans[1][1] self.showMineNum(self.mineNumShow) self.label.boardPossibility = ans[0] - self.label.update() # self.label.setMouseTracking(True) @@ -1231,7 +1255,8 @@ def screenShot(self): def render_poss_on_board(self): # 雷数条拉动后、改局面后,显示雷数并展示 try: - ans = ms.cal_possibility_onboard(self.label.ms_board.game_board, self.mineNumShow) + ans = ms.cal_possibility_onboard( + self.label.ms_board.game_board, self.mineNumShow) except: try: ans = ms.cal_possibility_onboard(self.label.ms_board.game_board, @@ -1263,7 +1288,6 @@ def render_poss_on_board(self): self.showMineNum(self.mineNumShow) - def showScores(self): # 按空格 if self.game_state == 'win' or self.game_state == 'fail': @@ -1282,11 +1306,11 @@ def showScores(self): # 删去用户标的雷,因为可能标错 # game_board = list(map(lambda x: list(map(lambda y: min(y, 10), x)), # self.label.ms_board.game_board)) - ans = ms.cal_possibility_onboard(self.label.ms_board.game_board, mineNum) + ans = ms.cal_possibility_onboard( + self.label.ms_board.game_board, mineNum) self.label.boardPossibility = ans[0] self.label.update() - def mineKeyReleaseEvent(self, keyName): # 松开空格键 if keyName == 'Space': @@ -1318,10 +1342,11 @@ def refreshSettingsDefault(self): self.game_setting.sync() # 打开录像文件的回调 - def action_OpenFile(self, openfile_name = None): + def action_OpenFile(self, openfile_name=None): if not openfile_name: openfile_name = QFileDialog.\ - getOpenFileName(self.mainWindow, '打开文件','../replay','All(*.avf *.evf *.rmv *.mvf);;Arbiter video(*.avf);;Metasweeper video(*.evf);;Vienna MineSweeper video(*.rmv);;Minesweeper Clone 0.97(*.mvf)') + getOpenFileName(self.mainWindow, '打开文件', '../replay', + 'All(*.avf *.evf *.rmv *.mvf);;Arbiter video(*.avf);;Metasweeper video(*.evf);;Vienna MineSweeper video(*.rmv);;Minesweeper Clone 0.97(*.mvf)') openfile_name = openfile_name[0] # 实例化 if not openfile_name: @@ -1355,18 +1380,18 @@ def play_video(self, video): # 检查evf的checksum,其余录像没有鉴定能力 if isinstance(video, ms.EvfVideo): self.score_board_manager.with_namespace({ - "checksum_ok": self.checksum_guard.\ - valid_checksum(video.raw_data[:-33], video.checksum), - }) + "checksum_ok": self.checksum_guard. + valid_checksum(video.raw_data[:-33], video.checksum), + }) else: self.score_board_manager.with_namespace({ "checksum_ok": False, - }) + }) self.score_board_manager.with_namespace({ "is_official": video.is_official, "is_fair": video.is_fair, "mode": video.mode, - }) + }) video.analyse_for_features(["high_risk_guess", "jump_judge", "needless_guess", "mouse_trace", "vision_transfer", "survive_poss"]) @@ -1376,27 +1401,29 @@ def play_video(self, video): t = event.time comment = event.comments if comment: - comments.append((t, [i.split(': ') for i in comment.split(';')[:-1]])) + comments.append((t, [i.split(': ') + for i in comment.split(';')[:-1]])) # 调整窗口 if (video.row, video.column) != (self.row, self.column): self.setBoard(video.row, video.column, video.mine_num) self.label.paintPossibility = False self.label.set_rcp(self.row, self.column, self.pixSize) # self.label.reloadCellPic(self.pixSize) - self.label.setMinimumSize(QtCore.QSize(self.pixSize*self.column + 8, self.pixSize*self.row + 8)) - self.label.setMaximumSize(QtCore.QSize(self.pixSize*self.column + 8, self.pixSize*self.row + 8)) + self.label.setMinimumSize(QtCore.QSize( + self.pixSize*self.column + 8, self.pixSize*self.row + 8)) + self.label.setMaximumSize(QtCore.QSize( + self.pixSize*self.column + 8, self.pixSize*self.row + 8)) self.label_2.reloadFace(self.pixSize) self.minimumWindow() - - self.timer_video = QTimer() self.timer_video.timeout.connect(self.video_playing_step) - self.ui_video_control = videoControl.ui_Form(self.r_path, video, comments, + self.ui_video_control = videoControl.ui_Form(self.r_path, video, comments, self.game_setting, self.mainWindow) # self.mainWindow.closeEvent_.connect(self.ui_video_control.QWidget.close) self.ui_video_control.pushButton_play.clicked.connect(self.video_play) - self.ui_video_control.pushButton_replay.clicked.connect(self.video_replay) + self.ui_video_control.pushButton_replay.clicked.connect( + self.video_replay) self.ui_video_control.videoSetTime.connect(self.video_set_time) self.ui_video_control.label_speed.wEvent.connect(self.video_set_speed) for labels in self.ui_video_control.comments_labels: @@ -1405,11 +1432,11 @@ def play_video(self, video): labels[2].Release.connect(self.video_set_a_time) self.ui_video_control.QWidget.show() - self.video_time = video.video_start_time # 录像当前时间 - self.video_stop_time = video.video_end_time # 录像停止时间 - self.video_time_step = 0.01 # 录像时间的步长,定时器始终是10毫秒 + self.video_time = video.video_start_time # 录像当前时间 + self.video_stop_time = video.video_end_time # 录像停止时间 + self.video_time_step = 0.01 # 录像时间的步长,定时器始终是10毫秒 self.label.paint_cursor = True - self.video_playing = True # 录像正在播放 + self.video_playing = True # 录像正在播放 # 禁用双击修改指标名称公式 self.score_board_manager.editing_row = -2 @@ -1420,9 +1447,8 @@ def play_video(self, video): self.label_info.setText(self.label.ms_board.player_identifier) # 改成录像的国旗 self.set_country_flag(self.label.ms_board.country) - - self.timer_video.start(10) + self.timer_video.start(10) def video_playing_step(self): # 播放录像时定时器的回调 @@ -1431,14 +1457,16 @@ def video_playing_step(self): self.timer_video.stop() self.video_playing = False self.label.update() - self.score_board_manager.show(self.label.ms_board, index_type = 3) + self.score_board_manager.show(self.label.ms_board, index_type=3) self.video_time += self.video_time_step self.showTime(int(self.video_time)) self.ui_video_control.horizontalSlider_time.blockSignals(True) - self.ui_video_control.horizontalSlider_time.setValue(int(self.video_time * 1000)) + self.ui_video_control.horizontalSlider_time.setValue( + int(self.video_time * 1000)) self.ui_video_control.horizontalSlider_time.blockSignals(False) self.ui_video_control.doubleSpinBox_time.blockSignals(True) - self.ui_video_control.doubleSpinBox_time.setValue(self.label.ms_board.time) + self.ui_video_control.doubleSpinBox_time.setValue( + self.label.ms_board.time) self.ui_video_control.doubleSpinBox_time.blockSignals(False) def video_play(self): @@ -1465,7 +1493,7 @@ def video_set_time(self, t): self.video_time = t / 1000 self.label.ms_board.current_time = self.video_time self.label.update() - self.score_board_manager.show(self.label.ms_board, index_type = 3) + self.score_board_manager.show(self.label.ms_board, index_type=3) def video_set_a_time(self, t): # 把录像定位到某一段时间,默认前后一秒,自动播放。是点录像事件的回调 @@ -1499,7 +1527,7 @@ def set_face(self, face_type): pixmap = QPixmap(self.pixmapNum[face_type]) self.label_2.setPixmap(pixmap) self.label_2.setScaledContents(True) - + def hidden_score_board(self): # 按/隐藏计数器,再按显示 if self.game_state == 'study': @@ -1530,28 +1558,32 @@ class RECT(ctypes.Structure): ("right", ctypes.c_long), ("bottom", ctypes.c_long)] # 创建RECT实例 - r = RECT(rect.left() + 4, rect.top() + 4, + r = RECT(rect.left() + 4, rect.top() + 4, rect.right() - 4, rect.bottom() - 4) # 调用Windows API函数ClipCursor来限制光标 ctypes.windll.user32.ClipCursor(ctypes.byref(r)) - def closeEvent_(self): # 主窗口关闭的回调 self.unlimit_cursor() # self.score_board_manager.close() - self.game_setting.set_value("DEFAULT/mainWinTop", str(self.mainWindow.x())) - self.game_setting.set_value("DEFAULT/mainWinLeft", str(self.mainWindow.y())) + self.game_setting.set_value( + "DEFAULT/mainWinTop", str(self.mainWindow.x())) + self.game_setting.set_value( + "DEFAULT/mainWinLeft", str(self.mainWindow.y())) self.game_setting.set_value("DEFAULT/row", str(self.row)) self.game_setting.set_value("DEFAULT/column", str(self.column)) self.game_setting.set_value("DEFAULT/mineNum", str(self.mineNum)) - + if (self.row, self.column, self.mineNum) == (8, 8, 10): - self.game_setting.set_value("BEGINNER/gamemode", str(self.gameMode)) + self.game_setting.set_value( + "BEGINNER/gamemode", str(self.gameMode)) self.game_setting.set_value("BEGINNER/pixsize", str(self.pixSize)) elif (self.row, self.column, self.mineNum) == (16, 16, 40): - self.game_setting.set_value("INTERMEDIATE/gamemode", str(self.gameMode)) - self.game_setting.set_value("INTERMEDIATE/pixsize", str(self.pixSize)) + self.game_setting.set_value( + "INTERMEDIATE/gamemode", str(self.gameMode)) + self.game_setting.set_value( + "INTERMEDIATE/pixsize", str(self.pixSize)) elif (self.row, self.column, self.mineNum) == (16, 30, 99): self.game_setting.set_value("EXPERT/gamemode", str(self.gameMode)) self.game_setting.set_value("EXPERT/pixsize", str(self.pixSize)) @@ -1561,12 +1593,3 @@ def closeEvent_(self): self.game_setting.sync() self.record_setting.sync() - - - - - - - - -