From 088470960385cd0a01aeb4559215cad5f3b67517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Fri, 22 Mar 2024 10:01:47 +0100 Subject: [PATCH] Persist Characters --- app/main.ts | 5 +++ app/storage/FileUtils.js | 5 +++ app/storage/FileUtils.ts | 6 ++++ app/storage/ModelComponentFileDirectory.js | 3 +- app/storage/ModelComponentFileDirectory.ts | 3 +- app/storage/StoredGameModel.js | 3 +- app/storage/StoredGameModel.ts | 5 ++- app/storage/loader/GameModelLoader.js | 2 +- app/storage/loader/GameModelLoader.ts | 2 +- app/storage/storing/CharacterStorage.js | 32 +++++++++++++++++ app/storage/storing/CharacterStorage.ts | 35 +++++++++++++++++++ app/storage/storing/GamesystemStorage.js | 1 + app/storage/storing/GamesystemStorage.ts | 1 + app/storage/storing/ScriptAccountStoring.js | 1 + app/storage/storing/ScriptAccountStoring.ts | 1 + src/app/app.component.ts | 4 ++- .../project/serializer/CharacterSerializer.ts | 26 ++++++++++++++ testModel/characters/Astrid Hofferson.json | 4 +++ testModel/characters/Hicks Haddock.json | 4 +++ .../Weathersystem/Weathersystem.json | 13 ++++++- 20 files changed, 146 insertions(+), 10 deletions(-) create mode 100644 app/storage/storing/CharacterStorage.js create mode 100644 app/storage/storing/CharacterStorage.ts create mode 100644 src/app/project/serializer/CharacterSerializer.ts create mode 100644 testModel/characters/Astrid Hofferson.json create mode 100644 testModel/characters/Hicks Haddock.json diff --git a/app/main.ts b/app/main.ts index 7745629..45b1f1a 100644 --- a/app/main.ts +++ b/app/main.ts @@ -6,6 +6,8 @@ import {StoredGameModel} from "./storage/StoredGameModel"; import {ScriptAccountStorage} from "./storage/storing/ScriptAccountStoring"; import {ModelComponentFileDirectory} from "./storage/ModelComponentFileDirectory"; import {GamesystemStorage} from "./storage/storing/GamesystemStorage"; +import {Character} from "../src/app/project/game-model/characters/Character"; +import {CharacterStorage} from "./storage/storing/CharacterStorage"; let win: BrowserWindow | null = null; const args = process.argv.slice(1), @@ -225,6 +227,9 @@ function recieveGameModelToStore(gameModel: StoredGameModel) { const gamesystemStorage = new GamesystemStorage(path.join(projectDirectory, ModelComponentFileDirectory.GAMESYSTEM_DIR_NAME)) gamesystemStorage.storeGamesystems(gameModel.storedGamesystems) + + const characterStorage = new CharacterStorage(path.join(projectDirectory, ModelComponentFileDirectory.CHARACTER_DIR_NAME)) + characterStorage.storeCharacters(gameModel.storedCharacters) } /*function deleteComponent(component: DeleteModel) { diff --git a/app/storage/FileUtils.js b/app/storage/FileUtils.js index 55d504f..28298f8 100644 --- a/app/storage/FileUtils.js +++ b/app/storage/FileUtils.js @@ -19,6 +19,11 @@ class FileUtils { (0, fs_1.mkdirSync)(parentDirectory, { recursive: true }); } } + static prepareDirectoryFroWriting(directoryFile) { + if (!fs.existsSync(directoryFile)) { + (0, fs_1.mkdirSync)(directoryFile, { recursive: true }); + } + } static removeFiles(files) { files.forEach(file => { if (fs.lstatSync(file).isDirectory()) { diff --git a/app/storage/FileUtils.ts b/app/storage/FileUtils.ts index cfab96a..3dc93ee 100644 --- a/app/storage/FileUtils.ts +++ b/app/storage/FileUtils.ts @@ -21,6 +21,12 @@ export class FileUtils { } } + public static prepareDirectoryFroWriting(directoryFile: string) { + if(!fs.existsSync(directoryFile)) { + mkdirSync(directoryFile, {recursive: true}) + } + } + public static removeFiles(files: string[]) { files.forEach(file => { if(fs.lstatSync(file).isDirectory()) { diff --git a/app/storage/ModelComponentFileDirectory.js b/app/storage/ModelComponentFileDirectory.js index 9e2de51..8d28902 100644 --- a/app/storage/ModelComponentFileDirectory.js +++ b/app/storage/ModelComponentFileDirectory.js @@ -6,6 +6,5 @@ class ModelComponentFileDirectory { exports.ModelComponentFileDirectory = ModelComponentFileDirectory; ModelComponentFileDirectory.SCRIPTACCOUNT_DIR_NAME = "script-accounts"; ModelComponentFileDirectory.GAMESYSTEM_DIR_NAME = "gamesystems"; -ModelComponentFileDirectory.GAMESYSTEM_SIMPLE_DIR_NAME = "simple"; -ModelComponentFileDirectory.GAMESYSTEM_PRODUCT_DIR_NAME = "product"; +ModelComponentFileDirectory.CHARACTER_DIR_NAME = "characters"; //# sourceMappingURL=ModelComponentFileDirectory.js.map \ No newline at end of file diff --git a/app/storage/ModelComponentFileDirectory.ts b/app/storage/ModelComponentFileDirectory.ts index 35514b9..a0b9c8c 100644 --- a/app/storage/ModelComponentFileDirectory.ts +++ b/app/storage/ModelComponentFileDirectory.ts @@ -1,6 +1,5 @@ export class ModelComponentFileDirectory { public static SCRIPTACCOUNT_DIR_NAME = "script-accounts" public static GAMESYSTEM_DIR_NAME = "gamesystems"; - public static GAMESYSTEM_SIMPLE_DIR_NAME = "simple"; - public static GAMESYSTEM_PRODUCT_DIR_NAME = "product"; + public static CHARACTER_DIR_NAME = "characters"; } diff --git a/app/storage/StoredGameModel.js b/app/storage/StoredGameModel.js index 126a61b..57bfbe7 100644 --- a/app/storage/StoredGameModel.js +++ b/app/storage/StoredGameModel.js @@ -2,10 +2,11 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.StoredGameModel = void 0; class StoredGameModel { - constructor(gameModelName, storedScriptAccounts, storedGamesystems) { + constructor(gameModelName, storedScriptAccounts, storedGamesystems, storedCharacters) { this.gameModelName = gameModelName; this.storedGamesystems = storedGamesystems; this.storedScriptAccounts = storedScriptAccounts; + this.storedCharacters = storedCharacters; } } exports.StoredGameModel = StoredGameModel; diff --git a/app/storage/StoredGameModel.ts b/app/storage/StoredGameModel.ts index 8edfee0..d9d762b 100644 --- a/app/storage/StoredGameModel.ts +++ b/app/storage/StoredGameModel.ts @@ -5,11 +5,14 @@ export class StoredGameModel { storedGamesystems: StoreComponent[] storedScriptAccounts: StoreComponent[] + storedCharacters: StoreComponent[] - constructor(gameModelName: string, storedScriptAccounts: StoreComponent[], storedGamesystems: StoreComponent[]) { + constructor(gameModelName: string, storedScriptAccounts: StoreComponent[], storedGamesystems: StoreComponent[], + storedCharacters: StoreComponent[]) { this.gameModelName = gameModelName; this.storedGamesystems = storedGamesystems; this.storedScriptAccounts = storedScriptAccounts; + this.storedCharacters = storedCharacters; } } diff --git a/app/storage/loader/GameModelLoader.js b/app/storage/loader/GameModelLoader.js index 7139cc9..47e6436 100644 --- a/app/storage/loader/GameModelLoader.js +++ b/app/storage/loader/GameModelLoader.js @@ -14,7 +14,7 @@ class GameModelLoader { const gameModelName = path.basename(this.gameModelDir); const storedScriptAccounts = this.loadScriptAccountComponents(); const storedGamesystems = this.loadGamesystems(); - return new StoredGameModel_1.StoredGameModel(gameModelName, storedScriptAccounts, storedGamesystems); + return new StoredGameModel_1.StoredGameModel(gameModelName, storedScriptAccounts, storedGamesystems, []); } loadScriptAccountComponents() { const scriptAccountDir = path.join(this.gameModelDir, ModelComponentFileDirectory_1.ModelComponentFileDirectory.SCRIPTACCOUNT_DIR_NAME); diff --git a/app/storage/loader/GameModelLoader.ts b/app/storage/loader/GameModelLoader.ts index bcbfa63..92060a7 100644 --- a/app/storage/loader/GameModelLoader.ts +++ b/app/storage/loader/GameModelLoader.ts @@ -20,7 +20,7 @@ export class GameModelLoader { const storedScriptAccounts = this.loadScriptAccountComponents(); const storedGamesystems = this.loadGamesystems(); - return new StoredGameModel(gameModelName, storedScriptAccounts, storedGamesystems); + return new StoredGameModel(gameModelName, storedScriptAccounts, storedGamesystems, []); } private loadScriptAccountComponents() { diff --git a/app/storage/storing/CharacterStorage.js b/app/storage/storing/CharacterStorage.js new file mode 100644 index 0000000..c2ac440 --- /dev/null +++ b/app/storage/storing/CharacterStorage.js @@ -0,0 +1,32 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CharacterStorage = void 0; +const FileUtils_1 = require("../FileUtils"); +const path = require("node:path"); +const fs = require("fs"); +class CharacterStorage { + constructor(characterDir) { + this.characterDir = characterDir; + FileUtils_1.FileUtils.prepareDirectoryFroWriting(characterDir); + } + storeCharacters(storedCharacters) { + this.persistDeletedCharacters(storedCharacters); + storedCharacters.forEach(storedCharacter => this.storeSingleCharacter(storedCharacter)); + } + persistDeletedCharacters(existingCharacters) { + const scriptAccountFiles = FileUtils_1.FileUtils.listFilesInDirectory(this.characterDir); + scriptAccountFiles.forEach(characterFile => { + const scriptAccountFileName = path.parse(path.basename(characterFile)).name; + if (existingCharacters.find(character => character.fileName === scriptAccountFileName) == undefined) { + //No scriptAccountFile was found with that nae of the file. So the scriptAccount was deleted. Remove file + fs.unlinkSync(characterFile); + } + }); + } + storeSingleCharacter(character) { + const completeScriptAccountFile = path.join(this.characterDir, character.fileName + ".json"); + fs.writeFileSync(completeScriptAccountFile, character.jsonString, 'utf-8'); + } +} +exports.CharacterStorage = CharacterStorage; +//# sourceMappingURL=CharacterStorage.js.map \ No newline at end of file diff --git a/app/storage/storing/CharacterStorage.ts b/app/storage/storing/CharacterStorage.ts new file mode 100644 index 0000000..8e53647 --- /dev/null +++ b/app/storage/storing/CharacterStorage.ts @@ -0,0 +1,35 @@ +import {StoreComponent} from "../StoreComponent"; +import {FileUtils} from "../FileUtils"; +import * as path from "node:path"; +import * as fs from "fs"; + +export class CharacterStorage { + private characterDir: string + + + constructor(characterDir: string) { + this.characterDir = characterDir; + FileUtils.prepareDirectoryFroWriting(characterDir) + } + + storeCharacters(storedCharacters: StoreComponent[]) { + this.persistDeletedCharacters(storedCharacters) + storedCharacters.forEach(storedCharacter => this.storeSingleCharacter(storedCharacter)) + } + + private persistDeletedCharacters(existingCharacters: StoreComponent[]) { + const scriptAccountFiles = FileUtils.listFilesInDirectory(this.characterDir); + scriptAccountFiles.forEach(characterFile => { + const scriptAccountFileName = path.parse(path.basename(characterFile)).name + if(existingCharacters.find(character => character.fileName === scriptAccountFileName) == undefined) { + //No scriptAccountFile was found with that nae of the file. So the scriptAccount was deleted. Remove file + fs.unlinkSync(characterFile) + } + }) + } + + private storeSingleCharacter(character: StoreComponent) { + const completeScriptAccountFile = path.join(this.characterDir, character.fileName + ".json") + fs.writeFileSync(completeScriptAccountFile, character.jsonString, 'utf-8') + } +} diff --git a/app/storage/storing/GamesystemStorage.js b/app/storage/storing/GamesystemStorage.js index 003890e..62730ff 100644 --- a/app/storage/storing/GamesystemStorage.js +++ b/app/storage/storing/GamesystemStorage.js @@ -7,6 +7,7 @@ const fs = require("fs"); class GamesystemStorage { constructor(gamesystemRootDir) { this.gamesystemRootDir = gamesystemRootDir; + FileUtils_1.FileUtils.prepareDirectoryFroWriting(gamesystemRootDir); } storeGamesystems(gamesystems) { const unreferencedFiles = this.detectUnusedGamesystemFiles(gamesystems); diff --git a/app/storage/storing/GamesystemStorage.ts b/app/storage/storing/GamesystemStorage.ts index c414f65..b3337c3 100644 --- a/app/storage/storing/GamesystemStorage.ts +++ b/app/storage/storing/GamesystemStorage.ts @@ -10,6 +10,7 @@ export class GamesystemStorage { constructor(gamesystemRootDir: string) { this.gamesystemRootDir = gamesystemRootDir; + FileUtils.prepareDirectoryFroWriting(gamesystemRootDir) } public storeGamesystems(gamesystems: StoreComponent[]) { diff --git a/app/storage/storing/ScriptAccountStoring.js b/app/storage/storing/ScriptAccountStoring.js index 49b0eab..331a1cb 100644 --- a/app/storage/storing/ScriptAccountStoring.js +++ b/app/storage/storing/ScriptAccountStoring.js @@ -7,6 +7,7 @@ const fs = require("fs"); class ScriptAccountStorage { constructor(scriptAccountDir) { this.scriptAccountDir = scriptAccountDir; + FileUtils_1.FileUtils.prepareDirectoryFroWriting(this.scriptAccountDir); } storeScriptAccounts(scriptAccounts) { this.persistDeletedScriptAccounts(scriptAccounts); diff --git a/app/storage/storing/ScriptAccountStoring.ts b/app/storage/storing/ScriptAccountStoring.ts index 6e73b17..eae0bdc 100644 --- a/app/storage/storing/ScriptAccountStoring.ts +++ b/app/storage/storing/ScriptAccountStoring.ts @@ -9,6 +9,7 @@ export class ScriptAccountStorage { constructor(scriptAccountDir: string) { this.scriptAccountDir = scriptAccountDir; + FileUtils.prepareDirectoryFroWriting(this.scriptAccountDir) } storeScriptAccounts(scriptAccounts: StoreComponent[]) { diff --git a/src/app/app.component.ts b/src/app/app.component.ts index a0ab599..1e2d9aa 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -22,6 +22,7 @@ import {StoreComponent} from "../../app/storage/StoreComponent"; import {GamesystemSerializer} from "./project/serializer/GamesystemSerializer"; import {Character} from "./project/game-model/characters/Character"; import {CharacterOverviewComponent} from "./side-overviews/character-overview/character-overview.component"; +import {CharacterSerializer} from "./project/serializer/CharacterSerializer"; @Component({ selector: 'app-root', @@ -215,7 +216,8 @@ export class AppComponent implements OnInit{ if(this.gameModel != undefined) { const storedScriptAccounts = ScriptAccountSerializer.serializeScriptAccounts(this.gameModel.scriptAccounts) const storedGamesystems: StoreComponent[] = GamesystemSerializer.serializeGamesystems(this.gameModel.gamesystems) - const storeModel = new StoredGameModel(this.gameModel.gameModelName, storedScriptAccounts, storedGamesystems) + const storedCharacters: StoreComponent[] = CharacterSerializer.serializeCharacters(this.gameModel.characters) + const storeModel = new StoredGameModel(this.gameModel.gameModelName, storedScriptAccounts, storedGamesystems, storedCharacters) if(this.electronService.isElectron) { this.electronService.ipcRenderer.send('save-model', storeModel) diff --git a/src/app/project/serializer/CharacterSerializer.ts b/src/app/project/serializer/CharacterSerializer.ts new file mode 100644 index 0000000..4923004 --- /dev/null +++ b/src/app/project/serializer/CharacterSerializer.ts @@ -0,0 +1,26 @@ +import {Character} from "../game-model/characters/Character"; +import {StoreComponent} from "../../../../app/storage/StoreComponent"; +import {SerializeConstants} from "./SerializeConstants"; +import {ModelComponentType} from "../game-model/ModelComponentType"; + +export class CharacterSerializer { + + public static serializeCharacters(characters: Character[]): StoreComponent[] { + const storedCharacters: StoreComponent[] = [] + characters.forEach(character => storedCharacters.push(this.serializeSingleCharacter(character))) + return storedCharacters; + } + + private static serializeSingleCharacter(character: Character): StoreComponent{ + const fileName = character.componentName + const jsonString = JSON.stringify(character, (key, value) => { + if(key === 'unsaved' || key === 'type') { + return undefined + } else { + return value; + } + }, SerializeConstants.JSON_INDENT) + + return new StoreComponent(jsonString, fileName, ModelComponentType.CHARACTER); + } +} diff --git a/testModel/characters/Astrid Hofferson.json b/testModel/characters/Astrid Hofferson.json new file mode 100644 index 0000000..0678c2b --- /dev/null +++ b/testModel/characters/Astrid Hofferson.json @@ -0,0 +1,4 @@ +{ + "componentName": "Astrid Hofferson", + "componentDescription": "" +} \ No newline at end of file diff --git a/testModel/characters/Hicks Haddock.json b/testModel/characters/Hicks Haddock.json new file mode 100644 index 0000000..1e611d7 --- /dev/null +++ b/testModel/characters/Hicks Haddock.json @@ -0,0 +1,4 @@ +{ + "componentName": "Hicks Haddock", + "componentDescription": "" +} \ No newline at end of file diff --git a/testModel/gamesystems/Weathersystem/Weathersystem.json b/testModel/gamesystems/Weathersystem/Weathersystem.json index df066e7..b9abfec 100644 --- a/testModel/gamesystems/Weathersystem/Weathersystem.json +++ b/testModel/gamesystems/Weathersystem/Weathersystem.json @@ -1 +1,12 @@ -{"componentName":"Weathersystem","componentDescription":"Ein Wettersystem, dass sich aus normalem Wetter (Sonne, Regen, Wolke, Schnee, Sturm etc.) und zusätzlich den Jahreszeiten (Frühling, Sommer, Herbst, Winter, etc.) zusammensetzt.","childsystems":[{"componentName":"Season"},{"componentName":"Weather"}]} \ No newline at end of file +{ + "componentName": "Weathersystem", + "componentDescription": "Ein Wettersystem, dass sich aus normalem Wetter (Sonne, Regen, Wolke, Schnee, Sturm etc.) und zusätzlich den Jahreszeiten (Frühling, Sommer, Herbst, Winter, etc.) zusammensetzt.", + "childsystems": [ + { + "componentName": "Season" + }, + { + "componentName": "Weather" + } + ] +} \ No newline at end of file