Find Gamesystems By Name in GameModel
All checks were successful
E2E Testing / test (push) Successful in 1m27s

This commit is contained in:
Sebastian Böckelmann 2024-02-09 20:04:52 +01:00
parent f55e8dde3d
commit b4cc5304fd
6 changed files with 172 additions and 7 deletions

View File

@ -0,0 +1,50 @@
import { BrowserContext, ElectronApplication, Page, _electron as electron } from 'playwright';
import { test, expect } from '@playwright/test';
import * as PATH from 'path';
import {GameModel} from "../../../src/app/game-model/GameModel";
import {Gamesystem} from "../../src/app/game-model/gamesystems/Gamesystem";
import {ScriptAccount} from "../../../src/app/game-model/scriptAccounts/ScriptAccount";
import {ModelComponentType} from "../../../src/app/game-model/ModelComponentType";
import {SimpleGamesystem} from "../../../src/app/game-model/gamesystems/SimpleGamesystem";
import exp = require("node:constants");
import {end} from "electron-debug";
import {GamesystemTrainer} from "./GamesystemTrainer";
test.describe('Test Find Gamesystems', () => {
const GAMEMODELNAME: string = "GameModel";
const SIMPLEGAMESYSTEM_NAME: string = "Simple Gamesystem";
test('Find null or undefined Gamesystem', async () => {
const gameModel = new GameModel(GAMEMODELNAME);
expect(gameModel.findGamesystem(null)).toBeUndefined();
expect(gameModel.findGamesystem(undefined)).toBeUndefined();
})
test('Find non existend Gamesystem', async () => {
const gameModel = new GameModel(GAMEMODELNAME);
expect(gameModel.findGamesystem("Gamesystem")).toBeUndefined();
})
test("Find existend simple Gamesystem on top layer", async () => {
const gameModel = new GameModel(GAMEMODELNAME);
const gamesystem = new SimpleGamesystem(SIMPLEGAMESYSTEM_NAME);
gameModel.addGamesystem(gamesystem);
expect(gameModel.findGamesystem(SIMPLEGAMESYSTEM_NAME)).toBeDefined();
expect(gameModel.findGamesystem(SIMPLEGAMESYSTEM_NAME)).toEqual(gamesystem);
})
test('Find existent product gamesystem on top layer', async () => {
const gameModel = GamesystemTrainer.givenGameModelWithProductGamesytemOnTopLayer();
const result = gameModel.findGamesystem(GamesystemTrainer.TOP_PRODUCT_GAMESYSTEM_NAME);
expect(result).toBeDefined();
})
test('Find existent simple gamesystem on lower layer', async () => {
const gameModel = GamesystemTrainer.givenGameModelWithProductGamesytemOnTopLayer();
const result = gameModel.findGamesystem(GamesystemTrainer.SIMPLEGAMESYSTEMNAME);
expect(result).toBeDefined();
})
});

View File

@ -0,0 +1,37 @@
import {GameModel} from "../../../src/app/game-model/GameModel";
import {SimpleGamesystem} from "../../../src/app/game-model/gamesystems/SimpleGamesystem";
import {ProductGamesystem} from "../../../src/app/game-model/gamesystems/ProductGamesystem";
export class GamesystemTrainer {
static GAMEMODELNAME: string = "GAMEMODEL";
static SIMPLEGAMESYSTEMNAME: string = "SIMPLE GAMESYSTEM";
static TOP_PRODUCT_GAMESYSTEM_NAME: string = "Top Product Gamesystem"
static SIMPLEGAMESYSTEM2: string = "Simple Gamesystem Leaf 2";
static givenEmptyGameModel() {
return new GameModel(GamesystemTrainer.GAMEMODELNAME);
}
static givenGameModelWithSimpleGamesystemOnTopLayer() {
const gameModel = new GameModel(GamesystemTrainer.GAMEMODELNAME);
const gamesytem = new SimpleGamesystem(GamesystemTrainer.SIMPLEGAMESYSTEMNAME);
gameModel.addGamesystem(gamesytem);
return gameModel;
}
static givenGameModelWithProductGamesytemOnTopLayer() {
const gameModel = new GameModel(GamesystemTrainer.GAMEMODELNAME);
const productGamesystem = new ProductGamesystem(this.TOP_PRODUCT_GAMESYSTEM_NAME);
const leaf1 = new SimpleGamesystem(this.SIMPLEGAMESYSTEMNAME);
const leaf2 = new SimpleGamesystem(this.SIMPLEGAMESYSTEM2);
productGamesystem.innerGamesystems.push(leaf1);
productGamesystem.innerGamesystems.push(leaf2);
gameModel.addGamesystem(productGamesystem);
return gameModel;
}
}

