umpires can be added to courts as umpires (removal also)

This commit is contained in:
2026-05-27 21:10:38 +02:00
parent 71c3733363
commit 0c071c0621
10 changed files with 436 additions and 90 deletions
+219 -48
View File
@@ -1,4 +1,4 @@
import { Component, effect, inject } from '@angular/core';
import { Component, computed, effect, inject } from '@angular/core';
import {
IonHeader,
IonToolbar,
@@ -25,15 +25,14 @@ import {
DragDropModule
} from '@angular/cdk/drag-drop';
import { CommonModule } from '@angular/common';
import { addIcons } from 'ionicons';
import { add } from 'ionicons/icons';
import { CourtUmpireService } from '../services/court.umpire.service';
import { CourtServiceJudgeService } from '../services/court.service.judge.service';
@Component({
selector: 'app-tab1',
templateUrl: 'tab1.page.html',
styleUrls: ['tab1.page.scss'],
imports: [
IonIcon,
IonLabel,
IonItem,
IonList,
@@ -56,63 +55,207 @@ export class Tab1Page {
readonly umpireService = inject(UmpireService);
readonly waitingUmpireService = inject(WaitingUmpiresService);
readonly waitingServiceJudgeService = inject(WaitingServiceJudgesService);
readonly courtUmpireService = inject(CourtUmpireService);
readonly courtServiceJudgeService = inject(CourtServiceJudgeService);
public readonly settings = this.settingsService.settings;
public readonly _umpires = this.umpireService.umpires;
public readonly _waitingUmpires = this.waitingUmpireService.waitingUmpires;
public readonly _waitingServiceJudges =
/**
* Raw signals from services
*/
readonly settings = this.settingsService.settings;
readonly _umpires = this.umpireService.umpires;
readonly _waitingUmpires = this.waitingUmpireService.waitingUmpires;
readonly _waitingServiceJudges =
this.waitingServiceJudgeService.waitingServiceJudges;
public onRest: Umpire[] = [];
public waitingUmpires: Umpire[] = [];
public waitingServiceJudges: Umpire[] = [];
readonly _courtUmpires = this.courtUmpireService.umpires;
constructor() {
addIcons({ add });
readonly _courtServiceJudges = this.courtServiceJudgeService.umpires;
effect(() => {
this.onRest = this._umpires().filter((umpire) => {
return (
!this.isUmpireOnCourt(umpire) &&
!this.isWaitingUmpire(umpire) &&
!this.isWaitingServiceJudge(umpire)
);
});
/**
* Fast O(1) umpire lookup
*/
readonly umpireMap = computed(() => {
return new Map<number, Umpire>(this._umpires().map((u) => [u.id, u]));
});
this.waitingUmpires = this._waitingUmpires()
.map((_wa) => {
return this._umpires().find((u) => u.id === _wa.umpireId);
})
.filter((u) => typeof u !== 'undefined');
/**
* Waiting umpire IDs
*/
readonly waitingUmpireIds = computed(() => {
return new Set(this._waitingUmpires().map((w) => w.umpireId));
});
this.waitingServiceJudges = this._waitingServiceJudges()
.map((_wsj) => {
return this._umpires().find((u) => u.id === _wsj.serviceJudgeId);
})
.filter((u) => typeof u !== 'undefined');
/**
* Waiting service judge IDs
*/
readonly waitingServiceJudgeIds = computed(() => {
return new Set(this._waitingServiceJudges().map((w) => w.serviceJudgeId));
});
/**
* Court umpire IDs
*/
readonly courtUmpireIds = computed(() => {
return new Set(
this._courtUmpires()
.map((c) => c.umpireId)
.filter((id): id is number => id !== null)
);
});
/**
* Court service judge IDs
*/
readonly courtServiceJudgeIds = computed(() => {
return new Set(
this._courtServiceJudges()
.map((c) => c.umpireId)
.filter((id): id is number => id !== null)
);
});
/**
* Umpires waiting as umpire
*/
readonly waitingUmpires = computed(() => {
const umpireMap = this.umpireMap();
return this._waitingUmpires()
.map((wu) => umpireMap.get(wu.umpireId))
.filter((u): u is Umpire => !!u);
});
/**
* Umpires waiting as service judge
*/
readonly waitingServiceJudges = computed(() => {
const umpireMap = this.umpireMap();
return this._waitingServiceJudges()
.map((wsj) => umpireMap.get(wsj.serviceJudgeId))
.filter((u): u is Umpire => !!u);
});
/**
* Court umpires
*/
readonly courtUmpires = computed(() => {
const umpireMap = this.umpireMap();
return this._courtUmpires()
.map((cu) => {
if (cu.umpireId == null) {
return undefined;
}
return umpireMap.get(cu.umpireId);
})
.filter((u): u is Umpire => !!u);
});
/**
* Court service judges
*/
readonly courtServiceJudges = computed(() => {
const umpireMap = this.umpireMap();
return this._courtServiceJudges()
.map((csj) => {
if (csj.umpireId == null) {
return undefined;
}
return umpireMap.get(csj.umpireId);
})
.filter((u): u is Umpire => !!u);
});
/**
* Umpires resting
*/
readonly onRest = computed(() => {
const waitingUmpireIds = this.waitingUmpireIds();
const waitingServiceJudgeIds = this.waitingServiceJudgeIds();
const courtUmpireIds = this.courtUmpireIds();
const courtServiceJudgeIds = this.courtServiceJudgeIds();
return this._umpires().filter((umpire) => {
return (
!waitingUmpireIds.has(umpire.id) &&
!waitingServiceJudgeIds.has(umpire.id) &&
!courtUmpireIds.has(umpire.id) &&
!courtServiceJudgeIds.has(umpire.id)
);
});
}
});
private isUmpireOnCourt(umpire: Umpire): boolean {
return false;
}
/**
* Court -> umpire map
*/
readonly umpireByCourt = computed(() => {
const map = new Map<number, Umpire>();
private isWaitingUmpire(umpire: Umpire): boolean {
return (
typeof this._waitingUmpires().find((wu) => wu.umpireId === umpire.id) !==
'undefined'
);
}
const umpireMap = this.umpireMap();
private isWaitingServiceJudge(umpire: Umpire): boolean {
return (
typeof this._waitingServiceJudges().find(
(wsj) => wsj.serviceJudgeId === umpire.id
) !== 'undefined'
);
}
for (const item of this._courtUmpires()) {
if (item.umpireId == null) {
continue;
}
const umpire = umpireMap.get(item.umpireId);
if (!umpire) {
continue;
}
map.set(item.courtNo, umpire);
}
return map;
});
/**
* Court -> service judge map
*/
readonly serviceJudgeByCourt = computed(() => {
const map = new Map<number, Umpire>();
const umpireMap = this.umpireMap();
for (const item of this._courtServiceJudges()) {
if (item.umpireId == null) {
continue;
}
const umpire = umpireMap.get(item.umpireId);
if (!umpire) {
continue;
}
map.set(item.courtNo, umpire);
}
return map;
});
/**
* Court indexes for template
*/
readonly courtIndexes = computed(() => {
const count = this.settings()?.numberOfCourts ?? 0;
return Array.from({ length: count }, (_, i) => i + 1);
});
dropToRest(event: CdkDragDrop<Umpire[]>) {
console.log('drop to rest');
if (event.previousContainer === event.container) {
return;
} else {
@@ -126,6 +269,10 @@ export class Tab1Page {
if ('list-waiting-umpires' === comingFrom) {
this.waitingUmpireService.removeByUmpireId(umpireToMove.id);
}
if (comingFrom.startsWith('court-umpire')) {
this.courtUmpireService.removeByUmpireId(umpireToMove.id);
}
}
}
@@ -140,6 +287,10 @@ export class Tab1Page {
if ('list-waiting-umpires' === comingFrom) {
this.waitingUmpireService.removeByUmpireId(umpireToMove.id);
}
if (comingFrom.startsWith('court-umpire')) {
this.courtUmpireService.removeByUmpireId(umpireToMove.id);
}
}
}
@@ -161,6 +312,26 @@ export class Tab1Page {
// Remove from waiting service judges
this.waitingServiceJudgeService.removeByUmpireId(umpireToMove.id);
}
if (comingFrom.startsWith('court-umpire')) {
this.courtUmpireService.removeByUmpireId(umpireToMove.id);
}
}
}
dropToUmpire(event: CdkDragDrop<Umpire[]>, courtNo: number) {
// TODO: stop dropping if there is already another umpire
const comingFrom = event.previousContainer.id;
const umpireToMove = event.item.data;
this.courtUmpireService.save({ umpireId: umpireToMove.id, courtNo });
if ('list-waiting-service-judges' === comingFrom) {
this.waitingServiceJudgeService.removeByUmpireId(umpireToMove.id);
}
if ('list-waiting-umpires' === comingFrom) {
this.waitingUmpireService.removeByUmpireId(umpireToMove.id);
}
}
}