diff --git a/app/main.ts b/app/main.ts index c4ffd82..e1bbffd 100644 --- a/app/main.ts +++ b/app/main.ts @@ -8,7 +8,7 @@ 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"; -import {ItemStorage} from "./storage/storing/ItemStorage"; +import {ItemgroupStorage} from "./storage/storing/ItemgroupStorage"; let win: BrowserWindow | null = null; const args = process.argv.slice(1), @@ -97,6 +97,29 @@ function createWindow(): BrowserWindow { click: () => { win!.webContents.send('context-menu', "new-character"); } + }, + { + label: "Itemgroup", + submenu: [ + { + label: "Abstract Itemgroup", + click: () => { + win!.webContents.send('context-menu', "new-itemgroup-abstract") + } + }, + { + label: "Concrete Itemgroup", + click: () => { + win!.webContents.send('context-menu', "new-itemgroup-concrete") + } + }, + { + label: "Item", + click: () => { + win!.webContents.send("context-menu", "new-item") + } + } + ] } ] @@ -249,8 +272,9 @@ function recieveGameModelToStore(gameModel: StoredGameModel) { const characterStorage = new CharacterStorage(path.join(projectDirectory, ModelComponentFileDirectory.CHARACTER_DIR_NAME)) characterStorage.storeCharacters(gameModel.storedCharacters) - const itemStorage = new ItemStorage(path.join(projectDirectory, ModelComponentFileDirectory.ITEM_DIR_NAME)) - itemStorage.storeItem(gameModel.storedItems); + const itemgroupStorage = new ItemgroupStorage(path.join(projectDirectory, ModelComponentFileDirectory.ITEMGROUP_DIR_NAME)) + itemgroupStorage.storeItemgroups(gameModel.storedItemgroups); + itemgroupStorage.storeItems(gameModel.storedItems) } /*function deleteComponent(component: DeleteModel) { diff --git a/app/storage/ModelComponentFileDirectory.js b/app/storage/ModelComponentFileDirectory.js index fa14422..eda48c4 100644 --- a/app/storage/ModelComponentFileDirectory.js +++ b/app/storage/ModelComponentFileDirectory.js @@ -7,5 +7,5 @@ exports.ModelComponentFileDirectory = ModelComponentFileDirectory; ModelComponentFileDirectory.SCRIPTACCOUNT_DIR_NAME = "script-accounts"; ModelComponentFileDirectory.GAMESYSTEM_DIR_NAME = "gamesystems"; ModelComponentFileDirectory.CHARACTER_DIR_NAME = "characters"; -ModelComponentFileDirectory.ITEM_DIR_NAME = "items"; +ModelComponentFileDirectory.ITEMGROUP_DIR_NAME = "items"; //# sourceMappingURL=ModelComponentFileDirectory.js.map \ No newline at end of file diff --git a/app/storage/ModelComponentFileDirectory.ts b/app/storage/ModelComponentFileDirectory.ts index 38e675a..c68a714 100644 --- a/app/storage/ModelComponentFileDirectory.ts +++ b/app/storage/ModelComponentFileDirectory.ts @@ -2,5 +2,5 @@ export class ModelComponentFileDirectory { public static SCRIPTACCOUNT_DIR_NAME = "script-accounts" public static GAMESYSTEM_DIR_NAME = "gamesystems"; public static CHARACTER_DIR_NAME = "characters"; - public static ITEM_DIR_NAME = "items"; + static ITEMGROUP_DIR_NAME = "items"; } diff --git a/app/storage/StoredGameModel.js b/app/storage/StoredGameModel.js index 2ba280b..860b91d 100644 --- a/app/storage/StoredGameModel.js +++ b/app/storage/StoredGameModel.js @@ -2,11 +2,12 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.StoredGameModel = void 0; class StoredGameModel { - constructor(gameModelName, storedScriptAccounts, storedGamesystems, storedCharacters, storedItems) { + constructor(gameModelName, storedScriptAccounts, storedGamesystems, storedCharacters, storedItemgroups, storedItems) { this.gameModelName = gameModelName; this.storedGamesystems = storedGamesystems; this.storedScriptAccounts = storedScriptAccounts; this.storedCharacters = storedCharacters; + this.storedItemgroups = storedItemgroups; this.storedItems = storedItems; } } diff --git a/app/storage/StoredGameModel.ts b/app/storage/StoredGameModel.ts index 5449edd..829b038 100644 --- a/app/storage/StoredGameModel.ts +++ b/app/storage/StoredGameModel.ts @@ -6,15 +6,17 @@ export class StoredGameModel { storedGamesystems: StoreComponent[] storedScriptAccounts: StoreComponent[] storedCharacters: StoreComponent[] + storedItemgroups: StoreComponent[] storedItems: StoreComponent[] constructor(gameModelName: string, storedScriptAccounts: StoreComponent[], storedGamesystems: StoreComponent[], - storedCharacters: StoreComponent[], storedItems: StoreComponent[]) { + storedCharacters: StoreComponent[], storedItemgroups: StoreComponent[], storedItems: StoreComponent[]) { this.gameModelName = gameModelName; this.storedGamesystems = storedGamesystems; this.storedScriptAccounts = storedScriptAccounts; this.storedCharacters = storedCharacters; + this.storedItemgroups = storedItemgroups; this.storedItems = storedItems; } } diff --git a/app/storage/loader/GameModelLoader.js b/app/storage/loader/GameModelLoader.js index 5431d73..0b8447e 100644 --- a/app/storage/loader/GameModelLoader.js +++ b/app/storage/loader/GameModelLoader.js @@ -10,6 +10,8 @@ const CharacterLoader_1 = require("./CharacterLoader"); const ItemLoader_1 = require("./ItemLoader"); class GameModelLoader { constructor(gameModelDir) { + this.loadedItemgroups = []; + this.loadedItems = []; this.gameModelDir = gameModelDir; } loadGameModel() { @@ -17,8 +19,8 @@ class GameModelLoader { const storedScriptAccounts = this.loadScriptAccountComponents(); const storedGamesystems = this.loadGamesystems(); const storedCharacters = this.loadCharacters(); - const storedItems = this.loadItems(); - return new StoredGameModel_1.StoredGameModel(gameModelName, storedScriptAccounts, storedGamesystems, storedCharacters, storedItems); + this.loadItemsAndItemgroups(); + return new StoredGameModel_1.StoredGameModel(gameModelName, storedScriptAccounts, storedGamesystems, storedCharacters, this.loadedItemgroups, this.loadedItems); } loadScriptAccountComponents() { const scriptAccountDir = path.join(this.gameModelDir, ModelComponentFileDirectory_1.ModelComponentFileDirectory.SCRIPTACCOUNT_DIR_NAME); @@ -35,10 +37,12 @@ class GameModelLoader { const characterLoader = new CharacterLoader_1.CharacterLoader(characterDir); return characterLoader.loadCharacters(); } - loadItems() { - const itemDir = path.join(this.gameModelDir, ModelComponentFileDirectory_1.ModelComponentFileDirectory.ITEM_DIR_NAME); - const itemLoader = new ItemLoader_1.ItemLoader(itemDir); - return itemLoader.loadItems(); + loadItemsAndItemgroups() { + const itemgroupDir = path.join(this.gameModelDir, ModelComponentFileDirectory_1.ModelComponentFileDirectory.ITEMGROUP_DIR_NAME); + const itemgroupLoader = new ItemLoader_1.ItemLoader(itemgroupDir); + itemgroupLoader.loadItemgroups(); + this.loadedItems = itemgroupLoader.loadedItems; + this.loadedItemgroups = itemgroupLoader.loadedItemgroups; } } exports.GameModelLoader = GameModelLoader; diff --git a/app/storage/loader/GameModelLoader.ts b/app/storage/loader/GameModelLoader.ts index 14dc146..9423d73 100644 --- a/app/storage/loader/GameModelLoader.ts +++ b/app/storage/loader/GameModelLoader.ts @@ -11,6 +11,9 @@ import {ItemLoader} from "./ItemLoader"; export class GameModelLoader { gameModelDir: string + loadedItemgroups: StoreComponent[] = [] + loadedItems: StoreComponent[] = [] + constructor(gameModelDir: string) { this.gameModelDir = gameModelDir; @@ -22,9 +25,9 @@ export class GameModelLoader { const storedScriptAccounts = this.loadScriptAccountComponents(); const storedGamesystems = this.loadGamesystems(); const storedCharacters = this.loadCharacters() - const storedItems = this.loadItems(); + this.loadItemsAndItemgroups(); - return new StoredGameModel(gameModelName, storedScriptAccounts, storedGamesystems, storedCharacters, storedItems); + return new StoredGameModel(gameModelName, storedScriptAccounts, storedGamesystems, storedCharacters, this.loadedItemgroups, this.loadedItems); } private loadScriptAccountComponents() { @@ -46,9 +49,12 @@ export class GameModelLoader { } - private loadItems(): StoreComponent[] { - const itemDir = path.join(this.gameModelDir, ModelComponentFileDirectory.ITEM_DIR_NAME); - const itemLoader = new ItemLoader(itemDir) - return itemLoader.loadItems(); + private loadItemsAndItemgroups() { + const itemgroupDir = path.join(this.gameModelDir, ModelComponentFileDirectory.ITEMGROUP_DIR_NAME); + const itemgroupLoader = new ItemLoader(itemgroupDir); + itemgroupLoader.loadItemgroups(); + + this.loadedItems = itemgroupLoader.loadedItems; + this.loadedItemgroups = itemgroupLoader.loadedItemgroups; } } diff --git a/app/storage/loader/ItemLoader.js b/app/storage/loader/ItemLoader.js index 7536397..acb1bff 100644 --- a/app/storage/loader/ItemLoader.js +++ b/app/storage/loader/ItemLoader.js @@ -1,30 +1,58 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ItemLoader = void 0; -const fs = require("node:fs"); const StoreComponent_1 = require("../StoreComponent"); -const ModelComponentType_1 = require("../../../src/app/project/game-model/ModelComponentType"); const FileUtils_1 = require("../FileUtils"); +const path = require("node:path"); +const ModelComponentType_1 = require("../../../src/app/project/game-model/ModelComponentType"); +const fs = require("node:fs"); class ItemLoader { constructor(itemDir) { + this._loadedItemgroups = []; + this._loadedItems = []; this.itemDir = itemDir; } - loadItems() { - const itemFiles = FileUtils_1.FileUtils.listFilesInDirectory(this.itemDir); - const loadedItems = []; - itemFiles.forEach(itemFile => { - const loadedItem = this.loadItem(itemFile); - if (loadedItem != undefined) { - loadedItems.push(loadedItem); + loadItemgroups() { + this.loadItemgroupsRecursively(this.itemDir); + } + get loadedItemgroups() { + return this._loadedItemgroups; + } + get loadedItems() { + return this._loadedItems; + } + loadItemgroupsRecursively(currentDir) { + const itemgroupFiles = FileUtils_1.FileUtils.listFilesInDirectory(currentDir); + itemgroupFiles.forEach(itemgroupFile => { + if (fs.lstatSync(itemgroupFile).isDirectory()) { + this.loadItemgroupsRecursively(itemgroupFile); + } + else if (path.basename(itemgroupFile).endsWith(".json") && this.fileRepresentsItemgroup(itemgroupFile)) { + const loadedItemgroup = this.loadSingleItemgroup(itemgroupFile); + this._loadedItemgroups.push(loadedItemgroup); + } + else if (path.basename(itemgroupFile).endsWith(".json")) { + const loadedItem = this.loadSingleItem(itemgroupFile); + this._loadedItems.push(loadedItem); } }); - return loadedItems; } - loadItem(itemFile) { - if (itemFile.endsWith(".json")) { - const itemData = fs.readFileSync(itemFile, 'utf-8'); - return new StoreComponent_1.StoreComponent(itemData, itemFile, ModelComponentType_1.ModelComponentType.ITEM); + loadSingleItemgroup(itemgroupFile) { + if (itemgroupFile.endsWith(".json")) { + const data = fs.readFileSync(itemgroupFile, "utf-8"); + return new StoreComponent_1.StoreComponent(data, itemgroupFile, ModelComponentType_1.ModelComponentType.ITEMGROUP); } + return undefined; + } + loadSingleItem(itemFile) { + if (itemFile.endsWith(".json")) { + const data = fs.readFileSync(itemFile, "utf-8"); + return new StoreComponent_1.StoreComponent(data, itemFile, ModelComponentType_1.ModelComponentType.ITEM); + } + return undefined; + } + fileRepresentsItemgroup(file) { + return path.basename(path.dirname(file)) === path.parse(path.basename(file)).name; } } exports.ItemLoader = ItemLoader; diff --git a/app/storage/loader/ItemLoader.ts b/app/storage/loader/ItemLoader.ts index aca7a9c..91b6a83 100644 --- a/app/storage/loader/ItemLoader.ts +++ b/app/storage/loader/ItemLoader.ts @@ -1,33 +1,65 @@ -import * as fs from "node:fs"; import {StoreComponent} from "../StoreComponent"; -import {ModelComponentType} from "../../../src/app/project/game-model/ModelComponentType"; import {FileUtils} from "../FileUtils"; +import * as path from "node:path"; +import {ModelComponentType} from "../../../src/app/project/game-model/ModelComponentType"; +import * as fs from "node:fs"; export class ItemLoader { - private itemDir: string + itemDir: string + private _loadedItemgroups: StoreComponent[] = [] + private _loadedItems: StoreComponent[] = [] constructor(itemDir: string) { this.itemDir = itemDir; } - loadItems() { - const itemFiles = FileUtils.listFilesInDirectory(this.itemDir); - const loadedItems :StoreComponent[] = [] - itemFiles.forEach(itemFile => { - const loadedItem = this.loadItem(itemFile); - if(loadedItem != undefined) { - loadedItems.push(loadedItem); + loadItemgroups(){ + this.loadItemgroupsRecursively(this.itemDir); + } + + + get loadedItemgroups(): StoreComponent[] { + return this._loadedItemgroups; + } + + get loadedItems(): StoreComponent[] { + return this._loadedItems; + } + + private loadItemgroupsRecursively(currentDir: string) { + const itemgroupFiles = FileUtils.listFilesInDirectory(currentDir); + + itemgroupFiles.forEach(itemgroupFile => { + if(fs.lstatSync(itemgroupFile).isDirectory()) { + this.loadItemgroupsRecursively(itemgroupFile); + } else if(path.basename(itemgroupFile).endsWith(".json") && this.fileRepresentsItemgroup(itemgroupFile)){ + const loadedItemgroup = this.loadSingleItemgroup(itemgroupFile)!; + this._loadedItemgroups.push(loadedItemgroup) + } else if(path.basename(itemgroupFile).endsWith(".json")) { + const loadedItem = this.loadSingleItem(itemgroupFile)!; + this._loadedItems.push(loadedItem); } }) - - return loadedItems; } - private loadItem(itemFile: string) { - if(itemFile.endsWith(".json")) { - const itemData = fs.readFileSync(itemFile, 'utf-8'); - return new StoreComponent(itemData, itemFile, ModelComponentType.ITEM) + private loadSingleItemgroup(itemgroupFile: string): StoreComponent | undefined { + if(itemgroupFile.endsWith(".json")) { + const data = fs.readFileSync(itemgroupFile, "utf-8"); + return new StoreComponent(data, itemgroupFile, ModelComponentType.ITEMGROUP); } + return undefined + } + + private loadSingleItem(itemFile: string) { + if(itemFile.endsWith(".json")) { + const data = fs.readFileSync(itemFile, "utf-8"); + return new StoreComponent(data, itemFile, ModelComponentType.ITEM); + } + return undefined + } + + private fileRepresentsItemgroup(file: string): boolean { + return path.basename(path.dirname(file)) === path.parse(path.basename(file)).name; } } diff --git a/app/storage/storing/ItemgroupStorage.js b/app/storage/storing/ItemgroupStorage.js new file mode 100644 index 0000000..2851c97 --- /dev/null +++ b/app/storage/storing/ItemgroupStorage.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ItemgroupStorage = void 0; +const FileUtils_1 = require("../FileUtils"); +const path = require("node:path"); +const fs = require("node:fs"); +class ItemgroupStorage { + constructor(itemgroupDir) { + this.itemgroupDir = itemgroupDir; + FileUtils_1.FileUtils.prepareDirectoryFroWriting(this.itemgroupDir); + } + storeItemgroups(itemgroups) { + itemgroups.forEach(itemgroup => { + this.storeItemgroup(itemgroup); + }); + } + storeItemgroup(itemgroup) { + const file = path.join(...itemgroup.fileName.split("/")); + const completeFileName = path.join(this.itemgroupDir, file); + const itemgroupDirectory = path.join(...itemgroup.fileName.split("/").slice(0, -1)); + const completeItemgroupDirectory = path.join(this.itemgroupDir, itemgroupDirectory); + FileUtils_1.FileUtils.prepareDirectoryFroWriting(completeItemgroupDirectory); + fs.writeFileSync(completeFileName + ".json", itemgroup.jsonString, "utf-8"); + } + storeItems(storedItems) { + storedItems.forEach(item => this.storeItemgroup(item)); + } +} +exports.ItemgroupStorage = ItemgroupStorage; +//# sourceMappingURL=ItemgroupStorage.js.map \ No newline at end of file diff --git a/app/storage/storing/ItemgroupStorage.ts b/app/storage/storing/ItemgroupStorage.ts new file mode 100644 index 0000000..84f7fdd --- /dev/null +++ b/app/storage/storing/ItemgroupStorage.ts @@ -0,0 +1,35 @@ +import {FileUtils} from "../FileUtils"; +import {StoreComponent} from "../StoreComponent"; +import * as path from "node:path"; +import * as fs from "node:fs"; + +export class ItemgroupStorage { + private itemgroupDir: string + + + constructor(itemgroupDir: string) { + this.itemgroupDir = itemgroupDir; + FileUtils.prepareDirectoryFroWriting(this.itemgroupDir); + } + + public storeItemgroups(itemgroups: StoreComponent[]) { + itemgroups.forEach(itemgroup => { + this.storeItemgroup(itemgroup) + }) + } + + private storeItemgroup(itemgroup: StoreComponent) { + const file = path.join(... itemgroup.fileName.split("/")); + const completeFileName = path.join(this.itemgroupDir, file); + + const itemgroupDirectory = path.join(... itemgroup.fileName.split("/").slice(0, -1)) + const completeItemgroupDirectory = path.join(this.itemgroupDir, itemgroupDirectory) + FileUtils.prepareDirectoryFroWriting(completeItemgroupDirectory); + fs.writeFileSync(completeFileName + ".json", itemgroup.jsonString, "utf-8") + } + + + storeItems(storedItems: StoreComponent[]) { + storedItems.forEach(item => this.storeItemgroup(item)) + } +} diff --git a/e2e/game-model/gamesystems/CreateGamesystem.spec.ts b/e2e/game-model/gamesystems/CreateGamesystem.spec.ts deleted file mode 100644 index fffea92..0000000 --- a/e2e/game-model/gamesystems/CreateGamesystem.spec.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { test, expect } from '@playwright/test'; -import {GamesystemTrainer} from "./GamesystemTrainer"; -import {ProductGamesystem} from "../../../src/app/project/game-model/gamesystems/ProductGamesystem"; -test.describe('Test Create Gamesystems', () => { - - test('Test creating gamesystem with invalid name', async => { - const gameModel = GamesystemTrainer.givenEmptyGameModel(); - let result = gameModel.createGamesystem(undefined, undefined); - expect(result).toBeUndefined(); - - result = gameModel.createGamesystem(null, undefined); - expect(result).toBeUndefined(); - }) - - test("Test creating gamesystem with valid name but without parent", async => { - const gameModel = GamesystemTrainer.givenEmptyGameModel(); - let result = gameModel.createGamesystem(GamesystemTrainer.SIMPLEGAMESYSTEMNAME, undefined); - expect(result).toBeDefined(); - expect(gameModel.gamesystems.length).toEqual(1); - expect(gameModel.findGamesystem(GamesystemTrainer.SIMPLEGAMESYSTEMNAME)).toBeDefined(); - }) - - test("Test creating Gamesystem with valid name but with Product Parent", async => { - const gameModel = GamesystemTrainer.givenGameModelWithProductGamesytemOnTopLayer(); - let result = gameModel.createGamesystem(GamesystemTrainer.SIMPLEGAMESYSTEM_LEAF_LEFT, GamesystemTrainer.TOP_PRODUCT_GAMESYSTEM_NAME); - expect(result).toBeDefined(); - expect(result.parentGamesystem!.componentName).toEqual(GamesystemTrainer.TOP_PRODUCT_GAMESYSTEM_NAME); - expect(result.parentGamesystem!.innerGamesystems.length).toEqual(3); - expect(result.parentGamesystem!.innerGamesystems.includes(result)).toBeTruthy(); - }) - - test("Test creating Gamesystem with valid name but with Simple Parent", async() => { - const gameModel = GamesystemTrainer.givenGameModelWithSimpleGamesystemOnTopLayer(); - let result = gameModel.createGamesystem(GamesystemTrainer.SIMPLEGAMESYSTEM_LEAF_LEFT, GamesystemTrainer.SIMPLEGAMESYSTEMNAME); - expect(result).toBeDefined(); - expect(gameModel.gamesystems.length).toEqual(1); - expect(gameModel.gamesystems[0]).toBeInstanceOf(ProductGamesystem); - expect(gameModel.gamesystems[0]).toEqual(result.parentGamesystem); - expect((gameModel.gamesystems[0] as ProductGamesystem).innerGamesystems.length).toEqual(1); - expect((gameModel.gamesystems[0] as ProductGamesystem).innerGamesystems.includes(result)).toBeTruthy(); - }) - - -}); diff --git a/e2e/game-model/scriptAccounts/ScriptAccountTest.spec.ts b/e2e/game-model/scriptAccounts/ScriptAccountTest.spec.ts deleted file mode 100644 index 27aaed2..0000000 --- a/e2e/game-model/scriptAccounts/ScriptAccountTest.spec.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { BrowserContext, ElectronApplication, Page, _electron as electron } from 'playwright'; -import { test, expect } from '@playwright/test'; -import * as PATH from 'path'; -import {GameModel} from "../../../src/app/project/game-model/GameModel"; -import {Gamesystem} from "../../src/app/project/game-model/gamesystems/Gamesystem"; -import {ScriptAccount} from "../../../src/app/project/game-model/scriptAccounts/ScriptAccount"; -import {ModelComponentType} from "../../../src/app/project/game-model/ModelComponentType"; - -test.describe('Test ScriptAccounts', () => { - - test("Test ScriptAccount Creation", async () => { - const scriptAccunt = new ScriptAccount("ScriptAccount", "Description"); - - expect(scriptAccunt.componentName).toEqual("ScriptAccount"); - expect(scriptAccunt.componentDescription).toEqual("Description"); - expect(scriptAccunt.type).toEqual(ModelComponentType.SCRIPTACCOUNT); - expect(scriptAccunt.minValue).toEqual(0); - expect(scriptAccunt.maxValue).toEqual(100); - }) - - test("Test Adding ScriptAccounts", async () => { - const gameModel: GameModel = new GameModel("GameModel"); - - let scriptAccount =gameModel.createScriptAccount("ScriptAccount"); - expect(scriptAccount).toBeDefined(); - expect(gameModel.scriptAccounts.length).toEqual(1); - expect(gameModel.scriptAccounts.includes(scriptAccount)).toBeTruthy(); - - //Test adding scriptAccount with already existing name - const scriptAccount2 = gameModel.createScriptAccount("ScriptAccount") - expect(scriptAccount2).toBeUndefined(); - expect(gameModel.scriptAccounts.length).toEqual(1); - - //Test for adding invalid names as scriptaccount names (null/undefined/empty) - let result = gameModel.createScriptAccount(null); - expect(result).toBeUndefined(); - expect(gameModel.scriptAccounts.length).toEqual(1); - result = gameModel.createScriptAccount(undefined); - expect(result).toBeUndefined(); - expect(gameModel.scriptAccounts.length).toEqual(1); - result = gameModel.createScriptAccount(""); - expect(result).toBeUndefined(); - expect(gameModel.scriptAccounts.length).toEqual(1); - }) - - test("test Removing ScriptAccounts", async () => { - const gameModel: GameModel = new GameModel("GameModel"); - let scriptAccount = new ScriptAccount("test", "") - - gameModel.removeScriptAccount(scriptAccount); - expect(gameModel.scriptAccounts.length).toEqual(0); - - scriptAccount = gameModel.createScriptAccount("ScriptAccount"); - gameModel.removeScriptAccount(scriptAccount); - expect(gameModel.scriptAccounts.length).toEqual(0); - - gameModel.removeScriptAccount(undefined); - expect(gameModel.scriptAccounts.length).toEqual(0); - - gameModel.removeScriptAccount(null); - expect(gameModel.scriptAccounts.length).toEqual(0); - - scriptAccount = gameModel.createScriptAccount(scriptAccount); - let scriptAccount2 = gameModel.createScriptAccount("ScriptAccount 2"); - - gameModel.removeScriptAccount(scriptAccount); - expect(gameModel.scriptAccounts.length).toEqual(1); - expect(gameModel.scriptAccounts.includes(scriptAccount2)).toBeTruthy(); - }) - -}); diff --git a/src/app/app.component.html b/src/app/app.component.html index 83a3954..c8c374d 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,13 +1,14 @@
+ (click)="openScriptAccountsOverview()">inventory_2 - + +
@@ -25,13 +26,15 @@ - +
- +
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 64992c3..4bfac7a 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -25,10 +25,17 @@ import {CharacterOverviewComponent} from "./side-overviews/character-overview/ch import {CharacterSerializer} from "./project/serializer/CharacterSerializer"; import {CharacterParser} from "./project/parser/characterParser/CharacterParser"; import {TemplateType} from "./project/game-model/templates/TemplateType"; -import {TemplateTypeUtilities} from "./project/game-model/templates/TemplateTypeUtilities"; import {SimpleTemplateGamesystem} from "./project/game-model/templates/simpleGamesystem/SimpleTemplateGamesystem"; import {ItemSerializer} from "./project/serializer/ItemSerializer"; -import {ItemParser} from "./project/parser/ItemParser"; +import {ItemgroupParser} from "./project/parser/itemParser/ItemgroupParser"; +import {ItemParser} from "./project/parser/itemParser/ItemParser"; +import {ItemgroupCreator} from "./project/game-model/utils/creator/ItemgroupCreator"; +import {ItemOverviewComponent} from "./side-overviews/item-overview/item-overview.component"; +import {Overview} from "./side-overviews/Overview"; +import {ItemCreator} from "./project/game-model/utils/creator/ItemCreator"; +import {ScriptAccountCreator} from "./project/game-model/utils/creator/ScriptAccountCreator"; +import {CharacterCreator} from "./project/game-model/utils/creator/CharacterCreator"; +import {GamesystemCreator} from "./project/game-model/utils/creator/GamesystemCreator"; @Component({ selector: 'app-root', @@ -43,6 +50,7 @@ export class AppComponent implements OnInit{ @ViewChild('scriptAccountOverview') scriptAccountOverview: ScriptAccountOverviewComponent | undefined @ViewChild('gamesystemOverview') gamesystemOverview: GamescriptOverviewComponent | undefined @ViewChild('characterOverview') characterOverview: CharacterOverviewComponent | undefined + @ViewChild('itemOverview') itemOverview: ItemOverviewComponent | undefined gameModel: GameModel | undefined @@ -81,12 +89,45 @@ export class AppComponent implements OnInit{ } else if(message.startsWith("new")) { const splittedMessage = message.split("-"); const modelComponentType = ModelComponentTypeUtillities.fromString(splittedMessage[1]); - const templateType = TemplateTypeUtilities.fromString(splittedMessage[2]); - if(modelComponentType != undefined) { - this.onCreateModelComponent(modelComponentType, templateType); - } else { - console.log("[ERROR] [App-Component] Unknown Context-Menu Command!") + if(modelComponentType !== undefined) { + let creationContext = ""; + if(splittedMessage.length > 2) { + creationContext = splittedMessage[2]; + } + + let componentCreator; + switch (modelComponentType) { + case ModelComponentType.ITEMGROUP: { + componentCreator = new ItemgroupCreator(creationContext, this.gameModel!, this.selectedModelComponent); + } break + case ModelComponentType.ITEM: { + componentCreator = new ItemCreator(creationContext, this.gameModel!, this.selectedModelComponent); + } break + case ModelComponentType.SCRIPTACCOUNT: { + componentCreator = new ScriptAccountCreator(creationContext, this.gameModel!, this.selectedModelComponent); + } break + case ModelComponentType.CHARACTER: { + componentCreator = new CharacterCreator(creationContext, this.gameModel!, this.selectedModelComponent); + } break + case ModelComponentType.GAMESYTEM: { + componentCreator = new GamesystemCreator(creationContext, this.gameModel!, this.selectedModelComponent); + } break + } + + if(componentCreator) { + const createdModel = componentCreator.createModelComponent(); + this.openModelComponent(createdModel!) + + const openedOverview = this.openedOverview; + if(openedOverview) { + openedOverview.refresh() + } + + } else { + console.log("[ERROR] Unknown Creation Command: ", message) + } } + } } @@ -109,6 +150,7 @@ export class AppComponent implements OnInit{ } }break + } } @@ -133,53 +175,6 @@ export class AppComponent implements OnInit{ }) } - private onCreateModelComponent(modelComponentType: ModelComponentType, templateType: TemplateType | undefined) { - switch (modelComponentType) { - case ModelComponentType.SCRIPTACCOUNT: this.onCreateNewScriptAccount(); break - case ModelComponentType.GAMESYTEM: this.onCreateNewGamesystem(templateType); break - case ModelComponentType.CHARACTER: this.onCreateNewCharacter(); break - } - } - - private onCreateNewScriptAccount() { - const createdScriptAccount = this.gameModel!.createScriptAccount("New ScriptAccount"); - if(createdScriptAccount != undefined) { - this.editor?.openGameModelComponent(createdScriptAccount); - } else { - console.log("[DEBUG] [App-Component] ScriptAccount could not be created (Name not unique)"); - } - } - - private onCreateNewGamesystem(templateType: TemplateType | undefined) { - let parentGamesystemName = undefined - if(this.openContent != ModelComponentType.GAMESYTEM) { - this.openGamesystemsOverview(); - } else { - parentGamesystemName = this.gamesystemOverview!.selectedGamesystemName; - } - - - let createdGamesystem; - if(parentGamesystemName == undefined) { - createdGamesystem = this.gameModel?.createSimpleGamesystem("New Gamesystem", templateType); - } else { - createdGamesystem = this.gameModel!.createSimpleGamesystemWithParent("New Gamesystem", parentGamesystemName, templateType) - } - - if(createdGamesystem != undefined) { - this.gamesystemOverview!.refresh(); - this.editor?.openGameModelComponent(createdGamesystem); - } - } - - private onCreateNewCharacter() { - const createdCharacter = this.gameModel!.createCharacter("New Character") - if(createdCharacter != undefined) { - this.editor?.openGameModelComponent(createdCharacter); - } else { - console.log("[DEBUG] [App-Component] ScriptAccount could not be created (Name not unique)"); - } - } private getSelectedModelComponent(): ModelComponent | undefined { if(this.openContent == ModelComponentType.SCRIPTACCOUNT) { @@ -225,7 +220,12 @@ export class AppComponent implements OnInit{ const characterParser = new CharacterParser(characterTemplateSystems, characterRelationTemplateSystems, gameModel.scriptAccounts); gameModel.characters = characterParser.parseCharacters(storedGameModel.storedCharacters) - gameModel.inventoryItems = ItemParser.parseItems(storedGameModel.storedItems) + const itemgroupParser = new ItemgroupParser(); + itemgroupParser.parseItemgroups(storedGameModel.storedItemgroups); + gameModel.itemgroups = itemgroupParser.getParsedTopItemgroups(); + + const itemParser = new ItemParser(itemgroupParser.getParsedItemgroups()) + itemParser.parseItems(storedGameModel.storedItems); this.gameModel = gameModel; } @@ -235,11 +235,12 @@ export class AppComponent implements OnInit{ const storedScriptAccounts = ScriptAccountSerializer.serializeScriptAccounts(this.gameModel.scriptAccounts) const storedGamesystems: StoreComponent[] = GamesystemSerializer.serializeGamesystems(this.gameModel.gamesystems) const storedCharacters: StoreComponent[] = CharacterSerializer.serializeCharacters(this.gameModel.characters) - const storedItems: StoreComponent[] = ItemSerializer.serializeItems(this.gameModel.inventoryItems); - console.log(this.gameModel.inventoryItems) - const storeModel = new StoredGameModel(this.gameModel.gameModelName, storedScriptAccounts, - storedGamesystems, storedCharacters, storedItems) + const itemSerializer = new ItemSerializer(); + const storedItemgroups: StoreComponent[] = itemSerializer.serializeItemgroups(this.gameModel!.itemgroups); + const storedItems: StoreComponent[] = itemSerializer.getSerializedItems() + + const storeModel = new StoredGameModel(this.gameModel.gameModelName, storedScriptAccounts, storedGamesystems, storedCharacters, storedItemgroups, storedItems) if(this.electronService.isElectron) { this.electronService.ipcRenderer.send('save-model', storeModel) @@ -262,8 +263,8 @@ export class AppComponent implements OnInit{ this.drawer!.open() } - openContentOverview(contentType: ModelComponentType) { - this.openContent = contentType; + openOverview(overviewType: ModelComponentType) { + this.openContent = overviewType; this.drawer!.open(); } @@ -296,5 +297,26 @@ export class AppComponent implements OnInit{ } } + get selectedModelComponent(): ModelComponent | undefined { + switch (this.openContent) { + case ModelComponentType.GAMESYTEM: return this.gamesystemOverview!.getSelectedGamesystem(); + case ModelComponentType.CHARACTER: return this.characterOverview!.selectedCharacter; + case ModelComponentType.SCRIPTACCOUNT: return this.scriptAccountOverview!.selectedScriptAccount; + case ModelComponentType.ITEMGROUP: return this.itemOverview!.selectedModelComponent; + case ModelComponentType.ITEM: return this.itemOverview!.selectedModelComponent; + default: return undefined + } + } + get openedOverview(): Overview | undefined { + if(this.openContent === ModelComponentType.ITEMGROUP || this.openContent === ModelComponentType.ITEM) { + return this.itemOverview; + } else if(this.openContent === ModelComponentType.SCRIPTACCOUNT) { + return this.scriptAccountOverview; + } else if(this.openContent === ModelComponentType.CHARACTER) { + return this.characterOverview; + } else if(this.openContent === ModelComponentType.GAMESYTEM) { + return this.gamesystemOverview; + } + } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index a3bac22..152535a 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -61,7 +61,7 @@ import { ProductStateEditorComponent } from "./editor/gamesystem-editor/state-editor/product-state-editor/product-state-editor.component"; import {MatTooltip} from "@angular/material/tooltip"; -import {MatCard, MatCardActions, MatCardContent, MatCardHeader, MatCardTitle} from "@angular/material/card"; +import {MatCard, MatCardContent, MatCardHeader, MatCardTitle} from "@angular/material/card"; import { ScriptaccountActionEditorComponent } from "./editor/gamesystem-editor/transition-editor/scriptaccount-action-editor/scriptaccount-action-editor.component"; @@ -72,7 +72,7 @@ import {CharacterOverviewComponent} from "./side-overviews/character-overview/ch import {CharacterEditorComponent} from "./editor/character-editor/character-editor.component"; import { MatAccordion, - MatExpansionPanel, + MatExpansionPanel, MatExpansionPanelDescription, MatExpansionPanelHeader, MatExpansionPanelTitle } from "@angular/material/expansion"; @@ -82,14 +82,15 @@ import { import { StateInitialCellComponent } from "./editor/gamesystem-editor/state-editor/simple-state-editor/state-initial-cell/state-initial-cell.component"; +import {ItemOverviewComponent} from "./side-overviews/item-overview/item-overview.component"; +import {ItemGroupEditorComponent} from "./editor/items/item-group-editor/item-group-editor.component"; +import {ItemEditorComponent} from "./editor/items/item-editor/item-editor.component"; import { - InventoryItemOverviewComponent -} from "./side-overviews/inventory-item-overview/inventory-item-overview.component"; -import {InventoryItemEditorComponent} from "./editor/inventory-item-editor/inventory-item-editor.component"; + ItemgroupInheritorComponent +} from "./editor/items/item-editor/itemgroup-inheritor/itemgroup-inheritor.component"; import { - ItemPropertyEditorComponent -} from "./editor/inventory-item-editor/item-property-editor/item-property-editor.component"; - + InheritedItemCharacteristicEditorComponent +} from "./editor/items/item-editor/inherited-item-characteristic-editor/inherited-item-characteristic-editor.component"; // AoT requires an exported function for factories const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json'); @@ -115,9 +116,11 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl CharacterEditorComponent, TemplateSpecificatorComponent, StateInitialCellComponent, - InventoryItemOverviewComponent, - InventoryItemEditorComponent, - ItemPropertyEditorComponent + ItemOverviewComponent, + ItemGroupEditorComponent, + ItemEditorComponent, + ItemgroupInheritorComponent, + InheritedItemCharacteristicEditorComponent ], imports: [ BrowserModule, @@ -181,7 +184,7 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl MatExpansionPanelTitle, MatCardTitle, MatExpansionPanelHeader, - MatCardActions, + MatExpansionPanelDescription ], providers: [], bootstrap: [AppComponent] diff --git a/src/app/editor/editor.component.html b/src/app/editor/editor.component.html index e856a70..ae86488 100644 --- a/src/app/editor/editor.component.html +++ b/src/app/editor/editor.component.html @@ -16,11 +16,11 @@ [scriptAccounts]="gameModel!.scriptAccounts"> + [gameModel]="gameModel!" + > + - - + + diff --git a/src/app/editor/editor.component.ts b/src/app/editor/editor.component.ts index b69cdbf..2b31b33 100644 --- a/src/app/editor/editor.component.ts +++ b/src/app/editor/editor.component.ts @@ -7,6 +7,7 @@ import {State} from "../project/game-model/gamesystems/states/State"; import {Transition} from "../project/game-model/gamesystems/transitions/Transition"; import {ModelComponentType} from "../project/game-model/ModelComponentType"; import {Character} from "../project/game-model/characters/Character"; +import {ItemGroup} from "../project/game-model/inventory/ItemGroup"; import {Item} from "../project/game-model/inventory/Item"; @@ -28,7 +29,6 @@ export class EditorComponent { } else { this.activeTab = this.gameModelComponents.findIndex(component => component.componentName === gameModelComponent.componentName); } - console.log(gameModelComponent) } closeGameModelComponent(gameModelComponent: ModelComponent) { @@ -60,10 +60,17 @@ export class EditorComponent { return undefined; } + convertModelComponentToItemGroup(modelComponent: ModelComponent) { + if(modelComponent instanceof ItemGroup) { + return modelComponent as ItemGroup + } + return undefined; + } + convertModelComponentToItem(modelComponent: ModelComponent) { if(modelComponent instanceof Item) { - return modelComponent as Item + return modelComponent as Item; } - return undefined + return undefined; } } diff --git a/src/app/editor/items/item-editor/inherited-item-characteristic-editor/inherited-item-characteristic-editor.component.html b/src/app/editor/items/item-editor/inherited-item-characteristic-editor/inherited-item-characteristic-editor.component.html new file mode 100644 index 0000000..42bbb40 --- /dev/null +++ b/src/app/editor/items/item-editor/inherited-item-characteristic-editor/inherited-item-characteristic-editor.component.html @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + +
Characteristic{{characteristicValue.key.characteristicName}}Value + {{characteristicValue.value}} + + Value + + + + + +
diff --git a/src/app/editor/items/item-editor/inherited-item-characteristic-editor/inherited-item-characteristic-editor.component.scss b/src/app/editor/items/item-editor/inherited-item-characteristic-editor/inherited-item-characteristic-editor.component.scss new file mode 100644 index 0000000..80c8212 --- /dev/null +++ b/src/app/editor/items/item-editor/inherited-item-characteristic-editor/inherited-item-characteristic-editor.component.scss @@ -0,0 +1,3 @@ +.mat-column-edit { + width: 32px; +} diff --git a/src/app/editor/items/item-editor/inherited-item-characteristic-editor/inherited-item-characteristic-editor.component.spec.ts b/src/app/editor/items/item-editor/inherited-item-characteristic-editor/inherited-item-characteristic-editor.component.spec.ts new file mode 100644 index 0000000..437d097 --- /dev/null +++ b/src/app/editor/items/item-editor/inherited-item-characteristic-editor/inherited-item-characteristic-editor.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InheritedItemCharacteristicEditorComponent } from './inherited-item-characteristic-editor.component'; + +describe('InheritedItemCharacteristicEditorComponent', () => { + let component: InheritedItemCharacteristicEditorComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [InheritedItemCharacteristicEditorComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(InheritedItemCharacteristicEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/editor/items/item-editor/inherited-item-characteristic-editor/inherited-item-characteristic-editor.component.ts b/src/app/editor/items/item-editor/inherited-item-characteristic-editor/inherited-item-characteristic-editor.component.ts new file mode 100644 index 0000000..167bd38 --- /dev/null +++ b/src/app/editor/items/item-editor/inherited-item-characteristic-editor/inherited-item-characteristic-editor.component.ts @@ -0,0 +1,42 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {ItemGroup} from "../../../../project/game-model/inventory/ItemGroup"; +import {Item} from "../../../../project/game-model/inventory/Item"; +import {MatTableDataSource} from "@angular/material/table"; +import {ItemgroupCharacteristicValue} from "../../../../project/game-model/inventory/ItemgroupCharacteristicValue"; + +@Component({ + selector: 'app-inherited-item-characteristic-editor', + templateUrl: './inherited-item-characteristic-editor.component.html', + styleUrl: './inherited-item-characteristic-editor.component.scss' +}) +export class InheritedItemCharacteristicEditorComponent implements OnInit{ + + @Input() inheritedItemgroup: ItemGroup | undefined + @Input() item: Item | undefined + + datasource: MatTableDataSource = new MatTableDataSource(); + displayedColumns: string[] = ['characteristic', 'value', 'edit'] + editedItemgroupCharacteristicValue: ItemgroupCharacteristicValue | undefined + + ngOnInit() { + this.item!.initializeItemCharacteristics(); + this.datasource.data = this.findCharacteristicValuesByItemgroup(this.inheritedItemgroup!); + } + + + findCharacteristicValuesByItemgroup(itemGroup: ItemGroup): ItemgroupCharacteristicValue[] { + const result = this.item?.itemCharacteristicValues.filter(value => value.key.itemgroup.componentName === itemGroup.componentName); + if(result != undefined) { + return result; + } + return [] + } + + editCharacteristicValue(itemCharacteristicValue: ItemgroupCharacteristicValue): void { + this.editedItemgroupCharacteristicValue = itemCharacteristicValue; + } + + finishEditing() { + this.editedItemgroupCharacteristicValue = undefined; + } +} diff --git a/src/app/editor/items/item-editor/item-editor.component.html b/src/app/editor/items/item-editor/item-editor.component.html new file mode 100644 index 0000000..8ff7a5d --- /dev/null +++ b/src/app/editor/items/item-editor/item-editor.component.html @@ -0,0 +1,20 @@ + + + Inherited Itemgroups + + + + + + {{itemgroup.componentName}} + {{itemgroup.componentDescription}} + + +
+ +
+
+
+ +
+
diff --git a/src/app/editor/items/item-editor/item-editor.component.scss b/src/app/editor/items/item-editor/item-editor.component.scss new file mode 100644 index 0000000..6fd81c6 --- /dev/null +++ b/src/app/editor/items/item-editor/item-editor.component.scss @@ -0,0 +1,3 @@ +.panel-actions { + float: right; +} diff --git a/src/app/editor/items/item-editor/item-editor.component.spec.ts b/src/app/editor/items/item-editor/item-editor.component.spec.ts new file mode 100644 index 0000000..a1e4546 --- /dev/null +++ b/src/app/editor/items/item-editor/item-editor.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ItemEditorComponent } from './item-editor.component'; + +describe('ItemEditorComponent', () => { + let component: ItemEditorComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ItemEditorComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ItemEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/editor/items/item-editor/item-editor.component.ts b/src/app/editor/items/item-editor/item-editor.component.ts new file mode 100644 index 0000000..05a673d --- /dev/null +++ b/src/app/editor/items/item-editor/item-editor.component.ts @@ -0,0 +1,49 @@ +import {Component, Input} from '@angular/core'; +import {Item} from "../../../project/game-model/inventory/Item"; +import {ItemGroup} from "../../../project/game-model/inventory/ItemGroup"; +import {GameModel} from "../../../project/game-model/GameModel"; +import {MatDialog} from "@angular/material/dialog"; +import {ItemgroupInheritorComponent} from "./itemgroup-inheritor/itemgroup-inheritor.component"; +import {ItemgroupUtilities} from "../../../project/game-model/utils/ItemgroupUtilities"; + +@Component({ + selector: 'app-item-editor', + templateUrl: './item-editor.component.html', + styleUrl: './item-editor.component.scss' +}) +export class ItemEditorComponent { + + @Input() item: Item | undefined + @Input() gameModel: GameModel | undefined; + + + constructor(private dialog: MatDialog) { + + } + + onAddNewInheritedItemgroup() { + const itemgroups = this.item!.manuallyInheritedGroups.concat(this.item!.hierarchyInheritedGroups); + const dialogRef = this.dialog.open(ItemgroupInheritorComponent, { + data: this.gameModel!.itemgroupsAsList.filter(group => !itemgroups.includes(group)), + width: "400px" + }) + + dialogRef.afterClosed().subscribe(res => { + if(res != undefined) { + this.item!.addInheritedGroup(res); + } + }) + } + + deleteInheritedItemgroup(itemgroup: ItemGroup) { + this.item!.deleteInheritedGroup(itemgroup); + } + + get automaticallyInheritedItemgroups() { + return ItemgroupUtilities.findItemgroupPathToItem(this.item!.componentName, this.gameModel!.itemgroups); + } + + get manuallyAndHierarchyItemgroups() { + return this.item!.hierarchyInheritedGroups.concat(this.item!.manuallyInheritedGroups); + } +} diff --git a/src/app/editor/items/item-editor/itemgroup-inheritor/itemgroup-inheritor.component.html b/src/app/editor/items/item-editor/itemgroup-inheritor/itemgroup-inheritor.component.html new file mode 100644 index 0000000..dc0ed23 --- /dev/null +++ b/src/app/editor/items/item-editor/itemgroup-inheritor/itemgroup-inheritor.component.html @@ -0,0 +1,13 @@ +

Inherit Itemgroup

+ + + Select Itemgroup + + {{itemgroup.componentName}} + + + + + + + diff --git a/src/app/editor/items/item-editor/itemgroup-inheritor/itemgroup-inheritor.component.scss b/src/app/editor/items/item-editor/itemgroup-inheritor/itemgroup-inheritor.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/editor/items/item-editor/itemgroup-inheritor/itemgroup-inheritor.component.spec.ts b/src/app/editor/items/item-editor/itemgroup-inheritor/itemgroup-inheritor.component.spec.ts new file mode 100644 index 0000000..3bdf452 --- /dev/null +++ b/src/app/editor/items/item-editor/itemgroup-inheritor/itemgroup-inheritor.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ItemgroupInheritorComponent } from './itemgroup-inheritor.component'; + +describe('ItemgroupInheritorComponent', () => { + let component: ItemgroupInheritorComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ItemgroupInheritorComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ItemgroupInheritorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/editor/items/item-editor/itemgroup-inheritor/itemgroup-inheritor.component.ts b/src/app/editor/items/item-editor/itemgroup-inheritor/itemgroup-inheritor.component.ts new file mode 100644 index 0000000..c71a02e --- /dev/null +++ b/src/app/editor/items/item-editor/itemgroup-inheritor/itemgroup-inheritor.component.ts @@ -0,0 +1,25 @@ +import {Component, Inject} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef, MatDialogTitle} from "@angular/material/dialog"; +import {ItemGroup} from "../../../../project/game-model/inventory/ItemGroup"; + +@Component({ + selector: 'app-itemgroup-inheritor', + templateUrl: './itemgroup-inheritor.component.html', + styleUrl: './itemgroup-inheritor.component.scss' +}) +export class ItemgroupInheritorComponent { + + selectedItemgroup: ItemGroup | undefined + + constructor(private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public availableItemgroups: ItemGroup[]) { + } + + cancel() { + this.dialogRef.close() + } + + submit() { + this.dialogRef.close(this.selectedItemgroup); + } +} diff --git a/src/app/editor/items/item-group-editor/item-group-editor.component.html b/src/app/editor/items/item-group-editor/item-group-editor.component.html new file mode 100644 index 0000000..caa4082 --- /dev/null +++ b/src/app/editor/items/item-group-editor/item-group-editor.component.html @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + +
Characteristic + {{element.characteristicName}} + + Name + + + Description + {{element.characteristicDescription}} + + Name + + + + + +
diff --git a/src/app/editor/items/item-group-editor/item-group-editor.component.scss b/src/app/editor/items/item-group-editor/item-group-editor.component.scss new file mode 100644 index 0000000..9aa19ce --- /dev/null +++ b/src/app/editor/items/item-group-editor/item-group-editor.component.scss @@ -0,0 +1,7 @@ +.mat-column-edit, .mat-column-delete { + width: 32px; +} + +.mat-column-Characteristic, { + width: 25%; +} diff --git a/src/app/editor/items/item-group-editor/item-group-editor.component.spec.ts b/src/app/editor/items/item-group-editor/item-group-editor.component.spec.ts new file mode 100644 index 0000000..a6bbd54 --- /dev/null +++ b/src/app/editor/items/item-group-editor/item-group-editor.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ItemGroupEditorComponent } from './item-group-editor.component'; + +describe('ItemGroupEditorComponent', () => { + let component: ItemGroupEditorComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ItemGroupEditorComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ItemGroupEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/editor/items/item-group-editor/item-group-editor.component.ts b/src/app/editor/items/item-group-editor/item-group-editor.component.ts new file mode 100644 index 0000000..2436e71 --- /dev/null +++ b/src/app/editor/items/item-group-editor/item-group-editor.component.ts @@ -0,0 +1,46 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {ItemGroup} from "../../../project/game-model/inventory/ItemGroup"; +import {MatColumnDef, MatTable, MatTableDataSource} from "@angular/material/table"; +import {ItemGroupCharacteristic} from "../../../project/game-model/inventory/ItemgroupCharacteristic"; +import {Item} from "../../../project/game-model/inventory/Item"; + +@Component({ + selector: 'app-item-group-editor', + templateUrl: './item-group-editor.component.html', + styleUrl: './item-group-editor.component.scss' +}) +export class ItemGroupEditorComponent implements OnInit{ + + @Input() itemgroup: ItemGroup | undefined + + itemQualityDatasource: MatTableDataSource = new MatTableDataSource(); + displayedColumns: string[] = ["Characteristic", "Description", 'edit', 'delete'] + + editedCharacteristic: ItemGroupCharacteristic | undefined; + + + ngOnInit(): void { + this.itemQualityDatasource.data = this.itemgroup!.itemGroupCharacteristics; + } + + deleteItemgroupCharacteristic(characteristic: ItemGroupCharacteristic) { + this.itemgroup!.itemGroupCharacteristics = this.itemgroup!.itemGroupCharacteristics.filter(igc => igc.characteristicName !== characteristic.characteristicName); + this.itemQualityDatasource.data = this.itemgroup!.itemGroupCharacteristics; + } + + editItemgroupCharacteristic(characteristic: ItemGroupCharacteristic) { + this.editedCharacteristic = characteristic; + } + + finishEditing() { + this.editedCharacteristic = undefined; + } + + addItemgroupCharacteristic() { + const itemgroupCharacteristic = new ItemGroupCharacteristic("", "", this.itemgroup!); + this.itemgroup!.addItemgroupCharacteristic(itemgroupCharacteristic); + + this.itemQualityDatasource.data = this.itemgroup!.itemGroupCharacteristics; + this.editedCharacteristic = itemgroupCharacteristic; + } +} diff --git a/src/app/project/game-model/GameModel.ts b/src/app/project/game-model/GameModel.ts index 4ba59a8..2a34fc9 100644 --- a/src/app/project/game-model/GameModel.ts +++ b/src/app/project/game-model/GameModel.ts @@ -11,7 +11,12 @@ import {SimpleTemplateGamesystem} from "./templates/simpleGamesystem/SimpleTempl import {ProductTemplateSystem} from "./templates/productGamesystem/ProductTemplateSystem"; import {ProductTemplateCreator} from "./templates/productGamesystem/ProductTemplateCreator"; import {CharacterRelation} from "./characters/CharacterRelation"; +import {ItemGroup} from "./inventory/ItemGroup"; +import {AbstractItemGroup} from "./inventory/AbstractItemGroup"; +import {ConcreteItemGroup} from "./inventory/ConcreteItemGroup"; import {Item} from "./inventory/Item"; +import {ItemgroupUtilities} from "./utils/ItemgroupUtilities"; +import {ItemGroupCharacteristic} from "./inventory/ItemgroupCharacteristic"; export class GameModel { gameModelName: string @@ -19,12 +24,28 @@ export class GameModel { gamesystems: Gamesystem[] = []; scriptAccounts: ScriptAccount[] = []; characters: Character[] = [] - inventoryItems: Item[] = [] + itemgroups: ItemGroup[] = [] constructor(gameModelName: string) { this.gameModelName = gameModelName; } + + public static findItemgroupByName(name: string, itemgroups: ItemGroup[]) { + const itemgroupQueue: ItemGroup[] = itemgroups.concat(); + while(itemgroupQueue.length > 0 ) { + const currentItemgroup = itemgroupQueue.shift()!; + + if(currentItemgroup.componentName === name) { + return currentItemgroup; + } + + if(currentItemgroup instanceof AbstractItemGroup) { + currentItemgroup.children.forEach(itemgroup => itemgroupQueue.push(itemgroup)); + } + } + } + addGamesystem(gamesystem: Gamesystem) { if(this.findGamesystem(gamesystem.componentName) == undefined) { this.gamesystems.push(gamesystem); @@ -40,16 +61,12 @@ export class GameModel { } } - createScriptAccount(scriptAccountName: string) { - if(scriptAccountName != undefined && scriptAccountName.length > 0) { - const scriptAccount = new ScriptAccount(scriptAccountName, ""); - const searchedScriptAccount = this.scriptAccounts.find(s => s.componentName === scriptAccount.componentName); - if(searchedScriptAccount == undefined) { - this.scriptAccounts.push(scriptAccount); - return scriptAccount; - } + addScriptAccount(scriptAccount: ScriptAccount) { + if(!this.scriptAccounts.find(sA => sA.componentName === scriptAccount.componentName)) { + this.scriptAccounts.push(scriptAccount) + return true; } - return undefined; + return false; } createSimpleGamesystem(gamesystemName: string, templateType: TemplateType | undefined, pushToTop: boolean = true) { @@ -103,12 +120,7 @@ export class GameModel { return simpleGamesystem; } - createInventoryItem(itemName: string) { - if(itemName != undefined) { - const item = new Item(itemName, "", ModelComponentType.ITEM); - this.inventoryItems.push(item); - } - } + createGamesystem(gamesystemName: string, parentGamesystemName: string | undefined, templateType: TemplateType | undefined) { if(gamesystemName != undefined && this.findGamesystem(gamesystemName) == undefined) { @@ -163,10 +175,6 @@ export class GameModel { } } - removeItem(item: Item) { - this.inventoryItems = this.inventoryItems.filter(i => i.componentName === item.componentName) - } - findGamesystem(gamesystemName: string) { const gamesystemQueue : Gamesystem, Transition>[] = []; this.gamesystems.forEach(gamesystem => gamesystemQueue.push(gamesystem)); @@ -182,10 +190,6 @@ export class GameModel { } } - addScriptAccount(scriptAccount: ScriptAccount) { - this.scriptAccounts.push(scriptAccount); - } - generateProductSystemContents() { this.gamesystems.forEach(gamesystem => { if(gamesystem instanceof ProductGamesystem) { @@ -213,4 +217,27 @@ export class GameModel { return requestedTemplates; } + + get itemgroupsAsList() { + let itemgroupQueue: ItemGroup[] = this.itemgroups.concat(); + const result: ItemGroup[] = [] + while(itemgroupQueue.length > 0) { + const currentGroup = itemgroupQueue.shift()!; + + if(currentGroup instanceof AbstractItemGroup) { + itemgroupQueue = itemgroupQueue.concat(currentGroup.children); + } + result.push(currentGroup); + } + + return result; + } + + addCharacter(character: Character) { + if(this.characters.find(c => c.componentName === character.componentName) === undefined) { + this.characters.push(character) + return true; + } + return false; + } } diff --git a/src/app/project/game-model/ModelComponentType.ts b/src/app/project/game-model/ModelComponentType.ts index 4baebb9..ffef110 100644 --- a/src/app/project/game-model/ModelComponentType.ts +++ b/src/app/project/game-model/ModelComponentType.ts @@ -2,5 +2,7 @@ export enum ModelComponentType { SCRIPTACCOUNT, GAMESYTEM, CHARACTER, + ITEMGROUP, ITEM + } diff --git a/src/app/project/game-model/ModelComponentTypeUtillities.ts b/src/app/project/game-model/ModelComponentTypeUtillities.ts index a2bdc40..984a7a2 100644 --- a/src/app/project/game-model/ModelComponentTypeUtillities.ts +++ b/src/app/project/game-model/ModelComponentTypeUtillities.ts @@ -5,8 +5,9 @@ export class ModelComponentTypeUtillities { switch (modelComponentType) { case ModelComponentType.SCRIPTACCOUNT: return "ScriptAccounts"; case ModelComponentType.GAMESYTEM: return "Gamesystems"; - case ModelComponentType.CHARACTER: return "Characters"; + case ModelComponentType.CHARACTER: return "Characters" case ModelComponentType.ITEM: return "Items"; + case ModelComponentType.ITEMGROUP: return "Itemgroups"; default: return "Undefined"; } } @@ -16,7 +17,8 @@ export class ModelComponentTypeUtillities { case ModelComponentType.SCRIPTACCOUNT: return "ScriptAccount"; case ModelComponentType.GAMESYTEM: return "Gamesystem"; case ModelComponentType.CHARACTER: return "Character" - case ModelComponentType.ITEM: return "Item" + case ModelComponentType.ITEM: return "Item"; + case ModelComponentType.ITEMGROUP: return "Itemgroup"; default: return "Undefined"; } } @@ -26,7 +28,8 @@ export class ModelComponentTypeUtillities { case "gamesystem": return ModelComponentType.GAMESYTEM; case "scriptaccount": return ModelComponentType.SCRIPTACCOUNT; case "character": return ModelComponentType.CHARACTER - case "item": return ModelComponentType.ITEM + case "item": return ModelComponentType.ITEM; + case "itemgroup": return ModelComponentType.ITEMGROUP; } } } diff --git a/src/app/project/game-model/gamesystems/Gamesystem.ts b/src/app/project/game-model/gamesystems/Gamesystem.ts index 981590a..e50cf3f 100644 --- a/src/app/project/game-model/gamesystems/Gamesystem.ts +++ b/src/app/project/game-model/gamesystems/Gamesystem.ts @@ -27,5 +27,4 @@ export abstract class Gamesystem extends ModelComponent{ this.transitions = updatedTransitions; return true; } - } diff --git a/src/app/project/game-model/gamesystems/ProductGamesystem.ts b/src/app/project/game-model/gamesystems/ProductGamesystem.ts index 2b77cdc..eb2dc3e 100644 --- a/src/app/project/game-model/gamesystems/ProductGamesystem.ts +++ b/src/app/project/game-model/gamesystems/ProductGamesystem.ts @@ -32,14 +32,12 @@ export class ProductGamesystem extends Gamesystem { + item.addInheritedHierarchyGroup(itemgroup); + }) + this.items.push(item); + } + } + + findItemByName(itemName: string) { + return this.items.find(item => item.componentName === itemName); + } + + protected addCharacteristicValue(characteristic: ItemGroupCharacteristic): void { + this.items.forEach(item => { + item.addCharacteristic(characteristic); + }) + } + + +} diff --git a/src/app/project/game-model/inventory/Item.ts b/src/app/project/game-model/inventory/Item.ts index 13f8a35..6d0978c 100644 --- a/src/app/project/game-model/inventory/Item.ts +++ b/src/app/project/game-model/inventory/Item.ts @@ -1,44 +1,59 @@ -import {ItemProperty} from "./ItemProperty"; -import {ItemQuality} from "./ItemQuality"; import {ModelComponent} from "../ModelComponent"; -import {ModelComponentType} from "../ModelComponentType"; -import {ItemPropertyDescription} from "./ItemPropertyDescription"; +import {ItemGroup} from "./ItemGroup"; +import {ItemgroupCharacteristicValue} from "./ItemgroupCharacteristicValue"; +import {ItemGroupCharacteristic} from "./ItemgroupCharacteristic"; export class Item extends ModelComponent { - possible_qualities: ItemQuality[] = [] - itemProperties: ItemProperty[] = [] - perQualityProperties: ItemPropertyDescription[] = [] + manuallyInheritedGroups: ItemGroup[] = [] + hierarchyInheritedGroups: ItemGroup[] = [] + itemCharacteristicValues: ItemgroupCharacteristicValue[] = [] - constructor(componentName: string, componentDescription: string, type: ModelComponentType) { - super(componentName, componentDescription, type); - this.itemProperties.push(new ItemProperty("Weight", "Some Weights", 10)) - this.possible_qualities.push(new ItemQuality(0.25)) - this.possible_qualities.push(new ItemQuality(0.50)) - this.possible_qualities.push(new ItemQuality(0.75)) - this.possible_qualities.push(new ItemQuality(1.00)) - - this.addPerQualityProperty(new ItemPropertyDescription("Price", "Price to buy item")) - } - - removePerQualityProperty(qualityProperty: ItemPropertyDescription) { - this.perQualityProperties = this.perQualityProperties.filter(perQualityProperty => perQualityProperty !== qualityProperty); - this.possible_qualities.forEach(quality => { - quality.removeQualityProperty(qualityProperty.propertyName); + initializeItemCharacteristics() { + const inheritedGroups = this.manuallyInheritedGroups.concat(this.hierarchyInheritedGroups); + inheritedGroups.forEach(itemGroup => { + this.initializeItemCharacteristicsOfItemgroup(itemGroup); }) } - addPerQualityProperty(qualityProperty: ItemPropertyDescription) { - if(this.perQualityProperties.find(property => property.propertyName === qualityProperty.propertyName) == undefined) { - this.perQualityProperties.push(qualityProperty); - this.possible_qualities.forEach(quality => quality.addQualityProperty(qualityProperty)) + initializeItemCharacteristicsOfItemgroup(itemGroup: ItemGroup) { + itemGroup.itemGroupCharacteristics.forEach(characteristic => { + this.addCharacteristic(characteristic); + }) + } + + private isValueInitialized(characteristic: ItemGroupCharacteristic) { + return this.itemCharacteristicValues.find(value => value.key.characteristicName === characteristic.characteristicName) !== undefined + } + + addInheritedGroup(itemgroup: ItemGroup) { + if(this.findItemgroupByName(itemgroup.componentName) == undefined) { + this.manuallyInheritedGroups.push(itemgroup); + itemgroup.manuallyInheritedItems.push(this); + this.initializeItemCharacteristicsOfItemgroup(itemgroup); } } - editPerQualityProperty(qualityProperty: ItemPropertyDescription) { - this.possible_qualities.forEach(quality => { - quality.editQualityProperty(qualityProperty, this.perQualityProperties.map(property => property.propertyName)) - }) + findItemgroupByName(groupName: string) { + const itemgroups = this.hierarchyInheritedGroups.concat(this.manuallyInheritedGroups); + return itemgroups.find(group => group.componentName === groupName); + } + + addCharacteristic(characteristic: ItemGroupCharacteristic) { + const characteristicValue = new ItemgroupCharacteristicValue(characteristic, 0); + if(!this.isValueInitialized(characteristic)) { + this.itemCharacteristicValues.push(characteristicValue); + } + } + + deleteInheritedGroup(itemgroup: ItemGroup) { + this.manuallyInheritedGroups = this.manuallyInheritedGroups.filter(manually => manually.componentName !== itemgroup.componentName); + } + + addInheritedHierarchyGroup(itemgroup: ItemGroup) { + this.hierarchyInheritedGroups.push(itemgroup); + this.initializeItemCharacteristicsOfItemgroup(itemgroup); + } } diff --git a/src/app/project/game-model/inventory/ItemGroup.ts b/src/app/project/game-model/inventory/ItemGroup.ts new file mode 100644 index 0000000..3096e7b --- /dev/null +++ b/src/app/project/game-model/inventory/ItemGroup.ts @@ -0,0 +1,35 @@ +import {ModelComponent} from "../ModelComponent"; +import {ItemGroupCharacteristic} from "./ItemgroupCharacteristic"; +import {AbstractItemGroup} from "./AbstractItemGroup"; +import {Item} from "./Item"; + +export abstract class ItemGroup extends ModelComponent { + + itemGroupCharacteristics: ItemGroupCharacteristic[] = [] + parentGroup: AbstractItemGroup | undefined + manuallyInheritedItems: Item[] = [] + + addItemgroupCharacteristic(itemgroupCharacteristic: ItemGroupCharacteristic) { + this.itemGroupCharacteristics.push(itemgroupCharacteristic); + this.addCharacteristicValueForManuallyItems(itemgroupCharacteristic); + this.addCharacteristicValue(itemgroupCharacteristic); + } + + protected abstract addCharacteristicValue(characteristic: ItemGroupCharacteristic): void; + + private addCharacteristicValueForManuallyItems(characteristic: ItemGroupCharacteristic) { + this.manuallyInheritedItems.forEach(item => { + item.addCharacteristic(characteristic); + }) + } + + inheritManualItem(item: Item) { + if(this.manuallyInheritedItems.find(inheritedItems => inheritedItems.componentName === item.componentName) == undefined) { + this.manuallyInheritedItems.push(item); + item.addInheritedGroup(this); + } + } + + + +} diff --git a/src/app/project/game-model/inventory/ItemgroupCharacteristic.ts b/src/app/project/game-model/inventory/ItemgroupCharacteristic.ts new file mode 100644 index 0000000..d28b9a1 --- /dev/null +++ b/src/app/project/game-model/inventory/ItemgroupCharacteristic.ts @@ -0,0 +1,14 @@ +import {ItemGroup} from "./ItemGroup"; + +export class ItemGroupCharacteristic { + characteristicName: string; + characteristicDescription: string + itemgroup: ItemGroup + + + constructor(characteristicName: string, characteristicDescription: string, itemgroup: ItemGroup) { + this.characteristicName = characteristicName; + this.characteristicDescription = characteristicDescription; + this.itemgroup = itemgroup; + } +} diff --git a/src/app/project/game-model/inventory/ItemgroupCharacteristicValue.ts b/src/app/project/game-model/inventory/ItemgroupCharacteristicValue.ts new file mode 100644 index 0000000..436d3b7 --- /dev/null +++ b/src/app/project/game-model/inventory/ItemgroupCharacteristicValue.ts @@ -0,0 +1,14 @@ +import {ItemGroupCharacteristic} from "./ItemgroupCharacteristic"; + +export class ItemgroupCharacteristicValue { + key: ItemGroupCharacteristic + value: number + + + constructor(key: ItemGroupCharacteristic, value: number) { + this.key = key; + this.value = value; + } + + +} diff --git a/src/app/project/game-model/inventory/ItemgroupType.ts b/src/app/project/game-model/inventory/ItemgroupType.ts new file mode 100644 index 0000000..f1ca933 --- /dev/null +++ b/src/app/project/game-model/inventory/ItemgroupType.ts @@ -0,0 +1,4 @@ +export enum ItemgroupType { + CONCRETE, + ABSTRACT +} diff --git a/src/app/project/game-model/utils/ItemgroupUtilities.ts b/src/app/project/game-model/utils/ItemgroupUtilities.ts new file mode 100644 index 0000000..25c9533 --- /dev/null +++ b/src/app/project/game-model/utils/ItemgroupUtilities.ts @@ -0,0 +1,67 @@ +import {GameModel} from "../GameModel"; +import {ItemGroup} from "../inventory/ItemGroup"; +import {AbstractItemGroup} from "../inventory/AbstractItemGroup"; +import {ConcreteItemGroup} from "../inventory/ConcreteItemGroup"; + +export class ItemgroupUtilities { + + public static findItemgroupPathToItem(searchedItemName: string, itemgroups: ItemGroup[]): ItemGroup[] { + for(let i=0; i 0) { + return found_path; + } + } + return []; + } + + public static findItemgroupPathToItemgroup(searchedItemgroupName: string, itemgroups: ItemGroup[]): ItemGroup[] { + for(let i=0; i 0) { + return found_path; + } + } + return []; + } + + private static findItemgroupPathToItemgroupRecursive(root: ItemGroup, searchedItemgroupName: string, path: ItemGroup[]): ItemGroup[] { + path.push(root); + + if(root.componentName === searchedItemgroupName) { + return path; + } + + if(root instanceof AbstractItemGroup) { + for(let i=0; i 0) { + return found_path; + } + } + return []; + } else { + return []; + } + } + + private static findItemgroupPathToItemRecursive(root: ItemGroup, searchedItemName: string, path: ItemGroup[]): ItemGroup[] { + path.push(root); + + if(root instanceof ConcreteItemGroup) { + const searchedItem = root.items.find(item => item.componentName === searchedItemName) + if(searchedItem != undefined) { + return path; + } + } else if(root instanceof AbstractItemGroup) { + for(let i=0; i 0) { + return found_path; + } + } + } + return []; + } + +} diff --git a/src/app/project/game-model/utils/creator/CharacterCreator.ts b/src/app/project/game-model/utils/creator/CharacterCreator.ts new file mode 100644 index 0000000..03d19a6 --- /dev/null +++ b/src/app/project/game-model/utils/creator/CharacterCreator.ts @@ -0,0 +1,22 @@ +import {ModelComponentCreator} from "./ModelComponentCreator"; +import {GameModel} from "../../GameModel"; +import {ModelComponent} from "../../ModelComponent"; +import {Character} from "../../characters/Character"; + +export class CharacterCreator extends ModelComponentCreator{ + + + constructor(context: string, gameModel: GameModel, selectedComponent: ModelComponent | undefined) { + super(context, gameModel, selectedComponent); + } + + createModelComponent(): ModelComponent | undefined { + const character = new Character("New Character", ""); + if(this.gameModel.addCharacter(character)) { + return character; + } + return undefined; + } + + +} diff --git a/src/app/project/game-model/utils/creator/GamesystemCreator.ts b/src/app/project/game-model/utils/creator/GamesystemCreator.ts new file mode 100644 index 0000000..6233ab4 --- /dev/null +++ b/src/app/project/game-model/utils/creator/GamesystemCreator.ts @@ -0,0 +1,86 @@ +import {ModelComponentCreator} from "./ModelComponentCreator"; +import {GameModel} from "../../GameModel"; +import {ModelComponent} from "../../ModelComponent"; +import {TemplateTypeUtilities} from "../../templates/TemplateTypeUtilities"; +import {Gamesystem} from "../../gamesystems/Gamesystem"; +import {SimpleGamesystem} from "../../gamesystems/SimpleGamesystem"; +import {ProductGamesystem} from "../../gamesystems/ProductGamesystem"; +import {SimpleTemplateGamesystem} from "../../templates/simpleGamesystem/SimpleTemplateGamesystem"; +import {ProductTemplateCreator} from "../../templates/productGamesystem/ProductTemplateCreator"; +import {ProductTemplateSystem} from "../../templates/productGamesystem/ProductTemplateSystem"; +import {TemplateType} from "../../templates/TemplateType"; + +export class GamesystemCreator extends ModelComponentCreator{ + + + constructor(context: string, gameModel: GameModel, selectedComponent: ModelComponent | undefined) { + super(context, gameModel, selectedComponent); + } + + createModelComponent(): ModelComponent | undefined { + const templateType = TemplateTypeUtilities.fromString(this.context); + let simpleGamesystem; + if(templateType == undefined) /**Aka normal**/{ + simpleGamesystem = new SimpleGamesystem("New Simple Gamesystem", ""); + } else { + simpleGamesystem = new SimpleTemplateGamesystem("New Simple Gamesystem", "", templateType) + } + + if(this.selectedComponent !== undefined && this.selectedComponent instanceof Gamesystem)/**Aka productGamesystem**/ { + const productParentsystem: ProductGamesystem = this.constructProductFromSimple(this.selectedComponent, undefined)! + productParentsystem.addChildGamesystem(simpleGamesystem); + } else { + this.gameModel!.gamesystems.push(simpleGamesystem); + } + + return simpleGamesystem; + } + + private constructProductFromSimple(simpleGamesystem: Gamesystem, producttemplateType: TemplateType | undefined): ProductGamesystem | undefined { + if(!(simpleGamesystem instanceof ProductTemplateSystem) && producttemplateType != undefined) { + console.log("Wierd, Debug") + return ProductTemplateCreator.convertProductToTemplate(simpleGamesystem as ProductGamesystem, this.gameModel, producttemplateType); + } + + if(simpleGamesystem instanceof ProductGamesystem) { + console.log("Wierder Debug") + return simpleGamesystem; + } + + let productGamesystem: ProductGamesystem + if(producttemplateType != undefined) { + productGamesystem = new ProductTemplateSystem(simpleGamesystem.componentName, simpleGamesystem.componentDescription, producttemplateType); + } else { + productGamesystem = new ProductGamesystem(simpleGamesystem.componentName, simpleGamesystem.componentDescription); + } + + this.constructGamesystemHierarchy(productGamesystem, simpleGamesystem as SimpleGamesystem) + return productGamesystem; + } + + private constructGamesystemHierarchy(productGamesystem: ProductGamesystem, simpleGamesystem: SimpleGamesystem) { + const simpleParentGamesystem = simpleGamesystem.parentGamesystem; + + if(simpleGamesystem.states.length > 0) { + simpleGamesystem.componentName += "(Child)"; + if(simpleParentGamesystem == undefined) { + this.gameModel.removeGamesystem(simpleGamesystem); + productGamesystem.addChildGamesystem(simpleGamesystem); + this.gameModel.addGamesystem(productGamesystem); + } else { + simpleParentGamesystem.removeChildGamesystem(simpleGamesystem); + productGamesystem.addChildGamesystem(simpleGamesystem); + simpleParentGamesystem.addChildGamesystem(productGamesystem); + } + } else { + if(simpleParentGamesystem == undefined) { + this.gameModel.removeGamesystem(simpleGamesystem); + this.gameModel.addGamesystem(productGamesystem); + } else { + simpleParentGamesystem.removeChildGamesystem(simpleGamesystem); + simpleParentGamesystem.addChildGamesystem(productGamesystem); + } + } + } + +} diff --git a/src/app/project/game-model/utils/creator/ItemCreator.ts b/src/app/project/game-model/utils/creator/ItemCreator.ts new file mode 100644 index 0000000..bc58902 --- /dev/null +++ b/src/app/project/game-model/utils/creator/ItemCreator.ts @@ -0,0 +1,37 @@ +import {ModelComponentCreator} from "./ModelComponentCreator"; +import {GameModel} from "../../GameModel"; +import {ModelComponent} from "../../ModelComponent"; +import {Item} from "../../inventory/Item"; +import {ModelComponentType} from "../../ModelComponentType"; +import {ConcreteItemGroup} from "../../inventory/ConcreteItemGroup"; +import {ItemGroup} from "../../inventory/ItemGroup"; + +export class ItemCreator extends ModelComponentCreator { + + + constructor(context: string, gameModel: GameModel, selectedComponent: ModelComponent | undefined) { + super(context, gameModel, selectedComponent); + } + + createModelComponent(): ModelComponent | undefined { + if(this.selectedComponent != undefined && this.selectedComponent instanceof ConcreteItemGroup) { + const item = new Item("New Item", "", ModelComponentType.ITEM); + this.selectedComponent.addItem(item, this.getInheritedGroups(this.selectedComponent)) + return item; + } else { + return undefined + } + } + + private getInheritedGroups(baseGroup: ItemGroup): ItemGroup[] { + const itemgroups: ItemGroup[] = [] + let currentGroup: ItemGroup | undefined = baseGroup; + while(currentGroup != undefined) { + itemgroups.push(currentGroup); + currentGroup = currentGroup.parentGroup; + } + return itemgroups; + } + + +} diff --git a/src/app/project/game-model/utils/creator/ItemgroupCreator.ts b/src/app/project/game-model/utils/creator/ItemgroupCreator.ts new file mode 100644 index 0000000..924ee6a --- /dev/null +++ b/src/app/project/game-model/utils/creator/ItemgroupCreator.ts @@ -0,0 +1,36 @@ +import {ModelComponentCreator} from "./ModelComponentCreator"; +import {ModelComponent} from "../../ModelComponent"; +import {GameModel} from "../../GameModel"; +import {AbstractItemGroup} from "../../inventory/AbstractItemGroup"; +import {ModelComponentType} from "../../ModelComponentType"; +import {ConcreteItemGroup} from "../../inventory/ConcreteItemGroup"; + +export class ItemgroupCreator extends ModelComponentCreator { + + + + constructor(context: string, gameModel: GameModel, selectedComponent: ModelComponent | undefined) { + super(context, gameModel, selectedComponent); + } + + createModelComponent(): ModelComponent | undefined{ + let itemgroup; + if(this.context === 'abstract') { + itemgroup = new AbstractItemGroup("New Abstract Itemgroup", "", ModelComponentType.ITEMGROUP); + } else if(this.context === 'concrete') { + itemgroup = new ConcreteItemGroup("New Concrete Itemgroup", "", ModelComponentType.ITEMGROUP); + } else { + return undefined + } + + if(this.selectedComponent != null && this.selectedComponent instanceof AbstractItemGroup) { + this.selectedComponent.addChildItemgroup(itemgroup); + } else { + this.gameModel.itemgroups.push(itemgroup); + } + + return itemgroup; + } + + +} diff --git a/src/app/project/game-model/utils/creator/ModelComponentCreator.ts b/src/app/project/game-model/utils/creator/ModelComponentCreator.ts new file mode 100644 index 0000000..68a90e2 --- /dev/null +++ b/src/app/project/game-model/utils/creator/ModelComponentCreator.ts @@ -0,0 +1,18 @@ +import {ModelComponent} from "../../ModelComponent"; +import {GameModel} from "../../GameModel"; +import {Overview} from "../../../../side-overviews/Overview"; + +export abstract class ModelComponentCreator { + context: string; + gameModel: GameModel + selectedComponent: ModelComponent | undefined + + + protected constructor(context: string, gameModel: GameModel, selectedComponent: ModelComponent | undefined) { + this.context = context; + this.gameModel = gameModel; + this.selectedComponent = selectedComponent; + } + + abstract createModelComponent(): ModelComponent | undefined; +} diff --git a/src/app/project/game-model/utils/creator/ScriptAccountCreator.ts b/src/app/project/game-model/utils/creator/ScriptAccountCreator.ts new file mode 100644 index 0000000..cee9fc4 --- /dev/null +++ b/src/app/project/game-model/utils/creator/ScriptAccountCreator.ts @@ -0,0 +1,22 @@ +import {ModelComponentCreator} from "./ModelComponentCreator"; +import {GameModel} from "../../GameModel"; +import {ModelComponent} from "../../ModelComponent"; +import {ScriptAccount} from "../../scriptAccounts/ScriptAccount"; + +export class ScriptAccountCreator extends ModelComponentCreator { + + constructor(context: string, gameModel: GameModel, selectedComponent: ModelComponent | undefined) { + super(context, gameModel, selectedComponent); + } + + createModelComponent(): ModelComponent | undefined { + const scriptAccount = new ScriptAccount("New ScriptAccount", ""); + if(this.gameModel.addScriptAccount(scriptAccount)) { + return scriptAccount; + } else { + return undefined; + } + } + + +} diff --git a/src/app/project/parser/itemParser/ItemParser.ts b/src/app/project/parser/itemParser/ItemParser.ts new file mode 100644 index 0000000..40da22f --- /dev/null +++ b/src/app/project/parser/itemParser/ItemParser.ts @@ -0,0 +1,87 @@ +import {ItemGroup} from "../../game-model/inventory/ItemGroup"; +import {StoreComponent} from "../../../../../app/storage/StoreComponent"; +import {Item} from "../../game-model/inventory/Item"; +import {ModelComponentType} from "../../game-model/ModelComponentType"; +import {ConcreteItemGroup} from "../../game-model/inventory/ConcreteItemGroup"; +import {ItemgroupCharacteristicValue} from "../../game-model/inventory/ItemgroupCharacteristicValue"; + +export class ItemParser { + parsedItemgroups: ItemGroup[] = [] + + constructor(itemgroups: ItemGroup[] = []) { + this.parsedItemgroups = itemgroups; + } + + parseItems(storeComponents: StoreComponent[]): Item[] { + const parsedItems: Item[] = [] + storeComponents.forEach(storeComponent => parsedItems.push(this.parseSingleItem(storeComponent))); + return parsedItems; + } + + private parseSingleItem(storeComponent: StoreComponent) { + const parsedData = JSON.parse(storeComponent.jsonString); + + const componentName = parsedData.componentName; + const componentDescription = parsedData.componentDescription; + + const manuallyInheritedGroups = this.parseInheritedGroups(parsedData.manuallyInheritedGroups); + const hierarchyInheritedGroups = this.parseInheritedGroups(parsedData.hierarchyInheritedGroups); + + const item = new Item(componentName, componentDescription, ModelComponentType.ITEM); + item.manuallyInheritedGroups = manuallyInheritedGroups; + item.hierarchyInheritedGroups = hierarchyInheritedGroups; + + const owningGroup = hierarchyInheritedGroups.find(itemgroup => itemgroup instanceof ConcreteItemGroup); + if (owningGroup) { + (owningGroup as ConcreteItemGroup).items.push(item); + } else { + console.log("[ERROR] No group found for item: ", item.componentName) + } + + + item.itemCharacteristicValues = this.parseItemCharacteristicValues(parsedData.itemCharacteristicValues); + return item; + } + + private parseInheritedGroups(inheritedGroupsData: any) { + const inheritedGroups: ItemGroup[] = [] + for(let i=0; i group.componentName === inheritedGroupName); + if (matchedGroup) { + inheritedGroups.push(matchedGroup); + } + } + + return inheritedGroups; + } + + private parseItemCharacteristicValues(data: any): ItemgroupCharacteristicValue[] { + const values: ItemgroupCharacteristicValue[] = [] + for(let i=0; i characteristic.characteristicName === itemCharacteristicName); + + if(characteristic != undefined) { + return characteristic; + } + } + return undefined; + } + + +} diff --git a/src/app/project/parser/itemParser/ItemgroupParser.ts b/src/app/project/parser/itemParser/ItemgroupParser.ts new file mode 100644 index 0000000..fb18e77 --- /dev/null +++ b/src/app/project/parser/itemParser/ItemgroupParser.ts @@ -0,0 +1,94 @@ +import {ItemGroup} from "../../game-model/inventory/ItemGroup"; +import {StoreComponent} from "../../../../../app/storage/StoreComponent"; +import {ItemGroupCharacteristic} from "../../game-model/inventory/ItemgroupCharacteristic"; +import {AbstractItemGroup} from "../../game-model/inventory/AbstractItemGroup"; +import {ModelComponentType} from "../../game-model/ModelComponentType"; +import {ConcreteItemGroup} from "../../game-model/inventory/ConcreteItemGroup"; + +export class ItemgroupParser { + + private parsedItemgroups: ItemGroup[] = [] + private topParsedItemgroups: ItemGroup[] = [] + + parseItemgroups(storeComponents: StoreComponent[]) { + const topologicalSort = this.topologicalSort(storeComponents); + topologicalSort.forEach(storeComponent => this.parseSingleItemgroup(storeComponent)); + return this.parsedItemgroups; + } + + private topologicalSort(storeComponents: StoreComponent[]) { + const sortedObjects: StoreComponent[] = [] + const visited: {[key: string]: boolean} = {}; + + const visit = (object: StoreComponent) => { + const jsonData = JSON.parse(object.jsonString) + if(visited[jsonData.componentName]) return; + visited[jsonData.componentName] = true; + + if(jsonData.parent) { + const parentObject = storeComponents.find(obj => JSON.parse(obj.jsonString).componentName === jsonData.parent); + if(parentObject) { + visit(parentObject); + } + } + sortedObjects.push(object); + } + + storeComponents.forEach(object => visit(object)); + + return sortedObjects; + } + + parseSingleItemgroup(storeComponent: StoreComponent) { + const data = JSON.parse(storeComponent.jsonString); + + const componentName = data.componentName; + const componentDescription = data.componentDescription; + const parentgroupName = data.parentgroup; + + let itemgroup; + if(data.itemgroupType == 0) { + itemgroup = new ConcreteItemGroup(componentName, componentDescription, ModelComponentType.ITEMGROUP); + } else { + itemgroup = new AbstractItemGroup(componentName, componentDescription, ModelComponentType.ITEMGROUP); + } + + const parentgroup = this.parsedItemgroups.find(parent => parent.componentName === parentgroupName); + + if(parentgroup != undefined) { + const abstractParentgroup = parentgroup as AbstractItemGroup; + abstractParentgroup.addChildItemgroup(itemgroup) + this.parsedItemgroups.push(itemgroup) + } else { + this.parsedItemgroups.push(itemgroup); + this.topParsedItemgroups.push(itemgroup); + } + + this.parseItemgroupCharacteristics(data.itemGroupCharacteristics, itemgroup); + } + + parseItemgroupCharacteristics(itemgroupCharacteristicsData: any, itemgroup: ItemGroup): ItemGroupCharacteristic[] { + const itemgroupCharacteristics: ItemGroupCharacteristic[] = [] + for(let i=0; i { if(this.IGNORED_SIMPLE_ATTRIBUTES.includes(key)) { diff --git a/src/app/project/serializer/ItemSerializer.ts b/src/app/project/serializer/ItemSerializer.ts index 352f4b4..80d51bf 100644 --- a/src/app/project/serializer/ItemSerializer.ts +++ b/src/app/project/serializer/ItemSerializer.ts @@ -1,38 +1,135 @@ -import {Item} from "../game-model/inventory/Item"; +import {ItemGroup} from "../game-model/inventory/ItemGroup"; import {StoreComponent} from "../../../../app/storage/StoreComponent"; +import {AbstractItemGroup} from "../game-model/inventory/AbstractItemGroup"; +import {ConcreteItemGroup} from "../game-model/inventory/ConcreteItemGroup"; +import {ModelComponentType} from "../game-model/ModelComponentType"; import {SerializeConstants} from "./SerializeConstants"; -import {ItemQuality} from "../game-model/inventory/ItemQuality"; -import {ItemPropertyDescription} from "../game-model/inventory/ItemPropertyDescription"; -import {ItemProperty} from "../game-model/inventory/ItemProperty"; +import {Item} from "../game-model/inventory/Item"; +import {ItemgroupType} from "../game-model/inventory/ItemgroupType"; export class ItemSerializer { - public static serializeItems(items: Item[]): StoreComponent[] { - const storedItems: StoreComponent[] = [] - items.forEach(item => storedItems.push(this.serializeSingleItem(item))) - return storedItems; + private serializedItemgroups: StoreComponent[] = [] + private serializedItems: StoreComponent[] = [] + private static ignoredGroupKeys: string[] = ['type', 'unsaved', "itemgroup", "manuallyInheritedGroups", "hierarchyInheritedGroups", "items"] + private static ignoredItemKeys: string[] = ['type', 'unsaved'] + + public serializeItemgroups(itemgroups: ItemGroup[]): StoreComponent[] { + itemgroups.forEach(itemgroup => { + this.serializeSingleItemgroupHierarchy(itemgroup) + }) + return this.serializedItemgroups; } - private static serializeSingleItem(item: Item): StoreComponent { - const fileName = item.componentName; - const componentType = item.type; - const jsonString = JSON.stringify(item,(key, value) => { - if(key === 'perQualityProperties') { - return value; - } else if(key == 'quality_propertes') { - return value.map((prop: ItemProperty) => ({ - ...prop, - propertyDescription: undefined - })); + private serializeSingleItemgroupHierarchy(itemgroup: ItemGroup) { + if(itemgroup instanceof AbstractItemGroup) { + const storeComponent = this.serializeAbstractItemgroup(itemgroup) + this.serializedItemgroups.push(storeComponent) + itemgroup.children.forEach(child => this.serializeSingleItemgroupHierarchy(child)); + } else { + const storeComponent = this.serializeConcreteItemgroup(itemgroup as ConcreteItemGroup); + this.serializedItemgroups.push(storeComponent) + + this.serializeItemsOfItemgroup(itemgroup as ConcreteItemGroup); + } + } + + private serializeAbstractItemgroup(itemgroup: AbstractItemGroup): StoreComponent { + const componentType = ModelComponentType.ITEMGROUP; + const fileName = ItemSerializer.computeItemgroupPath(itemgroup); + + const jsonObject = { + componentName: itemgroup.componentName, + componentDescription: itemgroup.componentDescription, + itemGroupCharacteristics: itemgroup.itemGroupCharacteristics.map(characteristic => { + return { + characteristicName: characteristic.characteristicName, + characteristicDescription: characteristic.characteristicDescription + } + }), + parentgroup: itemgroup.parentGroup, + itemgroupType: ItemgroupType.ABSTRACT + }; + + const jsonString = JSON.stringify(jsonObject, (key, value) => { + return value; + }, SerializeConstants.JSON_INDENT); + return new StoreComponent(jsonString, fileName, componentType) + } + + private serializeConcreteItemgroup(itemgroup: ConcreteItemGroup) { + const componentType = ModelComponentType.ITEMGROUP; + const fileName = ItemSerializer.computeItemgroupPath(itemgroup); + + const jsonObject = { + componentName: itemgroup.componentName, + componentDescription: itemgroup.componentDescription, + itemGroupCharacteristics: itemgroup.itemGroupCharacteristics.map(characteristic => { + return { + characteristicName: characteristic.characteristicName, + characteristicDescription: characteristic.characteristicDescription + } + }), + itemgroupType: ItemgroupType.CONCRETE, + parentgroup: itemgroup.parentGroup?.componentName + }; + + const jsonString = JSON.stringify(jsonObject, (key, value) => { + return value; + }, SerializeConstants.JSON_INDENT); + return new StoreComponent(jsonString, fileName, componentType) + } + + private static computeItemgroupPath(itemgroup: ItemGroup, itemPath: boolean = false): string { + const itemgroupPath: string[] = []; + itemgroupPath.push(itemgroup.componentName); + + if(!itemPath) { + itemgroupPath.push(itemgroup.componentName); + } + + + while(itemgroup.parentGroup !== undefined) { + itemgroupPath.unshift(itemgroup.parentGroup.componentName); + itemgroup = itemgroup.parentGroup; + } + + return itemgroupPath.join("/"); + } + + private serializeItemsOfItemgroup(itemgroup: ConcreteItemGroup) { + const fileName = ItemSerializer.computeItemgroupPath(itemgroup, true); + itemgroup.items.forEach(item => { + const storeComponent = this.serializeSingleItem(fileName, item); + this.serializedItems.push(storeComponent) + }) + + + } + + private serializeSingleItem(itemgroupPath: string, item: Item) { + const itemFile = itemgroupPath + "/" + item.componentName; + + const jsonString = JSON.stringify(item, (key, value) => { + if(ItemSerializer.ignoredItemKeys.includes(key)) { + return undefined } - if(key === 'unsaved' || key === 'type') { - return undefined; - } else { - return value; + if(value instanceof ItemGroup) { + return value.componentName } + + if(key == "key") { + return value.characteristicName + } + + return value; }, SerializeConstants.JSON_INDENT) - return new StoreComponent(jsonString, fileName, componentType); + return new StoreComponent(jsonString, itemFile, ModelComponentType.ITEM) + } + + getSerializedItems() { + return this.serializedItems; } } diff --git a/src/app/shared/Tupel.ts b/src/app/shared/Tupel.ts new file mode 100644 index 0000000..e05b237 --- /dev/null +++ b/src/app/shared/Tupel.ts @@ -0,0 +1,10 @@ +export class Tupel { + value00: A + value01: B + + + constructor(value00: A, value01: B) { + this.value00 = value00; + this.value01 = value01; + } +} diff --git a/src/app/side-overviews/Overview.ts b/src/app/side-overviews/Overview.ts new file mode 100644 index 0000000..88dd18f --- /dev/null +++ b/src/app/side-overviews/Overview.ts @@ -0,0 +1,3 @@ +export interface Overview { + refresh(): void +} diff --git a/src/app/side-overviews/character-overview/character-overview.component.ts b/src/app/side-overviews/character-overview/character-overview.component.ts index c182485..50ad56a 100644 --- a/src/app/side-overviews/character-overview/character-overview.component.ts +++ b/src/app/side-overviews/character-overview/character-overview.component.ts @@ -5,13 +5,17 @@ import {MatIcon} from "@angular/material/icon"; import {NgClass, NgForOf} from "@angular/common"; import {ScriptAccount} from "../../project/game-model/scriptAccounts/ScriptAccount"; import {Character} from "../../project/game-model/characters/Character"; +import {Overview} from "../Overview"; @Component({ selector: 'app-character-overview', templateUrl: './character-overview.component.html', styleUrl: './character-overview.component.scss' }) -export class CharacterOverviewComponent { +export class CharacterOverviewComponent implements Overview{ + refresh(): void { + //Nothing to-do + } @Input() gameModel: GameModel | undefined @Output("onOpenCharacterEditor") openCharacterEmitter: EventEmitter = new EventEmitter(); diff --git a/src/app/side-overviews/gamescript-overview/gamescript-overview.component.ts b/src/app/side-overviews/gamescript-overview/gamescript-overview.component.ts index 3194a5f..4c6fe9c 100644 --- a/src/app/side-overviews/gamescript-overview/gamescript-overview.component.ts +++ b/src/app/side-overviews/gamescript-overview/gamescript-overview.component.ts @@ -8,6 +8,7 @@ import {State} from "../../project/game-model/gamesystems/states/State"; import {Transition} from "../../project/game-model/gamesystems/transitions/Transition"; import {ProductGamesystem} from "../../project/game-model/gamesystems/ProductGamesystem"; import {SimpleGamesystem} from "../../project/game-model/gamesystems/SimpleGamesystem"; +import {Overview} from "../Overview"; interface FlatNode { @@ -20,7 +21,7 @@ interface FlatNode { templateUrl: './gamescript-overview.component.html', styleUrl: './gamescript-overview.component.scss' }) -export class GamescriptOverviewComponent implements OnInit { +export class GamescriptOverviewComponent implements OnInit, Overview { @Input('gameModel') gameModel: GameModel | undefined @Output('openGamesystemEditor') openGamesystemEmitter : EventEmitter, Transition>> = new EventEmitter, Transition>>(); diff --git a/src/app/side-overviews/item-overview/item-overview.component.html b/src/app/side-overviews/item-overview/item-overview.component.html new file mode 100644 index 0000000..2622561 --- /dev/null +++ b/src/app/side-overviews/item-overview/item-overview.component.html @@ -0,0 +1,22 @@ + + + + + + folder + data_object + {{node.name}} + + + + + folder + data_object + {{node.name}} + + diff --git a/src/app/side-overviews/item-overview/item-overview.component.scss b/src/app/side-overviews/item-overview/item-overview.component.scss new file mode 100644 index 0000000..d799155 --- /dev/null +++ b/src/app/side-overviews/item-overview/item-overview.component.scss @@ -0,0 +1,41 @@ +.mat-tree-node { + min-height: 1.8em !important; + height: 1.8em; +} + + +.small-icon-button { + width: 26px !important; + height: 26px !important; + padding: 0px !important; + display: inline-flex !important; + align-items: center; + justify-content: center; + margin-left: 5px; + margin-right: 5px; + margin-bottom: 2px; + + & > *[role=img] { + width: 18px; + height: 18px; + font-size: 18px; + + svg { + width: 18px; + height: 18px; + } + } + + .mat-mdc-button-touch-target { + width: 22px !important; + height: 22px !important; + } +} + +.small-icon-button mat-icon { + color: whitesmoke; +} + +.selected-node { + background-color: #545456 +} diff --git a/src/app/side-overviews/item-overview/item-overview.component.spec.ts b/src/app/side-overviews/item-overview/item-overview.component.spec.ts new file mode 100644 index 0000000..58c2547 --- /dev/null +++ b/src/app/side-overviews/item-overview/item-overview.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ItemOverviewComponent } from './item-overview.component'; + +describe('ItemOverviewComponent', () => { + let component: ItemOverviewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ItemOverviewComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ItemOverviewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/side-overviews/item-overview/item-overview.component.ts b/src/app/side-overviews/item-overview/item-overview.component.ts new file mode 100644 index 0000000..a41020e --- /dev/null +++ b/src/app/side-overviews/item-overview/item-overview.component.ts @@ -0,0 +1,153 @@ +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {GameModel} from "../../project/game-model/GameModel"; +import {FlatTreeControl} from "@angular/cdk/tree"; +import {MatTreeFlatDataSource, MatTreeFlattener} from "@angular/material/tree"; +import {AbstractItemGroup} from "../../project/game-model/inventory/AbstractItemGroup"; +import {ConcreteItemGroup} from "../../project/game-model/inventory/ConcreteItemGroup"; +import {ModelComponent} from "../../project/game-model/ModelComponent"; +import {ModelComponentType} from "../../project/game-model/ModelComponentType"; +import {ItemGroup} from "../../project/game-model/inventory/ItemGroup"; +import {Item} from "../../project/game-model/inventory/Item"; +import {Overview} from "../Overview"; + +interface FlatNode { + expandable: boolean, + name: string, + level: number, + type: ModelComponentType +} + +@Component({ + selector: 'app-item-overview', + templateUrl: './item-overview.component.html', + styleUrl: './item-overview.component.scss' +}) +export class ItemOverviewComponent implements OnInit, Overview{ + + @Input() gameModel: GameModel | undefined + @Output() openItemgroupEmitter: EventEmitter = new EventEmitter(); + @Output() onOpenItemEditor: EventEmitter = new EventEmitter(); + + private _transformer = (node: ModelComponent, level: number) => { + if(node instanceof AbstractItemGroup) { + return { + expandable: !!node.children && node.children.length > 0, + name: node.componentName, + level: level, + type: ModelComponentType.ITEMGROUP, + }; + } else if(node instanceof ConcreteItemGroup) { + return { + expandable: !!node.items && node.items.length > 0, + name: node.componentName, + level: level, + type: ModelComponentType.ITEMGROUP, + } + } else { + return { + expandable: false, + name: node.componentName, + level: level, + type: ModelComponentType.ITEM + } + } + }; + + + treeControl = new FlatTreeControl( + node => node.level, + node => node.expandable, + ); + + treeFlattener = new MatTreeFlattener( + this._transformer, + node => node.level, + node => node.expandable, + node => this.getNodeChildren(node) + ); + + dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener); + selectedItem: FlatNode | undefined + + hasChild = (_: number, node: FlatNode) => node.expandable; + + getNodeChildren(node: ModelComponent): ModelComponent[] { + if(node instanceof ConcreteItemGroup) { + return node.items; + } else if(node instanceof AbstractItemGroup) { + return node.children; + } else { + return []; + } + } + + ngOnInit() { + this.dataSource.data = this.gameModel!.itemgroups; + } + + protected readonly ModelComponentType = ModelComponentType; + + onSelectItem(node: FlatNode) { + this.selectedItem = node; + } + + openItemEditor(node: FlatNode) { + if(node.type == ModelComponentType.ITEMGROUP) { + const itemGroup = GameModel.findItemgroupByName(node.name, this.gameModel!.itemgroups); + if(itemGroup) { + this.openItemgroupEmitter.emit(itemGroup); + } + } else if(node.type == ModelComponentType.ITEM) { + const item = this.searchItemByName(node.name); + if(item !== undefined) { + this.onOpenItemEditor.emit(item); + } + } + } + + private searchItemByName(itemName: string): Item | undefined { + let groupQueue: ItemGroup[] = this.gameModel!.itemgroups.concat(); + while(groupQueue.length > 0) { + const currentGroup = groupQueue.shift()!; + + if(currentGroup instanceof AbstractItemGroup) { + groupQueue = groupQueue.concat(currentGroup.children); + } else if(currentGroup instanceof ConcreteItemGroup) { + const searchResult = currentGroup.items.find(item => item.componentName === itemName); + if(searchResult != undefined) { + return searchResult; + } + } + } + return undefined; + } + + get selectedModelComponent() { + if(this.selectedItem) { + if(this.selectedItem.type === ModelComponentType.ITEMGROUP) { + let groupQueue: ItemGroup[] = this.gameModel!.itemgroups.concat(); + while(groupQueue.length > 0) { + const currentGroup = groupQueue.shift()!; + + if(currentGroup.componentName === this.selectedItem.name) { + return currentGroup; + } + + if(currentGroup instanceof AbstractItemGroup) { + groupQueue = groupQueue.concat(currentGroup.children); + } + } + } else { + return this.searchItemByName(this.selectedItem!.name) + } + } else { + return undefined + } + } + + refresh(): void { + this.dataSource.data = this.gameModel!.itemgroups; + console.log("Opened Refreshed") + } + +} diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.ts b/src/app/side-overviews/script-account-overview/script-account-overview.component.ts index 3643289..fce194e 100644 --- a/src/app/side-overviews/script-account-overview/script-account-overview.component.ts +++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.ts @@ -2,13 +2,14 @@ import {Component, EventEmitter, Input, NgZone, Output} from '@angular/core'; import {ElectronService} from "../../core/services"; import {GameModel} from "../../project/game-model/GameModel"; import {ScriptAccount} from "../../project/game-model/scriptAccounts/ScriptAccount"; +import {Overview} from "../Overview"; @Component({ selector: 'app-script-account-overview', templateUrl: './script-account-overview.component.html', styleUrl: './script-account-overview.component.css' }) -export class ScriptAccountOverviewComponent { +export class ScriptAccountOverviewComponent implements Overview{ @Input("gameModel") gameModel: GameModel | undefined @Output("onOpenScriptAccount") openScriptAccountEmitter: EventEmitter = new EventEmitter(); @@ -17,6 +18,10 @@ export class ScriptAccountOverviewComponent { constructor() { } + refresh(): void { + //Nothing to do + } + onOpenScriptAccount(scriptAccount: ScriptAccount) { console.log("onOpenScriptAccount (overview)") this.openScriptAccountEmitter.emit(scriptAccount); diff --git a/testModel/gamesystems/Parentgamesystem.json b/testModel/gamesystems/Parentgamesystem.json new file mode 100644 index 0000000..75902da --- /dev/null +++ b/testModel/gamesystems/Parentgamesystem.json @@ -0,0 +1,7 @@ +{ + "componentName": "Parentgamesystem", + "componentDescription": "", + "states": [], + "transitions": [], + "generateIsolatedStates": false +} \ No newline at end of file diff --git a/testModel/items/Clothing/Clothing.json b/testModel/items/Clothing/Clothing.json new file mode 100644 index 0000000..af1c0a1 --- /dev/null +++ b/testModel/items/Clothing/Clothing.json @@ -0,0 +1,11 @@ +{ + "componentName": "Clothing", + "componentDescription": "", + "itemGroupCharacteristics": [ + { + "characteristicName": "Test0", + "characteristicDescription": "" + } + ], + "itemgroupType": 1 +} \ No newline at end of file diff --git a/testModel/items/Clothing/Hose/Hose 1.json b/testModel/items/Clothing/Hose/Hose 1.json new file mode 100644 index 0000000..e2f14c9 --- /dev/null +++ b/testModel/items/Clothing/Hose/Hose 1.json @@ -0,0 +1,17 @@ +{ + "componentName": "Hose 1", + "componentDescription": "", + "manuallyInheritedGroups": [ + "Inventory" + ], + "hierarchyInheritedGroups": [ + "Clothing", + "Hose" + ], + "itemCharacteristicValues": [ + { + "key": "Test0", + "value": 0 + } + ] +} \ No newline at end of file diff --git a/testModel/items/Clothing/Hose/Hose 2.json b/testModel/items/Clothing/Hose/Hose 2.json new file mode 100644 index 0000000..50ef84c --- /dev/null +++ b/testModel/items/Clothing/Hose/Hose 2.json @@ -0,0 +1,15 @@ +{ + "componentName": "Hose 2", + "componentDescription": "", + "manuallyInheritedGroups": [], + "hierarchyInheritedGroups": [ + "Clothing", + "Hose" + ], + "itemCharacteristicValues": [ + { + "key": "Test0", + "value": 0 + } + ] +} \ No newline at end of file diff --git a/testModel/items/Clothing/Hose/Hose.json b/testModel/items/Clothing/Hose/Hose.json new file mode 100644 index 0000000..241268e --- /dev/null +++ b/testModel/items/Clothing/Hose/Hose.json @@ -0,0 +1,7 @@ +{ + "componentName": "Hose", + "componentDescription": "", + "itemGroupCharacteristics": [], + "itemgroupType": 0, + "parentgroup": "Clothing" +} \ No newline at end of file diff --git a/testModel/items/Clothing/Oberteil/Oberteil.json b/testModel/items/Clothing/Oberteil/Oberteil.json new file mode 100644 index 0000000..1079ae4 --- /dev/null +++ b/testModel/items/Clothing/Oberteil/Oberteil.json @@ -0,0 +1,7 @@ +{ + "componentName": "Oberteil", + "componentDescription": "", + "itemGroupCharacteristics": [], + "itemgroupType": 0, + "parentgroup": "Clothing" +} \ No newline at end of file diff --git a/testModel/items/Inventory/Inventory.json b/testModel/items/Inventory/Inventory.json new file mode 100644 index 0000000..76568dd --- /dev/null +++ b/testModel/items/Inventory/Inventory.json @@ -0,0 +1,11 @@ +{ + "componentName": "Inventory", + "componentDescription": "", + "itemGroupCharacteristics": [ + { + "characteristicName": "Test0", + "characteristicDescription": "" + } + ], + "itemgroupType": 0 +} \ No newline at end of file diff --git a/testModel/items/Item 1.json b/testModel/items/Item 1.json deleted file mode 100644 index 2316aa2..0000000 --- a/testModel/items/Item 1.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "componentName": "Item 1", - "componentDescription": "", - "possible_qualities": [ - { - "quality_propertes": [ - { - "propertyName": "Price", - "property": 0 - } - ], - "quality_step": 0.25 - }, - { - "quality_propertes": [ - { - "propertyName": "Price", - "property": 0 - } - ], - "quality_step": 0.5 - }, - { - "quality_propertes": [ - { - "propertyName": "Price", - "property": 0 - } - ], - "quality_step": 0.75 - }, - { - "quality_propertes": [ - { - "propertyName": "Price", - "property": 0 - } - ], - "quality_step": 1 - } - ], - "itemProperties": [ - { - "propertyName": "Weight", - "propertyDescription": "Some Weights", - "property": 10 - } - ], - "perQualityProperties": [ - { - "propertyName": "Price", - "propertyDescription": "Price to buy item" - } - ] -} \ No newline at end of file diff --git a/testModel/items/Item 2.json b/testModel/items/Item 2.json deleted file mode 100644 index 1e3bc67..0000000 --- a/testModel/items/Item 2.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "componentName": "Item 2", - "componentDescription": "", - "possible_qualities": [ - { - "quality_propertes": [ - { - "propertyName": "Price", - "property": 0 - } - ], - "quality_step": 0.25 - }, - { - "quality_propertes": [ - { - "propertyName": "Price", - "property": 0 - } - ], - "quality_step": 0.5 - }, - { - "quality_propertes": [ - { - "propertyName": "Price", - "property": 0 - } - ], - "quality_step": 0.75 - }, - { - "quality_propertes": [ - { - "propertyName": "Price", - "property": 0 - } - ], - "quality_step": 1 - } - ], - "itemProperties": [ - { - "propertyName": "Weight", - "propertyDescription": "Some Weights", - "property": 10 - } - ], - "perQualityProperties": [ - { - "propertyName": "Price", - "propertyDescription": "Price to buy item" - } - ] -} \ No newline at end of file