Compare commits

...

2 Commits

Author SHA1 Message Date
87d9291bfb Use substitutions for disable button test
All checks were successful
Gitea/swiss-client/pipeline/head This commit looks good
2025-11-06 23:19:00 +01:00
c646ae15ee Optionally disable starting a match and show reason
All checks were successful
Gitea/swiss-client/pipeline/head This commit looks good
2025-11-06 23:00:00 +01:00
4 changed files with 130 additions and 53 deletions

View File

@@ -323,10 +323,19 @@
</td> </td>
<td class="align-middle w-fill"> <td class="align-middle w-fill">
@if (match.status == 'NOT_STARTED') { @if (match.status == 'NOT_STARTED') {
<button mat-button (click)="startMatch(match)"> @if (match.canStart) {
<mat-icon>play_arrow</mat-icon> <button mat-button (click)="startMatch(match)">
Wedstrijd starten <mat-icon>play_arrow</mat-icon>
</button> Wedstrijd starten
</button>
} @else {
<span [matTooltip]="match.cantStartReason" style="cursor: not-allowed;">
<button mat-button disabled>
<mat-icon>play_arrow</mat-icon>
Wedstrijd starten
</button>
</span>
}
} @else if (match.status == 'IN_PROGRESS') { } @else if (match.status == 'IN_PROGRESS') {
<button mat-button (click)="editResult(match, event, group, round)"> <button mat-button (click)="editResult(match, event, group, round)">
<mat-icon>leaderboard</mat-icon> <mat-icon>leaderboard</mat-icon>

View File

@@ -33,9 +33,10 @@ import {Standings} from "../../model/standings";
import {HeaderService} from "../../service/header.service"; import {HeaderService} from "../../service/header.service";
import {TournamentPlayersComponent} from "../tournament-players/tournament-players.component"; import {TournamentPlayersComponent} from "../tournament-players/tournament-players.component";
import {TournamentPlayer} from "../../model/tournamentPlayer"; import {TournamentPlayer} from "../../model/tournamentPlayer";
import {MatTooltip} from "@angular/material/tooltip";
import {TeamDisplayComponent} from "../team-display/team-display.component"; import {TeamDisplayComponent} from "../team-display/team-display.component";
import {CounterSelectionComponent} from "../counter-selection/counter-selection.component"; import {CounterSelectionComponent} from "../counter-selection/counter-selection.component";
import {Observable, Subscription, tap} from "rxjs";
import {MatTooltip} from '@angular/material/tooltip';
@Component({ @Component({
selector: 'app-tournament-manage', selector: 'app-tournament-manage',
@@ -66,6 +67,7 @@ import {CounterSelectionComponent} from "../counter-selection/counter-selection.
TournamentPlayersComponent, TournamentPlayersComponent,
MatExpansionPanelActionRow, MatExpansionPanelActionRow,
TeamDisplayComponent, TeamDisplayComponent,
MatTooltip,
], ],
providers: [ providers: [
FullNamePipe, FullNamePipe,
@@ -98,10 +100,10 @@ export class TournamentManageComponent implements OnInit, OnDestroy {
this.activeRoundTab = params['tab']; this.activeRoundTab = params['tab'];
} }
}) })
this.tournamentService.getById(Number(id)).subscribe(data => { this.loadTournament(
this.tournament = data; this.tournamentService.getById(Number(id)),
this.headerService.setTitle(this.tournament.name); (tournament) => this.headerService.setTitle(tournament.name)
}); );
} }
ngOnDestroy() { ngOnDestroy() {
@@ -152,45 +154,31 @@ export class TournamentManageComponent implements OnInit, OnDestroy {
} }
startRound(round: Round) { startRound(round: Round) {
this.tournamentService.startRound(this.tournament.id, round.id).subscribe(data => { this.loadTournament(this.tournamentService.startRound(this.tournament.id, round.id));
this.tournament = data;
});
} }
finishRound(round: Round) { finishRound(round: Round) {
this.tournamentService.finishRound(this.tournament.id, round.id).subscribe(data => { this.loadTournament(this.tournamentService.finishRound(this.tournament.id, round.id));
this.tournament = data;
});
} }
finishGroup(group: Group) { finishGroup(group: Group) {
this.tournamentService.finishGroup(this.tournament.id, group.id).subscribe(data => { this.loadTournament(this.tournamentService.finishGroup(this.tournament.id, group.id));
this.tournament = data;
});
} }
reopenGroup(group: Group) { reopenGroup(group: Group) {
this.tournamentService.reopenGroup(this.tournament.id, group.id).subscribe(data => { this.loadTournament(this.tournamentService.reopenGroup(this.tournament.id, group.id));
this.tournament = data;
});
} }
divideTournament() { divideTournament() {
this.tournamentService.divide(this.tournament.id).subscribe(data => { this.loadTournament(this.tournamentService.divide(this.tournament.id));
this.tournament = data;
});
} }
clearDivision() { clearDivision() {
this.tournamentService.clearDivision(this.tournament.id).subscribe(data => { this.loadTournament(this.tournamentService.clearDivision(this.tournament.id));
this.tournament = data;
});
} }
drawTournament() { drawTournament() {
this.tournamentService.draw(this.tournament.id).subscribe(data => { this.loadTournament(this.tournamentService.draw(this.tournament.id));
this.tournament = data;
});
} }
startMatch(match: Match) { startMatch(match: Match) {
@@ -214,9 +202,7 @@ export class TournamentManageComponent implements OnInit, OnDestroy {
minHeight: '250px' minHeight: '250px'
}).afterClosed().subscribe(result => { }).afterClosed().subscribe(result => {
if (result != undefined) { if (result != undefined) {
this.tournamentService.startMatch(this.tournament.id, match.id, result.court, result.counter.playerId).subscribe(data => { this.loadTournament(this.tournamentService.startMatch(this.tournament.id, match.id, result.court, result.counter.playerId));
this.tournament = data;
});
} }
}); });
} }
@@ -224,26 +210,48 @@ export class TournamentManageComponent implements OnInit, OnDestroy {
matchContainsPlayersThatArePlaying(match: Match): boolean { matchContainsPlayersThatArePlaying(match: Match): boolean {
let matchPlayers: number[] = []; let matchPlayers: number[] = [];
matchPlayers.push(this.getTournamentPlayerFromPlayer(match.team1.player1).id); matchPlayers.push(this.getPlayerOrSubstitute(match.team1.player1, match.type).id);
if (match.team1.player2) matchPlayers.push(this.getTournamentPlayerFromPlayer(match.team1.player2).id); if (match.team1.player2) matchPlayers.push(this.getPlayerOrSubstitute(match.team1.player2, match.type).id);
matchPlayers.push(this.getTournamentPlayerFromPlayer(match.team2.player1).id); matchPlayers.push(this.getPlayerOrSubstitute(match.team2.player1, match.type).id);
if (match.team2.player2) matchPlayers.push(this.getTournamentPlayerFromPlayer(match.team2.player2).id); if (match.team2.player2) matchPlayers.push(this.getPlayerOrSubstitute(match.team2.player2, match.type).id);
let matchPlayersThatArePlaying = this.tournament.playersPlaying.filter(Set.prototype.has, new Set(matchPlayers)); let matchPlayersThatArePlaying = this.tournament.playersPlaying.filter(Set.prototype.has, new Set(matchPlayers));
return matchPlayersThatArePlaying.length > 0; return matchPlayersThatArePlaying.length > 0;
} }
matchPlayersThatArePlaying(match: Match): number[] {
let matchPlayers: number[] = [];
matchPlayers.push(this.getPlayerOrSubstitute(match.team1.player1, match.type).id);
if (match.team1.player2) matchPlayers.push(this.getPlayerOrSubstitute(match.team1.player2, match.type).id);
matchPlayers.push(this.getPlayerOrSubstitute(match.team2.player1, match.type).id);
if (match.team2.player2) matchPlayers.push(this.getPlayerOrSubstitute(match.team2.player2, match.type).id);
return this.tournament.playersPlaying.filter(Set.prototype.has, new Set(matchPlayers));
}
matchContainsPlayersThatAreCounting(match: Match): boolean { matchContainsPlayersThatAreCounting(match: Match): boolean {
let matchPlayers: number[] = []; let matchPlayers: number[] = [];
matchPlayers.push(this.getTournamentPlayerFromPlayer(match.team1.player1).id); matchPlayers.push(this.getPlayerOrSubstitute(match.team1.player1, match.type).id);
if (match.team1.player2) matchPlayers.push(this.getTournamentPlayerFromPlayer(match.team1.player2).id); if (match.team1.player2) matchPlayers.push(this.getPlayerOrSubstitute(match.team1.player2, match.type).id);
matchPlayers.push(this.getTournamentPlayerFromPlayer(match.team2.player1).id); matchPlayers.push(this.getPlayerOrSubstitute(match.team2.player1, match.type).id);
if (match.team2.player2) matchPlayers.push(this.getTournamentPlayerFromPlayer(match.team2.player2).id); if (match.team2.player2) matchPlayers.push(this.getPlayerOrSubstitute(match.team2.player2, match.type).id);
let matchPlayersThatAreCounting = this.tournament.playersCounting.filter(Set.prototype.has, new Set(matchPlayers)); let matchPlayersThatAreCounting = this.tournament.playersCounting.filter(Set.prototype.has, new Set(matchPlayers));
return matchPlayersThatAreCounting.length > 0; return matchPlayersThatAreCounting.length > 0;
} }
matchPlayersThatAreCounting(match: Match): number[] {
let matchPlayers: number[] = [];
matchPlayers.push(this.getPlayerOrSubstitute(match.team1.player1, match.type).id);
if (match.team1.player2) matchPlayers.push(this.getPlayerOrSubstitute(match.team1.player2, match.type).id);
matchPlayers.push(this.getPlayerOrSubstitute(match.team2.player1, match.type).id);
if (match.team2.player2) matchPlayers.push(this.getPlayerOrSubstitute(match.team2.player2, match.type).id);
return this.tournament.playersCounting.filter(Set.prototype.has, new Set(matchPlayers));
}
getTournamentPlayerFromPlayer(player: Player): TournamentPlayer { getTournamentPlayerFromPlayer(player: Player): TournamentPlayer {
for (let tournamentPlayer of this.tournament.tournamentPlayers) { for (let tournamentPlayer of this.tournament.tournamentPlayers) {
if (tournamentPlayer.playerId == player.id) { if (tournamentPlayer.playerId == player.id) {
@@ -303,15 +311,11 @@ export class TournamentManageComponent implements OnInit, OnDestroy {
} }
stopMatch(match: Match) { stopMatch(match: Match) {
this.tournamentService.stopMatch(this.tournament.id, match.id).subscribe(data => { this.loadTournament(this.tournamentService.stopMatch(this.tournament.id, match.id));
this.tournament = data;
})
} }
newRound(group: Group) { newRound(group: Group) {
this.tournamentService.newRound(this.tournament.id, group.id).subscribe(data => { this.loadTournament(this.tournamentService.newRound(this.tournament.id, group.id));
this.tournament = data;
})
} }
getStrength(strength: string | undefined) { getStrength(strength: string | undefined) {
@@ -376,9 +380,7 @@ export class TournamentManageComponent implements OnInit, OnDestroy {
minWidth: '800px' minWidth: '800px'
}).afterClosed().subscribe(result => { }).afterClosed().subscribe(result => {
if (result != undefined) { if (result != undefined) {
this.tournamentService.saveResult(this.tournament.id, result.matchId, result).subscribe(data => { this.loadTournament(this.tournamentService.saveResult(this.tournament.id, result.matchId, result));
this.tournament = data;
})
} }
}); });
} }
@@ -439,13 +441,74 @@ export class TournamentManageComponent implements OnInit, OnDestroy {
minHeight: '250px' minHeight: '250px'
}).afterClosed().subscribe(result => { }).afterClosed().subscribe(result => {
if (result != undefined) { if (result != undefined) {
this.tournamentService.updateCounter(this.tournament.id, match.id, result.counter.playerId).subscribe(data => { this.loadTournament(this.tournamentService.updateCounter(this.tournament.id, match.id, result.counter.playerId));
this.tournament = data;
});
} }
}); });
} }
private loadTournament(
observable: Observable<Tournament>,
afterLoad?: (tournament: Tournament) => void
): Subscription {
return observable.subscribe(data => {
this.tournament = data;
this.updateMatchAvailability();
afterLoad?.(data); // Optional chaining
});
}
private updateMatchAvailability() {
for (const event of this.tournament.events) {
for (const group of event.groups) {
for (const round of group.rounds) {
for (const match of round.matches) {
let canStart = true;
let matchPlayersThatArePlaying = this.matchPlayersThatArePlaying(match);
let matchPlayersThatAreCounting = this.matchPlayersThatAreCounting(match);
let cantStartReason = "";
if (matchPlayersThatArePlaying.length > 0) {
canStart = false;
cantStartReason = this.joinWithEn(matchPlayersThatArePlaying.map(m => this.getTournamentPlayerFromId(m).name));
if (matchPlayersThatArePlaying.length == 1) {
cantStartReason += " is al aan het spelen";
} else {
cantStartReason += " zijn al aan het spelen";
}
}
if (matchPlayersThatAreCounting.length > 0) {
canStart = false;
if (cantStartReason.length > 0) {
cantStartReason += " en ";
}
cantStartReason += this.joinWithEn(matchPlayersThatAreCounting.map(m => this.getTournamentPlayerFromId(m).name));
if (matchPlayersThatAreCounting.length == 1) {
cantStartReason += " is aan het tellen";
} else {
cantStartReason += " zijn aan het tellen";
}
}
match.canStart = canStart;
match.cantStartReason = cantStartReason;
}
}
}
}
}
joinWithEn(items: string[], separator = ", "): string {
const len = items.length;
if (len === 0) return "";
if (len === 1) return items[0];
if (len === 2) return items.join(" en ");
return items.slice(0, -1).join(separator) + `${separator}and ${items[len - 1]}`;
}
} }
class ActiveMatch { class ActiveMatch {

View File

@@ -13,4 +13,6 @@ export class Match {
games: Game[]; games: Game[];
court: number; court: number;
counter: Player; counter: Player;
canStart?: boolean;
cantStartReason?: string;
} }

View File

@@ -7,3 +7,6 @@ body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
z-index: 2000 !important; z-index: 2000 !important;
} }
*/ */
.mat-tooltip {
white-space: pre-line !important;
}