main #48

Closed
sebastian wants to merge 44 commits from main into inventory
75 changed files with 1853 additions and 454 deletions

View File

@ -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) {

View File

@ -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

View File

@ -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";
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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) {
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 itemData = fs.readFileSync(itemFile, 'utf-8');
return new StoreComponent_1.StoreComponent(itemData, itemFile, ModelComponentType_1.ModelComponentType.ITEM);
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;

View File

@ -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) {
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 itemData = fs.readFileSync(itemFile, 'utf-8');
return new StoreComponent(itemData, itemFile, ModelComponentType.ITEM)
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;
}
}

View File

@ -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

View File

@ -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))
}
}

View File

@ -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();
})
});

View File

@ -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();
})
});

View File

@ -1,13 +1,14 @@
<div class="container">
<div class="full-height-container" >
<button mat-icon-button class="small-icon-button" [ngClass]="openContent === ModelComponentType.SCRIPTACCOUNT ? 'selected':''"
(click)="openScriptAccountsOverview()"><mat-icon>analytics</mat-icon></button>
(click)="openScriptAccountsOverview()"><mat-icon>inventory_2</mat-icon></button>
<button mat-icon-button class="small-icon-button" [ngClass]="openContent === ModelComponentType.GAMESYTEM ? 'selected':''"
(click)="openGamesystemsOverview()"><mat-icon>code</mat-icon></button>
<button mat-icon-button class="small-icon-button" [ngClass]="openContent === ModelComponentType.CHARACTER ? 'selected':''"
(click)="openCharactersOverview()"><mat-icon>person</mat-icon></button>
<button mat-icon-button class="small-icon-button" [ngClass]="openContent === ModelComponentType.ITEM ? 'selected':''"
(click)="openContentOverview(ModelComponentType.ITEM)"><mat-icon>inventory_2</mat-icon></button>
<button mat-icon-button class="small-icon-button" [ngClass]="openContent === ModelComponentType.ITEM || openContent === ModelComponentType.ITEMGROUP ? 'selected':''"
(click)="openOverview(ModelComponentType.ITEM)"><mat-icon>inventory_2</mat-icon></button>
</div>
@ -25,13 +26,15 @@
<button mat-menu-item (click)="openScriptAccountsOverview()">{{ModelComponentTypeUtillities.toString(ModelComponentType.SCRIPTACCOUNT)}}</button>
<button mat-menu-item (click)="openGamesystemsOverview()">{{ModelComponentTypeUtillities.toString(ModelComponentType.GAMESYTEM)}}</button>
<button mat-menu-item (click)="openCharactersOverview()">{{ModelComponentTypeUtillities.toString(ModelComponentType.CHARACTER)}}</button>
<button mat-menu-item (click)="openContentOverview(ModelComponentType.ITEM)">{{ModelComponentTypeUtillities.toString(ModelComponentType.ITEM)}}</button>
<button mat-menu-item (click)="openOverview(ModelComponentType.ITEMGROUP)">{{ModelComponentTypeUtillities.toString(ModelComponentType.ITEM)}}</button>
</mat-menu>
</div>
<app-script-account-overview *ngIf="openContent == ModelComponentType.SCRIPTACCOUNT" #scriptAccountOverview [gameModel]="gameModel" (onOpenScriptAccount)="openModelComponent($event)"></app-script-account-overview>
<app-gamescript-overview *ngIf="openContent == ModelComponentType.GAMESYTEM" #gamesystemOverview [gameModel]="gameModel" (openGamesystemEditor)="openModelComponent($event)"></app-gamescript-overview>
<app-character-overview *ngIf="openContent == ModelComponentType.CHARACTER" #characterOverview [gameModel]="gameModel" (onOpenCharacterEditor)="openModelComponent($event)"></app-character-overview>
<app-inventory-item-overview *ngIf="openContent === ModelComponentType.ITEM" #itemOverview [gameModel]="gameModel" (openItemEditor)="openModelComponent($event)"></app-inventory-item-overview>
<app-item-overview *ngIf="openContent == ModelComponentType.ITEMGROUP || openContent == ModelComponentType.ITEM"
#itemOverview [gameModel]="gameModel" (openItemgroupEmitter)="openModelComponent($event)"
(onOpenItemEditor)="openModelComponent($event)"></app-item-overview>
</mat-drawer>
<div class="example-sidenav-content">

View File

@ -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;
}
}
}

View File

