Skip to content

Commit d838483

Browse files
committed
feat:evfs施工中
1 parent 5927306 commit d838483

File tree

6 files changed

+191
-144
lines changed

6 files changed

+191
-144
lines changed

src/gameSettings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ def processParameter(self):
145145
self.game_setting.set_value("DEFAULT/cursor_limit", self.cursor_limit)
146146
self.game_setting.set_value("DEFAULT/auto_notification", self.auto_notification)
147147
self.game_setting.set_value("DEFAULT/autosave_video", self.autosave_video)
148+
self.game_setting.set_value("DEFAULT/autosave_video_set", self.autosave_video_set)
148149
self.game_setting.set_value("DEFAULT/filter_forever", self.filter_forever)
149150
self.game_setting.set_value("DEFAULT/player_identifier", self.player_identifier)
150151
self.game_setting.set_value("DEFAULT/race_identifier", self.race_identifier)

src/mineSweeperGUI.py

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ def save_evf_file_integrated():
145145
self.last_mouse_state_video_playing_step = 1
146146
# evfs模块
147147
self.evfs = ms.Evfs()
148+
# 不带后缀、有绝对路径的、不含最后次数的文件名
149+
# C:/path/zhangsan_20251111_190114_
148150
self.old_evfs_filename = ""
149151

150152
@property
@@ -620,7 +622,7 @@ def dump_evf_file_data(self):
620622
# 补上校验值
621623
checksum = self.checksum_guard.get_checksum(
622624
self.label.ms_board.raw_data[:-1])
623-
self.label.ms_board.checksum_evf_v4 = checksum
625+
self.label.ms_board.checksum = checksum
624626
return
625627
elif isinstance(self.label.ms_board, ms.EvfVideo):
626628
return
@@ -641,6 +643,11 @@ def save_evf_file(self):
641643
if not os.path.exists(self.replay_path):
642644
os.mkdir(self.replay_path)
643645

646+
self.label.ms_board.save_to_evf_file(self.cal_evf_filename())
647+
648+
649+
# 拼接evf录像的文件名
650+
def cal_evf_filename(self) -> str:
644651
if (self.label.ms_board.row, self.label.ms_board.column, self.label.ms_board.mine_num) == (8, 8, 10):
645652
filename_level = "b_"
646653
elif (self.label.ms_board.row, self.label.ms_board.column, self.label.ms_board.mine_num) == (16, 16, 40):
@@ -666,21 +673,30 @@ def save_evf_file(self):
666673
file_name += "_trans"
667674
elif not self.checksum_module_ok():
668675
file_name += "_fake"
676+
return file_name
669677

670-
self.label.ms_board.save_to_evf_file(file_name)
678+
671679

672680
# 保存evfs文件。先保存后一个文件,再删除前一个文件。
673681
def save_evfs_file(self):
674-
now = datetime.now()
675-
date_str = now.strftime("%Y%m%d")
676-
file_name = self.replay_path + '\\' + self.label.ms_board.player_identifier +\
677-
"_" + date_str + "_" + str(self.evfs.len())
678-
self.evfs.save_evfs_file(file_name)
679-
try:
680-
os.remove(self.old_evfs_filename)
681-
except Exception as e:
682-
...
683-
self.old_evfs_filename = file_name
682+
# 文件名包含秒为单位的时间戳,理论上不会重复
683+
# 即使重复,会变为文件名+(2)
684+
if self.old_evfs_filename:
685+
file_name = self.old_evfs_filename + str(self.evfs.len())
686+
self.evfs.save_evfs_file(file_name)
687+
old_evfs_filename = self.old_evfs_filename + str(self.evfs.len() - 1) + ".evfs"
688+
if os.path.exists(old_evfs_filename):
689+
# 进一步确认是文件而不是目录
690+
if os.path.isfile(old_evfs_filename):
691+
os.remove(old_evfs_filename)
692+
else:
693+
now = datetime.now()
694+
date_str = now.strftime("_%Y%m%d_%H%M%S_")
695+
file_name = self.replay_path + '\\' +\
696+
self.label.ms_board.player_identifier + date_str
697+
self.evfs.save_evfs_file(file_name + "1")
698+
self.old_evfs_filename = file_name
699+
684700

