From cec7faf053f961b17f3c462873fd4dc09ba5dbb9 Mon Sep 17 00:00:00 2001
From: codeboss <2422523675@qq.com>
Date: Mon, 29 Jul 2024 21:25:38 +0800
Subject: [PATCH] diff-view
---
.idea/workspace.xml | 69 ++++---
frame/CompareViews.py | 195 ++++++++++++++++++
frame/CompareWindow.py | 56 -----
frame/MergeView.py | 1 +
.../__pycache__/CompareWindow.cpython-312.pyc | Bin 3042 -> 0 bytes
frame/__pycache__/MergeView.cpython-312.pyc | Bin 0 -> 4234 bytes
manage/__pycache__/MileStone.cpython-312.pyc | Bin 0 -> 903 bytes
manage/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 145 bytes
parse/StoryMap.py | 6 +-
parse/StorylineCmp.py | 90 ++++++--
parse/__pycache__/StoryMap.cpython-312.pyc | Bin 7756 -> 7969 bytes
.../__pycache__/StorylineCmp.cpython-312.pyc | Bin 0 -> 6558 bytes
12 files changed, 314 insertions(+), 103 deletions(-)
create mode 100644 frame/CompareViews.py
delete mode 100644 frame/CompareWindow.py
delete mode 100644 frame/__pycache__/CompareWindow.cpython-312.pyc
create mode 100644 frame/__pycache__/MergeView.cpython-312.pyc
create mode 100644 manage/__pycache__/MileStone.cpython-312.pyc
create mode 100644 manage/__pycache__/__init__.cpython-312.pyc
create mode 100644 parse/__pycache__/StorylineCmp.cpython-312.pyc
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 13f6fbb..a316b03 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -5,7 +5,12 @@
-
+
+
+
+
+
+
@@ -35,6 +40,7 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -94,28 +122,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -161,19 +167,19 @@
+
-
+
-
@@ -199,9 +205,14 @@
- file://$PROJECT_DIR$/manage/NovelManage.py
- 4
-
+ file://$PROJECT_DIR$/frame/CompareViews.py
+ 167
+
+
+
+ file://$PROJECT_DIR$/frame/CompareViews.py
+ 164
+
diff --git a/frame/CompareViews.py b/frame/CompareViews.py
new file mode 100644
index 0000000..9006bf6
--- /dev/null
+++ b/frame/CompareViews.py
@@ -0,0 +1,195 @@
+from PyQt5.QtWidgets import QWidget, QVBoxLayout, QTableView, QSplitter, QApplication, QMainWindow
+from PyQt5.QtGui import QStandardItemModel, QStandardItem
+from typing import List, Dict, Tuple
+from manage.MileStone import base_store_path, current_store_path
+from parse.StorylineCmp import ModifyReason, CmpTool
+from parse.StoryMap import FragmentSlice, StoryMap, XAST_ParseTool, storyline_list2map
+import sys
+from PyQt5.QtCore import pyqtSignal, pyqtSlot, QModelIndex
+from frame.MergeView import LinesMergeView,MergeDestination
+
+
+class ResultList(QTableView):
+ def __init__(self, parent):
+ QTableView.__init__(self, parent)
+ self.model = QStandardItemModel(self)
+ self.model.setHorizontalHeaderLabels(["故事名称", "情节名称", "状态"])
+ self.setModel(self.model)
+ self.setSelectionMode(QTableView.SelectionMode.SingleSelection)
+ self.setSelectionBehavior(QTableView.SelectionBehavior.SelectRows)
+ pass
+
+ def present_affected_fragments(self,graph_new: Dict[str, StoryMap], cmp_result: Dict[ModifyReason, List[FragmentSlice]]):
+ """
+ 展示影响节点
+ :return:
+ """
+ old_remove = cmp_result[ModifyReason.Removed]
+ affected_list = []
+ for node in old_remove:
+ affected_list = affected_list + self.__find_remove_affected_slice_within_new(graph_new, node)
+ pass
+
+ fragm_items = self.__filter_and_related_defines_seek(affected_list)
+ self.__append_fragments_list(fragm_items, "REMOVE")
+
+ curr_append = cmp_result[ModifyReason.Append]
+ affected_list = self.__find_append_and_changed_affected_slice(curr_append)
+ fragm_items = self.__filter_and_related_defines_seek(affected_list)
+ self.__append_fragments_list(fragm_items, "APPEND")
+
+ curr_changed = cmp_result[ModifyReason.Changed]
+ affected_list = self.__find_append_and_changed_affected_slice(curr_changed)
+ fragm_items = self.__filter_and_related_defines_seek(affected_list)
+ self.__append_fragments_list(fragm_items, "UPDATE")
+
+ pass
+
+ def __find_remove_affected_slice_within_new(self, graph_new: Dict[str, StoryMap], peers_old: FragmentSlice) -> List[FragmentSlice]:
+ """
+ 获取受到移除节点直接影响的节点
+ :param graph_new: 新图
+ :param peers_old: 旧图节点
+ :return:
+ """
+ retvs = []
+ story_name = peers_old.parent_story
+
+ # 移除了情节定义
+ if peers_old.is_define_node[0]:
+ refer_list = peers_old.refers_slice
+
+ for refer_slice_prev in refer_list.values():
+ retvs = retvs + self.__find_remove_affect_within_new(graph_new, refer_slice_prev)
+ pass
+
+ story_curr = graph_new[story_name]
+ # 新图内故事线存在,非最后一个节点,计算影响
+ if story_curr is not None and peers_old.next_node is not None:
+ o_frag_def = peers_old.next_node
+ frag_curr_def = story_curr.get_fragment_defined(o_frag_def.is_define_node[1])
+ if frag_curr_def is not None:
+ retvs.append(frag_curr_def)
+ pass
+ pass
+ else:
+ refer_story_new = graph_new[story_name]
+ slice_affected = peers_old.next_node
+
+ # 非最后一个,需要计算影响,新图中的故事线存在,计算影响
+ if slice_affected is not None and refer_story_new is not None:
+ v_s_name = slice_affected.story_refer
+ v_f_name = slice_affected.fragm_refer
+
+ # 获取收到影响的情节片段
+ slice_refer_now = CmpTool.__locate_fragment_refer__(refer_story_new.slice_list[0], v_s_name, v_f_name)
+ if slice_refer_now is not None:
+ retvs.append(slice_refer_now)
+ pass
+ pass
+
+ return retvs
+
+ def __find_append_and_changed_affected_slice(self, peers_new: List[FragmentSlice]) -> List[FragmentSlice]:
+ retvs = []
+
+ for curr_node in peers_new:
+ next_slice = curr_node.next_node
+ if next_slice is not None:
+ retvs.append(next_slice)
+
+ return retvs
+
+ def __filter_and_related_defines_seek(self, affect_directed: List[FragmentSlice])-> List[Tuple[str, str]]:
+ story_fragment_names: Dict[str, Tuple[str, str]] = {}
+ for node in affect_directed:
+ # 情节定义节点
+ if node.is_define_node[0]:
+ fragm_key = f"{node.parent_story}#{node.is_define_node[1]}"
+ story_fragment_names[fragm_key] = (node.parent_story, node.is_define_node[1])
+
+ # 情节引用节点
+ else:
+ fragm_key = f"{node.story_refer}#{node.fragm_refer}"
+ story_fragment_names[fragm_key] = (node.story_refer, node.fragm_refer)
+ pass
+ pass
+
+ return list(story_fragment_names.values())
+
+ def __append_fragments_list(self, fragment_keys: List[Tuple[str, str]], type: str) -> None:
+ for key_def in fragment_keys:
+ row = []
+ row.append(QStandardItem(key_def[0]))
+ row.append(QStandardItem(key_def[1]))
+ row.append(QStandardItem(type))
+ for cell in row: cell.setEditable(False)
+ self.model.appendRow(row)
+ pass
+ pass
+
+ pass
+
+
+class CompareWindow(QWidget):
+ def __init__(self, graph_new: Dict[str, StoryMap], cmp_result: Dict[ModifyReason, List[FragmentSlice]], parent):
+ QWidget.__init__(self, parent)
+
+ self.graph_new_refer = graph_new
+
+ layout = QVBoxLayout(self)
+ self.splitter = QSplitter(self)
+ layout.addWidget(self.splitter)
+
+ self.result_list = ResultList(self)
+ self.splitter.addWidget(self.result_list)
+ self.splitter.addWidget(QWidget(self))
+
+ self.result_list.present_affected_fragments(graph_new, cmp_result)
+
+ self.result_list.clicked.connect(self.present_fragment_merge_content)
+ pass
+
+ def present_fragment_merge_content(self, index: QModelIndex):
+ if not index.isValid():
+ return
+
+ story_name = self.result_list.model.item(index.row(), 0).text()
+ fragm_name = self.result_list.model.item(index.row(), 1).text()
+ story_node = self.graph_new_refer[story_name]
+ fragm_node = story_node.get_fragment_defined(fragm_name)
+
+ main_point = MergeDestination(story_name, fragm_node.prev_node, fragm_node)
+ elist = []
+ for refstory in fragm_node.refers_slice.keys():
+ refslice = fragm_node.refers_slice[refstory]
+ elist.append(MergeDestination(refstory, refslice.prev_node, refslice))
+
+ new_view = LinesMergeView(main_point, elist, self)
+ new_view.load_from_mem()
+ self.splitter.replaceWidget(1, new_view)
+ pass
+
+ pass
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+ win = QMainWindow()
+
+ ast_old = XAST_ParseTool(base_store_path)
+ ast_new = XAST_ParseTool(current_store_path)
+ map_old = storyline_list2map(ast_old.story_list)
+ map_new = storyline_list2map(ast_new.story_list)
+
+ ast_old.storylines_plait(map_old)
+ ast_new.storylines_plait(map_new)
+
+ cmp_tool = CmpTool()
+ all_changed = cmp_tool.graph_compare(map_new, map_old)
+
+ view = CompareWindow(map_new, all_changed, win)
+ win.setCentralWidget(view)
+ win.show()
+
+ app.exec()
\ No newline at end of file
diff --git a/frame/CompareWindow.py b/frame/CompareWindow.py
deleted file mode 100644
index 8b3f761..0000000
--- a/frame/CompareWindow.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from PyQt5.QtWidgets import QWidget, QTreeView, QVBoxLayout
-from PyQt5.QtGui import QStandardItemModel, QStandardItem
-from typing import List
-from parse.ast_load import StoryLine, FragmentSlice, items_map
-
-
-class CompareWin(QWidget):
- def __init__(self):
- QWidget.__init__(self)
- self.setWindowTitle("故事线比较")
-
- self.__compare_model = QStandardItemModel(self)
- self.__compare_view = QTreeView(self)
- self.__compare_model.setHorizontalHeaderLabels(["节点名称", "比对参数"])
- self.__compare_view.setModel(self.__compare_model)
-
- layout = QVBoxLayout(self)
- layout.addWidget(self.__compare_view)
- pass
-
- def load_differents(self, changed: List[str], base_list: List[StoryLine], other_list: List[StoryLine]):
- base_map = items_map(base_list)
- other_map = items_map(other_list)
-
- for changed_item in changed:
- item = QStandardItem(changed_item)
- item2 = QStandardItem()
- item.setEditable(False)
- item2.setEditable(False)
- self.__compare_model.appendRow([item, item2])
-
- if changed_item in other_map:
- story_origin = other_map[changed_item]
- item_o = QStandardItem(story_origin.signature)
- if not changed_item in base_map:
- item2.setText("append")
- else:
- item2.setText("modify")
- item_o2 = QStandardItem(story_origin.file_path)
- item_o.setEditable(False)
- item_o2.setEditable(False)
- item.appendRow([item_o, item_o2])
- pass
- else:
- if changed_item in base_map:
- story_modif = base_map[changed_item]
- item_ext = QStandardItem(story_modif.signature)
- item2.setText("remove")
- item_ext2 = QStandardItem(story_modif.file_path)
- item_ext.setEditable(False)
- item_ext2.setEditable(False)
- item.appendRow([item_ext, item_ext2])
- pass
- pass
- pass
- pass
diff --git a/frame/MergeView.py b/frame/MergeView.py
index bd2f648..0b0613f 100644
--- a/frame/MergeView.py
+++ b/frame/MergeView.py
@@ -21,6 +21,7 @@ class LinesMergeView(QWidget, MemorySkin):
self.refers_line = refdefs
layout = QVBoxLayout(self)
+ layout.setContentsMargins(0, 0, 0, 0)
splitter = QSplitter(Qt.Orientation.Vertical, self)
layout.addWidget(splitter)
diff --git a/frame/__pycache__/CompareWindow.cpython-312.pyc b/frame/__pycache__/CompareWindow.cpython-312.pyc
deleted file mode 100644
index 8d1017109f69e54c3f9d72ba508b008b810484b3..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 3042
zcmahLOKcm*b(UN%hvbr?qD^E;w53XRB-)m08;xVdu>x3f;-Io(#Y)_=YPM_bNLrTU
zs=F)MbXP#(I)IQk2#qw5fL_>BS@;ki;~bhC0|WuIAcJKGDr}(sBtQ;Am0WVl%uq{8
zwh|4nGjHE}^X9!b?=xRSqhUZs@3$XJe+dEjAN}!0U=!GQivY_&1uB;TSuVw8eJNko
zpYn4Q=gaWfKq`x6&PGy^te6rx-~+D!HEWp+8AK4vt^c)EQ*q(D;Ob(3={%j3eW3p4P97DtUe0O8W3q;}wT(!#^;^EbQ7QCN;f}=BUbEiMnjU-;_YeZxX9UD`e_f}Sc$A1
zPHo7_gCsvTPt||;;oJ8=dH2yLpFaHPZ(slWuk&=<*Y8|=bnVWA!h4VYd7B{!?ZHQP
z9=w0;;fJ@A5rbY5hO(^XG)tCo%tRKsOI5!-p;;MZP_N;3xpB*~JXO1KIZH#*pl-))
zJ2EWLsBR+y&+3MDRnJ*U<}6ZFWQ;18P{zcNkXT$B^u}>WQPo;jkm%=4l$pjthGm0E
zW2UR?hhL4nFnQk4(`d>vC(q}tSv@z&0)Il+Gv?&9p=8lyLseqLz+B#-p1Io6Ko5Av
z(i<{wkm)aA4K}%Oj|2CtNENuR3Pl%oIIv?i(O-cB_dAc?-e2x~eu=NZ#M-{z690Fd
z!X1n+;lP9ok2~=A$Fa|2tIuDoz~9sbxNyG%_ZKJJ1B1?i!3uogesf}FqTJlQBvfI{
zJJM}C?6e)Oz<#oCgXjZraB5b`%^($rE-5CGGbGD#Shr@8!QiQSuoGtLJeF#7-kNH5
zJ#-iOMgrP?FLV|IHa7wa-0v>|uqaqm1{=0e=Lj~iw>GJZ&<^gFqBh)>1ElK-xha?|
z=}-gqAUkNoZAmEDfdydPumd(LOpBq0j&>-`3ca_tw$`l)+k(w6aK=+azvy-z`lr_Y
z#erP&Pw>>e$AN9<#-5Z{KR05BclAePSB~J0-U-{0t=`G~nb`=81)JaWkGMro@n`)L
z{Rx|S&ysC6i|L=UIc7(9wJ5eL$IdoK?bueELm)(=_y*zuDTRTtm$9JC&7qu%1yZ84
z={yz;l+_nd5*oBM7_@)j2q`{iRLxQ@kt#blv@UtM%JWXeDK=R
znW`9f#e^d!R^F(HJyo&U756&g-W604_cL0TBX+ssK}S4T8o7O-bgCi_-fQYu$vaJb
z)y}?B!s$F-5ZBtCE!uAHDW~^TxoxN*R9kzBSDe;gR;9M(b2rZw`@WJ6-SgmzbZD);
zwlrwyr+1k5ywfkV{MW_2j;n!=OhfBY6`%gRlr^}tgg|qdO>1kd4r9Zj@!_L5P
zxof2GYE??OQlBIBm7cChM900ZlyszI=|Dv~QkC{BkKG(Ao-JvsJtr#CAVH7=|0BlN
zPZ1BU4}nnBpiil>B%~cTN4gd1xM7)g(s>eFG8Sd|PxDHqMq!Q1piK(0f|}VRvoNI>sg%)#ed0T?ha7MFP?F_MSkrXqATlkzWS{{CMKCJ4Vb5AemB6NZeF1V>+kW)GRx{T#>L1t%SF@-7(s
YFKE3Bh8!^Top6+k7FxdtWMM*n1R|`gBLDyZ
diff --git a/frame/__pycache__/MergeView.cpython-312.pyc b/frame/__pycache__/MergeView.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..fd48e7e387f266b60fdf631fce0c87bb61499529
GIT binary patch
literal 4234
zcmb_fU2Gf25#A$@6;oED3GVlEO{hF
zD@6lzCG76a?#|54%ziWcOCaDQ(9)m$KJl8DkbmHZ-Q3m5_BDx+J47RzlqMNTl`;<1
zk#VZdjI7ETm+H#6Rkwuej_}jbtus`KPa($t_)o=W`22G$LERNtVg+d^D#qtMw8~#|?IgB^bYwWWTh$=Q8s~
zWv#mJ@(0OmM6%=yN!@_aF>TB?DqV|(exTkVjHr@EREH)pr{-X?=45iht;siJ)s=U_
zHQFW_pJU@pHm*bz<3ghFS7FXN#6RyTJKu)weU>sRz=>%^Fu6z%6d!f@&
zlYVI5j*cI{dXeW+Y}U}PUd$Ws=dxEXqxLhoTw1@H;Bbel;(}<*;rYBpW3gm5X~bg7
zoy`{?wwK^}5xpC_6|&jcyDHymv4_y%Rk=jFH>t7>%Onc+1BPg+Sj_UpVws$_kjA+Z
zi~V9Dp02Jqb%S%{%8~1R!h3Mugoq%Bu7t)Cy5-?aOm=u4
z<4bt{$I#y)M$ONunvY>ewG|*1Y^;!)B0uIdr6_pVY?;g?VC&c7g~243E4TT3EyAR$(>
zXu&Z~ey$O6-EI8PK2>n(eba1?~Kn2SWZw`SE(a-Y3(_>s09~_~<
z+M_e$Y%XiCtf5cF`CKxqb9{>&gT(Sr@g%HN0GwW7+<yqN_f
z1}ZQfp&apsqt*Ej#Gd&$hb7CM7D>;dx}6zikpX-{Kuqw*%ObX8t3V`rVfnyLh^k>V
zW(NHXg!~G5N?Xgc!=xQ+!L`K_J@l-*AJMvFvwJ{{&)a*}W{T|ttL{zOQl?>(hS$UE
z(;L#pScwij-P`lKOP^l5d#&7i#OyutP%G{|u}Z~G!Ly@82c8cOZy3eFBajjTo3yP=
zyG+`(cI4BOcTbjRLQsB7x+*>BSR^Q$r6oX(6-!!
z=Mpk$Xw4}1jhKBS<-TKP-?4Jvd9&|)v2UV8FFb4CS8g9L+XucO4v1Wc#K7&Tn^PsF
z7vs+bv@J@!mHK7(2>TQ0^_>xh_iSn@yXa}4LzMiVBdo#CwGyK)aCbj@DxMYS7yxI-
zj9jB%Ex(bwn2sm2A_#wrlI%5>DE
zqYr~$h8~5=V-x1sL~#tAx|_EEQEpAW?5v2xa&u-Z@N5)ty%(hL5O!F4REk%$i^yOc
zBaoxE97~LbBKIJEVuvM}eh4}&a=TrDuR_CH1jfg~uTDkHV^iDsv3;CE7xdWWE*``(
zI|DX@(%Lm2pJStz8;7N_NVnB`F+Xh_9iBESnNF|dRD>Uq^eS1>gP$UiI`zD6wThnx
z!>S4%TGW;z5^m+{;$CPIONNZRXgMJlS~BGECCddV
zZE4h!F{iy_UOr}$;ygV?Ko0^OEVlBBQ6yJhn3--z#P5-pPG
z-^l^^|F_#E1^z{#d(k!`1wMXfE%k!HWJ{BXtgJ5o)!F&PxBp}P&eCs|ioX7pvrqip
zYj1w`(|bRA6#3#uMgOUl@h3{p+D|^q-}}|0^IuF9mD4Ndp7=Z02G{qkdp3ea|M1HA
erc6IN|Ka%?6PvQ(_5@1&G`wT>2kFLQ)3+
literal 0
HcmV?d00001
diff --git a/manage/__pycache__/MileStone.cpython-312.pyc b/manage/__pycache__/MileStone.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..98b4483c0e30f67cd559c41c39dd5385abba2b31
GIT binary patch
literal 903
zcmaJ<&1(}u6o0e3+1+dsi>(z}1xtHLF0CI3Z4gg-v{q6)#D!(eOxjKNBg}4W5-LD`_s1k+9d(s&L
zf))~AA$uYUi|u>Qi{@K9B(CEVs}fLRdX7uNDDcT_(+;EdO%C8GZ3#qDVrtc@(!gU%
z)rtb9QW7<&Upb$U%u%?P`5De~w++$xTL9FqqY@~<25g`UeI+QM#e&4-iicUM64YA{
z3lbGnRB(o(eQN6T!Ly>dM1vZsM4`FVidF;PED4dzLEwg_XZ!XFF<?zP#=)A7-ZamFXcb1Jfn0rx1&`yT4_*9{OEd34kMaq5F>osBbLQdb?W#LQ*65O
zj>#_ZnL?TlFVq6Z{|+?6*{RTcsz31p+;GWLdWWY%TKJW_SVjmPgK-SEVim?7Z;l*|
z7xrN^RuP)%&&0sPPALhyrJ=}T9h7XReIQQ^lyqmNm+$7cUJf*)^Qbr9o&Wg0j}Ekn
zfu8NW`mAwE-T1WrVZ9Ufn%!m}^`*|np>}s?iCk8_|*
HCZhiWNblOe
literal 0
HcmV?d00001
diff --git a/manage/__pycache__/__init__.cpython-312.pyc b/manage/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f36462bd5206040b955bc7c4c83a66545099ee4b
GIT binary patch
literal 145
zcmX@j%ge<81c9u}(?IlN5P=Rpvj9b=GgLBYGWxA#C}INgK7-W!GH|hq2`I|XN=+^)
zjtQtN$;i)(2`&& str:
- return r"\n".join(self.text_sections)
+ return "\n".join(self.text_sections)
pass
def set_to_memory(self, content: str):
- self.text_sections = content.split(r"\n")
+ self.text_sections = content.split("\n")
pass
@@ -37,6 +38,7 @@ class StoryMap:
def append_fragment_slice(self, node: FragmentSlice):
self.slice_list[-1].next_node = node
+ node.parent_story = self.story_name
node.prev_node = self.slice_list[-1]
node.fragm_sort_i = len(self.slice_list)
self.slice_list.append(node)
diff --git a/parse/StorylineCmp.py b/parse/StorylineCmp.py
index b1360d0..a368b3e 100644
--- a/parse/StorylineCmp.py
+++ b/parse/StorylineCmp.py
@@ -14,20 +14,20 @@ class CmpTool:
def __init__(self):
pass
- def graph_compare(self, graph_new: Dict[str, StoryMap], graph_old: Dict[str, StoryMap]) -> Dict[ModifyReason, FragmentSlice]:
+ def graph_compare(self, graph_new: Dict[str, StoryMap], graph_old: Dict[str, StoryMap]) -> Dict[ModifyReason, List[FragmentSlice]]:
fragments_has_removed = []
for story in graph_old.values():
- fragments_has_removed = fragments_has_removed + self.__event_remove_check(graph_new, story)
+ fragments_has_removed = fragments_has_removed + self.__slice_remove_check(graph_new, story)
pass
fragments_has_appended = []
for story in graph_new.values():
- fragments_has_appended = fragments_has_appended + self.__event_append_check(graph_old, story)
+ fragments_has_appended = fragments_has_appended + self.__slice_append_check(graph_old, story)
pass
fragments_has_changed = []
for story in graph_new.values():
- fragments_has_changed = fragments_has_changed + self.__event_changed_check(graph_old, story)
+ fragments_has_changed = fragments_has_changed + self.__slice_changed_check(graph_old, story)
pass
return {
@@ -36,35 +36,78 @@ class CmpTool:
ModifyReason.Changed: fragments_has_changed,
}
- def __event_remove_check(self, graph_new: Dict[str, StoryMap], story_old: StoryMap) -> List[FragmentSlice]:
+ def __slice_remove_check(self, graph_new: Dict[str, StoryMap], story_old: StoryMap) -> List[FragmentSlice]:
list_retv = []
+ s_name = story_old.story_name
+ story_curr = graph_new[s_name]
+
for slice in story_old.slice_list[1:]:
+ if story_curr is None:
+ list_retv.append(slice)
+ continue
+
+ # 确定情节定义节点
if slice.is_define_node[0]:
- s_name = story_old.story_name
f_name = slice.is_define_node[1]
- story_findout = graph_new[s_name]
- if story_findout is None or story_findout.get_fragment_defined(f_name) is None:
+ if story_curr.get_fragment_defined(f_name) is None:
+ list_retv.append(slice)
+ pass
+ pass
+ # 确定情节引用节点
+ else:
+ s_refer_name = slice.story_refer
+ f_refer_name = slice.fragm_refer
+ refer_curr = CmpTool.__locate_fragment_refer__(story_curr.slice_list[0], s_refer_name, f_refer_name)
+ if refer_curr is None:
list_retv.append(slice)
pass
pass
pass
return list_retv
- def __event_append_check(self, graph_old: Dict[str, StoryMap], story_new: StoryMap) -> List[FragmentSlice]:
+ def __slice_append_check(self, graph_old: Dict[str, StoryMap], story_new: StoryMap) -> List[FragmentSlice]:
list_retv = []
+ s_name = story_new.story_name
+ story_prev = graph_old[s_name]
+
for slice in story_new.slice_list[1:]:
+ if story_prev is None:
+ list_retv.append(slice)
+ continue
+
+ # 确定情节定义节点
if slice.is_define_node[0]:
- s_name = story_new.story_name
f_name = slice.is_define_node[1]
- story_findout = graph_old[s_name]
- if story_findout is None or story_findout.get_fragment_defined(f_name) is None:
+ if story_prev.get_fragment_defined(f_name) is None:
+ list_retv.append(slice)
+ pass
+ pass
+ # 确定情节引用节点
+ else:
+ s_refer_name = slice.story_refer
+ f_refer_name = slice.fragm_refer
+ refer_prev = CmpTool.__locate_fragment_refer__(story_prev.slice_list[0], s_refer_name, f_refer_name)
+ if refer_prev is None:
list_retv.append(slice)
pass
pass
pass
+
return list_retv
- def __event_changed_check(self, graph_old: Dict[str, StoryMap], story_new: StoryMap) -> List[FragmentSlice]:
+ @classmethod
+ def __locate_fragment_refer__(cls, ref_story_head: FragmentSlice, story_self: str, fragm_self: str) -> FragmentSlice:
+ if ref_story_head is None:
+ return None
+
+ # 确定属于引用节点
+ if not ref_story_head.is_define_node[0]:
+ if ref_story_head.story_refer == story_self and ref_story_head.fragm_refer == fragm_self:
+ return ref_story_head
+
+ return cls.__locate_fragment_refer__(ref_story_head.next_node, story_self, fragm_self)
+
+ def __slice_changed_check(self, graph_old: Dict[str, StoryMap], story_new: StoryMap) -> List[FragmentSlice]:
story_old = graph_old[story_new.story_name]
if story_old is not None:
return self.__event_changed_chack_for(story_old, story_new)
@@ -73,19 +116,34 @@ class CmpTool:
def __event_changed_chack_for(self, story_old: StoryMap, story_new: StoryMap) -> List[FragmentSlice]:
list_retv = []
for fragm_curr in story_new.slice_list[1:]:
+ # 情节定义只比较定义节点本身
if fragm_curr.is_define_node[0]:
fragm_prev = story_old.get_fragment_defined(fragm_curr.is_define_node[1])
+ # 确定新旧图都定义了该情节
if fragm_prev is not None:
if fragm_curr.fragm_sort_i != fragm_prev.fragm_sort_i:
list_retv.append(fragm_curr)
- pass
-
- if len(fragm_curr.text_sections) != len(fragm_prev.text_sections):
+ elif len(fragm_curr.text_sections) != len(fragm_prev.text_sections):
list_retv.append(fragm_curr)
elif fragm_curr.text_sections != fragm_prev.text_sections:
list_retv.append(fragm_curr)
pass
pass
pass
+ else:
+ refer_curr = fragm_curr
+ refer_prev = CmpTool.__locate_fragment_refer__(story_old.slice_list[0], refer_curr.story_refer, refer_curr.fragm_refer)
+ # 确定新旧图都定义了该引用节点
+ if refer_prev is not None:
+ if refer_prev.fragm_sort_i != refer_curr.fragm_sort_i:
+ list_retv.append(refer_curr)
+ elif len(refer_prev.text_sections) != len(refer_curr.text_sections):
+ list_retv.append(refer_curr)
+ elif refer_prev.text_sections != refer_curr.text_sections:
+ list_retv.append(refer_curr)
+ pass
+ pass
+ pass
pass
+
return list_retv
\ No newline at end of file
diff --git a/parse/__pycache__/StoryMap.cpython-312.pyc b/parse/__pycache__/StoryMap.cpython-312.pyc
index 376af5411c922cd0e069783861d4c40df6b345eb..c7824f1175106aa0bc04860f0fa10bb0bd5dd3ac 100644
GIT binary patch
delta 1958
zcmZ`)>uVHO6rVdYyF1xu9+S;(_Nh&(qj{(i+k`YVT9s1W1d=`!+v%E}#Id`x%bkgB
zf>bS46a7nhhkk3J28D#71^ojGn??`!xKox}IgZhDDoj<;_qk
znzajT8+o!{e0?Xkpyf>fpkQmqCHZRPa%4taP!ji*_N8R@=Fp9y8r|{K&CHF=Y~w;4
zPF)HAk<8qZ??i4#?j?8B4k$tVc2P+$DCrsJzS6d&1Z(Y1f_wIl6lJ<{v5hAk0gEQp
z2*lpG(zxl^I2Kt>V_n_Lq?_%l8#;@8gE
z$iUwk$yL$g3C#ezAgW=nCp6o+B7msY`#kDwQ&j*lmwJSP`nfA~Fm}D6dA{2p5=k$6
zC3qpU2W*
G_7_h9w~eycd~E$Y#u0@vKKMV@Lp012@t$8ViqDK&N2w0mdnU+JlVYOZn`k+Gycx7Cr
zWR&=0V&n4!93e}%5o62sG4`NdBg4$!Fd60v@K1;_CSiH=w;LM8EtrPpcm3lgwVnMZ
z&0@jzoy^;LD2X10z1lS9nA@~X<776Vu@OTAEaM|*#5_?ntqDk<&l^UdZ?jHyJBhQS
z>Rxh;eWCsZgLSF-$s6czI_SVxowhONm}SeAQPX_%IDYpo0uRa?fbS1)GSy+V-hj0T
zccU4IP>t>-7TekKp_kV;#C~X*go4{*-K{(wY!tjr_}V^miA%9PWQu(i>#2Qpc>d3r
zj|}!_EMPq=TXAe{D(Pk35_WC0M#N!<;L|qmD9`9z!bcc-D{tGy=
Bw?F^@
delta 1636
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