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