685701
def gameFailed(self): # 失败后改脸和状态变量
686702
self.timer_10ms.stop()
@@ -865,16 +881,19 @@ def try_record_pop(self):
865881
# 当且仅当game_state发生变化,且旧状态为"playing"时调用(即使点一下就获胜也会经过"playing")
866882
# 加入evfs是空的,且当前游戏状态不是"win",则不追加
867883
def try_append_evfs(self, new_game_state):
884+
# 只有开启了自动保存evfs,才会保存。也要防止通过关闭这个选项,逃避自动记录重开
868885
if not self.autosave_video_set:
886+
self.evfs.clear()
869887
return
888+
# 从第一次扫开开始记录
870889
if new_game_state != "win" and self.evfs.is_empty():
871890
return
872891
# 存在以下断言
873892
# assert isinstance(self.label.ms_board, ms.BaseVideo)
874893
# assert self.label.ms_board.game_board_state in (2, 3, 4)
875894
if self.label.ms_board.game_board_state == 2:
876895
self.label.ms_board.step_game_state("replay")
877-
896+
# 生成当前局面的数据
878897
if not self.label.ms_board.raw_data:
879898
self.label.ms_board.use_question = False # 禁用问号是共识
880899
self.label.ms_board.use_cursor_pos_lim = self.cursor_limit
@@ -897,9 +916,24 @@ def try_append_evfs(self, new_game_state):
897916
# 补上校验值
898917
checksum = self.checksum_guard.get_checksum(
899918
self.label.ms_board.raw_data[:-1])
900-
self.label.ms_board.checksum_evf_v4 = checksum
901-
902-
...
919+
self.label.ms_board.checksum = checksum
920+
# 计算当前单元的校验码,并追加到evfs中
921+
# evfs的第一个单元的校验码,只考虑第一个录像
922+
# 此后每个单元,都考虑当前录像和最后一个单元的校验码
923+
if self.evfs.is_empty():
924+
# self.evfs[0].checksum
925+
checksum = self.checksum_guard.get_checksum(
926+
self.label.ms_board.raw_data)
927+
self.evfs.push(self.label.ms_board.raw_data,
928+
self.cal_evf_filename(), checksum)
929+
else:
930+
evfs_len = self.evfs.len()
931+
checksum = self.checksum_guard.get_checksum(
932+
self.label.ms_board.raw_data + self.evfs[evfs_len - 1].checksum)
933+
self.evfs.push(self.label.ms_board.raw_data,
934+
self.cal_evf_filename(), checksum)
935+
self.evfs.generate_evfs_v0_raw_data()
936+
self.save_evfs_file()
903937

904938

905939
def showMineNum(self, n):
@@ -1337,14 +1371,17 @@ def refreshSettingsDefault(self):
13371371
def is_official(self) -> bool:
13381372
# 局面开始时,判断一下局面是设置是否正式。
13391373
# 极端小的3BV依然是合法的,而网站是否认同不关软件的事。
1340-
if self.board_constraint:
1374+
if not self.is_fair():
13411375
return False
1342-
return self.game_state == "win" and self.gameMode == 0
1376+
# 检查获胜,且标准模式
1377+
return self.label.ms_board.game_board_state == 3 and self.gameMode == 0
13431378

13441379
def is_fair(self) -> bool:
13451380
if self.board_constraint:
13461381
return False
1347-
return self.game_state == "win" or self.game_state == "fail"
1382+
# 因为记录evfs是绑定game_state的setter方法的,所以假如勾选记录evfs,
1383+
# 此处就是"playing";反之,此处就是"win"或"fail",总之都是fair的
1384+
return self.game_state == "win" or self.game_state == "fail" or self.game_state == "playing"
13481385

13491386
def cell_is_in_board(self, i, j):
13501387
# 点在局面内,单位是格不是像素

src/mineSweeperVideoPlayer.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def action_OpenFile(self, openfile_name=None):
2626
return
2727
self.set_face(14)
2828