@ -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]

View File

@ -16,11 +16,11 @@
[scriptAccounts]="gameModel!.scriptAccounts"></app-gamesystem-editor>
<app-character-editor *ngIf="modelComponent.type === ModelComponentType.CHARACTER"
[character]="convertModelComponentToCharacter(modelComponent)"
[gameModel]="gameModel!">
[gameModel]="gameModel!"
>
</app-character-editor>
<app-inventory-item-editor *ngIf="modelComponent.type === ModelComponentType.ITEM"
[item]="convertModelComponentToItem(modelComponent)"
[gameModel]="gameModel!">
</app-inventory-item-editor>
<app-item-group-editor *ngIf="modelComponent.type === ModelComponentType.ITEMGROUP" [itemgroup]="convertModelComponentToItemGroup(modelComponent)"></app-item-group-editor>
<app-item-editor *ngIf="modelComponent.type === ModelComponentType.ITEM" [item]="convertModelComponentToItem(modelComponent)" [gameModel]="gameModel!"></app-item-editor>
</mat-tab>
</mat-tab-group>

View File

@ -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;
}
}

View File

@ -0,0 +1,28 @@
<table mat-table [dataSource]="findCharacteristicValuesByItemgroup(inheritedItemgroup!)" class="mat-elevation-z8">
<ng-container matColumnDef="characteristic">
<th mat-header-cell *matHeaderCellDef>Characteristic</th>
<td mat-cell *matCellDef="let characteristicValue">{{characteristicValue.key.characteristicName}}</td>
</ng-container>
<ng-container matColumnDef="value">
<th mat-header-cell *matHeaderCellDef>Value</th>
<td mat-cell *matCellDef="let characteristicValue">
<span *ngIf="characteristicValue !== editedItemgroupCharacteristicValue">{{characteristicValue.value}}</span>
<mat-form-field appearance="outline" style="width: 100%;" *ngIf="characteristicValue === editedItemgroupCharacteristicValue">
<mat-label>Value</mat-label>
<input matInput [(ngModel)]="characteristicValue.value">
</mat-form-field>
</td>
</ng-container>
<ng-container matColumnDef="edit">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let characteristicValue">
<button mat-icon-button *ngIf="editedItemgroupCharacteristicValue == undefined" (click)="editCharacteristicValue(characteristicValue)"><mat-icon>edit</mat-icon></button>
<button mat-icon-button *ngIf="editedItemgroupCharacteristicValue != undefined" (click)="finishEditing()" [disabled]="characteristicValue !== editedItemgroupCharacteristicValue"><mat-icon>done</mat-icon></button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

View File

@ -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<InheritedItemCharacteristicEditorComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [InheritedItemCharacteristicEditorComponent]
})
.compileComponents();
fixture = TestBed.createComponent(InheritedItemCharacteristicEditorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -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<ItemgroupCharacteristicValue> = new MatTableDataSource<ItemgroupCharacteristicValue>();
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;
}
}

View File

@ -0,0 +1,20 @@
<mat-card>
<mat-card-header>
<mat-card-title>Inherited Itemgroups</mat-card-title>
</mat-card-header>
<mat-card-content>
<mat-accordion>
<mat-expansion-panel *ngFor="let itemgroup of manuallyAndHierarchyItemgroups">
<mat-expansion-panel-header>
<mat-panel-title>{{itemgroup.componentName}}</mat-panel-title>
<mat-panel-description>{{itemgroup.componentDescription}}</mat-panel-description>
</mat-expansion-panel-header>
<app-inherited-item-characteristic-editor [inheritedItemgroup]="itemgroup" [item]="item"></app-inherited-item-characteristic-editor>
<div class="panel-actions">
<button mat-raised-button color="warn" [disabled]="automaticallyInheritedItemgroups.includes(itemgroup)" (click)="deleteInheritedItemgroup(itemgroup)">Delete</button>
</div>
</mat-expansion-panel>
</mat-accordion>
<button mat-stroked-button style="width: 100%" (click)="onAddNewInheritedItemgroup()">Add Itemgroup</button>
</mat-card-content>
</mat-card>

View File

@ -0,0 +1,3 @@
.panel-actions {
float: right;
}

View File

@ -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<ItemEditorComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ItemEditorComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ItemEditorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -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);
}
}

View File

