diff --git a/app/main.ts b/app/main.ts index 45b1f1a..449ef21 100644 --- a/app/main.ts +++ b/app/main.ts @@ -64,9 +64,20 @@ function createWindow(): BrowserWindow { submenu: [ { label: "Gamesystem", - click: () => { - win!.webContents.send('context-menu', "new-gamesystem"); - } + submenu: [ + { + label: "Normal", + click: () => { + win!.webContents.send('context-menu', "new-gamesystem-normal"); + } + }, + { + label: "Character", + click: () => { + win!.webContents.send('context-menu', "new-gamesystem-character"); + } + } + ] }, { label: "ScriptAccount", diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 41f2835..6b962e0 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -24,6 +24,9 @@ import {Character} from "./project/game-model/characters/Character"; import {CharacterOverviewComponent} from "./side-overviews/character-overview/character-overview.component"; 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"; @Component({ selector: 'app-root', @@ -76,8 +79,9 @@ 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); + this.onCreateModelComponent(modelComponentType, templateType); } else { console.log("[ERROR] [App-Component] Unknown Context-Menu Command!") } @@ -127,10 +131,10 @@ export class AppComponent implements OnInit{ }) } - private onCreateModelComponent(modelComponentType: ModelComponentType) { + private onCreateModelComponent(modelComponentType: ModelComponentType, templateType: TemplateType | undefined) { switch (modelComponentType) { case ModelComponentType.SCRIPTACCOUNT: this.onCreateNewScriptAccount(); break - case ModelComponentType.GAMESYTEM: this.onCreateNewGamesystem(); break + case ModelComponentType.GAMESYTEM: this.onCreateNewGamesystem(templateType); break case ModelComponentType.CHARACTER: this.onCreateNewCharacter(); break } } @@ -144,7 +148,7 @@ export class AppComponent implements OnInit{ } } - private onCreateNewGamesystem() { + private onCreateNewGamesystem(templateType: TemplateType | undefined) { let parentGamesystemName = undefined if(this.openContent != ModelComponentType.GAMESYTEM) { this.openGamesystemsOverview(); @@ -153,7 +157,13 @@ export class AppComponent implements OnInit{ } - const createdGamesystem = this.gameModel!.createGamesystem("New Gamesystem", parentGamesystemName); + 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); @@ -204,14 +214,13 @@ export class AppComponent implements OnInit{ const gamesystemParser = new GamesystemParser(scriptAccounts); const gamesystems = gamesystemParser.parseStoredGamesystems(storedGameModel.storedGamesystems); - const characterParser = new CharacterParser(); - const characters = characterParser.parseCharacters(storedGameModel.storedCharacters); - gameModel.scriptAccounts = scriptAccounts gameModel.gamesystems = gamesystems gameModel.generateProductSystemContents() - gameModel.characters = characters + const characterTemplateSystems = gameModel.getTemplateSystems(TemplateType.CHARACTER).map(templateSystem => templateSystem as SimpleTemplateGamesystem) + const characterParser = new CharacterParser(characterTemplateSystems, gameModel.scriptAccounts); + gameModel.characters = characterParser.parseCharacters(storedGameModel.storedCharacters) this.gameModel = gameModel; } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 7412843..0523803 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -61,7 +61,7 @@ import { ProductStateEditorComponent } from "./editor/gamesystem-editor/state-editor/product-state-editor/product-state-editor.component"; import {MatTooltip} from "@angular/material/tooltip"; -import {MatCard, MatCardContent} 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"; @@ -70,6 +70,15 @@ import { } from "./editor/gamesystem-editor/scriptaccount-condition-editor/scriptaccount-condition-editor.component"; import {CharacterOverviewComponent} from "./side-overviews/character-overview/character-overview.component"; import {CharacterEditorComponent} from "./editor/character-editor/character-editor.component"; +import { + MatAccordion, + MatExpansionPanel, + MatExpansionPanelHeader, + MatExpansionPanelTitle +} from "@angular/material/expansion"; +import { + TemplateSpecificatorComponent +} from "./editor/gamesystem-editor/template-specificator/template-specificator.component"; // AoT requires an exported function for factories const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json'); @@ -93,7 +102,8 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl ScriptaccountActionEditorComponent, ScriptaccountConditionEditorComponent, CharacterOverviewComponent, - CharacterEditorComponent + CharacterEditorComponent, + TemplateSpecificatorComponent ], imports: [ BrowserModule, @@ -150,7 +160,13 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl MatHint, MatTooltip, MatCard, - MatCardContent + MatCardContent, + MatCardHeader, + MatAccordion, + MatExpansionPanel, + MatExpansionPanelTitle, + MatCardTitle, + MatExpansionPanelHeader ], providers: [], bootstrap: [AppComponent] diff --git a/src/app/editor/character-editor/character-editor.component.html b/src/app/editor/character-editor/character-editor.component.html index 4750ae3..b13fddf 100644 --- a/src/app/editor/character-editor/character-editor.component.html +++ b/src/app/editor/character-editor/character-editor.component.html @@ -1 +1,16 @@ -

character-editor works!

+ + + Characterspecific Gamesystems + + + + + + {{templateSystem.componentName}} + + + + + + + diff --git a/src/app/editor/character-editor/character-editor.component.scss b/src/app/editor/character-editor/character-editor.component.scss index e69de29..4ce3702 100644 --- a/src/app/editor/character-editor/character-editor.component.scss +++ b/src/app/editor/character-editor/character-editor.component.scss @@ -0,0 +1,4 @@ +.specify-btn { + width: 100%; + margin-top: 10px; +} diff --git a/src/app/editor/character-editor/character-editor.component.ts b/src/app/editor/character-editor/character-editor.component.ts index 23e8438..72bd256 100644 --- a/src/app/editor/character-editor/character-editor.component.ts +++ b/src/app/editor/character-editor/character-editor.component.ts @@ -1,4 +1,11 @@ -import { Component } from '@angular/core'; +import {Component, Input} from '@angular/core'; +import {Character} from "../../project/game-model/characters/Character"; +import {GameModel} from "../../project/game-model/GameModel"; +import {MatDialog} from "@angular/material/dialog"; +import { + TemplateSpecificatorComponent +} from "../gamesystem-editor/template-specificator/template-specificator.component"; +import {TemplateType} from "../../project/game-model/templates/TemplateType"; @Component({ selector: 'app-character-editor', @@ -7,4 +14,19 @@ import { Component } from '@angular/core'; }) export class CharacterEditorComponent { + @Input() character: Character | undefined; + @Input() gameModel: GameModel | undefined; + + constructor(private dialog: MatDialog) { + } + + openTemplateSpecificator() { + const dialogRef = this.dialog.open(TemplateSpecificatorComponent, {data: this.gameModel?.getTemplateSystems(TemplateType.CHARACTER), minWidth: "400px"}); + dialogRef.afterClosed().subscribe(res => { + if(res != undefined) { + this.character!.addCharacterSpecificSimpleTemplatesystem(res); + } + }) + } + } diff --git a/src/app/editor/editor.component.html b/src/app/editor/editor.component.html index b351774..23be637 100644 --- a/src/app/editor/editor.component.html +++ b/src/app/editor/editor.component.html @@ -14,7 +14,10 @@ [gamesystem]="convertModelComponentToGamesystem(modelComponent)" (onOpenGamesystemEditor)="openGameModelComponent($event)" [scriptAccounts]="gameModel!.scriptAccounts"> - + diff --git a/src/app/editor/editor.component.ts b/src/app/editor/editor.component.ts index 887f4d8..50f44b9 100644 --- a/src/app/editor/editor.component.ts +++ b/src/app/editor/editor.component.ts @@ -6,6 +6,7 @@ import {Gamesystem} from "../project/game-model/gamesystems/Gamesystem"; 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"; @Component({ @@ -50,4 +51,10 @@ export class EditorComponent { } protected readonly ModelComponentType = ModelComponentType; + + convertModelComponentToCharacter(modelComponent: ModelComponent) { + if(modelComponent instanceof Character) + return modelComponent as Character + return undefined; + } } diff --git a/src/app/editor/gamesystem-editor/gamesystem-editor.component.html b/src/app/editor/gamesystem-editor/gamesystem-editor.component.html index 2eb564e..f4ef23b 100644 --- a/src/app/editor/gamesystem-editor/gamesystem-editor.component.html +++ b/src/app/editor/gamesystem-editor/gamesystem-editor.component.html @@ -1,3 +1,3 @@ - - + diff --git a/src/app/editor/gamesystem-editor/gamesystem-editor.component.ts b/src/app/editor/gamesystem-editor/gamesystem-editor.component.ts index f14dda3..2174be0 100644 --- a/src/app/editor/gamesystem-editor/gamesystem-editor.component.ts +++ b/src/app/editor/gamesystem-editor/gamesystem-editor.component.ts @@ -5,6 +5,7 @@ import { Transition } from '../../project/game-model/gamesystems/transitions/Tra import {ScriptAccount} from "../../project/game-model/scriptAccounts/ScriptAccount"; import {SimpleGamesystem} from "../../project/game-model/gamesystems/SimpleGamesystem"; import {ProductGamesystem} from "../../project/game-model/gamesystems/ProductGamesystem"; +import {TemplateElement} from "../../project/game-model/templates/TemplateElement"; @Component({ selector: 'app-gamesystem-editor', @@ -15,6 +16,7 @@ export class GamesystemEditorComponent implements OnInit{ @Input() gamesystem: Gamesystem, Transition> | undefined @Input() scriptAccounts: ScriptAccount[] = []; + @Input() templateElement: TemplateElement | undefined @Output('onOpenGamesystemEditor') openGamesystemEmitter = new EventEmitter(); ngOnInit() { diff --git a/src/app/editor/gamesystem-editor/product-gamesystem-editor/product-gamesystem-editor.component.html b/src/app/editor/gamesystem-editor/product-gamesystem-editor/product-gamesystem-editor.component.html index b2d1a1f..0eee76f 100644 --- a/src/app/editor/gamesystem-editor/product-gamesystem-editor/product-gamesystem-editor.component.html +++ b/src/app/editor/gamesystem-editor/product-gamesystem-editor/product-gamesystem-editor.component.html @@ -1,4 +1,4 @@ - +
- +
diff --git a/src/app/editor/gamesystem-editor/product-gamesystem-editor/product-gamesystem-editor.component.ts b/src/app/editor/gamesystem-editor/product-gamesystem-editor/product-gamesystem-editor.component.ts index d1f7f23..29319ca 100644 --- a/src/app/editor/gamesystem-editor/product-gamesystem-editor/product-gamesystem-editor.component.ts +++ b/src/app/editor/gamesystem-editor/product-gamesystem-editor/product-gamesystem-editor.component.ts @@ -4,6 +4,7 @@ import { } from "../transition-editor/product-transition-editor/product-transition-editor.component"; import {ProductGamesystem} from "../../../project/game-model/gamesystems/ProductGamesystem"; import {SimpleGamesystem} from "../../../project/game-model/gamesystems/SimpleGamesystem"; +import {TemplateElement} from "../../../project/game-model/templates/TemplateElement"; @@ -15,6 +16,7 @@ import {SimpleGamesystem} from "../../../project/game-model/gamesystems/SimpleGa export class ProductGamesystemEditorComponent { @Input() gamesystem: ProductGamesystem | undefined + @Input() templateElement: TemplateElement | undefined @Output("onOpenGamesystemEditor") openGamesystemEditorEmitter = new EventEmitter(); onOpenGamesystemEditor(gamesystem: SimpleGamesystem) { diff --git a/src/app/editor/gamesystem-editor/scriptaccount-condition-editor/scriptaccount-condition-editor.component.html b/src/app/editor/gamesystem-editor/scriptaccount-condition-editor/scriptaccount-condition-editor.component.html index 0cad14c..e9b79eb 100644 --- a/src/app/editor/gamesystem-editor/scriptaccount-condition-editor/scriptaccount-condition-editor.component.html +++ b/src/app/editor/gamesystem-editor/scriptaccount-condition-editor/scriptaccount-condition-editor.component.html @@ -18,7 +18,7 @@ {{condition.minValue}} Minimal Value - + @@ -29,7 +29,7 @@ {{condition.maxValue}} Maximal Value - + diff --git a/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.html b/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.html index 7d7dc52..a7ac8c2 100644 --- a/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.html +++ b/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.html @@ -1,4 +1,4 @@ - +
- +
diff --git a/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.ts b/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.ts index 36af424..af11955 100644 --- a/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.ts +++ b/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.ts @@ -2,6 +2,7 @@ import {Component, Input} from '@angular/core'; import {MatTableDataSource} from "@angular/material/table"; import {SimpleGamesystem} from "../../../project/game-model/gamesystems/SimpleGamesystem"; import {ScriptAccount} from "../../../project/game-model/scriptAccounts/ScriptAccount"; +import {TemplateElement} from "../../../project/game-model/templates/TemplateElement"; @Component({ selector: 'app-simple-gamesystem-editor', @@ -12,6 +13,7 @@ export class SimpleGamesystemEditorComponent { @Input() simpleGamesystem: SimpleGamesystem | undefined @Input() scriptAccunts: ScriptAccount[] = [] + @Input() templateElement: TemplateElement | undefined } diff --git a/src/app/editor/gamesystem-editor/state-editor/product-state-editor/product-state-editor.component.ts b/src/app/editor/gamesystem-editor/state-editor/product-state-editor/product-state-editor.component.ts index 328928e..066e478 100644 --- a/src/app/editor/gamesystem-editor/state-editor/product-state-editor/product-state-editor.component.ts +++ b/src/app/editor/gamesystem-editor/state-editor/product-state-editor/product-state-editor.component.ts @@ -8,6 +8,8 @@ import {ProductGamesystem} from "../../../../project/game-model/gamesystems/Prod import {SimpleGamesystem} from "../../../../project/game-model/gamesystems/SimpleGamesystem"; import {ProductState} from "../../../../project/game-model/gamesystems/states/ProductState"; import {State} from "../../../../project/game-model/gamesystems/states/State"; +import {TemplateElement} from "../../../../project/game-model/templates/TemplateElement"; +import {ProductTemplateSystem} from "../../../../project/game-model/templates/productGamesystem/ProductTemplateSystem"; @Component({ selector: 'app-product-state-editor', @@ -24,6 +26,7 @@ import {State} from "../../../../project/game-model/gamesystems/states/State"; export class ProductStateEditorComponent implements OnInit{ @Input() gamesystem: ProductGamesystem | undefined + @Input() templateElement: TemplateElement | undefined @Output('onOpenGamesystemEditor') openGamesystemEditorEmitter = new EventEmitter(); displayedColumns: string[] = []; expandedColumns: string[] = [] @@ -36,7 +39,13 @@ export class ProductStateEditorComponent implements OnInit{ this.generateColumnNamesRecursively(this.gamesystem!, ""); this.displayedColumns.push('Initial'); this.expandedColumns = [...this.displayedColumns, 'expand']; - this.datasource.data = this.gamesystem!.states; + + if(this.templateElement == undefined) { + this.datasource.data = this.gamesystem!.states; + } else if(this.gamesystem instanceof ProductTemplateSystem) { + this.datasource.data = this.gamesystem!.stateMap.get(this.templateElement)! + } + this.datasource.filterPredicate = (data: ProductState, filter: string) => { const leaf_states = LeafGamesystemCalculator.calcLeafStates(data); return leaf_states.some((state) => state.stateLabel.toLowerCase().includes(filter)) diff --git a/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.html b/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.html index 4e74bda..c8f2e06 100644 --- a/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.html +++ b/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.html @@ -27,7 +27,7 @@
-
diff --git a/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.ts b/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.ts index 049814c..f09ff92 100644 --- a/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.ts +++ b/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.ts @@ -6,6 +6,8 @@ import {SimpleState} from "../../../../project/game-model/gamesystems/states/Sim import {SimpleGamesystem} from "../../../../project/game-model/gamesystems/SimpleGamesystem"; import {ScriptAccount} from "../../../../project/game-model/scriptAccounts/ScriptAccount"; import {ScriptAccountCondition} from "../../../../project/game-model/gamesystems/conditions/ScriptAccountCondition"; +import {TemplateElement} from "../../../../project/game-model/templates/TemplateElement"; +import {SimpleTemplateState} from "../../../../project/game-model/templates/simpleGamesystem/SimpleTemplateState"; @Component({ selector: 'app-simple-state-editor', @@ -24,6 +26,7 @@ export class SimpleStateEditorComponent implements OnInit{ @Input() states: SimpleState[] = []; @Input() gamesystem: SimpleGamesystem | undefined @Input() scriptAccounts: ScriptAccount[] = [] + @Input() templateElement: TemplateElement | undefined dataSource = new MatTableDataSource(); displayedColumns = ["name", "initial", "edit", "delete"]; columnsToDisplayWithExpand = [...this.displayedColumns, 'expand']; @@ -40,6 +43,7 @@ export class SimpleStateEditorComponent implements OnInit{ this.dataSource.filterPredicate = (data: SimpleState, filter: string) => { return data.stateLabel.toLowerCase().includes(filter); } + console.log(this.templateElement) } editState(state: SimpleState) { @@ -96,11 +100,31 @@ export class SimpleStateEditorComponent implements OnInit{ } onCreateCondition(state: SimpleState, condition: ScriptAccountCondition) { - state.addScriptAccountCondition(condition); + if(this.templateElement != undefined && state instanceof SimpleTemplateState) { + state.conditionMap.get(this.templateElement)!.push(condition) + } else { + state.addScriptAccountCondition(condition); + } } deleteCondition(state: SimpleState, condition: ScriptAccountCondition) { - state.removeScriptAccountCondition(condition.scriptAccount); + if(this.templateElement != undefined && state instanceof SimpleTemplateState) { + let conditions = state.conditionMap.get(this.templateElement)! + conditions = conditions.filter(currentCondition => condition.scriptAccount !== currentCondition.scriptAccount)!; + state.conditionMap.set(this.templateElement, conditions); + } else { + state.removeScriptAccountCondition(condition.scriptAccount); + } + } + + getDisplayedConditions(state: SimpleState) { + if(this.templateElement == undefined) { + return state.conditions + } else if(state instanceof SimpleTemplateState){ + return (state as SimpleTemplateState).conditionMap.get(this.templateElement)! + } else { + return []; + } } } diff --git a/src/app/editor/gamesystem-editor/template-specificator/template-specificator.component.html b/src/app/editor/gamesystem-editor/template-specificator/template-specificator.component.html new file mode 100644 index 0000000..be2c11a --- /dev/null +++ b/src/app/editor/gamesystem-editor/template-specificator/template-specificator.component.html @@ -0,0 +1,14 @@ +

Specify Templatesystem

+
+

This will not affect the properties of the Templatesystem itself!

+ + Select Templatesystem + + {{templateSystem.componentName}} + + +
+
+ + +
diff --git a/src/app/editor/gamesystem-editor/template-specificator/template-specificator.component.scss b/src/app/editor/gamesystem-editor/template-specificator/template-specificator.component.scss new file mode 100644 index 0000000..4e80027 --- /dev/null +++ b/src/app/editor/gamesystem-editor/template-specificator/template-specificator.component.scss @@ -0,0 +1,3 @@ +.long-form { + width: 100%; +} diff --git a/src/app/editor/gamesystem-editor/template-specificator/template-specificator.component.spec.ts b/src/app/editor/gamesystem-editor/template-specificator/template-specificator.component.spec.ts new file mode 100644 index 0000000..36c46d3 --- /dev/null +++ b/src/app/editor/gamesystem-editor/template-specificator/template-specificator.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TemplateSpecificatorComponent } from './template-specificator.component'; + +describe('TemplateSpecificatorComponent', () => { + let component: TemplateSpecificatorComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [TemplateSpecificatorComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(TemplateSpecificatorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/editor/gamesystem-editor/template-specificator/template-specificator.component.ts b/src/app/editor/gamesystem-editor/template-specificator/template-specificator.component.ts new file mode 100644 index 0000000..bd85e38 --- /dev/null +++ b/src/app/editor/gamesystem-editor/template-specificator/template-specificator.component.ts @@ -0,0 +1,26 @@ +import {Component, Inject} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; +import {Gamesystem} from "../../../project/game-model/gamesystems/Gamesystem"; +import {FormControl, Validators} from "@angular/forms"; + +@Component({ + selector: 'app-template-specificator', + templateUrl: './template-specificator.component.html', + styleUrl: './template-specificator.component.scss' +}) +export class TemplateSpecificatorComponent { + + templateCtrl: FormControl = new FormControl('', [Validators.required]) + + constructor(private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public templateSystems: Gamesystem[] = []) { + } + + cancelSpecification() { + this.dialogRef.close() + } + + confirmSpecification() { + this.dialogRef.close(this.templateCtrl.value) + } +} diff --git a/src/app/editor/gamesystem-editor/transition-editor/product-transition-editor/product-transition-editor.component.ts b/src/app/editor/gamesystem-editor/transition-editor/product-transition-editor/product-transition-editor.component.ts index 2f164d6..6c12eec 100644 --- a/src/app/editor/gamesystem-editor/transition-editor/product-transition-editor/product-transition-editor.component.ts +++ b/src/app/editor/gamesystem-editor/transition-editor/product-transition-editor/product-transition-editor.component.ts @@ -8,6 +8,8 @@ import {ProductGamesystem} from "../../../../project/game-model/gamesystems/Prod import {SimpleGamesystem} from "../../../../project/game-model/gamesystems/SimpleGamesystem"; import {ProductTransition} from "../../../../project/game-model/gamesystems/transitions/ProductTransition"; import {ProductState} from "../../../../project/game-model/gamesystems/states/ProductState"; +import {TemplateElement} from "../../../../project/game-model/templates/TemplateElement"; +import {ProductTemplateSystem} from "../../../../project/game-model/templates/productGamesystem/ProductTemplateSystem"; class DisplayedColumnName { displayedName: string internalName: string @@ -34,6 +36,7 @@ export class ProductTransitionEditorComponent implements OnInit{ @Input() gamesystem: ProductGamesystem | undefined @Output() onOpenGamesystem = new EventEmitter(); + @Input() templateElement: TemplateElement | undefined dataSource = new MatTableDataSource(); displayedColumns: DisplayedColumnName[] = []; @@ -52,7 +55,12 @@ export class ProductTransitionEditorComponent implements OnInit{ this.columns = this.displayedColumns.map(column => column.internalName) this.columnsToDisplayWithExpand = [...this.columns, 'expand'] - this.dataSource.data = this.gamesystem.transitions; + if(this.templateElement == undefined) { + this.dataSource.data = this.gamesystem.transitions; + } else if(this.gamesystem instanceof ProductTemplateSystem){ + this.dataSource.data = this.gamesystem!.transitionMap.get(this.templateElement)! + } + this.dataSource.filterPredicate = (data: ProductTransition, filter: string) => { const leaf_starting_states = LeafGamesystemCalculator.calcLeafStates(data.startingState); const leaf_ending_states = LeafGamesystemCalculator.calcLeafStates(data.endingState); diff --git a/src/app/editor/gamesystem-editor/transition-editor/scriptaccount-action-editor/scriptaccount-action-editor.component.ts b/src/app/editor/gamesystem-editor/transition-editor/scriptaccount-action-editor/scriptaccount-action-editor.component.ts index e8392ee..67ae272 100644 --- a/src/app/editor/gamesystem-editor/transition-editor/scriptaccount-action-editor/scriptaccount-action-editor.component.ts +++ b/src/app/editor/gamesystem-editor/transition-editor/scriptaccount-action-editor/scriptaccount-action-editor.component.ts @@ -3,6 +3,10 @@ import {MatTableDataSource} from "@angular/material/table"; import {ScriptAccount} from "../../../../project/game-model/scriptAccounts/ScriptAccount"; import {Transition} from "../../../../project/game-model/gamesystems/transitions/Transition"; import {ScriptAccountAction} from "../../../../project/game-model/gamesystems/actions/ScriptAccountAction"; +import {TemplateElement} from "../../../../project/game-model/templates/TemplateElement"; +import { + SimpleTemplateTransition +} from "../../../../project/game-model/templates/simpleGamesystem/SimpleTemplateTransition"; @Component({ selector: 'app-scriptaccount-action-editor', @@ -13,6 +17,7 @@ export class ScriptaccountActionEditorComponent implements OnInit{ @Input() transition: Transition | undefined @Input() scriptAccounts: ScriptAccount[] = [] @Input() enableEditing: boolean = false; + @Input() templateElement: TemplateElement | undefined dataSource: MatTableDataSource = new MatTableDataSource(); displayedColumns: string[] = ['scriptAccount', "valueChange", 'edit', 'delete']; @@ -21,7 +26,9 @@ export class ScriptaccountActionEditorComponent implements OnInit{ addedAction: ScriptAccountAction | undefined ngOnInit() { - this.dataSource.data = this.transition!.scriptAccountActions.map(action => action); + this.dataSource.data = this.getDisplayedActions() + + if(!this.enableEditing) { this.displayedColumns = this.displayedColumns.slice(0, -2); @@ -41,17 +48,42 @@ export class ScriptaccountActionEditorComponent implements OnInit{ finishEditing() { if(this.addedAction != undefined && this.addedAction.scriptAccount.componentName !== '') { - this.transition?.addScriptAccountAction(this.addedAction) - console.log(this.addedAction.scriptAccount) - this.dataSource.data = this.transition!.scriptAccountActions; - console.log(this.dataSource.data.length, this.transition!.scriptAccountActions.length) + if(this.templateElement != undefined && this.transition instanceof SimpleTemplateTransition) { + if(this.transition.actionMap.has(this.templateElement!)) { + this.transition.actionMap.get(this.templateElement!)!.push(this.addedAction) + } else { + this.transition.actionMap.set(this.templateElement!, [this.addedAction]) + } + } else { + this.transition?.addScriptAccountAction(this.addedAction) + } + + + this.dataSource.data = this.getDisplayedActions(); this.addedAction = undefined; } this.editedAction = undefined; } + getDisplayedActions(): ScriptAccountAction[] { + if(this.templateElement == undefined) { + return this.transition!.scriptAccountActions.map(action => action); + } else if(this.transition instanceof SimpleTemplateTransition) { + return this.transition!.actionMap.get(this.templateElement)! + } else { + return [] + } + } + deleteAction(action: ScriptAccountAction) { - this.transition!.removeScriptAccountAction(action.scriptAccount) - this.dataSource.data = this.transition!.scriptAccountActions + if(this.templateElement != undefined && this.transition instanceof SimpleTemplateTransition && this.transition.actionMap.has(this.templateElement!)) { + const updatedAction = this.transition.actionMap.get(this.templateElement)!.filter(currentAction => + currentAction.scriptAccount !== action.scriptAccount) + this.transition.actionMap.set(this.templateElement!, updatedAction) + } else { + this.transition!.removeScriptAccountAction(action.scriptAccount) + } + + this.dataSource.data = this.getDisplayedActions() } } diff --git a/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.html b/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.html index 91f3790..7a57e18 100644 --- a/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.html +++ b/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.html @@ -42,10 +42,10 @@ [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
- +
-
diff --git a/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.ts b/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.ts index d26acd6..ceaf686 100644 --- a/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.ts +++ b/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.ts @@ -8,6 +8,10 @@ import {ScriptAccount} from "../../../../project/game-model/scriptAccounts/Scrip import {SimpleTransition} from "../../../../project/game-model/gamesystems/transitions/SimpleTransition"; import {SimpleState} from "../../../../project/game-model/gamesystems/states/SimpleState"; import {ScriptAccountCondition} from "../../../../project/game-model/gamesystems/conditions/ScriptAccountCondition"; +import {TemplateElement} from "../../../../project/game-model/templates/TemplateElement"; +import { + SimpleTemplateTransition +} from "../../../../project/game-model/templates/simpleGamesystem/SimpleTemplateTransition"; @Component({ selector: 'app-simple-transition-editor', templateUrl: './simple-transition-editor.component.html', @@ -24,6 +28,8 @@ export class SimpleTransitionEditorComponent implements OnInit { @Input() gamesystem: SimpleGamesystem | undefined @Input() scriptAccounts: ScriptAccount[] = [] + @Input() templateElement: TemplateElement | undefined + displayedColumns: string[] = ["starting-state", "ending-state", "edit", "delete"]; dataSource = new MatTableDataSource(); columnsToDisplayWithExpand = [...this.displayedColumns, 'expand']; @@ -91,10 +97,33 @@ export class SimpleTransitionEditorComponent implements OnInit { protected readonly transition = transition; onCreateCondition(transition: SimpleTransition, condition: ScriptAccountCondition) { - transition.addScriptAccountCondition(condition); + if(this.templateElement != undefined && transition instanceof SimpleTemplateTransition) { + transition.conditionMap.get(this.templateElement)!.push(condition) + } else { + transition.addScriptAccountCondition(condition); + } + } deleteCondition(trasition: SimpleTransition, condition: ScriptAccountCondition) { - trasition.removeScriptAccountCondition(condition.scriptAccount); + if(this.templateElement != undefined && trasition instanceof SimpleTemplateTransition) { + let updatedConditions = trasition.conditionMap.get(this.templateElement)! + updatedConditions = updatedConditions.filter(currentCondition => condition.scriptAccount !== currentCondition.scriptAccount); + trasition.conditionMap.set(this.templateElement, updatedConditions); + } else { + console.log(this.templateElement) + trasition.removeScriptAccountCondition(condition.scriptAccount); + } + + } + + getDisplayedConditions(transition: SimpleTransition) { + if(this.templateElement == undefined) { + return transition.scriptAccountConditions + } else if(transition instanceof SimpleTemplateTransition) { + return transition.conditionMap.get(this.templateElement)! + } else { + return []; + } } } diff --git a/src/app/project/game-model/GameModel.ts b/src/app/project/game-model/GameModel.ts index 8497737..b59445a 100644 --- a/src/app/project/game-model/GameModel.ts +++ b/src/app/project/game-model/GameModel.ts @@ -6,6 +6,10 @@ import {ProductGamesystem} from "./gamesystems/ProductGamesystem"; import {SimpleGamesystem} from "./gamesystems/SimpleGamesystem"; import {Character} from "./characters/Character"; import {ModelComponentType} from "./ModelComponentType"; +import {TemplateType} from "./templates/TemplateType"; +import {SimpleTemplateGamesystem} from "./templates/simpleGamesystem/SimpleTemplateGamesystem"; +import {ProductTemplateSystem} from "./templates/productGamesystem/ProductTemplateSystem"; +import {ProductTemplateCreator} from "./templates/productGamesystem/ProductTemplateCreator"; export class GameModel { gameModelName: string @@ -45,9 +49,62 @@ export class GameModel { return undefined; } - createGamesystem(gamesystemName: string, parentGamesystemName: string | undefined) { + createSimpleGamesystem(gamesystemName: string, templateType: TemplateType | undefined, pushToTop: boolean = true) { + if(gamesystemName != undefined && this.findGamesystem(gamesystemName) == undefined) { + let simpleGamesystem: SimpleGamesystem + + if(templateType == undefined) { + simpleGamesystem = new SimpleGamesystem(gamesystemName, "") + } else { + simpleGamesystem = new SimpleTemplateGamesystem(gamesystemName, "", templateType) + } + + if(pushToTop) { + this.gamesystems.push(simpleGamesystem) + } + return simpleGamesystem; + } + return undefined; + } + + createSimpleGamesystemWithParent(gamesystemName: string, parentGamesystemName: string, templateType: TemplateType | undefined) { + const simpleGamesystem = this.createSimpleGamesystem(gamesystemName, templateType, false)!; + + const parentGamesystem = this.findGamesystem(parentGamesystemName) + if(parentGamesystem == undefined) {return undefined} + + let parentProductGamesystem: ProductGamesystem; + if(parentGamesystem instanceof SimpleTemplateGamesystem) { + parentProductGamesystem = ProductTemplateCreator.constructTemplateFromSimpleGamesystem(parentGamesystem, this, templateType!) + } else if(parentGamesystem instanceof SimpleGamesystem) { + if(simpleGamesystem instanceof SimpleTemplateGamesystem) { + parentProductGamesystem = ProductTemplateCreator.constructTemplateFromSimpleGamesystem(parentGamesystem, this, templateType!) + } else { + console.log("Test") + parentProductGamesystem = ProductGamesystem.constructFromSimpleGamesystem(parentGamesystem, this); + console.log(this.gamesystems) + } + } else { + if(simpleGamesystem instanceof SimpleTemplateGamesystem) { + parentProductGamesystem = ProductTemplateCreator.convertProductToTemplate(parentGamesystem as ProductGamesystem, this, templateType!) + } else { + parentProductGamesystem = parentGamesystem as ProductGamesystem + } + + } + + parentProductGamesystem.addChildGamesystem(simpleGamesystem); + simpleGamesystem.parentGamesystem = parentProductGamesystem; + + return simpleGamesystem; + } + + + + createGamesystem(gamesystemName: string, parentGamesystemName: string | undefined, templateType: TemplateType | undefined) { if(gamesystemName != undefined && this.findGamesystem(gamesystemName) == undefined) { const simpleGamesystem = new SimpleGamesystem(gamesystemName, ""); + if(parentGamesystemName != undefined) { const parentGamesystem = this.findGamesystem(parentGamesystemName); if(parentGamesystem instanceof SimpleGamesystem) { @@ -61,7 +118,6 @@ export class GameModel { } } else { this.gamesystems.push(simpleGamesystem); - } return simpleGamesystem; } @@ -115,4 +171,24 @@ export class GameModel { } }) } + + getTemplateSystems(templateType: TemplateType) { + const requestedTemplates: Gamesystem[] = [] + const gamesystemQueue: Gamesystem[] = this.gamesystems.concat(); + while(gamesystemQueue.length > 0) { + const currentGamesystem = gamesystemQueue.shift()!; + + if(currentGamesystem instanceof SimpleTemplateGamesystem && currentGamesystem.templateType === templateType) { + requestedTemplates.push(currentGamesystem) + } else if(currentGamesystem instanceof ProductTemplateSystem && currentGamesystem.templateType === templateType) { + requestedTemplates.push(currentGamesystem) + } + + if(currentGamesystem instanceof ProductGamesystem) { + currentGamesystem.innerGamesystems.forEach(innerGamesystem => gamesystemQueue.push(innerGamesystem)) + } + } + + return requestedTemplates; + } } diff --git a/src/app/project/game-model/characters/Character.ts b/src/app/project/game-model/characters/Character.ts index 07acf19..4d9bf6c 100644 --- a/src/app/project/game-model/characters/Character.ts +++ b/src/app/project/game-model/characters/Character.ts @@ -1,9 +1,43 @@ import {ModelComponent} from "../ModelComponent"; import {ModelComponentType} from "../ModelComponentType"; +import {TemplateElement} from "../templates/TemplateElement"; +import {TemplateGamesystem} from "../templates/TemplateGamesystem"; +import {Gamesystem} from "../gamesystems/Gamesystem"; +import {SimpleTemplateGamesystem} from "../templates/simpleGamesystem/SimpleTemplateGamesystem"; +import {ProductTemplateSystem} from "../templates/productGamesystem/ProductTemplateSystem"; +import {ProductGamesystem} from "../gamesystems/ProductGamesystem"; -export class Character extends ModelComponent{ +export class Character extends ModelComponent implements TemplateElement { + + characterSpecificTemplateSystems: Gamesystem[] = [] constructor(componentName: string, componentDescription: string) { super(componentName, componentDescription, ModelComponentType.CHARACTER); } + + addCharacterSpecificSimpleTemplatesystem(gamesystem: Gamesystem, recursiveCall: boolean = false) { + if(!this.isTemplateSystemCharacterSpecific(gamesystem.componentName)) { + if(gamesystem instanceof SimpleTemplateGamesystem) { + this.characterSpecificTemplateSystems.push(gamesystem) + gamesystem.addTemplateElement(this) + } else if(gamesystem instanceof ProductTemplateSystem) { + this.characterSpecificTemplateSystems.push(gamesystem) + gamesystem.addTemplateElement(this) + + if(!recursiveCall) { + gamesystem.innerGamesystems.forEach(innerGamesystem => this.addCharacterSpecificSimpleTemplatesystem(innerGamesystem, true)) + } + + } + + if(gamesystem.parentGamesystem != undefined) { + this.addCharacterSpecificSimpleTemplatesystem(gamesystem.parentGamesystem, true) + } + } + } + + private isTemplateSystemCharacterSpecific(gamesystemName: string) { + return this.characterSpecificTemplateSystems.find(gamesystem => gamesystem.componentName === gamesystemName) != undefined + } + } diff --git a/src/app/project/game-model/gamesystems/ProductGamesystem.ts b/src/app/project/game-model/gamesystems/ProductGamesystem.ts index e3e2daf..a7d380f 100644 --- a/src/app/project/game-model/gamesystems/ProductGamesystem.ts +++ b/src/app/project/game-model/gamesystems/ProductGamesystem.ts @@ -9,6 +9,8 @@ import {GameModel} from "../GameModel"; import {ScriptAccountCondition} from "./conditions/ScriptAccountCondition"; import {ScriptAccountAction} from "./actions/ScriptAccountAction"; import {ProductSystemGenerator} from "./productSystemGenerator/ProductSystemGenerator"; +import {TemplateType} from "../templates/TemplateType"; +import {ProductTemplateSystem} from "../templates/productGamesystem/ProductTemplateSystem"; export class ProductGamesystem extends Gamesystem { @@ -16,25 +18,28 @@ export class ProductGamesystem extends Gamesystem 0) { simpleGamesystem.componentName += "(Child)"; - productGamesystem.addChildGamesystem(simpleGamesystem); - simpleGamesystem.parentGamesystem = productGamesystem + this.addChildGamesystem(simpleGamesystem); + simpleGamesystem.parentGamesystem = this } if(parentGamesystem != undefined) { parentGamesystem.removeChildGamesystem(simpleGamesystem); - parentGamesystem.addChildGamesystem(productGamesystem); - productGamesystem.parentGamesystem = parentGamesystem + parentGamesystem.addChildGamesystem(this); + this.parentGamesystem = parentGamesystem } else { gameModel.removeGamesystem(simpleGamesystem); - gameModel.addGamesystem(productGamesystem); + gameModel.addGamesystem(this); } - - return productGamesystem; } createState(innerStates: State[]): ProductState | undefined { diff --git a/src/app/project/game-model/gamesystems/productSystemGenerator/ProductSystemGenerator.ts b/src/app/project/game-model/gamesystems/productSystemGenerator/ProductSystemGenerator.ts index d84bbb0..816533b 100644 --- a/src/app/project/game-model/gamesystems/productSystemGenerator/ProductSystemGenerator.ts +++ b/src/app/project/game-model/gamesystems/productSystemGenerator/ProductSystemGenerator.ts @@ -8,6 +8,7 @@ import {ProductGeneratorResult} from "./ProductGeneratorResult"; import {Gamesystem} from "../Gamesystem"; import {ProductGenerationData} from "./ProductGenerationData"; import {ProductTransition} from "../transitions/ProductTransition"; +import {SimpleTemplateTransition} from "../../templates/simpleGamesystem/SimpleTemplateTransition"; export class ProductSystemGenerator { productGamesystem: ProductGamesystem @@ -109,35 +110,34 @@ export class ProductSystemGenerator { protected generateBinaryProductTransition(startingState: ProductState, endingState: ProductState, usedTransition: Transition, generatedTransitions: ProductTransition[]) { const transition = new ProductTransition(startingState, endingState); - transition.scriptAccountActions = [... usedTransition.scriptAccountActions]; - transition.scriptAccountConditions = [... usedTransition.scriptAccountConditions]; + transition.scriptAccountActions = [... this.getTransitionActions(usedTransition)]; + transition.scriptAccountConditions = [... this.getTransitionConditions(usedTransition)]; if(generatedTransitions.find(generatedTransition => generatedTransition.startingState.equals(startingState) && generatedTransition.endingState.equals(endingState)) == undefined) { generatedTransitions.push(transition) - } else { - console.log(transition) } } protected generateBinaryProductTransitionMulti(startingState: ProductState, endingState: ProductState, leftTransition: Transition, rightTransition: Transition, generatedTransitions: ProductTransition[]) { - const leftConditions = leftTransition.scriptAccountConditions; - const rightConditions = rightTransition.scriptAccountConditions; + const leftConditions = this.getTransitionConditions(leftTransition) + const rightConditions = this.getTransitionConditions(rightTransition) if(!this.contradictCombinedConditions(leftConditions, rightConditions)) { const transition = new ProductTransition(startingState, endingState) - transition.scriptAccountActions = this.generateCombinedActions(leftTransition.scriptAccountActions, rightTransition.scriptAccountActions); - transition.scriptAccountConditions = this.generateCombinedConditions(leftTransition.scriptAccountConditions, rightTransition.scriptAccountConditions); + transition.scriptAccountActions = this.generateCombinedActions(this.getTransitionActions(leftTransition), this.getTransitionActions(rightTransition)); + transition.scriptAccountConditions = this.generateCombinedConditions(this.getTransitionConditions(leftTransition), this.getTransitionConditions(rightTransition)); if(generatedTransitions.find(generatedTransition => generatedTransition.startingState.equals(startingState) && generatedTransition.endingState.equals(endingState)) == undefined) { generatedTransitions.push(transition) - } else { - console.log(transition) } } } protected generateBinaryProductState(leftState: State, rightState: State, generatedStates: ProductState[]): ProductState | undefined { - const combinedStateConditions: ScriptAccountCondition[] = leftState.conditions.concat(rightState.conditions); + const leftConditions = this.getStateConditions(leftState) + const rightConditions = this.getStateConditions(rightState) + + const combinedStateConditions: ScriptAccountCondition[] = leftConditions.concat(rightConditions) for(let i=0; i) { + return transition.scriptAccountConditions; + } + + protected getTransitionActions(transition: Transition) { + return transition.scriptAccountActions; + } + + protected getStateConditions(state: State) { + return state.conditions; + } + } diff --git a/src/app/project/game-model/gamesystems/productSystemGenerator/TemplateProductSystemGenerator.ts b/src/app/project/game-model/gamesystems/productSystemGenerator/TemplateProductSystemGenerator.ts new file mode 100644 index 0000000..9a7915d --- /dev/null +++ b/src/app/project/game-model/gamesystems/productSystemGenerator/TemplateProductSystemGenerator.ts @@ -0,0 +1,54 @@ +import {ProductSystemGenerator} from "./ProductSystemGenerator"; +import {ProductGeneratorResult} from "./ProductGeneratorResult"; +import {TemplateElement} from "../../templates/TemplateElement"; +import {ProductTemplateSystem} from "../../templates/productGamesystem/ProductTemplateSystem"; +import {ProductState} from "../states/ProductState"; +import {Transition} from "../transitions/Transition"; +import {ProductTransition} from "../transitions/ProductTransition"; +import {State} from "../states/State"; +import {SimpleTemplateTransition} from "../../templates/simpleGamesystem/SimpleTemplateTransition"; +import {state, transition} from "@angular/animations"; +import {ScriptAccountCondition} from "../conditions/ScriptAccountCondition"; +import {SimpleTemplateState} from "../../templates/simpleGamesystem/SimpleTemplateState"; + +export class TemplateProductSystemGenerator extends ProductSystemGenerator { + + templateElement: TemplateElement + + + constructor(productGamesystem: ProductTemplateSystem, templateElement: TemplateElement) { + super(productGamesystem); + this.templateElement = templateElement; + } + + protected assignGeneratedStatesAndTransitions(generationResult: ProductGeneratorResult) { + const productTemplateSystem = this.productGamesystem as ProductTemplateSystem + productTemplateSystem.transitionMap.set(this.templateElement, generationResult.transitions) + productTemplateSystem.stateMap.set(this.templateElement, generationResult.states) + } + + protected getTransitionConditions(transition: Transition) { + if(transition instanceof SimpleTemplateTransition) { + return transition.conditionMap.get(this.templateElement)! + } else { + return transition.scriptAccountConditions; + } + } + + protected getTransitionActions(transition: Transition) { + if(transition instanceof SimpleTemplateTransition) { + return transition.actionMap.get(this.templateElement)! + } else { + return transition.scriptAccountActions; + } + } + + + protected getStateConditions(state: State): ScriptAccountCondition[] { + if(state instanceof SimpleTemplateState) { + return state.conditionMap.get(this.templateElement)! + } else { + return state.conditions + } + } +} diff --git a/src/app/project/game-model/templates/TemplateElement.ts b/src/app/project/game-model/templates/TemplateElement.ts new file mode 100644 index 0000000..4282a32 --- /dev/null +++ b/src/app/project/game-model/templates/TemplateElement.ts @@ -0,0 +1,2 @@ +export interface TemplateElement { +} diff --git a/src/app/project/game-model/templates/TemplateGamesystem.ts b/src/app/project/game-model/templates/TemplateGamesystem.ts new file mode 100644 index 0000000..ef16f2f --- /dev/null +++ b/src/app/project/game-model/templates/TemplateGamesystem.ts @@ -0,0 +1,9 @@ +import {Gamesystem} from "../gamesystems/Gamesystem"; +import {TemplateElement} from "./TemplateElement"; + +export interface TemplateGamesystem { + + + + addTemplateElement(templateElement: TemplateElement): void; +} diff --git a/src/app/project/game-model/templates/TemplateType.ts b/src/app/project/game-model/templates/TemplateType.ts new file mode 100644 index 0000000..6961052 --- /dev/null +++ b/src/app/project/game-model/templates/TemplateType.ts @@ -0,0 +1,3 @@ +export enum TemplateType { + CHARACTER +} diff --git a/src/app/project/game-model/templates/TemplateTypeUtilities.ts b/src/app/project/game-model/templates/TemplateTypeUtilities.ts new file mode 100644 index 0000000..7efc792 --- /dev/null +++ b/src/app/project/game-model/templates/TemplateTypeUtilities.ts @@ -0,0 +1,9 @@ +import {TemplateType} from "./TemplateType"; + +export class TemplateTypeUtilities { + static fromString(string: string) { + if(string === 'character') { + return TemplateType.CHARACTER + } + } +} diff --git a/src/app/project/game-model/templates/productGamesystem/ProductTemplateCreator.ts b/src/app/project/game-model/templates/productGamesystem/ProductTemplateCreator.ts new file mode 100644 index 0000000..1befc41 --- /dev/null +++ b/src/app/project/game-model/templates/productGamesystem/ProductTemplateCreator.ts @@ -0,0 +1,30 @@ +import {SimpleGamesystem} from "../../gamesystems/SimpleGamesystem"; +import {GameModel} from "../../GameModel"; +import {TemplateType} from "../TemplateType"; +import {ProductTemplateSystem} from "./ProductTemplateSystem"; +import {ProductGamesystem} from "../../gamesystems/ProductGamesystem"; + +export class ProductTemplateCreator { + static constructTemplateFromSimpleGamesystem(simpleGamesystem: SimpleGamesystem, gameModel: GameModel, templateType: TemplateType) { + const productGamesystem = new ProductTemplateSystem(simpleGamesystem.componentName, simpleGamesystem.componentDescription, templateType); + productGamesystem.constructHierarchyFromSimpleGamesystem(simpleGamesystem, gameModel); + return productGamesystem; + } + + static convertProductToTemplate(productGamesystem: ProductGamesystem, gameModel: GameModel, templateType: TemplateType) { + const productTemplate = new ProductTemplateSystem(productGamesystem.componentName, productGamesystem.componentDescription, templateType); + productTemplate.states = productGamesystem.states + productTemplate.transitions = productGamesystem.transitions + productTemplate.innerGamesystems = productGamesystem.innerGamesystems; + productGamesystem.innerGamesystems.forEach(innerGamesystem => innerGamesystem.parentGamesystem = productTemplate); + + if(productGamesystem.parentGamesystem == undefined) { + gameModel.removeGamesystem(productGamesystem) + gameModel.gamesystems.push(productTemplate) + } else { + productTemplate.parentGamesystem = productGamesystem.parentGamesystem; + productGamesystem.parentGamesystem.addChildGamesystem(productTemplate); + } + return productTemplate; + } +} diff --git a/src/app/project/game-model/templates/productGamesystem/ProductTemplateSystem.ts b/src/app/project/game-model/templates/productGamesystem/ProductTemplateSystem.ts new file mode 100644 index 0000000..e6957fd --- /dev/null +++ b/src/app/project/game-model/templates/productGamesystem/ProductTemplateSystem.ts @@ -0,0 +1,28 @@ +import {ProductGamesystem} from "../../gamesystems/ProductGamesystem"; +import {TemplateGamesystem} from "../TemplateGamesystem"; +import {TemplateElement} from "../TemplateElement"; +import {ProductState} from "../../gamesystems/states/ProductState"; +import {ProductTransition} from "../../gamesystems/transitions/ProductTransition"; +import {SimpleGamesystem} from "../../gamesystems/SimpleGamesystem"; +import {GameModel} from "../../GameModel"; +import {TemplateType} from "../TemplateType"; +import {TemplateProductSystemGenerator} from "../../gamesystems/productSystemGenerator/TemplateProductSystemGenerator"; + +export class ProductTemplateSystem extends ProductGamesystem implements TemplateGamesystem{ + + stateMap: Map = new Map(); + transitionMap: Map = new Map() + templateType: TemplateType + + + constructor(gamesystemName: string, gamesystemDescription: string, templateType: TemplateType) { + super(gamesystemName, gamesystemDescription); + this.templateType = templateType; + } + + addTemplateElement(templateElement: TemplateElement): void { + const productTemplateGenerator = new TemplateProductSystemGenerator(this, templateElement); + productTemplateGenerator.generateFromChildsystems() + } + +} diff --git a/src/app/project/game-model/templates/simpleGamesystem/SimpleTemplateGamesystem.ts b/src/app/project/game-model/templates/simpleGamesystem/SimpleTemplateGamesystem.ts new file mode 100644 index 0000000..17856d2 --- /dev/null +++ b/src/app/project/game-model/templates/simpleGamesystem/SimpleTemplateGamesystem.ts @@ -0,0 +1,42 @@ +import {SimpleGamesystem} from "../../gamesystems/SimpleGamesystem"; +import {TemplateGamesystem} from "../TemplateGamesystem"; +import {TemplateElement} from "../TemplateElement"; +import {SimpleState} from "../../gamesystems/states/SimpleState"; +import {SimpleTransition} from "../../gamesystems/transitions/SimpleTransition"; +import {SimpleTemplateState} from "./SimpleTemplateState"; +import {SimpleTemplateTransition} from "./SimpleTemplateTransition"; +import {TemplateType} from "../TemplateType"; + +export class SimpleTemplateGamesystem extends SimpleGamesystem implements TemplateGamesystem { + + templateType: TemplateType + + constructor(gamesystemName: string, gamesystemDescription: string, templateType: TemplateType) { + super(gamesystemName, gamesystemDescription); + this.templateType = templateType; + } + + addTemplateElement(templateElement: TemplateElement): void { + this.states.forEach(state => { + (state as SimpleTemplateState).addTemplateElement(templateElement); + }) + + this.transitions.forEach(transition => { + (transition as SimpleTemplateTransition).addTemplateElement(templateElement); + }) + } + + createState(label: string, description: string): SimpleState | undefined { + const state = new SimpleTemplateState(label, description); + this.states.push(state) + return state; + } + + createTransition(startingState: SimpleState, endingState: SimpleState): SimpleTransition | undefined { + return new SimpleTemplateTransition(startingState, endingState); + } + + removeState(state: SimpleState): boolean { + return super.removeState(state); + } +} diff --git a/src/app/project/game-model/templates/simpleGamesystem/SimpleTemplateState.ts b/src/app/project/game-model/templates/simpleGamesystem/SimpleTemplateState.ts new file mode 100644 index 0000000..50bb918 --- /dev/null +++ b/src/app/project/game-model/templates/simpleGamesystem/SimpleTemplateState.ts @@ -0,0 +1,18 @@ +import {SimpleState} from "../../gamesystems/states/SimpleState"; +import {TemplateElement} from "../TemplateElement"; +import {ScriptAccountCondition} from "../../gamesystems/conditions/ScriptAccountCondition"; + +export class SimpleTemplateState extends SimpleState { + + conditionMap: Map = new Map(); + + addTemplateElement(templateElement: TemplateElement) { + if(!this.conditionMap.has(templateElement)) { + this.conditionMap.set(templateElement, this.conditions) + } + } + + removeTemplateElement(templateElement: TemplateElement) { + this.conditionMap.delete(templateElement) + } +} diff --git a/src/app/project/game-model/templates/simpleGamesystem/SimpleTemplateTransition.ts b/src/app/project/game-model/templates/simpleGamesystem/SimpleTemplateTransition.ts new file mode 100644 index 0000000..90529ba --- /dev/null +++ b/src/app/project/game-model/templates/simpleGamesystem/SimpleTemplateTransition.ts @@ -0,0 +1,25 @@ +import {SimpleTransition} from "../../gamesystems/transitions/SimpleTransition"; +import {TemplateElement} from "../TemplateElement"; +import {ScriptAccountCondition} from "../../gamesystems/conditions/ScriptAccountCondition"; +import {ScriptAccountAction} from "../../gamesystems/actions/ScriptAccountAction"; + +export class SimpleTemplateTransition extends SimpleTransition{ + conditionMap: Map = new Map(); + actionMap: Map = new Map(); + + addTemplateElement(templateElement: TemplateElement) { + if(!this.conditionMap.has(templateElement)) { + this.conditionMap.set(templateElement, this.scriptAccountConditions.concat()) + } + + if(!this.actionMap.has(templateElement)) { + this.actionMap.set(templateElement, this.scriptAccountActions.concat()) + } + + } + + removeTemplateElement(templateElement: TemplateElement) { + this.conditionMap.delete(templateElement) + this.actionMap.delete(templateElement) + } +} diff --git a/src/app/project/parser/characterParser/CharacterParser.ts b/src/app/project/parser/characterParser/CharacterParser.ts index 07d7378..0570861 100644 --- a/src/app/project/parser/characterParser/CharacterParser.ts +++ b/src/app/project/parser/characterParser/CharacterParser.ts @@ -1,9 +1,26 @@ import {StoreComponent} from "../../../../../app/storage/StoreComponent"; import {Character} from "../../game-model/characters/Character"; +import {SimpleTemplateGamesystem} from "../../game-model/templates/simpleGamesystem/SimpleTemplateGamesystem"; +import {ScriptAccountActionParser} from "../gamesystemParser/ScriptAccountActionParser"; +import {ScriptAccountConditionParser} from "../gamesystemParser/ScriptAccountConditionParser"; +import {ScriptAccount} from "../../game-model/scriptAccounts/ScriptAccount"; +import {SimpleTemplateState} from "../../game-model/templates/simpleGamesystem/SimpleTemplateState"; +import {SimpleTemplateTransition} from "../../game-model/templates/simpleGamesystem/SimpleTemplateTransition"; export class CharacterParser { + characterSpecificGamesystems: SimpleTemplateGamesystem[] + scriptAccountConditionParser: ScriptAccountConditionParser + scriptAccountActionParser: ScriptAccountActionParser + + constructor(characterSpecificGamesystems: SimpleTemplateGamesystem[], scriptAccounts: ScriptAccount[]) { + this.characterSpecificGamesystems = characterSpecificGamesystems; + this.scriptAccountActionParser = new ScriptAccountActionParser(scriptAccounts); + this.scriptAccountConditionParser = new ScriptAccountConditionParser(scriptAccounts) + } + + public parseCharacters(characters: StoreComponent[]): Character[] { const loadedCharacters: Character[] = [] characters.forEach(character => loadedCharacters.push(this.parseSingleCharacter(JSON.parse(character.jsonString)))) @@ -11,6 +28,61 @@ export class CharacterParser { } private parseSingleCharacter(characterData: any): Character { - return new Character(characterData.componentName, characterData.componentDescription); + const character = new Character(characterData.componentName, characterData.componentDescription); + const templateSpecificGamesystems = this.parseCharacterSpecificGamesystems(character, characterData.characterSpecificTemplateSystems); + templateSpecificGamesystems.forEach(system => character.addCharacterSpecificSimpleTemplatesystem(system)) + return character; + } + + private parseCharacterSpecificGamesystems(character: Character, characterSpecificGamesystems: any): SimpleTemplateGamesystem[] { + const result: SimpleTemplateGamesystem[] = [] + for(let i=0; i gamesystem.componentName === componentName) + } + + private findReferencedState(gamesystem: SimpleTemplateGamesystem, stateLabel: string) { + return gamesystem.states.find(state => state.stateLabel === stateLabel); + } + + private findReferencedTransition(gamesystem: SimpleTemplateGamesystem, startingLabel: string, endingLabel: string) { + return gamesystem.transitions.find(transition => transition.startingState.stateLabel === startingLabel && transition.endingState.stateLabel === endingLabel); + } + } diff --git a/src/app/project/parser/gamesystemParser/GamesystemParser.ts b/src/app/project/parser/gamesystemParser/GamesystemParser.ts index e085bba..0e4ce93 100644 --- a/src/app/project/parser/gamesystemParser/GamesystemParser.ts +++ b/src/app/project/parser/gamesystemParser/GamesystemParser.ts @@ -6,6 +6,8 @@ import {SimpleGamesystem} from "../../game-model/gamesystems/SimpleGamesystem"; import {StateParser} from "./StateParser"; import {ScriptAccount} from "../../game-model/scriptAccounts/ScriptAccount"; import {TransitionParser} from "./TransitionParser"; +import {SimpleTemplateGamesystem} from "../../game-model/templates/simpleGamesystem/SimpleTemplateGamesystem"; +import {ProductTemplateSystem} from "../../game-model/templates/productGamesystem/ProductTemplateSystem"; export class GamesystemParser { @@ -40,18 +42,32 @@ export class GamesystemParser { } parseSimpleGamesystem(gamesystemData: any): SimpleGamesystem { - const simpleGamesystem = new SimpleGamesystem(gamesystemData.componentName, gamesystemData.componentDescription) + let simpleGamesystem + if(gamesystemData.templateType != undefined) { + simpleGamesystem = new SimpleTemplateGamesystem(gamesystemData.componentName, gamesystemData.componentDescription, gamesystemData.templateType) + } else { + simpleGamesystem = new SimpleGamesystem(gamesystemData.componentName, gamesystemData.componentDescription) + } + const stateParser = new StateParser(this.scriptAccounts); - simpleGamesystem.states = stateParser.parseStates(gamesystemData.states) + simpleGamesystem.states = stateParser.parseStates(gamesystemData.states, gamesystemData.templateType) const transitionParser = new TransitionParser(simpleGamesystem.states, this.scriptAccounts) - simpleGamesystem.transitions = transitionParser.parseTransitions(gamesystemData.transitions) + simpleGamesystem.transitions = transitionParser.parseTransitions(gamesystemData.transitions, gamesystemData.templateType) + + return simpleGamesystem } parseProductGamesystem(gamesystemData: any) { - const productGamesystem = new ProductGamesystem(gamesystemData.componentName, gamesystemData.componentDescription); + let productGamesystem; + if(gamesystemData.templateType == undefined) { + productGamesystem = new ProductGamesystem(gamesystemData.componentName, gamesystemData.componentDescription); + } else { + productGamesystem = new ProductTemplateSystem(gamesystemData.componentName, gamesystemData.componentDescription, gamesystemData.templateType) + } + const childsystemNames: string[] = [] for(let i=0; i storedCharacters.push(this.serializeSingleCharacter(character))) @@ -13,14 +17,41 @@ export class CharacterSerializer { private static serializeSingleCharacter(character: Character): StoreComponent{ const fileName = character.componentName + const templateGamesystemBackup = character.characterSpecificTemplateSystems.concat(); + character.characterSpecificTemplateSystems = character.characterSpecificTemplateSystems.filter(system => system instanceof SimpleTemplateGamesystem) + console.log("Templatesystem: ", character.characterSpecificTemplateSystems) const jsonString = JSON.stringify(character, (key, value) => { - if(key === 'unsaved' || key === 'type') { + if(value instanceof Gamesystem) { + return { + ...value, + componentDescription: undefined, + parentGamesystem: undefined + } + } + + if(key === 'scriptAccount') { + return value.componentName + } + + if(key === 'conditionMap' || key === 'actionMap') { + if(value.get(character) == undefined) { + return [] + } + return value.get(character) + } + + if(key === 'startingState' || key === 'endingState') { + return value.stateLabel + } + + if(this.ignoredKeys.includes(key)) { return undefined } else { return value; } }, SerializeConstants.JSON_INDENT) + character.characterSpecificTemplateSystems = templateGamesystemBackup return new StoreComponent(jsonString, fileName, ModelComponentType.CHARACTER); } } diff --git a/src/app/project/serializer/GamesystemSerializer.ts b/src/app/project/serializer/GamesystemSerializer.ts index 8ffcafc..41ebcf3 100644 --- a/src/app/project/serializer/GamesystemSerializer.ts +++ b/src/app/project/serializer/GamesystemSerializer.ts @@ -4,10 +4,11 @@ import {SimpleGamesystem} from "../game-model/gamesystems/SimpleGamesystem"; import {ProductGamesystem} from "../game-model/gamesystems/ProductGamesystem"; import {SerializeConstants} from "./SerializeConstants"; import {ModelComponentType} from "../game-model/ModelComponentType"; +import {ProductTemplateSystem} from "../game-model/templates/productGamesystem/ProductTemplateSystem"; export class GamesystemSerializer { - private static IGNORED_SIMPLE_ATTRIBUTES = ["parentGamesystem", 'incomingTransitions', "outgoingTransitions", "unsaved", "type"] + private static IGNORED_SIMPLE_ATTRIBUTES = ["parentGamesystem", 'incomingTransitions', "outgoingTransitions", "unsaved", "type", "conditionMap", "actionMap"] public static serializeGamesystems(gamesystems: Gamesystem[]): StoreComponent[] { let storedGamesystems: StoreComponent[] = [] @@ -59,12 +60,24 @@ export class GamesystemSerializer { storedChildsystems.forEach(storedChildsystem => storedGamesystems.push(storedChildsystem)) }) - const jsonString = { - 'componentName': productGamesystem.componentName, - 'componentDescription': productGamesystem.componentDescription, - 'childsystems': innerGamesystemJsonArray + let jsonString; + if(productGamesystem instanceof ProductTemplateSystem) { + jsonString = { + 'componentName': productGamesystem.componentName, + 'componentDescription': productGamesystem.componentDescription, + 'childsystems': innerGamesystemJsonArray, + 'templateType': productGamesystem.templateType + } + } else { + jsonString = { + 'componentName': productGamesystem.componentName, + 'componentDescription': productGamesystem.componentDescription, + 'childsystems': innerGamesystemJsonArray, + } } + + const storedProductsystem = new StoreComponent(JSON.stringify(jsonString, null, SerializeConstants.JSON_INDENT), fileName, ModelComponentType.GAMESYTEM) storedGamesystems.push(storedProductsystem) diff --git a/testModel/characters/Astrid Hofferson.json b/testModel/characters/Astrid Hofferson.json index 0678c2b..014ec69 100644 --- a/testModel/characters/Astrid Hofferson.json +++ b/testModel/characters/Astrid Hofferson.json @@ -1,4 +1,50 @@ { "componentName": "Astrid Hofferson", - "componentDescription": "" + "componentDescription": "", + "characterSpecificTemplateSystems": [ + { + "componentName": "TemplateGamesystem", + "states": [ + { + "stateLabel": "A", + "conditionMap": [ + { + "scriptAccount": "Luftfeuchtigkeit", + "minValue": 0, + "maxValue": "10" + } + ] + }, + { + "stateLabel": "B", + "conditionMap": [ + { + "scriptAccount": "New ScriptAccount", + "minValue": 0, + "maxValue": 100 + } + ] + } + ], + "transitions": [ + { + "startingState": "A", + "endingState": "B", + "conditionMap": [ + { + "scriptAccount": "Temperature", + "minValue": 0, + "maxValue": 10 + } + ], + "actionMap": [ + { + "changingValue": 10, + "scriptAccount": "Luftfeuchtigkeit" + } + ] + } + ] + } + ] } \ No newline at end of file diff --git a/testModel/characters/Hicks Haddock.json b/testModel/characters/Hicks Haddock.json index 1e611d7..158b912 100644 --- a/testModel/characters/Hicks Haddock.json +++ b/testModel/characters/Hicks Haddock.json @@ -1,4 +1,60 @@ { "componentName": "Hicks Haddock", - "componentDescription": "" + "componentDescription": "", + "characterSpecificTemplateSystems": [ + { + "componentName": "TemplateGamesystem", + "states": [ + { + "stateLabel": "A", + "conditionMap": [ + { + "scriptAccount": "Luftfeuchtigkeit", + "minValue": 0, + "maxValue": "10" + } + ] + }, + { + "stateLabel": "B", + "conditionMap": [ + { + "scriptAccount": "New ScriptAccount", + "minValue": 0, + "maxValue": 100 + } + ] + } + ], + "transitions": [ + { + "startingState": "A", + "endingState": "B", + "conditionMap": [], + "actionMap": [] + } + ] + }, + { + "componentName": "Letters", + "states": [ + { + "stateLabel": "A", + "conditionMap": [] + }, + { + "stateLabel": "B", + "conditionMap": [] + } + ], + "transitions": [ + { + "startingState": "A", + "endingState": "B", + "conditionMap": [], + "actionMap": [] + } + ] + } + ] } \ No newline at end of file diff --git a/testModel/gamesystems/NormalGamesystem.json b/testModel/gamesystems/NormalGamesystem.json new file mode 100644 index 0000000..7525520 --- /dev/null +++ b/testModel/gamesystems/NormalGamesystem.json @@ -0,0 +1,6 @@ +{ + "componentName": "NormalGamesystem", + "componentDescription": "", + "states": [], + "transitions": [] +} \ No newline at end of file diff --git a/testModel/gamesystems/Producttest/Letters.json b/testModel/gamesystems/Producttest/Letters.json new file mode 100644 index 0000000..9bab958 --- /dev/null +++ b/testModel/gamesystems/Producttest/Letters.json @@ -0,0 +1,27 @@ +{ + "componentName": "Letters", + "componentDescription": "", + "states": [ + { + "initial": false, + "conditions": [], + "stateLabel": "A", + "stateDescription": "" + }, + { + "initial": false, + "conditions": [], + "stateLabel": "B", + "stateDescription": "" + } + ], + "transitions": [ + { + "scriptAccountActions": [], + "scriptAccountConditions": [], + "startingState": "A", + "endingState": "B" + } + ], + "templateType": 0 +} \ No newline at end of file diff --git a/testModel/gamesystems/Producttest/Numbers.json b/testModel/gamesystems/Producttest/Numbers.json new file mode 100644 index 0000000..89f1e28 --- /dev/null +++ b/testModel/gamesystems/Producttest/Numbers.json @@ -0,0 +1,26 @@ +{ + "componentName": "Numbers", + "componentDescription": "", + "states": [ + { + "initial": false, + "conditions": [], + "stateLabel": "1", + "stateDescription": "" + }, + { + "initial": false, + "conditions": [], + "stateLabel": "2", + "stateDescription": "" + } + ], + "transitions": [ + { + "scriptAccountActions": [], + "scriptAccountConditions": [], + "startingState": "1", + "endingState": "2" + } + ] +} \ No newline at end of file diff --git a/testModel/gamesystems/Producttest/Producttest.json b/testModel/gamesystems/Producttest/Producttest.json new file mode 100644 index 0000000..239e216 --- /dev/null +++ b/testModel/gamesystems/Producttest/Producttest.json @@ -0,0 +1,13 @@ +{ + "componentName": "Producttest", + "componentDescription": "", + "childsystems": [ + { + "componentName": "Letters" + }, + { + "componentName": "Numbers" + } + ], + "templateType": 0 +} \ No newline at end of file diff --git a/testModel/gamesystems/TemplateGamesystem.json b/testModel/gamesystems/TemplateGamesystem.json new file mode 100644 index 0000000..0a1da3d --- /dev/null +++ b/testModel/gamesystems/TemplateGamesystem.json @@ -0,0 +1,50 @@ +{ + "componentName": "TemplateGamesystem", + "componentDescription": "", + "states": [ + { + "initial": false, + "conditions": [ + { + "scriptAccount": "Luftfeuchtigkeit", + "minValue": 0, + "maxValue": "10" + } + ], + "stateLabel": "A", + "stateDescription": "" + }, + { + "initial": false, + "conditions": [ + { + "scriptAccount": "New ScriptAccount", + "minValue": 0, + "maxValue": 100 + } + ], + "stateLabel": "B", + "stateDescription": "" + } + ], + "transitions": [ + { + "scriptAccountActions": [ + { + "changingValue": 10, + "scriptAccount": "Luftfeuchtigkeit" + } + ], + "scriptAccountConditions": [ + { + "scriptAccount": "Temperature", + "minValue": 0, + "maxValue": 10 + } + ], + "startingState": "A", + "endingState": "B" + } + ], + "templateType": 0 +} \ No newline at end of file