InventoryConditionEditor for Interactions
All checks were successful
E2E Testing / test (push) Successful in 1m29s

This commit is contained in:
sebastian 2024-06-02 19:27:47 +02:00
parent 8c4d2ad5ca
commit d010dfbce6
17 changed files with 372 additions and 78 deletions

View File

@ -113,6 +113,12 @@ import {
import { import {
GamesystemConditionEditorComponent GamesystemConditionEditorComponent
} from "./editor/interaction-editor/conditions/gamesystem-condition-editor/gamesystem-condition-editor.component"; } from "./editor/interaction-editor/conditions/gamesystem-condition-editor/gamesystem-condition-editor.component";
import {
ItemConditionEditorComponent
} from "./editor/interaction-editor/conditions/item-condition-editor/item-condition-editor.component";
import {
ItemSelectorComponent
} from "./editor/interaction-editor/conditions/item-condition-editor/item-selector/item-selector.component";
// AoT requires an exported function for factories // AoT requires an exported function for factories
const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json'); const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json');
@ -149,75 +155,77 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl
RequieredInheritancesEditorComponent, RequieredInheritancesEditorComponent,
RequieredInheritancesCreatorComponent, RequieredInheritancesCreatorComponent,
CharacterInteractionEditorComponent, CharacterInteractionEditorComponent,
GamesystemConditionEditorComponent GamesystemConditionEditorComponent,
ItemConditionEditorComponent,
ItemSelectorComponent
],
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
CoreModule,
SharedModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: httpLoaderFactory,
deps: [HttpClient]
}
}),
BrowserAnimationsModule,
MatIcon,
MatToolbar,
MatButton,
MatFormField,
MatInput,
MatDrawerContainer,
MatDrawer,
MatIconButton,
MatMenuTrigger,
MatMenu,
MatMenuItem,
MatListItem,
MatActionList,
MatTabGroup,
MatTab,
MatTabLabel,
MatLabel,
MatFormField,
ReactiveFormsModule,
MatError,
MatDialogTitle,
MatDialogContent,
MatDialogActions,
MatMiniFabButton,
MatTreeModule,
MatTable,
MatColumnDef,
MatHeaderCell,
MatHeaderCellDef,
MatCellDef,
MatCell,
MatHeaderRow,
MatRow,
MatHeaderRowDef,
MatRowDef,
MatCheckbox,
MatSelect,
MatOption,
MatHint,
MatTooltip,
MatCard,
MatCardContent,
MatCardHeader,
MatAccordion,
MatExpansionPanel,
MatExpansionPanelTitle,
MatCardTitle,
MatExpansionPanelHeader,
MatExpansionPanelDescription,
MatAutocomplete,
MatAutocompleteTrigger,
MatNoDataRow
], ],
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
CoreModule,
SharedModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: httpLoaderFactory,
deps: [HttpClient]
}
}),
BrowserAnimationsModule,
MatIcon,
MatToolbar,
MatButton,
MatFormField,
MatInput,
MatDrawerContainer,
MatDrawer,
MatIconButton,
MatMenuTrigger,
MatMenu,
MatMenuItem,
MatListItem,
MatActionList,
MatTabGroup,
MatTab,
MatTabLabel,
MatLabel,
MatFormField,
ReactiveFormsModule,
MatError,
MatDialogTitle,
MatDialogContent,
MatDialogActions,
MatMiniFabButton,
MatTreeModule,
MatTable,
MatColumnDef,
MatHeaderCell,
MatHeaderCellDef,
MatCellDef,
MatCell,
MatHeaderRow,
MatRow,
MatHeaderRowDef,
MatRowDef,
MatCheckbox,
MatSelect,
MatOption,
MatHint,
MatTooltip,
MatCard,
MatCardContent,
MatCardHeader,
MatAccordion,
MatExpansionPanel,
MatExpansionPanelTitle,
MatCardTitle,
MatExpansionPanelHeader,
MatExpansionPanelDescription,
MatAutocomplete,
MatAutocompleteTrigger,
MatNoDataRow
],
providers: [], providers: [],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })

View File

