添加比对窗口雏形
This commit is contained in:
parent
d9231fa131
commit
81f27ccb4c
|
@ -5,6 +5,8 @@
|
|||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="f609c0f2-cd0d-4eea-87f1-8caf02d3f04f" name="Changes" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/frame/CompareWindow.py" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/frame/__init__.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/entry.py" beforeDir="false" afterPath="$PROJECT_DIR$/entry.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/parse/ast_load.py" beforeDir="false" afterPath="$PROJECT_DIR$/parse/ast_load.py" afterDir="false" />
|
||||
|
@ -24,9 +26,9 @@
|
|||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectColorInfo"><![CDATA[{
|
||||
"associatedIndex": 1
|
||||
}]]></component>
|
||||
<component name="ProjectColorInfo">{
|
||||
"associatedIndex": 1
|
||||
}</component>
|
||||
<component name="ProjectId" id="2jEMCq2fbwwqDBeLk1htGPoMtzQ" />
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true">
|
||||
<ConfirmationsSetting value="2" id="Add" />
|
||||
|
@ -39,8 +41,10 @@
|
|||
"keyToString": {
|
||||
"Python.ast_load.executor": "Debug",
|
||||
"Python.entry.executor": "Debug",
|
||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"git-widget-placeholder": "master"
|
||||
"git-widget-placeholder": "master",
|
||||
"last_opened_file_path": "D:/Projects/Python/StoryCheckTools"
|
||||
}
|
||||
}]]></component>
|
||||
<component name="RunManager">
|
||||
|
@ -75,7 +79,7 @@
|
|||
<component name="SharedIndexes">
|
||||
<attachedChunks>
|
||||
<set>
|
||||
<option value="bundled-python-sdk-5b207ade9991-746f403e7f0c-com.jetbrains.pycharm.community.sharedIndexes.bundled-PC-241.17890.14" />
|
||||
<option value="bundled-python-sdk-50da183f06c8-d3b881c8e49f-com.jetbrains.pycharm.community.sharedIndexes.bundled-PC-233.13135.95" />
|
||||
</set>
|
||||
</attachedChunks>
|
||||
</component>
|
||||
|
|
11
entry.py
11
entry.py
|
@ -1,8 +1,17 @@
|
|||
from PyQt5.QtWidgets import QWidget, QApplication
|
||||
from frame.CompareWindow import CompareWin
|
||||
from sys import argv
|
||||
from parse.ast_load import global_ast_path, AstParse
|
||||
|
||||
|
||||
tool = AstParse(global_ast_path)
|
||||
print(tool.generate_time())
|
||||
tool.peak_storylines()
|
||||
storys = tool.peak_storylines()
|
||||
storys_2 = tool.peak_storylines()
|
||||
defferent_list = tool.storylines_compare(storys, storys_2)
|
||||
|
||||
app = QApplication(argv)
|
||||
win = CompareWin()
|
||||
win.load_differents(defferent_list, storys, storys_2)
|
||||
win.show()
|
||||
app.exec()
|
|
@ -0,0 +1,56 @@
|
|||
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
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,5 +1,5 @@
|
|||
from lxml import etree
|
||||
from typing import List
|
||||
from typing import List, Dict
|
||||
|
||||
|
||||
global_ast_path = r"E:\storyline.xast"
|
||||
|
@ -15,35 +15,151 @@ def items_filter(items, proc):
|
|||
return values
|
||||
|
||||
|
||||
def items_map(items: List['StoryLine']) -> Dict[str, 'StoryLine']:
|
||||
map: Dict[str, 'StoryLine'] = {}
|
||||
for inst in items:
|
||||
map[inst.signature] = inst
|
||||
pass
|
||||
return map
|
||||
|
||||
|
||||
class FragmentSlice():
|
||||
def __init__(self, signature: str):
|
||||
"""
|
||||
故事情节片段
|
||||
"""
|
||||
def __init__(self, signature: str, file_path: str):
|
||||
self.signature = signature
|
||||
self.file_path = file_path
|
||||
self.text_sections = []
|
||||
self.refer_items: 'FragmentSlice' = []
|
||||
pass
|
||||
|
||||
def append_text_section(self, section: str):
|
||||
"""
|
||||
添加描述文本段落
|
||||
|
||||
:param section: 文本段落
|
||||
:return: None
|
||||
"""
|
||||
self.text_sections.append(section)
|
||||
pass
|
||||
|
||||
def append_refer_slice(self, refer:'FragmentSlice'):
|
||||
"""
|
||||
添加引用描述段落内容
|
||||
|
||||
class StorySlice():
|
||||
def __init__(self, signature: str):
|
||||
:param refer: 引用段落
|
||||
:return: None
|
||||
"""
|
||||
self.refer_items.append(refer)
|
||||
pass
|
||||
|
||||
def content_equal(self, other: 'FragmentSlice') -> bool:
|
||||
"""
|
||||
内容比较
|
||||
|
||||
:param other: 其他片段
|
||||
:return: 比较结果
|
||||
"""
|
||||
if self.signature != other.signature:
|
||||
return False
|
||||
|
||||
if len(self.text_sections) != len(other.text_sections):
|
||||
return False
|
||||
|
||||
for line0 in self.text_sections:
|
||||
if not line0 in other.text_sections:
|
||||
return False
|
||||
pass
|
||||
|
||||
if len(self.refer_items) != len(other.refer_items):
|
||||
return False
|
||||
|
||||
for slice in self.refer_items:
|
||||
find: bool = False
|
||||
for slice_1 in other.refer_items:
|
||||
if slice.content_equal(slice_1):
|
||||
find = True
|
||||
pass
|
||||
pass
|
||||
|
||||
if not find:
|
||||
return False
|
||||
pass
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class StoryLine():
|
||||
"""
|
||||
故事线结果
|
||||
"""
|
||||
def __init__(self, signature: str, file_path: str):
|
||||
self.signature = signature
|
||||
self.file_path = file_path
|
||||
self.text_sections = []
|
||||
self.fragment_slices = []
|
||||
pass
|
||||
|
||||
def append_text_section(self, section: str):
|
||||
"""
|
||||
添加文本描述
|
||||
|
||||
:param section: 文本段落
|
||||
:return: None
|
||||
"""
|
||||
self.text_sections.append(section)
|
||||
pass
|
||||
|
||||
def append_fragment_slice(self, slice: FragmentSlice):
|
||||
"""
|
||||
添加情节
|
||||
|
||||
:param slice: 情节实例
|
||||
:return: None
|
||||
"""
|
||||
self.fragment_slices.append(slice)
|
||||
pass
|
||||
|
||||
def content_equal(self, other: "StoryLine") -> bool:
|
||||
"""
|
||||
内容比较
|
||||
|
||||
:param other: 其他实例
|
||||
:return: 比较结果
|
||||
"""
|
||||
if self.signature != other.signature:
|
||||
return False
|
||||
|
||||
if len(self.text_sections) != len(other.text_sections):
|
||||
return False
|
||||
|
||||
for line in self.text_sections:
|
||||
if not line in other.text_sections:
|
||||
return False
|
||||
pass
|
||||
|
||||
if len(self.fragment_slices) != len(other.fragment_slices):
|
||||
return False
|
||||
|
||||
for slice0 in self.fragment_slices:
|
||||
find: bool = False
|
||||
for slice1 in other.fragment_slices:
|
||||
if slice0.content_equal(slice1):
|
||||
find = True
|
||||
pass
|
||||
pass
|
||||
if not find:
|
||||
return False
|
||||
pass
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class AstParse():
|
||||
"""
|
||||
Ast解析器
|
||||
"""
|
||||
def __init__(self, ast_path: str):
|
||||
self.ast_path = ast_path
|
||||
ast_file = open(ast_path, "rb")
|
||||
|
@ -52,27 +168,42 @@ class AstParse():
|
|||
pass
|
||||
|
||||
def generate_time(self) -> str:
|
||||
"""
|
||||
获取生成时间
|
||||
|
||||
:return: 生成时间字符串
|
||||
"""
|
||||
attr_time = self.ast_inst.xpath("/ast[1]/@time")[0]
|
||||
return str(attr_time)
|
||||
|
||||
def peak_storylines(self) -> List[StorySlice]:
|
||||
def peak_storylines(self) -> List[StoryLine]:
|
||||
"""
|
||||
提取所有故事线
|
||||
|
||||
:return: 故事线列表
|
||||
"""
|
||||
story_list = self.ast_inst.xpath("/ast/story") # 获取所有故事节点
|
||||
|
||||
story_items = []
|
||||
fragm_map: Dict[str, FragmentSlice] = {}
|
||||
for story in story_list:
|
||||
story_name = story.xpath("@name")[0]
|
||||
story_slice = StorySlice("story:"+story_name)
|
||||
story_file = story.xpath("@file-path")[0]
|
||||
story_slice = StoryLine("story:" + story_name, story_file)
|
||||
story_items.append(story_slice)
|
||||
|
||||
story_text_lines = story.xpath("text-section/@text") # 获取所有描述
|
||||
story_text_lines = story.xpath("text-section/@text") #获取所有描述
|
||||
for line in story_text_lines:
|
||||
story_slice.append_text_section(line)
|
||||
pass
|
||||
|
||||
fragment_items = story.xpath("fragment") # 获取所有情节定义
|
||||
fragment_items = story.xpath("fragment") #获取所有情节定义
|
||||
for fragm in fragment_items:
|
||||
fragment_name = fragm.xpath("@name")
|
||||
fragm_slice = FragmentSlice("fragment:"+story_name+"#"+fragment_name)
|
||||
fragment_name = fragm.xpath("@name")[0]
|
||||
fragm_slice = FragmentSlice(f"fragment:{story_name}#{fragment_name}", story_file)
|
||||
story_slice.append_fragment_slice(fragm_slice)
|
||||
fragm_map[fragm_slice.signature] = fragm_slice
|
||||
|
||||
fragm_text_lines = fragm.xpath("text-section/@text")
|
||||
for line in fragm_text_lines:
|
||||
fragm_slice.append_text_section(line)
|
||||
|
@ -80,14 +211,62 @@ class AstParse():
|
|||
pass
|
||||
pass
|
||||
|
||||
fragm_refers = self.ast_inst.xpath("//refer")
|
||||
for refer in fragm_refers:
|
||||
story_name = refer.xpath("@story")
|
||||
fragm_name = refer.xpath("@fragment")
|
||||
story_refers = items_filter(story_items, lambda x:x.signature == f"story:{story_name}")
|
||||
if(len(story_refers) > 0):
|
||||
story_refer = story_refers[0]
|
||||
|
||||
fragm_refer_items = self.ast_inst.xpath("//refer")
|
||||
for refer_item in fragm_refer_items:
|
||||
story_name_refer = refer_item.xpath("@story")[0]
|
||||
fragm_name_refer = refer_item.xpath("@fragment")[0]
|
||||
fragm_file = refer_item.xpath("@file-path")[0]
|
||||
fragm_signature = f"fragment:{story_name_refer}#{fragm_name_refer}"
|
||||
fragment_target = fragm_map[fragm_signature]
|
||||
|
||||
fragm_pnode = refer_item.xpath("..")[0]
|
||||
|
||||
if fragm_pnode.xpath("name()") == "story":
|
||||
this_story_name = fragm_pnode.xpath("@name")[0]
|
||||
refer_slice = FragmentSlice(f"refer:<{this_story_name}>{story_name_refer}#{fragm_name_refer}", fragm_file)
|
||||
fragment_target.append_refer_slice(refer_slice)
|
||||
|
||||
refer_lines = refer_item.xpath("text-section/@text")
|
||||
for line in refer_lines:
|
||||
refer_slice.append_text_section(line)
|
||||
pass
|
||||
pass
|
||||
|
||||
if fragm_pnode.xpath("name()") == "article":
|
||||
this_article_name = fragm_pnode.xpath("@name")[0]
|
||||
this_volume_node = fragm_pnode.xpath("..")[0]
|
||||
this_volume_name = this_volume_node.xpath("@name")[0]
|
||||
refer_slice = FragmentSlice(f"refer-article<{this_volume_name}#{this_article_name}>{story_name_refer}#{fragm_name_refer}", fragm_file)
|
||||
fragment_target.append_refer_slice(refer_slice)
|
||||
|
||||
refer_lines = refer_item.xpath("text-section/@text")
|
||||
for line in refer_lines:
|
||||
refer_slice.append_text_section(line)
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
return story_items
|
||||
|
||||
def storylines_compare(self, base_list: List[StoryLine], other_list: List[StoryLine]) -> List[str]:
|
||||
changed_list: List[str] = []
|
||||
base_map = items_map(base_list)
|
||||
|
||||
for other_item in other_list:
|
||||
if not other_item.signature in base_map:
|
||||
changed_list.append(other_item.signature)
|
||||
continue
|
||||
|
||||
base_item = base_map[other_item.signature]
|
||||
if not other_item.content_equal(base_item):
|
||||
changed_list.append(other_item.signature)
|
||||
pass
|
||||
|
||||
base_map.pop(other_item.signature)
|
||||
pass
|
||||
|
||||
for addit in base_map.values():
|
||||
changed_list.append(addit.signature)
|
||||
pass
|
||||
|
||||
return changed_list
|
||||
|
|
Loading…
Reference in New Issue