diff --git a/app/main.ts b/app/main.ts index c4ffd82..30431c1 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/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..6a0240f 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -28,7 +28,8 @@ 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"; @Component({ selector: 'app-root', @@ -225,7 +226,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 +241,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 +269,8 @@ export class AppComponent implements OnInit{ this.drawer!.open() } - openContentOverview(contentType: ModelComponentType) { - this.openContent = contentType; + openOverview(overviewType: ModelComponentType) { + this.openContent = overviewType; this.drawer!.open(); } @@ -297,4 +304,5 @@ export class AppComponent implements OnInit{ } + protected readonly open = open; } 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..dde1cc3 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,69 @@ export class GameModel { gamesystems: Gamesystem[] = []; scriptAccounts: ScriptAccount[] = []; characters: Character[] = [] - inventoryItems: Item[] = [] + itemgroups: ItemGroup[] = [] constructor(gameModelName: string) { this.gameModelName = gameModelName; } + addAbstractItemgroup(groupName: string, parentgroup: AbstractItemGroup | undefined) { + //Ensure that Itemgroup does not exist + if(parentgroup == undefined) { + if(GameModel.findItemgroupByName(groupName, this.itemgroups) == undefined) { + const itemgroup = new AbstractItemGroup(groupName, "", ModelComponentType.ITEMGROUP) + this.itemgroups.push(itemgroup); + itemgroup.addItemgroupCharacteristic(new ItemGroupCharacteristic("Test0", "", itemgroup)); + } + } else { + if(GameModel.findItemgroupByName(groupName, parentgroup.children) == undefined) { + parentgroup.addChildItemgroup(new AbstractItemGroup(groupName, "", ModelComponentType.ITEMGROUP)); + } + } + } + + addConcreteItemgroup(groupName: string, parentgroup: AbstractItemGroup | undefined) { + //Ensure that Itemgroup does not exist + if(parentgroup == undefined) { + if(GameModel.findItemgroupByName(groupName, this.itemgroups) == undefined) { + this.itemgroups.push(new ConcreteItemGroup(groupName, "", ModelComponentType.ITEMGROUP)); + } + } else { + if(GameModel.findItemgroupByName(groupName, parentgroup.children) == undefined) { + parentgroup.addChildItemgroup(new ConcreteItemGroup(groupName, "", ModelComponentType.ITEMGROUP)); + } + } + } + + addItem(itemName: string, conceteItemgroupName: string) { + const itemgroup = GameModel.findItemgroupByName(conceteItemgroupName, this.itemgroups); + if(itemgroup instanceof ConcreteItemGroup) { + const itemgroups: ItemGroup[] = ItemgroupUtilities.findItemgroupPathToItemgroup(conceteItemgroupName, this.itemgroups); + + if(itemgroups.length > 0) { + const item = new Item(itemName, "", ModelComponentType.ITEM ) + itemgroup.addItem(item, itemgroups) + return item; + } + } + } + + + 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); @@ -103,12 +165,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 +220,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)); @@ -213,4 +266,19 @@ 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; + } } 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/inventory/AbstractItemGroup.ts b/src/app/project/game-model/inventory/AbstractItemGroup.ts new file mode 100644 index 0000000..cc95cb0 --- /dev/null +++ b/src/app/project/game-model/inventory/AbstractItemGroup.ts @@ -0,0 +1,20 @@ +import {ItemGroup} from "./ItemGroup"; +import {ItemGroupCharacteristic} from "./ItemgroupCharacteristic"; +import {ItemgroupType} from "./ItemgroupType"; + +export class AbstractItemGroup extends ItemGroup { + + children: ItemGroup[] = []; + itemgroupType = ItemgroupType.ABSTRACT + + addChildItemgroup(itemGroup: ItemGroup) { + this.children.push(itemGroup) + itemGroup.parentGroup = this; + } + + protected addCharacteristicValue(characteristic: ItemGroupCharacteristic): void { + //Do Nothing + } + + +} diff --git a/src/app/project/game-model/inventory/ConcreteItemGroup.ts b/src/app/project/game-model/inventory/ConcreteItemGroup.ts new file mode 100644 index 0000000..5ad4710 --- /dev/null +++ b/src/app/project/game-model/inventory/ConcreteItemGroup.ts @@ -0,0 +1,31 @@ +import {ItemGroup} from "./ItemGroup"; +import {Item} from "./Item"; +import {ItemGroupCharacteristic} from "./ItemgroupCharacteristic"; +import {ItemgroupType} from "./ItemgroupType"; + +export class ConcreteItemGroup extends ItemGroup { + + items: Item[] = []; + itemgroupType = ItemgroupType.CONCRETE + + addItem(item: Item, parentItemgroups: ItemGroup[]) { + if(this.findItemByName(item.componentName) == undefined) { + parentItemgroups.forEach(itemgroup => { + 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/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/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..3ae9aa0 --- /dev/null +++ b/src/app/side-overviews/item-overview/item-overview.component.ts @@ -0,0 +1,123 @@ +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"; + +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{ + + @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; + } +} 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..27b2fe9 --- /dev/null +++ b/testModel/items/Inventory/Inventory.json @@ -0,0 +1,11 @@ +{ + "componentName": "Inventory", + "componentDescription": "", + "itemGroupCharacteristics": [ + { + "characteristicName": "Test0", + "characteristicDescription": "" + } + ], + "itemgroupType": 1 +} \ No newline at end of file