@ -103,8 +103,11 @@
<mat-tab label="ScriptAccount Conditions"> <mat-tab label="ScriptAccount Conditions">
<app-scriptaccount-condition-editor [scriptAccounts]="gameModel!.scriptAccounts" [conditions]="element.scriptAccountConditions"></app-scriptaccount-condition-editor> <app-scriptaccount-condition-editor [scriptAccounts]="gameModel!.scriptAccounts" [conditions]="element.scriptAccountConditions"></app-scriptaccount-condition-editor>
</mat-tab> </mat-tab>
<mat-tab label="Inventory Conditions"> <mat-tab label="Inventory Itemgroup Conditions">
<p>Inventory Conditions</p> <app-item-condition-editor [interaction]="element" [gameModel]="gameModel" [group]="true"></app-item-condition-editor>
</mat-tab>
<mat-tab label="Inventory Item Conditions">
<app-item-condition-editor [interaction]="element" [gameModel]="gameModel" [group]="false"></app-item-condition-editor>
</mat-tab> </mat-tab>
<mat-tab label="Gamesystem Conditions"> <mat-tab label="Gamesystem Conditions">
<app-gamesystem-condition-editor [intgeraction]="element" [gamesystems]="gameModel!.gamesystemsAsList" <app-gamesystem-condition-editor [intgeraction]="element" [gamesystems]="gameModel!.gamesystemsAsList"

View File

