Skip to content

Commit

Permalink
persist and load diagrams
Browse files Browse the repository at this point in the history
  • Loading branch information
zkovari committed Sep 5, 2023
1 parent 3d4a7a8 commit 8b29074
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 7 deletions.
44 changes: 40 additions & 4 deletions src/main/python/plotlyst/core/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
three_act_structure, SceneStoryBeat, Tag, default_general_tags, TagType, \
default_tag_types, LanguageSettings, ImportOrigin, NovelPreferences, Goal, CharacterPreferences, TagReference, \
ScenePlotReferenceData, MiceQuotient, SceneDrive, WorldBuilding, Board, \
default_big_five_values, CharacterPlan, ManuscriptGoals
default_big_five_values, CharacterPlan, ManuscriptGoals, Diagram, DiagramData, default_events_map, \
default_character_networks
from src.main.python.plotlyst.core.template import Role, exclude_if_empty, exclude_if_black
from src.main.python.plotlyst.env import app_env

Expand Down Expand Up @@ -200,6 +201,8 @@ class NovelInfo:
world: WorldBuilding = field(default_factory=WorldBuilding)
board: Board = field(default_factory=Board)
manuscript_goals: ManuscriptGoals = field(default_factory=ManuscriptGoals)
events_map: Diagram = field(default_factory=default_events_map)
character_networks: List[Diagram] = field(default_factory=default_character_networks)


@dataclass
Expand Down Expand Up @@ -287,6 +290,12 @@ def scenes_dir(self, novel: Optional[Union[Novel, NovelInfo]] = None) -> Path:
scenes_dir_.mkdir()
return scenes_dir_

def diagrams_dir(self, novel: Novel):
diagrams_dir_ = self.novels_dir.joinpath(str(novel.id)).joinpath('diagrams')
if not diagrams_dir_.exists():
diagrams_dir_.mkdir()
return diagrams_dir_

def docs_dir(self, novel: Novel) -> Path:
docs_dir_ = self.novels_dir.joinpath(str(novel.id)).joinpath('docs')
if not docs_dir_.exists():
Expand Down Expand Up @@ -395,12 +404,23 @@ def load_manuscript(self, novel: Novel):
if scene.manuscript and not scene.manuscript.loaded:
self.load_document(novel, scene.manuscript)

def save_document(self, novel: Novel, document: Document):
def load_diagram(self, novel: Novel, diagram: Diagram):
if diagram.loaded:
return

json_str = self.__load_diagram(novel, diagram.id)
diagram.data = DiagramData.from_json(json_str)
diagram.loaded = True

def update_document(self, novel: Novel, document: Document):
self.__persist_doc(novel, document)

def delete_document(self, novel: Novel, document: Document):
self.__delete_doc(novel, document)

def update_diagram(self, novel: Novel, diagram: Diagram):
self._persist_diagram(novel, diagram)

def fetch_novel(self, id: uuid.UUID) -> Novel:
project_novel_info: ProjectNovelInfo = self._find_project_novel_info_or_fail(id)
novel_info = self._read_novel_info(project_novel_info.id)
Expand Down Expand Up @@ -527,7 +547,8 @@ def fetch_novel(self, id: uuid.UUID) -> Novel:
story_structures=novel_info.story_structures, character_profiles=novel_info.character_profiles,
conflicts=conflicts, goals=[x for x in novel_info.goals if str(x.id) in goal_ids], tags=tags_dict,
documents=novel_info.documents, premise=novel_info.premise, synopsis=novel_info.synopsis,
prefs=novel_info.prefs, manuscript_goals=novel_info.manuscript_goals)
prefs=novel_info.prefs, manuscript_goals=novel_info.manuscript_goals, events_map=novel_info.events_map,
character_networks=novel_info.character_networks)

world_path = self.novels_dir.joinpath(str(novel_info.id)).joinpath('world.json')
if os.path.exists(world_path):
Expand Down Expand Up @@ -565,7 +586,8 @@ def _persist_novel(self, novel: Novel):
tag_types=list(novel.tags.keys()),
documents=novel.documents,
premise=novel.premise, synopsis=novel.synopsis,
version=LATEST_VERSION, prefs=novel.prefs, manuscript_goals=novel.manuscript_goals)
version=LATEST_VERSION, prefs=novel.prefs, manuscript_goals=novel.manuscript_goals,
events_map=novel.events_map, character_networks=novel.character_networks)

self.__persist_info(self.novels_dir, novel_info)
self._persist_world(novel.id, novel.world)
Expand Down Expand Up @@ -609,6 +631,12 @@ def _persist_scene(self, scene: Scene, novel: Optional[Novel] = None):
drive=scene.drive)
self.__persist_info(self.scenes_dir(novel), info)

