Visualize SimpleStates of Simplegamesystems
All checks were successful
E2E Testing / test (push) Successful in 1m27s

This commit is contained in:
Sebastian Böckelmann 2024-02-10 11:03:26 +01:00
parent 81cda122a4
commit 9462de256b
17 changed files with 312 additions and 41 deletions

View File

@ -147,6 +147,9 @@ export class AppComponent implements OnInit{
const weather = new SimpleGamesystem("Weather"); const weather = new SimpleGamesystem("Weather");
const season = new SimpleGamesystem("Season"); const season = new SimpleGamesystem("Season");
season.createState("Spring", "Spring, also known as springtime, is one of the four temperate seasons, succeeding winter and preceding summer.");
season.createState("Summer", "Summer is the hottest and brightest of the four temperate seasons, occurring after spring and before autumn. ");
this.gameModel.addGamesystem(weather) this.gameModel.addGamesystem(weather)
this.gameModel.addGamesystem(season); this.gameModel.addGamesystem(season);
} }

View File

@ -30,6 +30,22 @@ import {DeleteConfirmationDialogComponent} from "./delete-confirmation-dialog/de
import {MatDialogActions, MatDialogContent, MatDialogTitle} from "@angular/material/dialog"; import {MatDialogActions, MatDialogContent, MatDialogTitle} from "@angular/material/dialog";
import {GamescriptOverviewComponent} from "./side-overviews/gamescript-overview/gamescript-overview.component"; import {GamescriptOverviewComponent} from "./side-overviews/gamescript-overview/gamescript-overview.component";
import {MatTree, MatTreeModule} from "@angular/material/tree"; import {MatTree, MatTreeModule} from "@angular/material/tree";
import {GamesystemEditorComponent} from "./editor/gamesystem-editor/gamesystem-editor.component";
import {
SimpleGamesystemEditorComponent
} from "./editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component";
import {
SimpleStateEditorComponent
} from "./editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component";
import {
MatCell,
MatCellDef,
MatColumnDef,
MatHeaderCell,
MatHeaderCellDef,
MatHeaderRow, MatHeaderRowDef, MatRow, MatRowDef,
MatTable
} from "@angular/material/table";
// 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');
@ -42,48 +58,61 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl
ScriptAccountEditorComponent, ScriptAccountEditorComponent,
ModelComponentEditorComponent, ModelComponentEditorComponent,
DeleteConfirmationDialogComponent, DeleteConfirmationDialogComponent,
GamescriptOverviewComponent GamescriptOverviewComponent,
GamesystemEditorComponent,
SimpleGamesystemEditorComponent,
SimpleStateEditorComponent
],
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
], ],
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,
],
providers: [], providers: [],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })

View File

@ -10,6 +10,8 @@
<app-model-component-editor [modelComponent]="modelComponent" (onModelNameUpdated)="onModelNameUpdate()"></app-model-component-editor> <app-model-component-editor [modelComponent]="modelComponent" (onModelNameUpdated)="onModelNameUpdate()"></app-model-component-editor>
<app-script-account-editor *ngIf="modelComponent.type === ModelComponentType.SCRIPTACCOUNT" <app-script-account-editor *ngIf="modelComponent.type === ModelComponentType.SCRIPTACCOUNT"
[scriptAccount]="convertModelComponentToScriptAccount(modelComponent)"></app-script-account-editor> [scriptAccount]="convertModelComponentToScriptAccount(modelComponent)"></app-script-account-editor>
<app-gamesystem-editor *ngIf="modelComponent.type == ModelComponentType.GAMESYTEM"
[gamesystem]="convertModelComponentToGamesystem(modelComponent)"></app-gamesystem-editor>
</mat-tab> </mat-tab>
</mat-tab-group> </mat-tab-group>

View File

