issue-5-product-gamesystems #10
@ -0,0 +1,35 @@
 | 
			
		||||
import {Gamesystem} from "../../../game-model/gamesystems/Gamesystem";
 | 
			
		||||
import {SimpleGamesystem} from "../../../game-model/gamesystems/SimpleGamesystem";
 | 
			
		||||
import {ProductGamesystem} from "../../../game-model/gamesystems/ProductGamesystem";
 | 
			
		||||
import {State} from "../../../game-model/gamesystems/State";
 | 
			
		||||
import {ProductState} from "../../../game-model/gamesystems/ProductState";
 | 
			
		||||
import {SimpleState} from "../../../game-model/gamesystems/SimpleState";
 | 
			
		||||
 | 
			
		||||
export class LeafGamesystemCalculator {
 | 
			
		||||
 | 
			
		||||
  static calcLeafGeamesystems(gamesystem: Gamesystem<any, any>) {
 | 
			
		||||
    if(gamesystem instanceof SimpleGamesystem) {
 | 
			
		||||
      return [gamesystem];
 | 
			
		||||
    } else {
 | 
			
		||||
      const product_gamesystem = gamesystem as ProductGamesystem;
 | 
			
		||||
      const leaf_gamesystems: SimpleGamesystem[] = [];
 | 
			
		||||
      product_gamesystem.innerGamesystems.forEach(innerGamesystem => {
 | 
			
		||||
        LeafGamesystemCalculator.calcLeafGeamesystems(innerGamesystem).forEach(leafGamesystem => leaf_gamesystems.push(leafGamesystem))
 | 
			
		||||
      })
 | 
			
		||||
      return leaf_gamesystems;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static calcLeafStates(state: State<any>) {
 | 
			
		||||
    if(state instanceof SimpleState) {
 | 
			
		||||
      return [state];
 | 
			
		||||
    } else {
 | 
			
		||||
      const productState = state as ProductState;
 | 
			
		||||
      const leafStates: SimpleState[] = [];
 | 
			
		||||
      productState.innerStates.forEach(innerState => {
 | 
			
		||||
        LeafGamesystemCalculator.calcLeafStates(innerState).forEach(leafState => leafStates.push(leafState));
 | 
			
		||||
      })
 | 
			
		||||
      return leafStates;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1 +1,2 @@
 | 
			
		||||
<app-product-state-editor [gamesystem]="gamesystem" (onOpenGamesystemEditor)="onOpenGamesystemEditor($event)"></app-product-state-editor>
 | 
			
		||||
<app-product-transition-editor [gamesystem]="gamesystem" (onOpenGamesystem)="onOpenGamesystemEditor($event)"></app-product-transition-editor>
 | 
			
		||||
 | 
			
		||||
@ -2,12 +2,18 @@ import {Component, EventEmitter, Input, Output} from '@angular/core';
 | 
			
		||||
import {ProductGamesystem} from "../../../game-model/gamesystems/ProductGamesystem";
 | 
			
		||||
import {ProductStateEditorComponent} from "../state-editor/product-state-editor/product-state-editor.component";
 | 
			
		||||
import {SimpleGamesystem} from "../../../game-model/gamesystems/SimpleGamesystem";
 | 
			
		||||
import {
 | 
			
		||||
  ProductTransitionEditorComponent
 | 
			
		||||
} from "../transition-editor/product-transition-editor/product-transition-editor.component";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-product-gamesystem-editor',
 | 
			
		||||
  standalone: true,
 | 
			
		||||
  imports: [
 | 
			
		||||
    ProductStateEditorComponent
 | 
			
		||||
    ProductStateEditorComponent,
 | 
			
		||||
    ProductTransitionEditorComponent
 | 
			
		||||
  ],
 | 
			
		||||
  templateUrl: './product-gamesystem-editor.component.html',
 | 
			
		||||
  styleUrl: './product-gamesystem-editor.component.scss'
 | 
			
		||||
 | 
			
		||||
@ -17,6 +17,7 @@ import {NgForOf, NgIf} from "@angular/common";
 | 
			
		||||
import {ProductState} from "../../../../game-model/gamesystems/ProductState";
 | 
			
		||||
import {MatIcon} from "@angular/material/icon";
 | 
			
		||||
import {Gamesystem} from "../../../../game-model/gamesystems/Gamesystem";
 | 
			
		||||
import {LeafGamesystemCalculator} from "../../product-gamesystem-editor/LeafGamesystemCalculator";
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-product-state-editor',
 | 
			
		||||
@ -67,38 +68,13 @@ export class ProductStateEditorComponent implements OnInit{
 | 
			
		||||
  protected readonly SimpleState = SimpleState;
 | 
			
		||||
 | 
			
		||||
  getLeafState(state: State<any>, i: number) {
 | 
			
		||||
    return this.computeLeafStates(state)[i];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  computeLeafStates(state: State<any>) {
 | 
			
		||||
    if(state instanceof SimpleState) {
 | 
			
		||||
      return [state];
 | 
			
		||||
    } else {
 | 
			
		||||
      const productState = state as ProductState;
 | 
			
		||||
      const leafStates: SimpleState[] = [];
 | 
			
		||||
      productState.innerStates.forEach(innerState => {
 | 
			
		||||
        this.computeLeafStates(innerState).forEach(leafState => leafStates.push(leafState));
 | 
			
		||||
      })
 | 
			
		||||
      return leafStates;
 | 
			
		||||
    }
 | 
			
		||||
    return LeafGamesystemCalculator.calcLeafStates(state)[i];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  clickOnInnerState(leafIndex: number) {
 | 
			
		||||
    const leaf_gamesystems = this.computeLeafGamesystems(this.gamesystem!);
 | 
			
		||||
    const leaf_gamesystems = LeafGamesystemCalculator.calcLeafGeamesystems(this.gamesystem!);
 | 
			
		||||
    const clicked_gamesystem = leaf_gamesystems[leafIndex];
 | 
			
		||||
    this.openGamesystemEditorEmitter.emit(clicked_gamesystem);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  computeLeafGamesystems(gamesystem: Gamesystem<any, any>) {
 | 
			
		||||
    if(gamesystem instanceof SimpleGamesystem) {
 | 
			
		||||
      return [gamesystem];
 | 
			
		||||
    } else {
 | 
			
		||||
      const product_gamesystem = gamesystem as ProductGamesystem;
 | 
			
		||||
      const leaf_gamesystems: SimpleGamesystem[] = [];
 | 
			
		||||
      product_gamesystem.innerGamesystems.forEach(innerGamesystem => {
 | 
			
		||||
        this.computeLeafGamesystems(innerGamesystem).forEach(leafGamesystem => leaf_gamesystems.push(leafGamesystem))
 | 
			
		||||
      })
 | 
			
		||||
      return leaf_gamesystems;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,42 @@
 | 
			
		||||
<table mat-table [dataSource]="dataSource">
 | 
			
		||||
  <ng-container *ngFor="let col of displayedColumns; let i = index" [matColumnDef]="col.internalName">
 | 
			
		||||
    <th mat-header-cell *matHeaderCellDef>{{col.displayedName}}</th>
 | 
			
		||||
    <td mat-cell *matCellDef="let transition">
 | 
			
		||||
      {{getLeafStateByIndex(transition, i).stateLabel}}
 | 
			
		||||
    </td>
 | 
			
		||||
  </ng-container>
 | 
			
		||||
 | 
			
		||||
  <ng-container matColumnDef="header-row-sec-group">
 | 
			
		||||
    <th
 | 
			
		||||
      mat-header-cell
 | 
			
		||||
      *matHeaderCellDef
 | 
			
		||||
      [style.text-align]="'center'"
 | 
			
		||||
      [attr.colspan]="numberLeafSystems"
 | 
			
		||||
      class="start-end-col"
 | 
			
		||||
    >
 | 
			
		||||
      Starting State
 | 
			
		||||
    </th>
 | 
			
		||||
  </ng-container>
 | 
			
		||||
  <ng-container matColumnDef="header-row-third-group">
 | 
			
		||||
    <th
 | 
			
		||||
      mat-header-cell
 | 
			
		||||
      *matHeaderCellDef
 | 
			
		||||
      [style.text-align]="'center'"
 | 
			
		||||
      [attr.colspan]="numberLeafSystems"
 | 
			
		||||
    >
 | 
			
		||||
      Ending State
 | 
			
		||||
    </th>
 | 
			
		||||
  </ng-container>
 | 
			
		||||
 | 
			
		||||
  <ng-container *ngIf="displayedColumns.length">
 | 
			
		||||
    <tr
 | 
			
		||||
      mat-header-row
 | 
			
		||||
      *matHeaderRowDef="['header-row-sec-group', 'header-row-third-group']"
 | 
			
		||||
    ></tr>
 | 
			
		||||
  </ng-container>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  <tr mat-header-row *matHeaderRowDef="columns;sticky:true"></tr>
 | 
			
		||||
  <tr mat-row *matRowDef="let row; columns: columns;"></tr>
 | 
			
		||||
 | 
			
		||||
</table>
 | 
			
		||||
@ -0,0 +1,23 @@
 | 
			
		||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { ProductTransitionEditorComponent } from './product-transition-editor.component';
 | 
			
		||||
 | 
			
		||||
describe('ProductTransitionEditorComponent', () => {
 | 
			
		||||
  let component: ProductTransitionEditorComponent;
 | 
			
		||||
  let fixture: ComponentFixture<ProductTransitionEditorComponent>;
 | 
			
		||||
 | 
			
		||||
  beforeEach(async () => {
 | 
			
		||||
    await TestBed.configureTestingModule({
 | 
			
		||||
      imports: [ProductTransitionEditorComponent]
 | 
			
		||||
    })
 | 
			
		||||
    .compileComponents();
 | 
			
		||||
    
 | 
			
		||||
    fixture = TestBed.createComponent(ProductTransitionEditorComponent);
 | 
			
		||||
    component = fixture.componentInstance;
 | 
			
		||||
    fixture.detectChanges();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should create', () => {
 | 
			
		||||
    expect(component).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@ -0,0 +1,87 @@
 | 
			
		||||
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
 | 
			
		||||
import {ProductGamesystem} from "../../../../game-model/gamesystems/ProductGamesystem";
 | 
			
		||||
import {SimpleGamesystem} from "../../../../game-model/gamesystems/SimpleGamesystem";
 | 
			
		||||
import {
 | 
			
		||||
  MatCell, MatCellDef,
 | 
			
		||||
  MatColumnDef,
 | 
			
		||||
  MatHeaderCell,
 | 
			
		||||
  MatHeaderCellDef, MatHeaderRow, MatHeaderRowDef, MatRow, MatRowDef,
 | 
			
		||||
  MatTable,
 | 
			
		||||
  MatTableDataSource
 | 
			
		||||
} from "@angular/material/table";
 | 
			
		||||
import {LeafGamesystemCalculator} from "../../product-gamesystem-editor/LeafGamesystemCalculator";
 | 
			
		||||
import {NgForOf, NgIf} from "@angular/common";
 | 
			
		||||
import {ProductTransition} from "../../../../game-model/gamesystems/ProductTransition";
 | 
			
		||||
import {ProductState} from "../../../../game-model/gamesystems/ProductState";
 | 
			
		||||
 | 
			
		||||
class DisplayedColumnName {
 | 
			
		||||
  displayedName: string
 | 
			
		||||
  internalName: string
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  constructor(displayedName: string, internalName: string) {
 | 
			
		||||
    this.displayedName = displayedName;
 | 
			
		||||
    this.internalName = internalName;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-product-transition-editor',
 | 
			
		||||
  standalone: true,
 | 
			
		||||
  imports: [
 | 
			
		||||
    MatTable,
 | 
			
		||||
    NgForOf,
 | 
			
		||||
    MatColumnDef,
 | 
			
		||||
    MatHeaderCell,
 | 
			
		||||
    MatHeaderCellDef,
 | 
			
		||||
    MatCell,
 | 
			
		||||
    MatCellDef,
 | 
			
		||||
    NgIf,
 | 
			
		||||
    MatHeaderRow,
 | 
			
		||||
    MatRow,
 | 
			
		||||
    MatHeaderRowDef,
 | 
			
		||||
    MatRowDef
 | 
			
		||||
  ],
 | 
			
		||||
  templateUrl: './product-transition-editor.component.html',
 | 
			
		||||
  styleUrl: './product-transition-editor.component.scss'
 | 
			
		||||
})
 | 
			
		||||
export class ProductTransitionEditorComponent implements OnInit{
 | 
			
		||||
 | 
			
		||||
  @Input() gamesystem: ProductGamesystem | undefined
 | 
			
		||||
  @Output() onOpenGamesystem = new EventEmitter<SimpleGamesystem>();
 | 
			
		||||
 | 
			
		||||
  dataSource = new MatTableDataSource();
 | 
			
		||||
  displayedColumns: DisplayedColumnName[] = [];
 | 
			
		||||
  columns: string[] = [];
 | 
			
		||||
  numberLeafSystems: number = -1;
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    if(this.gamesystem != undefined) {
 | 
			
		||||
      const leafGamesystems: SimpleGamesystem[] = LeafGamesystemCalculator.calcLeafGeamesystems(this.gamesystem);
 | 
			
		||||
      this.displayedColumns = leafGamesystems.map(leafGamesystem => new DisplayedColumnName(leafGamesystem.componentName, leafGamesystem.componentName + "-start"));
 | 
			
		||||
      this.displayedColumns = this.displayedColumns.concat( leafGamesystems.map(leafGamesystem => new DisplayedColumnName(leafGamesystem.componentName, leafGamesystem.componentName + "-end")));
 | 
			
		||||
 | 
			
		||||
      this.numberLeafSystems = leafGamesystems.length;
 | 
			
		||||
      this.columns = this.displayedColumns.map(column => column.internalName)
 | 
			
		||||
 | 
			
		||||
      this.dataSource.data = this.gamesystem.transitions;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getLeafStateByIndex(transition: ProductTransition, leafIndex: number) {
 | 
			
		||||
    let state: ProductState;
 | 
			
		||||
    let index = leafIndex;
 | 
			
		||||
    if(leafIndex < this.numberLeafSystems) {
 | 
			
		||||
      state = transition.startingState
 | 
			
		||||
    } else {
 | 
			
		||||
      state = transition.endingState;
 | 
			
		||||
      index = leafIndex - this.numberLeafSystems;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    const leafStates = LeafGamesystemCalculator.calcLeafStates(state);
 | 
			
		||||
    console.log(leafStates)
 | 
			
		||||
    return leafStates[index];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -135,9 +135,6 @@ export class ProductGamesystem extends Gamesystem<ProductState, ProductTransitio
 | 
			
		||||
    return binary_productState!;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  addChildGamesystem(gamesystem: Gamesystem<State<any>, Transition<any>>) {
 | 
			
		||||
    this.innerGamesystems.push(gamesystem);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user