diff --git a/app/storage/FileUtils.js b/app/storage/FileUtils.js index 6a966ba..a13984e 100644 --- a/app/storage/FileUtils.js +++ b/app/storage/FileUtils.js @@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.FileUtils = void 0; const fs = require("fs"); const path = require("node:path"); +const fs_1 = require("fs"); class FileUtils { static listFilesInDirectory(directory) { if (fs.lstatSync(directory).isDirectory()) { @@ -12,6 +13,12 @@ class FileUtils { return []; } } + static prepareFileForWriting(file) { + const parentDirectory = path.dirname(file); + if (!fs.existsSync(parentDirectory)) { + (0, fs_1.mkdirSync)(parentDirectory, { recursive: true }); + } + } } exports.FileUtils = FileUtils; //# sourceMappingURL=FileUtils.js.map \ No newline at end of file diff --git a/app/storage/FileUtils.ts b/app/storage/FileUtils.ts index 3d267fb..decb4fc 100644 --- a/app/storage/FileUtils.ts +++ b/app/storage/FileUtils.ts @@ -1,5 +1,6 @@ import * as fs from "fs"; import * as path from "node:path"; +import {mkdirSync} from "fs"; export class FileUtils { @@ -10,4 +11,12 @@ export class FileUtils { return []; } } + + public static prepareFileForWriting(file: string) { + const parentDirectory = path.dirname(file) + + if(!fs.existsSync(parentDirectory)) { + mkdirSync(parentDirectory, {recursive: true}) + } + } } diff --git a/app/storage/storing/GamesystemStorage.js b/app/storage/storing/GamesystemStorage.js new file mode 100644 index 0000000..a75c04c --- /dev/null +++ b/app/storage/storing/GamesystemStorage.js @@ -0,0 +1,45 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.GamesystemStorage = void 0; +const FileUtils_1 = require("../FileUtils"); +const path = require("node:path"); +const fs = require("fs"); +class GamesystemStorage { + constructor(gamesystemRootDir) { + this.gamesystemRootDir = gamesystemRootDir; + } + storeGamesystems(gamesystems) { + this.detectUnusedGamesystemFiles(this.gamesystemRootDir, gamesystems); + gamesystems.forEach(gamesystem => this.storeGamesystem(gamesystem)); + } + detectUnusedGamesystemFiles(gamesystemDir, gamesystems) { + const gamesystemFiles = FileUtils_1.FileUtils.listFilesInDirectory(gamesystemDir); + gamesystemFiles.forEach(gamesystemFile => { + if (fs.lstatSync(gamesystemFile).isDirectory()) { + this.detectUnusedGamesystemFiles(gamesystemFile, gamesystems); + } + else { + const currentFileName = path.parse(path.basename(gamesystemFile)).name; + const searchedGamesystem = gamesystems.find(gamesystem => path.basename(gamesystem.fileName) === currentFileName); + if (searchedGamesystem != undefined) { + if (path.dirname(searchedGamesystem.fileName) === currentFileName) { + //Aus Simple wurde Product => Delete .json + fs.unlinkSync(gamesystemFile); + } + } + else { + fs.unlinkSync(gamesystemFile); + } + } + }); + } + storeGamesystem(gamesystem) { + const gamesystemFile = path.join(...gamesystem.fileName.split("/")); + console.log(gamesystem.jsonString); + const completeGamesystemFile = path.join(this.gamesystemRootDir, gamesystemFile); + FileUtils_1.FileUtils.prepareFileForWriting(completeGamesystemFile); + fs.writeFileSync(completeGamesystemFile + ".json", gamesystem.jsonString, 'utf-8'); + } +} +exports.GamesystemStorage = GamesystemStorage; +//# sourceMappingURL=GamesystemStorage.js.map \ No newline at end of file diff --git a/app/storage/storing/GamesystemStorage.ts b/app/storage/storing/GamesystemStorage.ts new file mode 100644 index 0000000..a25848d --- /dev/null +++ b/app/storage/storing/GamesystemStorage.ts @@ -0,0 +1,47 @@ +import {StoreComponent} from "../StoreComponent"; +import {FileUtils} from "../FileUtils"; +import * as path from "node:path"; +import * as fs from "fs"; + +export class GamesystemStorage { + + private gamesystemRootDir: string + + + constructor(gamesystemRootDir: string) { + this.gamesystemRootDir = gamesystemRootDir; + } + + public storeGamesystems(gamesystems: StoreComponent[]) { + this.detectUnusedGamesystemFiles(this.gamesystemRootDir, gamesystems) + gamesystems.forEach(gamesystem => this.storeGamesystem(gamesystem)) + } + + private detectUnusedGamesystemFiles(gamesystemDir: string, gamesystems: StoreComponent[]) { + const gamesystemFiles = FileUtils.listFilesInDirectory(gamesystemDir); + gamesystemFiles.forEach(gamesystemFile => { + if(fs.lstatSync(gamesystemFile).isDirectory()) { + this.detectUnusedGamesystemFiles(gamesystemFile, gamesystems) + } else { + const currentFileName = path.parse(path.basename(gamesystemFile)).name + const searchedGamesystem = gamesystems.find(gamesystem => path.basename(gamesystem.fileName) === currentFileName); + if(searchedGamesystem != undefined) { + if(path.dirname(searchedGamesystem.fileName) === currentFileName) { + //Aus Simple wurde Product => Delete .json + fs.unlinkSync(gamesystemFile) + } + } else { + fs.unlinkSync(gamesystemFile) + } + } + }) + } + + private storeGamesystem(gamesystem: StoreComponent) { + const gamesystemFile = path.join(... gamesystem.fileName.split("/")) + console.log(gamesystem.jsonString) + const completeGamesystemFile = path.join(this.gamesystemRootDir, gamesystemFile) + FileUtils.prepareFileForWriting(completeGamesystemFile) + fs.writeFileSync(completeGamesystemFile + ".json", gamesystem.jsonString, 'utf-8') + } +} diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 27f2b40..36d1fd0 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -19,6 +19,7 @@ import {ScriptAccountParser} from "./project/parser/ScriptAccountParser"; import {ElectronService} from "./core/services"; import {ScriptAccountSerializer} from "./project/serializer/ScriptAccountSerializer"; import {StoreComponent} from "../../app/storage/StoreComponent"; +import {GamesystemSerializer} from "./project/serializer/GamesystemSerializer"; @Component({ selector: 'app-root', @@ -183,13 +184,15 @@ export class AppComponent implements OnInit{ } onSaveProject() { - const storedScriptAccounts = ScriptAccountSerializer.serializeScriptAccounts(this.gameModel!.scriptAccounts) - const storedGamesystems: StoreComponent[] = []; - const storeModel = new StoredGameModel(this.gameModel!.gameModelName, storedScriptAccounts, storedGamesystems) + 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) - if(this.electronService.isElectron) { - this.electronService.ipcRenderer.send('save-model', storeModel) - } + if(this.electronService.isElectron) { + this.electronService.ipcRenderer.send('save-model', storeModel) + } + } } openScriptAccountsOverview() { diff --git a/src/app/project/parser/gamesystemParser/GamesystemParser.ts b/src/app/project/parser/gamesystemParser/GamesystemParser.ts index afb076f..e085bba 100644 --- a/src/app/project/parser/gamesystemParser/GamesystemParser.ts +++ b/src/app/project/parser/gamesystemParser/GamesystemParser.ts @@ -67,6 +67,7 @@ export class GamesystemParser { const searchedParentsystem = this.findParentsystem(parsedGamesystem.componentName) if(searchedParentsystem != undefined) { searchedParentsystem.addChildGamesystem(parsedGamesystem) + parsedGamesystem.parentGamesystem = searchedParentsystem } else { topGamesystems.push(parsedGamesystem) } diff --git a/src/app/project/serializer/GamesystemSerializer.ts b/src/app/project/serializer/GamesystemSerializer.ts new file mode 100644 index 0000000..3088fe6 --- /dev/null +++ b/src/app/project/serializer/GamesystemSerializer.ts @@ -0,0 +1,107 @@ +import {Gamesystem} from "../game-model/gamesystems/Gamesystem"; +import {StoreComponent} from "../../../../app/storage/StoreComponent"; +import {SimpleGamesystem} from "../game-model/gamesystems/SimpleGamesystem"; +import {ProductGamesystem} from "../game-model/gamesystems/ProductGamesystem"; +import {SerializeConstants} from "./SerializeConstants"; +import {ModelComponentType} from "../game-model/ModelComponentType"; + +export class GamesystemSerializer { + + private static IGNORED_SIMPLE_ATTRIBUTES = ["parentGamesystem", 'incomingTransitions', "outgoingTransitions", "unsaved", "type"] + + public static serializeGamesystems(gamesystems: Gamesystem[]): StoreComponent[] { + let storedGamesystems: StoreComponent[] = [] + gamesystems.forEach(gamesystem => storedGamesystems = storedGamesystems.concat(this.serializeSingleGamesystem(gamesystem))) + return storedGamesystems + } + + private static serializeSingleGamesystem(gamesystem: Gamesystem): StoreComponent[] { + if(gamesystem instanceof SimpleGamesystem) { + console.log("Simple Gamesystem") + return [this.serializeSimpleGamesystem(gamesystem as SimpleGamesystem)] + } else { + return this.serializeProductGamesystem(gamesystem as ProductGamesystem) + } + } + + private static serializeSimpleGamesystem(simpleGamesystem: SimpleGamesystem): StoreComponent { + const fileName = this.computeSimpleGamesystemPath(simpleGamesystem); + const jsonString = JSON.stringify(simpleGamesystem, (key, value) => { + + if(this.IGNORED_SIMPLE_ATTRIBUTES.includes(key)) { + return undefined + } else if(key === 'startingState' || key === 'endingState') { + return value.stateLabel + } else if(key === 'scriptAccount') { + return value.componentName + } else { + return value; + } + }, SerializeConstants.JSON_INDENT) + + console.log(jsonString) + return new StoreComponent(jsonString, fileName, ModelComponentType.GAMESYTEM) + } + + private static serializeProductGamesystem(productGamesystem: ProductGamesystem): StoreComponent[] { + const storedGamesystems: StoreComponent[] = [] + + const fileName = this.computeProductGamesystemPath(productGamesystem) + const innerGamesystemJsonArray: {'componentName': string}[] = [] + productGamesystem.innerGamesystems.forEach(innerGamesystem => { + innerGamesystemJsonArray.push({ + 'componentName': innerGamesystem.componentName + }) + + const storedChildsystems = this.serializeSingleGamesystem(innerGamesystem); + storedChildsystems.forEach(storedChildsystem => storedGamesystems.push(storedChildsystem)) + }) + + const jsonString = { + 'componentName': productGamesystem.componentName, + 'componentDescription': productGamesystem.componentDescription, + 'childsystems': innerGamesystemJsonArray + } + + const storedProductsystem = new StoreComponent(JSON.stringify(jsonString), fileName, ModelComponentType.GAMESYTEM) + storedGamesystems.push(storedProductsystem) + + return storedGamesystems; + } + + private static computeSimpleGamesystemPath(simpleGamesystem: SimpleGamesystem): string { + if(simpleGamesystem.parentGamesystem == undefined) { + return simpleGamesystem.componentName + } else { + const pathElements: string[] = [simpleGamesystem.componentName] + let currentGamesystem: ProductGamesystem | undefined = simpleGamesystem.parentGamesystem + while(currentGamesystem != undefined) { + pathElements.unshift(currentGamesystem.componentName) + currentGamesystem = currentGamesystem.parentGamesystem + } + let output = "" + for(let i=0; i