@ -0,0 +1,13 @@
<h1 mat-dialog-title>Inherit Itemgroup</h1>
<mat-dialog-content>
<mat-form-field appearance="outline" style="width: 100%;">
<mat-label>Select Itemgroup</mat-label>
<mat-select [(ngModel)]="selectedItemgroup">
<mat-option *ngFor="let itemgroup of availableItemgroups" [value]="itemgroup">{{itemgroup.componentName}}</mat-option>
</mat-select>
</mat-form-field>
</mat-dialog-content>
<mat-dialog-actions align="end">
<button mat-stroked-button (click)="cancel()">Cancel</button>
<button mat-raised-button color="primary" (click)="submit()">Confim</button>
</mat-dialog-actions>

View File

@ -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<ItemgroupInheritorComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ItemgroupInheritorComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ItemgroupInheritorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -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<ItemgroupInheritorComponent>,
@Inject(MAT_DIALOG_DATA) public availableItemgroups: ItemGroup[]) {
}
cancel() {
this.dialogRef.close()
}
submit() {
this.dialogRef.close(this.selectedItemgroup);
}
}

View File

@ -0,0 +1,36 @@
<table mat-table [dataSource]="itemQualityDatasource" class="mat-elevation-z8">
<ng-container matColumnDef="Characteristic">
<th mat-header-cell *matHeaderCellDef> Characteristic </th>
<td mat-cell *matCellDef="let element">
<span *ngIf="editedCharacteristic !== element">{{element.characteristicName}}</span>
<mat-form-field appearance="outline" *ngIf="editedCharacteristic === element" style="width: 100%">
<mat-label>Name</mat-label>
<input matInput [(ngModel)]="element.characteristicName">
</mat-form-field>
</td>
</ng-container>
<ng-container matColumnDef="Description">
<th mat-header-cell *matHeaderCellDef> Description </th>
<td mat-cell *matCellDef="let element">
<span *ngIf="editedCharacteristic !== element">{{element.characteristicDescription}}</span>
<mat-form-field appearance="outline" *ngIf="editedCharacteristic === element" style="width: 100%">
<mat-label>Name</mat-label>
<textarea matInput [(ngModel)]="element.characteristicDescription" rows="3"></textarea>
</mat-form-field>
</td>
</ng-container>
<ng-container matColumnDef="edit">
<th mat-header-cell *matHeaderCellDef> </th>
<td mat-cell *matCellDef="let element">
<button mat-icon-button *ngIf="editedCharacteristic !== element" [disabled]="editedCharacteristic" (click)="editItemgroupCharacteristic(element)"><mat-icon>edit</mat-icon></button>
<button mat-icon-button *ngIf="editedCharacteristic === element" (click)="finishEditing()"><mat-icon>done</mat-icon></button>
</td>
</ng-container>
<ng-container matColumnDef="delete">
<th mat-header-cell *matHeaderCellDef> <button mat-icon-button (click)="addItemgroupCharacteristic()"><mat-icon>add</mat-icon></button> </th>
<td mat-cell *matCellDef="let element"><button mat-icon-button color="warn" (click)="deleteItemgroupCharacteristic(element)"><mat-icon>delete</mat-icon></button></td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

View File

@ -0,0 +1,7 @@
.mat-column-edit, .mat-column-delete {
width: 32px;
}
.mat-column-Characteristic, {
width: 25%;
}

View File

@ -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<ItemGroupEditorComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ItemGroupEditorComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ItemGroupEditorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -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<ItemGroupCharacteristic> = new MatTableDataSource<ItemGroupCharacteristic>();
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;
}
}

View File

@ -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<any, any>[] = [];
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<any, any>) {
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<State<any>, Transition<any>>[] = [];
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;
}
}

View File

@ -2,5 +2,7 @@ export enum ModelComponentType {
SCRIPTACCOUNT,
GAMESYTEM,
CHARACTER,
ITEMGROUP,
ITEM
}

View File

@ -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;
}
}
}

View File

@ -27,5 +27,4 @@ export abstract class Gamesystem<S, T> extends ModelComponent{
this.transitions = updatedTransitions;
return true;
}
}

View File

@ -32,14 +32,12 @@ export class ProductGamesystem extends Gamesystem<ProductState, ProductTransitio
simpleGamesystem.parentGamesystem = this
}
if(parentGamesystem != undefined) {
if(parentGamesystem == undefined || parentGamesystem.componentName === this.componentName) {
gameModel.removeGamesystem(simpleGamesystem);
this.addChildGamesystem(simpleGamesystem);
} else {
parentGamesystem.removeChildGamesystem(simpleGamesystem);
parentGamesystem.addChildGamesystem(this);
this.parentGamesystem = parentGamesystem
} else {
gameModel.removeGamesystem(simpleGamesystem);
gameModel.addGamesystem(this);
}
}