29+
video_set = None
2930
try:
3031
if openfile_name[-3:] == "avf":
3132
video = ms.AvfVideo(openfile_name)
@@ -35,21 +36,29 @@ def action_OpenFile(self, openfile_name=None):
3536
video = ms.EvfVideo(openfile_name)
3637
elif openfile_name[-3:] == "mvf":
3738
video = ms.MvfVideo(openfile_name)
38-
elif openfile_name[-3:] == "evfs":
39-
video = ms.Evfs(openfile_name)
39+
elif openfile_name[-4:] == "evfs":
40+
video_set = ms.Evfs(openfile_name)
41+
# 包含对每个evf的parse
42+
video_set.parse()
43+
video = video_set[0].evf_video
4044
else:
4145
return
4246
except:
4347
return
44-
self.play_video(video)
48+
self.play_video(video, video_set)
49+
4550

51+
# 录像播放控制器关闭时,播放新文件
4652
# 播放AvfVideo、RmvVideo、EvfVideo、MvfVideo或BaseVideo
47-
def play_video(self, video):
48-
if self.game_state == 'display':
49-
self.ui_video_control.QWidget.close()
50-
self.game_state = 'display'
53+
def play_video(self, video, video_set):
54+
# if self.game_state == 'display':
55+
# self.ui_video_control.QWidget.close()
56+
# self.game_state = 'display'
57+
if self.game_state != 'display':
58+
self.game_state = 'display'
5159

52-
video.parse_video()
60+
if not video_set:
61+
video.parse_video()
5362
video.analyse()
5463
# 检查evf的checksum,其余录像没有鉴定能力
5564
if isinstance(video, ms.EvfVideo):
@@ -96,7 +105,7 @@ def play_video(self, video):
96105