@ -3,6 +3,9 @@ import {GameModel} from "../game-model/GameModel";
import {ModelComponent} from "../game-model/ModelComponent"; import {ModelComponent} from "../game-model/ModelComponent";
import {ModelComponentType} from "../game-model/ModelComponentType"; import {ModelComponentType} from "../game-model/ModelComponentType";
import {ScriptAccount} from "../game-model/scriptAccounts/ScriptAccount"; import {ScriptAccount} from "../game-model/scriptAccounts/ScriptAccount";
import {Gamesystem} from "../game-model/gamesystems/Gamesystem";
import {State} from "../game-model/gamesystems/State";
import {Transition} from "../game-model/gamesystems/Transition";
@Component({ @Component({
selector: 'app-editor', selector: 'app-editor',
@ -29,6 +32,12 @@ export class EditorComponent {
} }
} }
convertModelComponentToGamesystem(modelComponent: ModelComponent) {
if(modelComponent instanceof Gamesystem) {
return modelComponent as Gamesystem<State<any>, Transition<any>>;
}
}
protected readonly ModelComponentType = ModelComponentType; protected readonly ModelComponentType = ModelComponentType;
onModelNameUpdate() { onModelNameUpdate() {

View File

@ -0,0 +1 @@
<app-simple-gamesystem-editor *ngIf="isSimpleGamesystem()" [simpleGamesystem]="convertGamesystemToSimpleGamesystem()"></app-simple-gamesystem-editor>

View File

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

View File

@ -0,0 +1,33 @@
import {Component, Input} from '@angular/core';
import {GameModel} from "../../game-model/GameModel";
import {Gamesystem} from "../../game-model/gamesystems/Gamesystem";
import {State} from "../../game-model/gamesystems/State";
import {Transition} from "../../game-model/gamesystems/Transition";
import {SimpleGamesystem} from "../../game-model/gamesystems/SimpleGamesystem";
import {ProductGamesystem} from "../../game-model/gamesystems/ProductGamesystem";
@Component({
selector: 'app-gamesystem-editor',
templateUrl: './gamesystem-editor.component.html',
styleUrl: './gamesystem-editor.component.scss'
})
export class GamesystemEditorComponent {
@Input() gamesystem: Gamesystem<State<any>, Transition<any>> | undefined
isSimpleGamesystem() {
return this.gamesystem instanceof SimpleGamesystem;
}
convertGamesystemToSimpleGamesystem() {
if(this.gamesystem instanceof SimpleGamesystem) {
return this.gamesystem as SimpleGamesystem;
}
}
convertGamesystemToProductGamesystem() {
if(this.gamesystem instanceof ProductGamesystem) {
return this.gamesystem as ProductGamesystem;
}
}
}

View File

@ -0,0 +1 @@
<app-simple-state-editor [states]="simpleGamesystem!.states"></app-simple-state-editor>

View File

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

View File

@ -0,0 +1,16 @@
import {Component, Input} from '@angular/core';
import {SimpleGamesystem} from "../../../game-model/gamesystems/SimpleGamesystem";
import {MatTableDataSource} from "@angular/material/table";
@Component({
selector: 'app-simple-gamesystem-editor',
templateUrl: './simple-gamesystem-editor.component.html',
styleUrl: './simple-gamesystem-editor.component.scss'
})
export class SimpleGamesystemEditorComponent {
@Input() simpleGamesystem: SimpleGamesystem | undefined
}

View File

@ -0,0 +1,36 @@
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>Label</th>
<td mat-cell *matCellDef="let state">{{state.stateLabel}}</td>
</ng-container>
<ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef>Label</th>
<td mat-cell *matCellDef="let state">{{state.stateDescription}}</td>
</ng-container>
<ng-container matColumnDef="initial">
<th mat-header-cell *matHeaderCellDef>Initial</th>
<td mat-cell *matCellDef="let state">
<mat-icon *ngIf="state.initial">done</mat-icon>
<mat-icon *ngIf="!state.initial">close</mat-icon>
</td>
</ng-container>
<ng-container matColumnDef="edit">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let state">
<button mat-icon-button color="primary"><mat-icon>edit</mat-icon></button>
</td>
</ng-container>
<ng-container matColumnDef="delete">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let state">
<button mat-icon-button 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,51 @@
table {
width: 100%;
}
tr.example-detail-row {
height: 0;
}
tr.example-element-row:not(.example-expanded-row):hover {
background: whitesmoke;
}
tr.example-element-row:not(.example-expanded-row):active {
background: #efefef;
}
.example-element-row td {
border-bottom-width: 0;
}
.example-element-detail {
overflow: hidden;
display: flex;
}
.example-element-diagram {
min-width: 80px;
border: 2px solid black;
padding: 8px;
font-weight: lighter;
margin: 8px 0;
height: 104px;
}
.example-element-symbol {
font-weight: bold;
font-size: 40px;
line-height: normal;
}
.example-element-description {
padding: 16px;
}
.example-element-description-attribution {
opacity: 0.5;
}
.mat-column-edit, .mat-column-delete {
width: 32px;
}

View File

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

View File

@ -0,0 +1,19 @@
import {Component, Input, OnInit} from '@angular/core';
import {SimpleState} from "../../../../game-model/gamesystems/SimpleState";
import {MatTableDataSource} from "@angular/material/table";
@Component({
selector: 'app-simple-state-editor',
templateUrl: './simple-state-editor.component.html',
styleUrl: './simple-state-editor.component.scss'
})
export class SimpleStateEditorComponent implements OnInit{
@Input() states: SimpleState[] = [];
dataSource = new MatTableDataSource();
displayedColumns = ["name", "initial", "edit", "delete"];
ngOnInit() {
this.dataSource.data = this.states;
}
}

View File

@ -6,6 +6,8 @@ export abstract class State<T extends Transition<any>> {
incomingTransitions: T[] =[]; incomingTransitions: T[] =[];
outgoingTransitions: T[] =[]; outgoingTransitions: T[] =[];
initial: boolean = false;
constructor(stateLabel: string, stateDescription: string) { constructor(stateLabel: string, stateDescription: string) {
this.stateLabel = stateLabel; this.stateLabel = stateLabel;