View File

@ -1,5 +1,8 @@
import {Gamesystem} from "./gamesystems/Gamesystem"; import {Gamesystem} from "./gamesystems/Gamesystem";
import {ScriptAccount} from "./scriptAccounts/ScriptAccount"; import {ScriptAccount} from "./scriptAccounts/ScriptAccount";
import {Transition} from "./gamesystems/Transition";
import {State} from "./gamesystems/State";
import {ProductGamesystem} from "./gamesystems/ProductGamesystem";
export class GameModel { export class GameModel {
private readonly _gameModelName: string private readonly _gameModelName: string
@ -48,4 +51,19 @@ export class GameModel {
} }
} }
findGamesystem(gamesystemName: string) {
const gamesystemQueue : Gamesystem<State<any>, Transition<any>>[] = [];
this.gamesystems.forEach(gamesystem => gamesystemQueue.push(gamesystem));
while(gamesystemQueue.length > 0) {
const currentGamesystem = gamesystemQueue.shift()!;
if(currentGamesystem.componentName == gamesystemName) {
return currentGamesystem;
} else if(currentGamesystem instanceof ProductGamesystem) {
const currentProductGamesystem = currentGamesystem as ProductGamesystem;
currentProductGamesystem.innerGamesystems.forEach(gamesystem => gamesystemQueue.push(gamesystem));
}
}
}
} }

View File

