from parse.StoryMap import StoryMap, FragmentSlice from enum import Enum from typing import Dict, List class ModifyReason(Enum): Removed = 0, Append = 1, Changed = 2, Nothing = 4, class CmpTool: def __init__(self): pass 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.__slice_remove_check(graph_new, story) pass fragments_has_appended = [] for story in graph_new.values(): 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.__slice_changed_check(graph_old, story) pass return { ModifyReason.Removed: fragments_has_removed, ModifyReason.Append: fragments_has_appended, ModifyReason.Changed: fragments_has_changed, } 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]: f_name = slice.is_define_node[1] 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 __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]: f_name = slice.is_define_node[1] 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 @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) return [] 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) 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