View File

@ -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
}
}

View File

@ -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);
})
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,4 @@
export enum ItemgroupType {
CONCRETE,
ABSTRACT
}

View File

@ -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<itemgroups.length; i++) {
const found_path = this.findItemgroupPathToItemRecursive(itemgroups[i], searchedItemName, []);
if(found_path.length > 0) {
return found_path;
}
}
return [];
}
public static findItemgroupPathToItemgroup(searchedItemgroupName: string, itemgroups: ItemGroup[]): ItemGroup[] {
for(let i=0; i<itemgroups.length; i++) {
const found_path = this.findItemgroupPathToItemgroupRecursive(itemgroups[i], searchedItemgroupName, []);
if(found_path.length > 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<root.children.length; i++) {
const found_path = this.findItemgroupPathToItemgroupRecursive(root.children[i], searchedItemgroupName, path.concat())
if(found_path != undefined && found_path.length > 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<root.children.length; i++) {
const found_path = this.findItemgroupPathToItemRecursive(root.children[i], searchedItemName, path.concat());
if(found_path.length > 0) {
return found_path;
}
}
}
return [];
}
}

View File

@ -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;
}
}

View File

@ -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<any, any>, 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);
}
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}
}
}

View File

@ -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<inheritedGroupsData.length; i++) {
const inheritedGroupName = inheritedGroupsData[i];
const matchedGroup = this.parsedItemgroups.find(group => group.componentName === inheritedGroupName);
if (matchedGroup) {
inheritedGroups.push(matchedGroup);
}
}
return inheritedGroups;
}
private parseItemCharacteristicValues(data: any): ItemgroupCharacteristicValue[] {
const values: ItemgroupCharacteristicValue[] = []
for(let i=0; i<data.length; i++) {
const key = this.findItemCharacteristic(data[i].key);
if (key) {
const characteristicValue = new ItemgroupCharacteristicValue(key!, data[i].value)
values.push(characteristicValue)
} else {
console.log("[ERROR] Characteristic not found: ", data[i].key)
}
}
return values;
}
private findItemCharacteristic(itemCharacteristicName: string) {
for(let i=0; i<this.parsedItemgroups.length; i++) {
const characteristic = this.parsedItemgroups[i].itemGroupCharacteristics
.find(characteristic=> characteristic.characteristicName === itemCharacteristicName);
if(characteristic != undefined) {
return characteristic;
}
}
return undefined;
}
}

View File

@ -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<itemgroupCharacteristicsData.length; i++) {
this.parseSingleItemgroupCharacteristic(itemgroupCharacteristicsData[i], itemgroup)
}
return itemgroupCharacteristics;
}
private parseSingleItemgroupCharacteristic(itemgroupCharacteristicData: any, itemgroup: ItemGroup) {
const name = itemgroupCharacteristicData.characteristicName;
const description = itemgroupCharacteristicData.characteristicDescription;
const characteristic = new ItemGroupCharacteristic(name, description, itemgroup);
characteristic.itemgroup.addItemgroupCharacteristic(characteristic);
return characteristic;
}
getParsedTopItemgroups() {
return this.topParsedItemgroups;
}
getParsedItemgroups() {
return this.parsedItemgroups;
}
}

View File