@ -1,14 +1,17 @@
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl"> <mat-tree [dataSource]="dataSource" [treeControl]="treeControl" (contextmenu)="onContextMenu($event)">
<!-- This is the tree node template for leaf nodes --> <!-- This is the tree node template for leaf nodes -->
<mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding> <mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding matTreeNodePaddingIndent="10" [ngClass]="selectedGamesystem === node ? 'selected-node':''"
(click)="onSelectGamesystem(node)" (contextmenu)="onSelectGamesystem(node)" (dblclick)="openGamesystemEditor(node)">
<!-- use a disabled button to provide padding for tree leaf --> <!-- use a disabled button to provide padding for tree leaf -->
<button mat-icon-button disabled></button> <button mat-icon-button class="small-icon-button" [disabled]="true"></button>
{{node.name}} {{node.name}}
</mat-tree-node> </mat-tree-node>
<!-- This is the tree node template for expandable nodes --> <!-- This is the tree node template for expandable nodes -->
<mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding> <mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding matTreeNodePaddingIndent="10"
(click)="onSelectGamesystem(node)" (contextmenu)="onSelectGamesystem(node)" [ngClass]="selectedGamesystem === node ? 'selected-node':''"
(dblclick)="openGamesystemEditor(node)">
<button mat-icon-button matTreeNodeToggle <button mat-icon-button matTreeNodeToggle
[attr.aria-label]="'Toggle ' + node.name"> [attr.aria-label]="'Toggle ' + node.name" class="small-icon-button">
<mat-icon class="mat-icon-rtl-mirror"> <mat-icon class="mat-icon-rtl-mirror">
{{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}} {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
</mat-icon> </mat-icon>

View File

@ -0,0 +1,40 @@
.mat-tree-node {
min-height: 1.8em !important;
height: 1.8em;
}
.small-icon-button {
width: 26px !important;
height: 26px !important;
padding: 0px !important;
display: inline-flex !important;
align-items: center;
justify-content: center;
margin-left: 5px;
margin-bottom: 2px;
& > *[role=img] {
width: 18px;
height: 18px;
font-size: 18px;
svg {
width: 18px;
height: 18px;
}
}
.mat-mdc-button-touch-target {
width: 22px !important;
height: 22px !important;
}
}
.small-icon-button mat-icon {
color: whitesmoke;
}
.selected-node {
background-color: #545456
}

View File

@ -1,4 +1,4 @@
import {Component, Input, OnInit} from '@angular/core'; import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {Gamesystem} from "../../game-model/gamesystems/Gamesystem"; import {Gamesystem} from "../../game-model/gamesystems/Gamesystem";
import {State} from "../../game-model/gamesystems/State"; import {State} from "../../game-model/gamesystems/State";
import {Transition} from "../../game-model/gamesystems/Transition"; import {Transition} from "../../game-model/gamesystems/Transition";
@ -15,6 +15,7 @@ import {MatIcon} from "@angular/material/icon";
import {MatIconButton} from "@angular/material/button"; import {MatIconButton} from "@angular/material/button";
import {SimpleGamesystem} from "../../game-model/gamesystems/SimpleGamesystem"; import {SimpleGamesystem} from "../../game-model/gamesystems/SimpleGamesystem";
import {GameModel} from "../../game-model/GameModel"; import {GameModel} from "../../game-model/GameModel";
import {ElectronService} from "../../core/services";
interface FlatNode { interface FlatNode {
@ -30,6 +31,8 @@ interface FlatNode {
export class GamescriptOverviewComponent implements OnInit { export class GamescriptOverviewComponent implements OnInit {
@Input('gameModel') gameModel: GameModel | undefined @Input('gameModel') gameModel: GameModel | undefined
@Output('openGamesystemEditor') openGamesystemEmitter : EventEmitter<Gamesystem<State<any>, Transition<any>>> = new EventEmitter<Gamesystem<State<any>, Transition<any>>>();
ngOnInit() { ngOnInit() {
this.dataSource.data = this.gameModel!.gamesystems; this.dataSource.data = this.gameModel!.gamesystems;
@ -56,13 +59,15 @@ export class GamescriptOverviewComponent implements OnInit {
); );
dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener); dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
selectedGamesystem: FlatNode | undefined;
constructor() { constructor(private electronService: ElectronService) {
} }
hasChild = (_: number, node: FlatNode) => node.expandable; hasChild = (_: number, node: FlatNode) => node.expandable;
isSimpleGamesystem(gamesystem: Gamesystem<State<any>, Transition<any>>) { isSimpleGamesystem(gamesystem: Gamesystem<State<any>, Transition<any>>) {
return gamesystem instanceof SimpleGamesystem; return gamesystem instanceof SimpleGamesystem;
} }
@ -70,4 +75,16 @@ export class GamescriptOverviewComponent implements OnInit {
isProductGamesystem(gamesystem: Gamesystem<State<any>, Transition<any>>) { isProductGamesystem(gamesystem: Gamesystem<State<any>, Transition<any>>) {
return gamesystem instanceof ProductGamesystem; return gamesystem instanceof ProductGamesystem;
} }
onSelectGamesystem(node: FlatNode) {
this.selectedGamesystem = node;
}
onContextMenu(event: MouseEvent) {
this.electronService.ipcRenderer.send('context-menu', {x: event.x, y: event.y});
}
openGamesystemEditor(node: FlatNode) {
const gamesystem: Gamesystem<State<any>, Transition<any>>| undefined= this.gameModel!.findGamesystem(node.name);
}
} }