diff --git a/app/LoadModel.js b/app/LoadModel.js new file mode 100644 index 0000000..a376e51 --- /dev/null +++ b/app/LoadModel.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LoadModel = void 0; +class LoadModel { + constructor(jsonString, modelType) { + this.jsonString = jsonString; + this.modelType = modelType; + } +} +exports.LoadModel = LoadModel; +//# sourceMappingURL=LoadModel.js.map \ No newline at end of file diff --git a/app/LoadModel.ts b/app/LoadModel.ts new file mode 100644 index 0000000..9effb8d --- /dev/null +++ b/app/LoadModel.ts @@ -0,0 +1,12 @@ +import {ModelComponentType} from "../src/app/game-model/ModelComponentType"; + +export class LoadModel { + jsonString: string + modelType: ModelComponentType + + + constructor(jsonString: string, modelType: ModelComponentType) { + this.jsonString = jsonString; + this.modelType = modelType; + } +} diff --git a/app/LoadedProject.js b/app/LoadedProject.js new file mode 100644 index 0000000..66d4596 --- /dev/null +++ b/app/LoadedProject.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LoadedProject = void 0; +class LoadedProject { + constructor(projectName, loadedModels) { + this.projectName = projectName; + this.loadedModels = loadedModels; + } +} +exports.LoadedProject = LoadedProject; +//# sourceMappingURL=LoadedProject.js.map \ No newline at end of file diff --git a/app/LoadedProject.ts b/app/LoadedProject.ts new file mode 100644 index 0000000..be710b8 --- /dev/null +++ b/app/LoadedProject.ts @@ -0,0 +1,12 @@ +import {LoadModel} from "./LoadModel"; + +export class LoadedProject { + projectName: string + loadedModels: LoadModel[] + + + constructor(projectName: string, loadedModels: LoadModel[]) { + this.projectName = projectName; + this.loadedModels = loadedModels; + } +} diff --git a/app/RecursiveLoadModel.js b/app/RecursiveLoadModel.js new file mode 100644 index 0000000..7599083 --- /dev/null +++ b/app/RecursiveLoadModel.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RecursiveLoadModel = void 0; +const LoadModel_1 = require("./LoadModel"); +class RecursiveLoadModel extends LoadModel_1.LoadModel { + constructor(jsonString, modelType, parentLoadModelname) { + super(jsonString, modelType); + this.parentLoadModelname = parentLoadModelname; + } +} +exports.RecursiveLoadModel = RecursiveLoadModel; +//# sourceMappingURL=RecursiveLoadModel.js.map \ No newline at end of file diff --git a/app/RecursiveLoadModel.ts b/app/RecursiveLoadModel.ts new file mode 100644 index 0000000..1b9d251 --- /dev/null +++ b/app/RecursiveLoadModel.ts @@ -0,0 +1,12 @@ +import {LoadModel} from "./LoadModel"; +import {ModelComponentType} from "../src/app/game-model/ModelComponentType"; + +export class RecursiveLoadModel extends LoadModel { + parentLoadModelname: string + + + constructor(jsonString: string, modelType: ModelComponentType, parentLoadModelname: string) { + super(jsonString, modelType); + this.parentLoadModelname = parentLoadModelname; + } +} diff --git a/app/SaveProject.js b/app/SaveProject.js new file mode 100644 index 0000000..0e77adc --- /dev/null +++ b/app/SaveProject.js @@ -0,0 +1,100 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SaveProject = void 0; +const fs = require("fs"); +const path = require("node:path"); +const LoadModel_1 = require("./LoadModel"); +const ModelComponentType_1 = require("../src/app/game-model/ModelComponentType"); +const LoadedProject_1 = require("./LoadedProject"); +const RecursiveLoadModel_1 = require("./RecursiveLoadModel"); +class SaveProject { + static saveProject(projectDir, storageModels) { + if (!fs.existsSync(projectDir)) { + fs.mkdirSync(projectDir, { recursive: true }); + } + console.log(storageModels); + storageModels.forEach(storageModel => { + let modelDir = path.join(projectDir, storageModel.storageRootDir); + storageModel.storagePath.forEach(pathElement => modelDir = path.join(modelDir, pathElement)); + if (!fs.existsSync(modelDir)) { + fs.mkdirSync(modelDir, { recursive: true }); + } + const filePath = path.join(modelDir, storageModel.fileName + ".json"); + fs.writeFile(filePath, storageModel.jsonString, 'utf-8', (err) => { + if (err) { + console.error('Error writing JSON to file:', err); + } + else { + console.log('JSON file saved successfully:', filePath); + } + }); + }); + } + static loadProject(projectDir) { + let loadedScriptAccounts = SaveProject.loadScriptAccounts(projectDir); + loadedScriptAccounts = loadedScriptAccounts.concat(SaveProject.loadGamesystems(projectDir)); + return new LoadedProject_1.LoadedProject(path.basename(projectDir), loadedScriptAccounts); + } + static loadScriptAccounts(projectDir) { + const scriptAccountDir = path.join(projectDir, "script-accounts"); + if (!fs.existsSync(scriptAccountDir)) { + return []; + } + const loadedScriptAccounts = []; + const scriptAccountFileNames = fs.readdirSync(scriptAccountDir); + scriptAccountFileNames.forEach(scriptAccountFileName => { + const scriptAccountFile = path.join(scriptAccountDir, scriptAccountFileName); + const scriptAccountData = fs.readFileSync(scriptAccountFile, 'utf-8'); + loadedScriptAccounts.push({ + modelType: ModelComponentType_1.ModelComponentType.SCRIPTACCOUNT, + jsonString: scriptAccountData + }); + }); + return loadedScriptAccounts; + } + static loadGamesystems(projectDir) { + const gamesystemDir = path.join(projectDir, "gamesystems"); + const loadedGamesystems = this.loadGamesystemsRecursively(gamesystemDir); + console.log("LoadedGamesystems: ", loadedGamesystems.length); + return loadedGamesystems; + } + static loadGamesystemsRecursively(gamesystemDir) { + let loadedGamesystems = []; + const gamesystemFileNames = fs.readdirSync(gamesystemDir); + gamesystemFileNames.forEach(fileName => { + const gamesystemPath = path.join(gamesystemDir, fileName); + if (fs.lstatSync(gamesystemPath).isDirectory()) { + const childModels = SaveProject.loadGamesystemsRecursively(gamesystemPath); + loadedGamesystems = loadedGamesystems.concat(childModels); + } + else { + const gamesystemData = fs.readFileSync(path.join(gamesystemDir, fileName), "utf-8"); + if (path.parse(fileName).name === path.basename(gamesystemDir)) { + if ((path.basename(gamesystemDir) === path.parse(fileName).name) && path.basename(path.parse(gamesystemDir).dir) === "gamesystems") { + const loadedModel = new LoadModel_1.LoadModel(gamesystemData, ModelComponentType_1.ModelComponentType.GAMESYTEM); + loadedGamesystems.unshift(loadedModel); + } + else { + const loadedModel = new RecursiveLoadModel_1.RecursiveLoadModel(gamesystemData, ModelComponentType_1.ModelComponentType.GAMESYTEM, path.basename(gamesystemDir)); + loadedGamesystems.unshift(loadedModel); + } + } + else { + const secondCon = path.basename(gamesystemDir) === path.parse(fileName).name; + const thirdCon = path.basename(path.parse(gamesystemDir).dir) === "gamesystems"; + if (path.basename(gamesystemDir) === "gamesystems") { + const loadedModel = new LoadModel_1.LoadModel(gamesystemData, ModelComponentType_1.ModelComponentType.GAMESYTEM); + loadedGamesystems.push(loadedModel); + } + else { + const loadedModel = new RecursiveLoadModel_1.RecursiveLoadModel(gamesystemData, ModelComponentType_1.ModelComponentType.GAMESYTEM, path.basename(gamesystemDir)); + loadedGamesystems.push(loadedModel); + } + } + } + }); + return loadedGamesystems; + } +} +exports.SaveProject = SaveProject; +//# sourceMappingURL=SaveProject.js.map \ No newline at end of file diff --git a/app/SaveProject.ts b/app/SaveProject.ts new file mode 100644 index 0000000..7c010d3 --- /dev/null +++ b/app/SaveProject.ts @@ -0,0 +1,110 @@ +import {StorageModel} from "../src/app/game-model/fs/StorageModel"; +import * as fs from "fs"; +import * as path from "node:path"; +import {LoadModel} from "./LoadModel"; +import {ModelComponentType} from "../src/app/game-model/ModelComponentType"; +import {LoadedProject} from "./LoadedProject"; +import {RecursiveLoadModel} from "./RecursiveLoadModel"; + + +export class SaveProject { + static saveProject(projectDir: string, storageModels: StorageModel[]) { + if(!fs.existsSync(projectDir)) { + fs.mkdirSync(projectDir, {recursive: true}); + } + + console.log(storageModels) + storageModels.forEach(storageModel => { + let modelDir = path.join(projectDir, storageModel.storageRootDir); + storageModel.storagePath.forEach(pathElement => modelDir = path.join(modelDir, pathElement)); + if(!fs.existsSync(modelDir)) { + fs.mkdirSync(modelDir, {recursive: true}); + } + + const filePath = path.join(modelDir, storageModel.fileName + ".json"); + fs.writeFile(filePath, storageModel.jsonString ,'utf-8', (err) => { + if (err) { + console.error('Error writing JSON to file:', err); + } else { + console.log('JSON file saved successfully:', filePath); + } + }) + }) + } + + static loadProject(projectDir: string) { + let loadedScriptAccounts: LoadModel[] = SaveProject.loadScriptAccounts(projectDir) + loadedScriptAccounts = loadedScriptAccounts.concat(SaveProject.loadGamesystems(projectDir)) + return new LoadedProject(path.basename(projectDir), loadedScriptAccounts); + } + + static loadScriptAccounts(projectDir: string): LoadModel[] { + const scriptAccountDir = path.join(projectDir, "script-accounts"); + if (!fs.existsSync(scriptAccountDir)) { + return []; + } + + const loadedScriptAccounts: LoadModel[] = []; + + const scriptAccountFileNames = fs.readdirSync(scriptAccountDir); + scriptAccountFileNames.forEach(scriptAccountFileName => { + const scriptAccountFile = path.join(scriptAccountDir, scriptAccountFileName) + const scriptAccountData: string = fs.readFileSync(scriptAccountFile, 'utf-8'); + + loadedScriptAccounts.push({ + modelType: ModelComponentType.SCRIPTACCOUNT, + jsonString: scriptAccountData + }); + }) + + return loadedScriptAccounts; + } + + static loadGamesystems(projectDir: string): LoadModel[] { + const gamesystemDir = path.join(projectDir, "gamesystems"); + const loadedGamesystems = this.loadGamesystemsRecursively(gamesystemDir); + console.log("LoadedGamesystems: ", loadedGamesystems.length); + return loadedGamesystems; + } + + static loadGamesystemsRecursively(gamesystemDir: string): LoadModel[] { + let loadedGamesystems: LoadModel[] = []; + const gamesystemFileNames = fs.readdirSync(gamesystemDir); + + gamesystemFileNames.forEach(fileName => { + const gamesystemPath = path.join(gamesystemDir, fileName); + + if(fs.lstatSync(gamesystemPath).isDirectory()) { + const childModels: LoadModel[] = SaveProject.loadGamesystemsRecursively(gamesystemPath); + loadedGamesystems = loadedGamesystems.concat(childModels); + } else { + const gamesystemData = fs.readFileSync(path.join(gamesystemDir, fileName), "utf-8"); + if(path.parse(fileName).name === path.basename(gamesystemDir) ) { + if((path.basename(gamesystemDir) === path.parse(fileName).name) && path.basename(path.parse(gamesystemDir).dir) === "gamesystems") { + const loadedModel = new LoadModel(gamesystemData, ModelComponentType.GAMESYTEM); + loadedGamesystems.unshift(loadedModel) + } else { + const loadedModel = new RecursiveLoadModel(gamesystemData, ModelComponentType.GAMESYTEM, path.basename(gamesystemDir)) + loadedGamesystems.unshift(loadedModel); + } + + } else { + const secondCon = path.basename(gamesystemDir) === path.parse(fileName).name + const thirdCon = path.basename(path.parse(gamesystemDir).dir) === "gamesystems" + + if(path.basename(gamesystemDir) === "gamesystems"){ + const loadedModel = new LoadModel(gamesystemData, ModelComponentType.GAMESYTEM) + loadedGamesystems.push(loadedModel); + } else { + + const loadedModel = new RecursiveLoadModel(gamesystemData, ModelComponentType.GAMESYTEM, path.basename(gamesystemDir)) + loadedGamesystems.push(loadedModel); + } + + } + } + }) + return loadedGamesystems; + } + +} diff --git a/app/StorageModel.ts b/app/StorageModel.ts new file mode 100644 index 0000000..392016a --- /dev/null +++ b/app/StorageModel.ts @@ -0,0 +1,12 @@ +class StorageModel { + jsonString: string + fileName: string + storageDir: string + + + constructor(jsonString: string, fileName: string, storageDir: string) { + this.jsonString = jsonString; + this.fileName = fileName; + this.storageDir = storageDir; + } +} diff --git a/app/main.ts b/app/main.ts index 0668026..af69ce5 100644 --- a/app/main.ts +++ b/app/main.ts @@ -1,11 +1,15 @@ -import {app, BrowserWindow, screen, Menu, ipcMain} from 'electron'; +import {app, BrowserWindow, screen, Menu, ipcMain, dialog, globalShortcut} from 'electron'; import * as path from 'path'; import * as fs from 'fs'; +import {json} from "node:stream/consumers"; +import {StorageModel} from "../src/app/game-model/fs/StorageModel"; +import {SaveProject} from "./SaveProject"; let win: BrowserWindow | null = null; const args = process.argv.slice(1), serve = args.some(val => val === '--serve'); +let projectDirectory = "testModel" function createWindow(): BrowserWindow { const size = screen.getPrimaryDisplay().workAreaSize; @@ -90,6 +94,38 @@ function createWindow(): BrowserWindow { contextMenu.popup({ window: win!, x: params.x, y: params.y }); }) + ipcMain.on('save-model', (event, storageModels: StorageModel[]) => { + console.log("Save Model") + SaveProject.saveProject(projectDirectory, storageModels); + }) + + const menuTemplate = [ + { + label: 'File', + submenu: [ + { + label: "New Project", + click: () => { + createNewProject(); + } + }, + { + label: "Open Project", + click: () => { + openProject() + } + }, + { + label: "Save", + click: () => { + saveProject(); + } + } + ] + } + ] + const menu = Menu.buildFromTemplate(menuTemplate); + Menu.setApplicationMenu(menu) return win; } @@ -118,7 +154,38 @@ try { } }); + app.whenReady().then(() => { + globalShortcut.register('CommandOrControl+S', () => { + saveProject(); + }) + }) + } catch (e) { // Catch Error // throw e; } + + +function createNewProject() { + +} + +function openProject() { + const selectedPaths = dialog.showOpenDialogSync(win!, { + title: "Open Game-Model", + properties: [ + "openDirectory", + ] + }) + + if(selectedPaths != undefined) { + projectDirectory = selectedPaths[0]; + console.log("Open Project-Directory: ", projectDirectory) + const loadedProject = SaveProject.loadProject(projectDirectory) + win!.webContents.send("open-project", loadedProject) + } +} + +function saveProject() { + win!.webContents.send('get-project-data') +} diff --git a/e2e/game-model/gamesystems/productGamesystems/ProductStateTrainer.ts b/e2e/game-model/gamesystems/productGamesystems/ProductStateTrainer.ts index a0d09a4..e473f9f 100644 --- a/e2e/game-model/gamesystems/productGamesystems/ProductStateTrainer.ts +++ b/e2e/game-model/gamesystems/productGamesystems/ProductStateTrainer.ts @@ -16,13 +16,13 @@ export class ProductStateTrainer { static PRODUCT_GAMESYSTEM_NAME = "Product Gamesystem"; static givenFullProductGamesystemWithTwoStates() { - const letter_Gamesystem = new SimpleGamesystem(this.LETTERS_GAMESYSTEM_NAME); + const letter_Gamesystem = new SimpleGamesystem(this.LETTERS_GAMESYSTEM_NAME, ""); const letter_1 = letter_Gamesystem.createState(this.INNERSTATE_LETTER_1, "")!; const letter_2 = letter_Gamesystem.createState(this.INNERSTATE_LETTER_2, "")!; - const number_gamesystem = new SimpleGamesystem(this.NUMBERS_GAMESYSTEM_NAME); + const number_gamesystem = new SimpleGamesystem(this.NUMBERS_GAMESYSTEM_NAME, ""); const number_1 = number_gamesystem.createState(this.INNERSTATE_NUMBER_1, "")!; const number_2 = number_gamesystem.createState(this.INNERSTATE_NUMBER_2, "")!; - const productGamesystem = new ProductGamesystem(this.PRODUCT_GAMESYSTEM_NAME); + const productGamesystem = new ProductGamesystem(this.PRODUCT_GAMESYSTEM_NAME, ""); productGamesystem.states.push(new ProductState( [letter_1, number_1])); productGamesystem.states.push(new ProductState( [letter_1, number_2])); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 95cb454..2c24f78 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -17,6 +17,10 @@ import {GamescriptOverviewComponent} from "./side-overviews/gamescript-overview/ import {SimpleGamesystem} from "./game-model/gamesystems/SimpleGamesystem"; import {ProductGamesystem} from "./game-model/gamesystems/ProductGamesystem"; import {ProductState} from "./game-model/gamesystems/ProductState"; +import {LoadModel} from "../../app/LoadModel"; +import {LoadedProject} from "../../app/LoadedProject"; +import {ProcessLoadedProject} from "./game-model/fs/ProcessLoadedProject"; +import {StoreProject} from "./game-model/fs/store/StoreProject"; @Component({ selector: 'app-root', @@ -50,11 +54,26 @@ export class AppComponent implements OnInit{ this.onContextMenuMessageRecieved(message); }); }) + + electronService.ipcRenderer.on('get-project-data', (event: any, message: string) => { + this.zone.run(() => { + this.saveGameModel(); + }) + }) + + electronService.ipcRenderer.on('open-project', (event: any, loadedProject: LoadedProject) => { + this.gameModel = ProcessLoadedProject.processLoadedProject(loadedProject) + }) } else { console.log('Run in browser'); } } + saveGameModel() { + const storageModels = StoreProject.storeProject(this.gameModel!); + this.electronService.ipcRenderer.send('save-model', storageModels) + } + onContextMenuMessageRecieved(message: string) { if(message == "edit") { this.onEditModelComponent(); @@ -142,7 +161,7 @@ export class AppComponent implements OnInit{ } ngOnInit() { - this.gameModel = new GameModel("No More"); + /*this.gameModel = new GameModel("No More"); this.gameModel.createScriptAccount("Temperature"); this.gameModel.createScriptAccount("Luftfeuchtigkeit"); @@ -164,7 +183,7 @@ export class AppComponent implements OnInit{ weather_season.createState([springState!, sunnyState!]); - this.gameModel.addGamesystem(weather_season); + this.gameModel.addGamesystem(weather_season);*/ } openScriptAccountsOverview() { diff --git a/src/app/editor/editor.component.html b/src/app/editor/editor.component.html index 59dcd6f..b43ce41 100644 --- a/src/app/editor/editor.component.html +++ b/src/app/editor/editor.component.html @@ -10,7 +10,7 @@ - diff --git a/src/app/editor/script-account-editor/script-account-editor.component.html b/src/app/editor/script-account-editor/script-account-editor.component.html index 2b36b86..0935334 100644 --- a/src/app/editor/script-account-editor/script-account-editor.component.html +++ b/src/app/editor/script-account-editor/script-account-editor.component.html @@ -10,4 +10,6 @@ Please enter a valid number! + + diff --git a/src/app/editor/script-account-editor/script-account-editor.component.ts b/src/app/editor/script-account-editor/script-account-editor.component.ts index bdf6bc2..271352a 100644 --- a/src/app/editor/script-account-editor/script-account-editor.component.ts +++ b/src/app/editor/script-account-editor/script-account-editor.component.ts @@ -6,6 +6,7 @@ import {MatInput} from "@angular/material/input"; import {FormControl, FormGroupDirective, FormsModule, NgForm, Validators} from "@angular/forms"; import {NgIf} from "@angular/common"; import {ErrorStateMatcher} from "@angular/material/core"; +import {ElectronService} from "../../core/services"; export class MyErrorStateMatcher implements ErrorStateMatcher { isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean { @@ -24,6 +25,9 @@ export class ScriptAccountEditorComponent implements OnInit{ minCtrl: FormControl = new FormControl(0, [Validators.required, Validators.pattern('^[0-9]*$')]); maxCtrl: FormControl = new FormControl(100, [Validators.required, Validators.pattern('^[0-9]*$')]); matcher = new MyErrorStateMatcher(); + + constructor(private electronService: ElectronService) { + } ngOnInit() { this.minCtrl.setValue(this.scriptAccount!.minValue); this.maxCtrl.setValue(this.scriptAccount!.maxValue); @@ -46,4 +50,9 @@ export class ScriptAccountEditorComponent implements OnInit{ this.scriptAccount!.maxValue = Number(this.maxCtrl.value); this.scriptAccount!.onModifyContent(); } + + save() { + const jsonString = JSON.stringify(this.scriptAccount!, null, 4); + this.electronService.ipcRenderer.send('save-json', jsonString, this.scriptAccount!.componentName + ".json"); + } } diff --git a/src/app/game-model/GameModel.ts b/src/app/game-model/GameModel.ts index ac4d355..487f53f 100644 --- a/src/app/game-model/GameModel.ts +++ b/src/app/game-model/GameModel.ts @@ -4,6 +4,7 @@ import {Transition} from "./gamesystems/Transition"; import {State} from "./gamesystems/State"; import {ProductGamesystem} from "./gamesystems/ProductGamesystem"; import {SimpleGamesystem} from "./gamesystems/SimpleGamesystem"; +import {StorageModel} from "./fs/StorageModel"; export class GameModel { private readonly _gameModelName: string @@ -49,7 +50,7 @@ export class GameModel { createGamesystem(gamesystemName: string, parentGamesystemName: string | undefined) { if(gamesystemName != undefined && this.findGamesystem(gamesystemName) == undefined) { - const simpleGamesystem = new SimpleGamesystem(gamesystemName); + const simpleGamesystem = new SimpleGamesystem(gamesystemName, ""); if(parentGamesystemName != undefined) { const parentGamesystem = this.findGamesystem(parentGamesystemName); if(parentGamesystem instanceof SimpleGamesystem) { @@ -90,4 +91,7 @@ export class GameModel { } } + addScriptAccount(scriptAccount: ScriptAccount) { + this.scriptAccounts.push(scriptAccount); + } } diff --git a/src/app/game-model/SaveComponent.ts b/src/app/game-model/SaveComponent.ts index 473f0c5..cf2b2a8 100644 --- a/src/app/game-model/SaveComponent.ts +++ b/src/app/game-model/SaveComponent.ts @@ -1,6 +1,8 @@ export abstract class SaveComponent { unsaved: boolean = false; + static JSON_INDENT = 4; + onModifyContent() { this.unsaved = true; } @@ -8,6 +10,4 @@ export abstract class SaveComponent { onSaveContent() { this.unsaved = false; } - - abstract save(): void; } diff --git a/src/app/game-model/fs/ProcessLoadedProject.ts b/src/app/game-model/fs/ProcessLoadedProject.ts new file mode 100644 index 0000000..b6fe4d1 --- /dev/null +++ b/src/app/game-model/fs/ProcessLoadedProject.ts @@ -0,0 +1,76 @@ +import {GameModel} from "../GameModel"; +import {LoadedProject} from "../../../../app/LoadedProject"; +import {LoadModel} from "../../../../app/LoadModel"; +import {ModelComponentType} from "../ModelComponentType"; +import {ScriptAccount} from "../scriptAccounts/ScriptAccount"; +import {RecursiveLoadModel} from "../../../../app/RecursiveLoadModel"; +import {SimpleGamesystemParser} from "./parser/SimpleGamesystemParser"; +import {SimpleGamesystem} from "../gamesystems/SimpleGamesystem"; +import {ProductGamesystem} from "../gamesystems/ProductGamesystem"; +import {ProductGamesystemParser} from "./parser/ProductGamesystemParser"; +import {Gamesystem} from "../gamesystems/Gamesystem"; + +export class ProcessLoadedProject { + + static processLoadedProject(loadedProject: LoadedProject): GameModel { + const gameModel = new GameModel(loadedProject.projectName); + loadedProject.loadedModels.forEach(loadedModel => this.processLoadedModel(gameModel, loadedModel)) + //Generate product Gamesystems + this.generateProductGamesystems(gameModel.gamesystems) + return gameModel; + } + + static generateProductGamesystems(gamesystems: Gamesystem[]) { + gamesystems.forEach(gamesystem => { + if(gamesystem instanceof ProductGamesystem) { + gamesystem.generateFromChildsystems(); + } + }) + } + + static processLoadedModel(gameModel: GameModel, loadedModel: LoadModel) { + switch (loadedModel.modelType) { + case ModelComponentType.SCRIPTACCOUNT: this.processLoadedScriptAccount(gameModel, loadedModel); break; + case ModelComponentType.GAMESYTEM: this.processLoadedGamesystem(gameModel, loadedModel); break; + } + } + static processLoadedScriptAccount(gameModel: GameModel, loadedModel: LoadModel) { + const scriptAccount = new ScriptAccount("", ""); + Object.assign(scriptAccount, JSON.parse(loadedModel.jsonString)); + gameModel.addScriptAccount(scriptAccount); + } + + static processLoadedGamesystem(gameModel: GameModel, loadedModel: LoadModel) { + const parsedJsonString = JSON.parse(loadedModel.jsonString); + if(loadedModel.hasOwnProperty('parentLoadModelname')) { + const recursiveLoadModel = loadedModel as RecursiveLoadModel + console.log("Loaded Model should be an instance of recursivemodel") + if(parsedJsonString.hasOwnProperty('states') && parsedJsonString.hasOwnProperty('transitions')) { + //SimpleGamesystem + const simpleGamesystem: SimpleGamesystem = SimpleGamesystemParser.parseSimpleGamesystem(parsedJsonString); + const parentModel: ProductGamesystem = gameModel.findGamesystem(recursiveLoadModel.parentLoadModelname) as ProductGamesystem + parentModel.addChildGamesystem(simpleGamesystem); + } else { + console.log("Gamesystems: ", ) + //ProductGamesystem + const productGamesystem: ProductGamesystem = ProductGamesystemParser.parseProductGamesystem(parsedJsonString); + const parentModel: ProductGamesystem = gameModel.findGamesystem(recursiveLoadModel.parentLoadModelname) as ProductGamesystem; + parentModel.addChildGamesystem(productGamesystem); + } + } else { + //Top Gamesystem + if(parsedJsonString.hasOwnProperty('states') && parsedJsonString.hasOwnProperty('transitions')) { + //SimpleGamesystem + const simpleGamesystem: SimpleGamesystem = SimpleGamesystemParser.parseSimpleGamesystem(parsedJsonString); + gameModel.addGamesystem(simpleGamesystem); + } else { + //ProductGamesystem + const productGamesystem = ProductGamesystemParser.parseProductGamesystem(parsedJsonString); + console.log("Generated Productsystem: ", productGamesystem) + gameModel.addGamesystem(productGamesystem); + } + } + } + + +} diff --git a/src/app/game-model/fs/StorageModel.ts b/src/app/game-model/fs/StorageModel.ts new file mode 100644 index 0000000..800754e --- /dev/null +++ b/src/app/game-model/fs/StorageModel.ts @@ -0,0 +1,14 @@ +export class StorageModel { + jsonString: string + fileName: string + storagePath: string[] + storageRootDir: string + + + constructor(jsonString: string, fileName: string, storagePath: string[], storageRootDir: string) { + this.jsonString = jsonString; + this.fileName = fileName; + this.storagePath = storagePath; + this.storageRootDir = storageRootDir; + } +} diff --git a/src/app/game-model/fs/parser/ProductGamesystemParser.ts b/src/app/game-model/fs/parser/ProductGamesystemParser.ts new file mode 100644 index 0000000..612f7bd --- /dev/null +++ b/src/app/game-model/fs/parser/ProductGamesystemParser.ts @@ -0,0 +1,9 @@ +import {ProductGamesystem} from "../../gamesystems/ProductGamesystem"; + +export class ProductGamesystemParser { + static parseProductGamesystem(jsonObject: any): ProductGamesystem { + const componentName = jsonObject.componentName; + const componentDescript = jsonObject.componentDescription; + return new ProductGamesystem(componentName, componentDescript); + } +} diff --git a/src/app/game-model/fs/parser/SimpleGamesystemParser.ts b/src/app/game-model/fs/parser/SimpleGamesystemParser.ts new file mode 100644 index 0000000..b36c282 --- /dev/null +++ b/src/app/game-model/fs/parser/SimpleGamesystemParser.ts @@ -0,0 +1,47 @@ +import {SimpleGamesystem} from "../../gamesystems/SimpleGamesystem"; +import {SimpleState} from "../../gamesystems/SimpleState"; +import {SimpleTransition} from "../../gamesystems/SimpleTransition"; + +export class SimpleGamesystemParser { + + static parseSimpleGamesystem(jsonObject: any) : SimpleGamesystem { + const gamesystemName = jsonObject.componentName; + const gamesystemDescription = jsonObject.componentDescription; + const simpleStates = SimpleGamesystemParser.parseSimpleStates(jsonObject) + const simpleTransitions = SimpleGamesystemParser.parseSimpleTransitions(jsonObject, simpleStates); + + const gamesystem = new SimpleGamesystem(gamesystemName, gamesystemDescription); + gamesystem.states = simpleStates; + gamesystem.transitions = simpleTransitions; + + return gamesystem; + } + + static parseSimpleStates(jsonObject: any): SimpleState[] { + const states: SimpleState[] = []; + for(let i=0; i state.stateLabel === startingStateLabel); + const endingState = states.find(state => state.stateLabel === endingStateLabel); + + if(startingState != undefined && endingState != undefined) { + transitions.push(new SimpleTransition(startingState, endingState)); + } else { + console.error("Starting or Ending State are not defined!", startingState, endingState) + } + } + return transitions; + } +} diff --git a/src/app/game-model/fs/store/StoreProject.ts b/src/app/game-model/fs/store/StoreProject.ts new file mode 100644 index 0000000..6503281 --- /dev/null +++ b/src/app/game-model/fs/store/StoreProject.ts @@ -0,0 +1,84 @@ +import {StorageModel} from "../StorageModel"; +import {GameModel} from "../../GameModel"; +import {ScriptAccount} from "../../scriptAccounts/ScriptAccount"; +import {Gamesystem} from "../../gamesystems/Gamesystem"; +import {SimpleGamesystem} from "../../gamesystems/SimpleGamesystem"; +import {ModelComponent} from "../../ModelComponent"; +import {ProductGamesystem} from "../../gamesystems/ProductGamesystem"; + +export class StoreProject { + + static JSON_INDENT = 4 + + static storeProject(gameModel: GameModel): StorageModel[] { + let storageModels: StorageModel[] = []; + storageModels = storageModels.concat(this.storeScriptAccounts(gameModel.scriptAccounts)); + storageModels = storageModels.concat(this.storeGamesystems(gameModel.gamesystems)); + return storageModels; + } + + static storeScriptAccounts(scriptAcccounts: ScriptAccount[]): StorageModel[] { + const storedScriptAccounts: StorageModel[] = []; + scriptAcccounts.forEach(scriptAccount => { + storedScriptAccounts.push({ + fileName: scriptAccount.componentName, + jsonString: JSON.stringify(scriptAccount, (key,value) => { + if(key === 'unsaved' || key === 'type') { + return undefined + } else { + return value; + } + }, StoreProject.JSON_INDENT), + storageRootDir: "script-accounts", + storagePath: [] + }) + scriptAccount.onSaveContent(); + }) + return storedScriptAccounts; + } + + static storeGamesystems(gamesystems: Gamesystem[]): StorageModel[] { + let storedGamesystems: StorageModel[] = []; + gamesystems.forEach(gamesystem => { + const storageModels: StorageModel[] = StoreProject.storeIndividualGamesystem(gamesystem, []); + storedGamesystems = storedGamesystems.concat(storageModels); + }) + return storedGamesystems; + } + + static storeIndividualGamesystem(gamesystem: Gamesystem, storagePath: string[]): StorageModel[] { + if(gamesystem instanceof SimpleGamesystem) { + return [new StorageModel(JSON.stringify(gamesystem, (key, value) => { + if(key === 'startingState' || key === 'endingState') { + return value.stateLabel + } + + if(key === 'incomingTransitions' || key === 'outgoingTransitions' || key === 'unsaved' || key === 'type') { + return undefined; + } else { + return value; + } + }, this.JSON_INDENT), gamesystem.componentName, storagePath, "gamesystems")]; + } else if(gamesystem instanceof ProductGamesystem) { + const storageModels: StorageModel[] = []; + //Root-StorageModel + storagePath.push(gamesystem.componentName); + (gamesystem as ProductGamesystem).innerGamesystems.forEach(innerGamesystem => { + const innerStorageModels: StorageModel[] = StoreProject.storeIndividualGamesystem(innerGamesystem, storagePath) + innerStorageModels.forEach(storageModel => storageModels.push(storageModel)) + }) + + const productData = { + 'componentName': gamesystem.componentName, + 'componentDescription': gamesystem.componentDescription + } + + + storageModels.push(new StorageModel(JSON.stringify(productData, null, this.JSON_INDENT), gamesystem.componentName, storagePath, "gamesystems")) + return storageModels; + } else { + return []; + } + } + +} diff --git a/src/app/game-model/gamesystems/Gamesystem.ts b/src/app/game-model/gamesystems/Gamesystem.ts index 2625649..e182c25 100644 --- a/src/app/game-model/gamesystems/Gamesystem.ts +++ b/src/app/game-model/gamesystems/Gamesystem.ts @@ -7,8 +7,8 @@ export abstract class Gamesystem extends ModelComponent{ states: S[] = []; transitions: T[] = []; - constructor(gamesystemName: string) { - super(gamesystemName, "", ModelComponentType.GAMESYTEM); + constructor(gamesystemName: string, gamesystemDescription: string) { + super(gamesystemName, gamesystemDescription, ModelComponentType.GAMESYTEM); } abstract createTransition(startingState: S, endingState: S): T|undefined; @@ -25,9 +25,4 @@ export abstract class Gamesystem extends ModelComponent{ return true; } - - save() { - - } - } diff --git a/src/app/game-model/gamesystems/ProductGamesystem.ts b/src/app/game-model/gamesystems/ProductGamesystem.ts index ecef1d3..7795942 100644 --- a/src/app/game-model/gamesystems/ProductGamesystem.ts +++ b/src/app/game-model/gamesystems/ProductGamesystem.ts @@ -14,7 +14,7 @@ export class ProductGamesystem extends Gamesystem 0) { @@ -65,10 +65,25 @@ export class ProductGamesystem extends Gamesystem[] = [this.innerGamesystems[0], this.innerGamesystems[1]]; + if(this.innerGamesystems[0] instanceof ProductGamesystem) { + this.innerGamesystems[0].generateFromChildsystems(); + } + + if(this.innerGamesystems[1] instanceof ProductGamesystem) { + this.innerGamesystems[1].generateFromChildsystems(); + } let gamesystem: ProductGamesystem = ProductGamesystem.generateFromChildsystems(this.innerGamesystems[0], this.innerGamesystems[1], false, integratedSystems); for(let i=2; i, rightSystem: Gamesystem, left_temp: boolean, integratedSystems: Gamesystem[]) { - const productGamesystem = new ProductGamesystem("Temporary Gamesystem"); + const productGamesystem = new ProductGamesystem("Temporary Gamesystem", ""); integratedSystems.forEach(integratedSystem => productGamesystem.addChildGamesystem(integratedSystem)); leftSystem.states.forEach(leftState => { diff --git a/src/app/game-model/gamesystems/SimpleGamesystem.ts b/src/app/game-model/gamesystems/SimpleGamesystem.ts index 4021c93..d5b4f1f 100644 --- a/src/app/game-model/gamesystems/SimpleGamesystem.ts +++ b/src/app/game-model/gamesystems/SimpleGamesystem.ts @@ -10,6 +10,8 @@ export class SimpleGamesystem extends Gamesystem parentGamesystem: ProductGamesystem | undefined + + createState(label: string, description: string): SimpleState | undefined { if(label == null) { return undefined; @@ -55,6 +57,4 @@ export class SimpleGamesystem extends Gamesystem return updated; } - - } diff --git a/src/app/game-model/scriptAccounts/ScriptAccount.ts b/src/app/game-model/scriptAccounts/ScriptAccount.ts index f47f3c7..65967f4 100644 --- a/src/app/game-model/scriptAccounts/ScriptAccount.ts +++ b/src/app/game-model/scriptAccounts/ScriptAccount.ts @@ -1,5 +1,6 @@ import {ModelComponent} from "../ModelComponent"; import {ModelComponentType} from "../ModelComponentType"; +import {SaveComponent} from "../SaveComponent"; export class ScriptAccount extends ModelComponent{ minValue: number = 0; @@ -7,8 +8,4 @@ export class ScriptAccount extends ModelComponent{ constructor(componentName: string, componentDescription: string) { super(componentName, componentDescription, ModelComponentType.SCRIPTACCOUNT); } - - save(): void { - } - } diff --git a/testModel/script-accounts/Luftfeuchtigkeit.json b/testModel/script-accounts/Luftfeuchtigkeit.json new file mode 100644 index 0000000..b948f4b --- /dev/null +++ b/testModel/script-accounts/Luftfeuchtigkeit.json @@ -0,0 +1,8 @@ +{ + "unsaved": false, + "componentName": "Luftfeuchtigkeit", + "componentDescription": "", + "type": 0, + "minValue": 0, + "maxValue": 100 +} \ No newline at end of file diff --git a/testModel/script-accounts/Temperature.json b/testModel/script-accounts/Temperature.json new file mode 100644 index 0000000..c53736b --- /dev/null +++ b/testModel/script-accounts/Temperature.json @@ -0,0 +1,8 @@ +{ + "unsaved": false, + "componentName": "Temperature", + "componentDescription": "", + "type": 0, + "minValue": 0, + "maxValue": 100 +} \ No newline at end of file