@ -0,0 +1,79 @@
<table mat-table class="mat-elevation-z8" [dataSource]="conditionDataSource">
<ng-container matColumnDef="item">
<th mat-header-cell *matHeaderCellDef>{{group? 'Itemgroup':'Item'}}</th>
<td mat-cell *matCellDef="let condition">
@if(group) {
@if(condition == editedCondition) {
<mat-form-field appearance="fill" class="long-form">
<mat-label>Itemgroup</mat-label>
<mat-select [(ngModel)]="conditionAsItemgroupCondition(condition)!.itemgroup">
<mat-option *ngFor="let itemgroup of gameModel!.itemgroupsAsList" [value]="itemgroup">{{itemgroup.componentName}}</mat-option>
</mat-select>
</mat-form-field>
} @else {
<p *ngIf="conditionAsItemgroupCondition(condition)!.itemgroup != undefined">
{{conditionAsItemgroupCondition(condition)!.itemgroup!.componentName}}
</p>
}
} @else {
@if(condition == editedCondition) {
<app-item-selector [itemgroups]="gameModel!.itemgroupsAsList" [selectedItem]="conditionAsItemCondition(condition)!.item"
(onSelectedItemChange)="onSelectedItemChange(condition, $event)"
></app-item-selector>
} @else {
<p *ngIf="conditionAsItemCondition(condition)!.item != undefined">
{{conditionAsItemCondition(condition)!.item!.componentName}}
</p>
}
}
</td>
</ng-container>
<ng-container matColumnDef="min">
<th mat-header-cell *matHeaderCellDef>Min</th>
<td mat-cell *matCellDef="let condition">
@if(condition == editedCondition) {
<mat-form-field appearance="fill" class="long-form">
<mat-label>Min Value</mat-label>
<input matInput [(ngModel)]="editedCondition!.minValue">
</mat-form-field>
} @else {
{{condition.minValue}}
}
</td>
</ng-container>
<ng-container matColumnDef="max">
<th mat-header-cell *matHeaderCellDef>Min</th>
<td mat-cell *matCellDef="let condition">
@if(condition == editedCondition) {
<mat-form-field appearance="fill" class="long-form">
<mat-label>Max Value</mat-label>
<input matInput [(ngModel)]="editedCondition!.maxValue">
</mat-form-field>
} @else {
{{condition.maxValue}}
}
</td>
</ng-container>
<ng-container matColumnDef="edit">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let condition">
<button mat-icon-button *ngIf="condition !== editedCondition" [disabled]="editedCondition != undefined" (click)="editCondition(condition)"><mat-icon>edit</mat-icon></button>
<button mat-icon-button *ngIf="condition === editedCondition" (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)="addCondition()"><mat-icon>add</mat-icon></button>
</th>
<td mat-cell *matCellDef="let condition">
<button mat-icon-button (click)="deleteCondition(condition)" color="warn"><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,3 @@
.mat-column-edit, .mat-column-delete {
width: 32px;
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ItemConditionEditorComponent } from './item-condition-editor.component';
describe('ItemConditionEditorComponent', () => {
let component: ItemConditionEditorComponent;
let fixture: ComponentFixture<ItemConditionEditorComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ItemConditionEditorComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ItemConditionEditorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,90 @@
import {Component, Input, OnInit} from '@angular/core';
import {AbstractInteraction} from "../../../../project/game-model/interactions/AbstractInteraction";
import {GameModel} from "../../../../project/game-model/GameModel";
import {MatTable, MatTableDataSource} from "@angular/material/table";
import {InventoryCondition} from "../../../../project/game-model/interactions/condition/InventoryCondition";
import {InventoryItemCondition} from "../../../../project/game-model/interactions/condition/InventoryItemCondition";
import {CharacterDependency} from "../../../../project/game-model/interactions/CharacterDependency";
import {
InventoryItemgroupCondition
} from "../../../../project/game-model/interactions/condition/InventoryItemgroupCondition";
import {Item} from "../../../../project/game-model/inventory/Item";
@Component({
selector: 'app-item-condition-editor',
templateUrl: './item-condition-editor.component.html',
styleUrl: './item-condition-editor.component.scss'
})
export class ItemConditionEditorComponent implements OnInit{
@Input() interaction: AbstractInteraction | undefined
@Input() gameModel: GameModel | undefined
@Input() group: boolean = false;
conditionDataSource: MatTableDataSource<InventoryCondition> = new MatTableDataSource();
displayedColumns: string[] = ["item", "min", "max", "edit", "delete"];
editedCondition: InventoryCondition | undefined
addedCondition: InventoryCondition | undefined
ngOnInit() {
this.conditionDataSource.data = this.interaction!.inventoryConditions;
}
addCondition() {
if(this.group) {
this.addedCondition = new InventoryItemgroupCondition(CharacterDependency.NONE, 0, 0, undefined);
} else {
this.addedCondition = new InventoryItemCondition(CharacterDependency.NONE, 0, 0, undefined);
}
this.editedCondition = this.addedCondition;
const displayedColumns = this.conditionDataSource.data;
displayedColumns.push(this.addedCondition);
this.conditionDataSource.data = displayedColumns;
}
editCondition(condition: InventoryCondition) {
this.editedCondition = condition;
}
finishEditing() {
if(this.editedCondition == undefined) {
return;
}
if(this.editedCondition.validate()) {
if(this.addedCondition != undefined) {
this.interaction!.addConditon(this.addedCondition);
this.addedCondition = undefined;
}
this.editedCondition = undefined;
}
}
deleteCondition(deletedCondition: InventoryCondition) {
this.interaction!.removeCondition(deletedCondition);
this.conditionDataSource.data = this.conditionDataSource.data.filter(condition => condition !== deletedCondition);
}
conditionAsItemCondition(condition: InventoryCondition) {
if(condition instanceof InventoryItemCondition) {
return condition;
} else {
return undefined;
}
}
conditionAsItemgroupCondition(condition: InventoryCondition) {
if(condition instanceof InventoryItemgroupCondition) {
return condition;
} else {
return undefined;
}
}
onSelectedItemChange(condition: InventoryCondition, item: Item) {
(condition as InventoryItemCondition).item = item;
console.log(condition)
}
}

View File

@ -0,0 +1,13 @@
<mat-form-field appearance="fill">
<mat-label>Itemgroup</mat-label>
<mat-select [(ngModel)]="selectedItemgroup">
<mat-option *ngFor="let itemgroup of itemgroups" [value]="itemgroup">{{itemgroup.componentName}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill" *ngIf="selectedItemgroup != undefined">
<mat-label>Item</mat-label>
<mat-select [(ngModel)]="selectedItem" (ngModelChange)="onItemChange($event)">
<mat-option *ngFor="let item of selectedItemgroup!.getInheritedItems()" [value]="item">{{item.componentName}}</mat-option>
</mat-select>
</mat-form-field>

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ItemSelectorComponent } from './item-selector.component';
describe('ItemSelectorComponent', () => {
let component: ItemSelectorComponent;
let fixture: ComponentFixture<ItemSelectorComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ItemSelectorComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ItemSelectorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,30 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {ItemGroup} from "../../../../../project/game-model/inventory/ItemGroup";
import {Item} from "../../../../../project/game-model/inventory/Item";
import {MatFormField} from "@angular/material/form-field";
import {MatSelect} from "@angular/material/select";
@Component({
selector: 'app-item-selector',
templateUrl: './item-selector.component.html',
styleUrl: './item-selector.component.scss'
})
export class ItemSelectorComponent implements OnInit{
@Input() itemgroups: ItemGroup[] = []
@Input() selectedItem: Item | undefined
@Output() onSelectedItemChange = new EventEmitter<Item>();
selectedItemgroup: ItemGroup | undefined
ngOnInit() {
if(this.selectedItem != undefined) {
this.selectedItemgroup = this.itemgroups.find(itemgroup => itemgroup.getInheritedItems().includes(this.selectedItem!));
}
}
onItemChange(item: Item) {
this.selectedItem = item;
this.onSelectedItemChange.emit(item);
}
}

View File

@ -28,7 +28,7 @@ export abstract class AbstractInteraction {
} }
get inventoryConditions() { get inventoryConditions() {
return this.conditions.filter(condition => condition instanceof InventoryCondition) return this.conditions.filter(condition => condition instanceof InventoryCondition).map(condition => condition as InventoryCondition)
} }
get gamesystemConditions(): GamesystemCondition[] { get gamesystemConditions(): GamesystemCondition[] {

View File

@ -7,9 +7,11 @@ export abstract class InventoryCondition extends Condition {
minValue: number minValue: number
maxValue: number maxValue: number
constructor(characterDependency: CharacterDependency, minValue: number, maxValue: number) { protected constructor(characterDependency: CharacterDependency, minValue: number, maxValue: number) {
super(characterDependency); super(characterDependency);
this.minValue = minValue; this.minValue = minValue;
this.maxValue = maxValue; this.maxValue = maxValue;
} }
abstract validate(): boolean;
} }

View File

@ -4,10 +4,14 @@ import {CharacterDependency} from "../CharacterDependency";
export class InventoryItemCondition extends InventoryCondition { export class InventoryItemCondition extends InventoryCondition {
item: Item item: Item | undefined
constructor(characterDependency: CharacterDependency, minValue: number, maxValue: number, item: Item) { constructor(characterDependency: CharacterDependency, minValue: number, maxValue: number, item: Item | undefined) {
super(characterDependency, minValue, maxValue); super(characterDependency, minValue, maxValue);
this.item = item; this.item = item;
} }
validate() {
return this.item != undefined;
}
} }

View File

@ -3,11 +3,17 @@ import {ItemGroup} from "../../inventory/ItemGroup";
import {CharacterDependency} from "../CharacterDependency"; import {CharacterDependency} from "../CharacterDependency";
export class InventoryItemgroupCondition extends InventoryCondition { export class InventoryItemgroupCondition extends InventoryCondition {
itemgroup: ItemGroup itemgroup: ItemGroup | undefined
constructor(characterDependency: CharacterDependency, minValue: number, maxValue: number, itemgroup: ItemGroup) { constructor(characterDependency: CharacterDependency, minValue: number, maxValue: number, itemgroup: ItemGroup | undefined) {
super(characterDependency, minValue, maxValue); super(characterDependency, minValue, maxValue);
this.itemgroup = itemgroup; this.itemgroup = itemgroup;
} }
validate(): boolean {
return this.itemgroup != undefined;
}
} }

View File

@ -1,6 +1,7 @@
import {ItemGroup} from "./ItemGroup"; import {ItemGroup} from "./ItemGroup";
import {ItemGroupCharacteristic} from "./ItemgroupCharacteristic"; import {ItemGroupCharacteristic} from "./ItemgroupCharacteristic";
import {ItemgroupType} from "./ItemgroupType"; import {ItemgroupType} from "./ItemgroupType";
import {Item} from "./Item";
export class AbstractItemGroup extends ItemGroup { export class AbstractItemGroup extends ItemGroup {
@ -16,5 +17,11 @@ export class AbstractItemGroup extends ItemGroup {
//Do Nothing //Do Nothing
} }
getInheritedItems(): Item[] {
let items: Item[] = [];
this.children.forEach(child => items = items.concat(child.getInheritedItems()))
return items;
}
} }

View File

@ -27,5 +27,9 @@ export class ConcreteItemGroup extends ItemGroup {
}) })
} }
getInheritedItems(): Item[] {
return this.items;
}
} }

View File

@ -30,6 +30,5 @@ export abstract class ItemGroup extends ModelComponent {
} }
} }
abstract getInheritedItems(): Item[]
} }