97106
self.timer_video = QTimer()
98107
self.timer_video.timeout.connect(self.video_playing_step)
99-
self.ui_video_control = videoControl.ui_Form(self.r_path, video, comments,
108+
self.ui_video_control = videoControl.ui_Form(self.r_path, video, video_set, comments,
100109
self.game_setting, self.mainWindow)
101110
# self.mainWindow.closeEvent_.connect(self.ui_video_control.QWidget.close)
102111
self.ui_video_control.pushButton_play.clicked.connect(self.video_play)

src/ui/ui_video_control.py

Lines changed: 51 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -165,20 +165,56 @@ def setupUi(self, Form):
165165
self.tabWidget.setMovable(True)
166166
self.tabWidget.setTabBarAutoHide(True)
167167
self.tabWidget.setObjectName("tabWidget")
168-
self.tab_3 = QtWidgets.QWidget()
169-
self.tab_3.setObjectName("tab_3")
170-
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.tab_3)
171-
self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
172-
self.verticalLayout_3.setSpacing(0)
173-
self.verticalLayout_3.setObjectName("verticalLayout_3")
174-
self.scrollArea = QtWidgets.QScrollArea(self.tab_3)
168+
self.tab_0 = QtWidgets.QWidget()
169+
self.tab_0.setObjectName("tab_0")
170+
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.tab_0)
171+
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
172+
self.verticalLayout_2.setSpacing(0)
173+
self.verticalLayout_2.setObjectName("verticalLayout_2")
174+
self.scrollArea_0 = QtWidgets.QScrollArea(self.tab_0)
175+
self.scrollArea_0.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
176+
self.scrollArea_0.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
177+
self.scrollArea_0.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
178+
self.scrollArea_0.setWidgetResizable(True)
179+
self.scrollArea_0.setObjectName("scrollArea_0")
180+
self.scrollAreaWidgetContents_0 = QtWidgets.QWidget()
181+
self.scrollAreaWidgetContents_0.setGeometry(QtCore.QRect(0, 0, 457, 459))
182+
self.scrollAreaWidgetContents_0.setMinimumSize(QtCore.QSize(0, 0))
183+
self.scrollAreaWidgetContents_0.setObjectName("scrollAreaWidgetContents_0")
184+
self.label_video = QtWidgets.QLabel(self.scrollAreaWidgetContents_0)
185+
self.label_video.setGeometry(QtCore.QRect(120, 0, 271, 42))
186+
font = QtGui.QFont()
187+
font.setFamily("微软雅黑")
188+
font.setPointSize(12)
189+
self.label_video.setFont(font)
190+
self.label_video.setAlignment(QtCore.Qt.AlignCenter)
191+
self.label_video.setObjectName("label_video")
192+
self.checkBox_choose = QtWidgets.QCheckBox(self.scrollAreaWidgetContents_0)
193+
self.checkBox_choose.setGeometry(QtCore.QRect(10, 0, 91, 42))
194+
font = QtGui.QFont()
195+
font.setFamily("微软雅黑")
196+
font.setPointSize(12)
197+
self.checkBox_choose.setFont(font)
198+
self.checkBox_choose.setObjectName("checkBox_choose")
199+
self.checkBox_choose.raise_()
200+
self.label_video.raise_()
201+
self.scrollArea_0.setWidget(self.scrollAreaWidgetContents_0)
202+
self.verticalLayout_2.addWidget(self.scrollArea_0)
203+
self.tabWidget.addTab(self.tab_0, "")
204+
self.tab = QtWidgets.QWidget()
205+
self.tab.setObjectName("tab")
206+
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.tab)
207+
self.verticalLayout_4.setContentsMargins(0, 0, 0, -1)
208+
self.verticalLayout_4.setSpacing(0)
209+
self.verticalLayout_4.setObjectName("verticalLayout_4")
210+
self.scrollArea = QtWidgets.QScrollArea(self.tab)
175211
self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
176212
self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
177213
self.scrollArea.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
178214
self.scrollArea.setWidgetResizable(True)
179215
self.scrollArea.setObjectName("scrollArea")
180216
self.scrollAreaWidgetContents = QtWidgets.QWidget()
181-
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 457, 459))
217+
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 457, 448))
182218
self.scrollAreaWidgetContents.setMinimumSize(QtCore.QSize(0, 0))
183219
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
184220
self.label_time = QtWidgets.QLabel(self.scrollAreaWidgetContents)
@@ -206,61 +242,24 @@ def setupUi(self, Form):
206242
self.label_event.setAlignment(QtCore.Qt.AlignCenter)
207243
self.label_event.setObjectName("label_event")
208244
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
209-
self.verticalLayout_3.addWidget(self.scrollArea)
210-
self.tabWidget.addTab(self.tab_3, "")
211-
self.tab_4 = QtWidgets.QWidget()
212-
self.tab_4.setObjectName("tab_4")
213-
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.tab_4)
214-
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
215-
self.verticalLayout_2.setSpacing(0)
216-
self.verticalLayout_2.setObjectName("verticalLayout_2")
217-
self.scrollArea_2 = QtWidgets.QScrollArea(self.tab_4)
218-
self.scrollArea_2.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
219-
self.scrollArea_2.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
220-
self.scrollArea_2.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
221-
self.scrollArea_2.setWidgetResizable(True)
222-
self.scrollArea_2.setObjectName("scrollArea_2")
223-
self.scrollAreaWidgetContents_2 = QtWidgets.QWidget()
224-
self.scrollAreaWidgetContents_2.setGeometry(QtCore.QRect(0, 0, 457, 459))
225-
self.scrollAreaWidgetContents_2.setMinimumSize(QtCore.QSize(0, 0))
226-
self.scrollAreaWidgetContents_2.setObjectName("scrollAreaWidgetContents_2")
227-
self.label_video = QtWidgets.QLabel(self.scrollAreaWidgetContents_2)
228-
self.label_video.setGeometry(QtCore.QRect(120, 0, 271, 42))
229-
font = QtGui.QFont()
230-
font.setFamily("微软雅黑")
231-
font.setPointSize(12)
232-
self.label_video.setFont(font)
233-
self.label_video.setAlignment(QtCore.Qt.AlignCenter)
234-
self.label_video.setObjectName("label_video")
235-
self.checkBox_choose = QtWidgets.QCheckBox(self.scrollAreaWidgetContents_2)
236-
self.checkBox_choose.setGeometry(QtCore.QRect(10, 0, 91, 42))
237-
font = QtGui.QFont()
238-
font.setFamily("微软雅黑")
239-
font.setPointSize(12)
240-
self.checkBox_choose.setFont(font)
241-
self.checkBox_choose.setObjectName("checkBox_choose")
242-
self.checkBox_choose.raise_()
243-
self.label_video.raise_()
244-
self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2)
245-
self.verticalLayout_2.addWidget(self.scrollArea_2)
246-
self.scrollArea_2.raise_()
247-
self.tabWidget.addTab(self.tab_4, "")
245+
self.verticalLayout_4.addWidget(self.scrollArea)
246+
self.tabWidget.addTab(self.tab, "")
248247
self.verticalLayout.addWidget(self.tabWidget)
249248