@ -27,9 +27,7 @@ export class GamesystemSerializer {
private static serializeSimpleGamesystem(simpleGamesystem: SimpleGamesystem): StoreComponent {
const fileName = this.computeSimpleGamesystemPath(simpleGamesystem);
if(simpleGamesystem.componentName === "Weather(Child)") {
console.log(fileName)
}
const jsonString = JSON.stringify(simpleGamesystem, (key, value) => {
if(this.IGNORED_SIMPLE_ATTRIBUTES.includes(key)) {

View File

@ -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
}));
}
if(key === 'unsaved' || key === 'type') {
return 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 {
return value;
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(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;
}
}

10
src/app/shared/Tupel.ts Normal file
View File

@ -0,0 +1,10 @@
export class Tupel<A, B> {
value00: A
value01: B
constructor(value00: A, value01: B) {
this.value00 = value00;
this.value01 = value01;
}
}

View File

@ -0,0 +1,3 @@
export interface Overview {
refresh(): void
}

View File

@ -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<Character> = new EventEmitter<Character>();

View File

@ -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<Gamesystem<State<any>, Transition<any>>> = new EventEmitter<Gamesystem<State<any>, Transition<any>>>();

View File

@ -0,0 +1,22 @@
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
<!-- This is the tree node template for leaf nodes -->
<mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding matTreeNodePaddingIndent="10" (click)="onSelectItem(node)" (contextmenu)="onSelectItem(node)" (dblclick)="openItemEditor(node)">
<!-- use a disabled button to provide padding for tree leaf -->
<button class="small-icon-button" mat-icon-button disabled></button>
<mat-icon class="small-icon-button" *ngIf="node.type == ModelComponentType.ITEMGROUP">folder</mat-icon>
<mat-icon class="small-icon-button" *ngIf="node.type == ModelComponentType.ITEM">data_object</mat-icon>
{{node.name}}
</mat-tree-node>
<!-- This is the tree node template for expandable nodes -->
<mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding matTreeNodePaddingIndent="10" (click)="onSelectItem(node)" (contextmenu)="onSelectItem(node)" (dblclick)="openItemEditor(node)">
<button class="small-icon-button" mat-icon-button matTreeNodeToggle
[attr.aria-label]="'Toggle ' + node.name">
<mat-icon class="mat-icon-rtl-mirror">
{{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
</mat-icon>
</button>
<mat-icon class="small-icon-button" *ngIf="node.type == ModelComponentType.ITEMGROUP">folder</mat-icon>
<mat-icon class="small-icon-button" *ngIf="node.type == ModelComponentType.ITEM">data_object</mat-icon>
{{node.name}}
</mat-tree-node>
</mat-tree>

View File

@ -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
}

View File

@ -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<ItemOverviewComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ItemOverviewComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ItemOverviewComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -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<ItemGroup> = new EventEmitter();
@Output() onOpenItemEditor: EventEmitter<Item> = 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<FlatNode>(
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")
}
}

View File

@ -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<ScriptAccount> = new EventEmitter<ScriptAccount>();
@ -17,6 +18,10 @@ export class ScriptAccountOverviewComponent {
constructor() {
}
refresh(): void {
//Nothing to do
}
onOpenScriptAccount(scriptAccount: ScriptAccount) {
console.log("onOpenScriptAccount (overview)")
this.openScriptAccountEmitter.emit(scriptAccount);

View File

@ -0,0 +1,7 @@
{
"componentName": "Parentgamesystem",
"componentDescription": "",
"states": [],
"transitions": [],
"generateIsolatedStates": false
}

View File

@ -0,0 +1,11 @@
{
"componentName": "Clothing",
"componentDescription": "",
"itemGroupCharacteristics": [
{
"characteristicName": "Test0",
"characteristicDescription": ""
}
],
"itemgroupType": 1
}

View File

@ -0,0 +1,17 @@
{
"componentName": "Hose 1",
"componentDescription": "",
"manuallyInheritedGroups": [
"Inventory"
],
"hierarchyInheritedGroups": [
"Clothing",
"Hose"
],
"itemCharacteristicValues": [
{
"key": "Test0",
"value": 0
}
]
}

View File

@ -0,0 +1,15 @@
{
"componentName": "Hose 2",
"componentDescription": "",
"manuallyInheritedGroups": [],
"hierarchyInheritedGroups": [
"Clothing",
"Hose"
],
"itemCharacteristicValues": [
{
"key": "Test0",
"value": 0
}
]
}

View File

@ -0,0 +1,7 @@
{
"componentName": "Hose",
"componentDescription": "",
"itemGroupCharacteristics": [],
"itemgroupType": 0,
"parentgroup": "Clothing"
}

View File

@ -0,0 +1,7 @@
{
"componentName": "Oberteil",
"componentDescription": "",
"itemGroupCharacteristics": [],
"itemgroupType": 0,
"parentgroup": "Clothing"
}

View File

@ -0,0 +1,11 @@
{
"componentName": "Inventory",
"componentDescription": "",
"itemGroupCharacteristics": [
{
"characteristicName": "Test0",
"characteristicDescription": ""
}
],
"itemgroupType": 0
}

View File

@ -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"
}
]
}

View File

@ -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"
}
]
}