def _persist_diagram(self, novel: Novel, diagram: Diagram):
diagrams_dir = self.diagrams_dir(novel)
if not os.path.exists(str(diagrams_dir)):
os.mkdir(diagrams_dir)
self.__persist_info(diagrams_dir, diagram.data)

@staticmethod
def __id_or_none(item):
return item.id if item else None
Expand Down Expand Up @@ -651,6 +679,14 @@ def __load_doc_data(self, novel: Novel, data_uuid: uuid.UUID) -> str:
with open(path, encoding='utf8') as json_file:
return json_file.read()

def __load_diagram(self, novel: Novel, diagram_uuid: uuid.UUID) -> str:
diagrams_dir = self.diagrams_dir(novel)
path = diagrams_dir.joinpath(self.__json_file(diagram_uuid))
if not os.path.exists(path):
return ''
with open(path, encoding='utf8') as json_file:
return json_file.read()

def __persist_doc(self, novel: Novel, doc: Document):
novel_doc_dir = self.docs_dir(novel).joinpath(str(novel.id))
if not os.path.exists(str(novel_doc_dir)):
Expand Down
31 changes: 30 additions & 1 deletion src/main/python/plotlyst/core/domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -1727,13 +1727,40 @@ class CharacterNode(Node, CharacterBased):
character_id: Optional[uuid.UUID] = None


@dataclass_json(undefined=Undefined.EXCLUDE)
@dataclass
class DiagramData:
nodes: List[Node] = field(default_factory=list)


@dataclass
class Diagram:
title: str
id: uuid.UUID = field(default_factory=uuid.uuid4)
icon: str = field(default='', metadata=config(exclude=exclude_if_empty))
icon_color: str = field(default='black', metadata=config(exclude=exclude_if_black))
nodes: List[Node] = field(default_factory=list)

def __post_init__(self):
self.loaded: bool = False
self.data: Optional[DiagramData] = None

@overrides
def __eq__(self, other: 'Diagram'):
if isinstance(other, Diagram):
return self.id == other.id
return False

@overrides
def __hash__(self):
return hash(str(self.id))


def default_events_map() -> Diagram:
return Diagram('Events', id=uuid.UUID('6c74e40f-d3de-4c83-bcd2-0ca5e626081d'))


def default_character_networks() -> List[Diagram]:
return [Diagram('Character relations', id=uuid.UUID('bfd1f2d3-cb33-48a6-a09e-b4332c3d1ed1'))]


@dataclass
Expand Down Expand Up @@ -1802,6 +1829,8 @@ class Novel(NovelDescriptor):
world: WorldBuilding = field(default_factory=WorldBuilding)
board: Board = field(default_factory=Board)
manuscript_goals: ManuscriptGoals = field(default_factory=ManuscriptGoals)
events_map: Diagram = field(default_factory=default_events_map)
character_networks: List[Diagram] = field(default_factory=default_character_networks)

def pov_characters(self) -> List[Character]:
pov_ids = set()
Expand Down
16 changes: 14 additions & 2 deletions src/main/python/plotlyst/service/persistence.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ def update_doc(self, novel: Novel, document: Document):
self._operations.append(Operation(OperationType.UPDATE, novel=novel, doc=document))
self._persist_if_test_env()

def update_diagram(self, novel: Novel, diagram: Diagram):
if self._persistence_enabled:
self._operations.append(Operation(OperationType.UPDATE, novel=novel, diagram=diagram))
self._persist_if_test_env()

def delete_doc(self, novel: Novel, document: Document):
if self._persistence_enabled:
self._operations.append(Operation(OperationType.DELETE, novel=novel, doc=document))
Expand Down Expand Up @@ -188,6 +193,7 @@ def _persist_operations(operations: List[Operation]):
updated_novel_cache: Set[Novel] = set()
updated_scene_cache: Set[Scene] = set()
updated_character_cache: Set[Character] = set()
updated_diagram_cache: Set[Diagram] = set()

for op in operations:
# scenes
Expand All @@ -210,13 +216,19 @@ def _persist_operations(operations: List[Operation]):
elif op.character and op.novel and op.type == OperationType.DELETE:
client.delete_character(op.novel, op.character)

# novel and document
# novel, document, diagram
elif op.doc and op.type == OperationType.UPDATE:
if op.doc not in updated_doc_cache:
json_client.save_document(op.novel, op.doc)
json_client.update_document(op.novel, op.doc)
updated_doc_cache.add(op.doc)
elif op.doc and op.type == OperationType.DELETE:
json_client.delete_document(op.novel, op.doc)

elif op.diagram and op.type == OperationType.UPDATE:
if op.diagram not in updated_diagram_cache:
json_client.update_diagram(op.novel, op.diagram)
updated_diagram_cache.add(op.diagram)

elif op.novel and op.type == OperationType.UPDATE:
if op.novel not in updated_novel_cache:
client.update_novel(op.novel)
Expand Down

0 comments on commit 8b29074

Please sign in to comment.