250249
self.retranslateUi(Form)
251-
self.tabWidget.setCurrentIndex(0)
250+
self.tabWidget.setCurrentIndex(1)
252251
QtCore.QMetaObject.connectSlotsByName(Form)
253252

254253
def retranslateUi(self, Form):
255254
_translate = QtCore.QCoreApplication.translate
256255
self.pushButton_replay.setToolTip(_translate("Form", "重播"))
257256
self.pushButton_play.setToolTip(_translate("Form", "播放/暂停"))
258257
self.label_speed.setToolTip(_translate("Form", "滑动滚轮修改播放速度"))
258+
self.label_video.setText(_translate("Form", "录像"))
259+
self.checkBox_choose.setText(_translate("Form", "选择"))
260+
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_0), _translate("Form", "目录"))
259261
self.label_time.setText(_translate("Form", "时间"))
260262
self.label_tag.setText(_translate("Form", "标签"))
261263
self.label_event.setText(_translate("Form", "事件"))
262-
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("Form", "录像"))
263-
self.label_video.setText(_translate("Form", "录像"))
264-
self.checkBox_choose.setText(_translate("Form", "选择"))
265-
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_4), _translate("Form", "Tab 2"))
264+
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("Form", "录像1"))
266265
from ui.uiComponents import SpeedLabel

src/videoControl.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class ui_Form(QWidget, Ui_Form):
1515
# barSetMineNumCalPoss = QtCore.pyqtSignal(int)
1616
# time_current = 0.0
1717

18-
def __init__(self, r_path, video, comments, game_setting, parent):
18+
def __init__(self, r_path, video, video_set, comments, game_setting, parent):
1919
super (ui_Form, self).__init__()
2020

2121
self.QWidget = RoundQWidget(parent)
@@ -45,9 +45,15 @@ def __init__(self, r_path, video, comments, game_setting, parent):
4545
self.comments_labels.append([c1, c2, c3])
4646
comment_row += 1
4747
self.scrollAreaWidgetContents.setFixedHeight(42 * (comment_row + 1))
48-
self.pushButton_replay.setStyleSheet("QPushButton{border-image: url(" + str(r_path.with_name('media').joinpath('replay.svg')).replace("\\", "/") + ");}")
49-
self.pushButton_play.setStyleSheet("QPushButton{border-image: url(" + str(r_path.with_name('media').joinpath('play.svg')).replace("\\", "/") + ");}")
50-
self.label_speed.setStyleSheet("QLabel{border-image: url(" + str(r_path.with_name('media').joinpath('speed.svg')).replace("\\", "/") + ");\n"
48+
self.pushButton_replay.setStyleSheet("QPushButton{border-image: url(" +\
49+
str(r_path.with_name('media').\
50+
joinpath('replay.svg')).replace("\\", "/") + ");}")
51+
self.pushButton_play.setStyleSheet("QPushButton{border-image: url(" +\
52+
str(r_path.with_name('media').\
53+
joinpath('play.svg')).replace("\\", "/") + ");}")
54+
self.label_speed.setStyleSheet("QLabel{border-image: url(" +\
55+
str(r_path.with_name('media').\
56+
joinpath('speed.svg')).replace("\\", "/") + ");\n"
5157
"font: 12pt \"微软雅黑\";\n"
5258
"color: #50A6EA;}")
5359
self.label_2.setStyleSheet("border-image: url(" + str(r_path.with_name('media').joinpath('mul.svg')).replace("\\", "/") + ");\n"

0 commit comments

Comments
 (0)