feat: bots (#9)
Co-authored-by: Lala, Shahd <Shahd.Lala@sybit.de> Reviewed-on: #9 Co-authored-by: Leon Hermann <lq@blackhole.local> Co-committed-by: Leon Hermann <lq@blackhole.local>
This commit was merged in pull request #9.
This commit is contained in:
@@ -192,12 +192,12 @@
|
||||
<span class="dialog-brand">Join with a bot</span>
|
||||
<button type="button" class="dialog-close" (click)="closeJoinDialog()">×</button>
|
||||
</div>
|
||||
<p class="join-hint">Select one of your bots to enter this tournament. Its token will be rotated to authenticate the join.</p>
|
||||
<p class="join-hint">Select an official (engine-backed) bot to enter this tournament. These are the bots that actually play their moves.</p>
|
||||
|
||||
@if (botsLoading) {
|
||||
<div class="dialog-loading"><span class="pulse"></span>Loading bots…</div>
|
||||
} @else if (userBots.length === 0) {
|
||||
<p class="join-empty">You have no bots yet. Go to <strong>Bots</strong> in the nav to create one first.</p>
|
||||
<p class="join-empty">No official bots are available. The official-bots engine service must be running to register them.</p>
|
||||
} @else {
|
||||
<div class="bot-pick-list">
|
||||
@for (bot of userBots; track bot.id) {
|
||||
|
||||
@@ -158,7 +158,7 @@ export class TournamentsComponent implements OnInit {
|
||||
this.joinDialogTournamentId = tournamentId;
|
||||
this.joinError = null;
|
||||
this.botsLoading = true;
|
||||
this.botService.list()
|
||||
this.botService.listOfficial()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe({
|
||||
next: bots => { this.userBots = bots; this.botsLoading = false; },
|
||||
@@ -176,30 +176,22 @@ export class TournamentsComponent implements OnInit {
|
||||
if (!this.joinDialogTournamentId || this.joiningBotId) return;
|
||||
this.joiningBotId = bot.id;
|
||||
this.joinError = null;
|
||||
this.botService.rotateToken(bot.id).subscribe({
|
||||
next: token => {
|
||||
this.tournamentService.joinWithBotToken(this.joinDialogTournamentId!, token).subscribe({
|
||||
next: () => {
|
||||
this.joiningBotId = null;
|
||||
const tid = this.joinDialogTournamentId!;
|
||||
this.closeJoinDialog();
|
||||
this.tournamentService.get(tid)
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe(updated => {
|
||||
this.created = this.created.map(x => x.id === tid ? updated : x);
|
||||
this.started = this.started.map(x => x.id === tid ? updated : x);
|
||||
if (this.selectedTournament?.id === tid) this.selectedTournament = updated;
|
||||
});
|
||||
},
|
||||
error: err => {
|
||||
this.joiningBotId = null;
|
||||
this.joinError = err.error?.message ?? err.error?.error ?? 'Failed to join tournament.';
|
||||
}
|
||||
});
|
||||
},
|
||||
error: () => {
|
||||
this.tournamentService.join(this.joinDialogTournamentId, bot.id, bot.name).subscribe({
|
||||
next: () => {
|
||||
this.joiningBotId = null;
|
||||
this.joinError = 'Failed to get bot token.';
|
||||
const tid = this.joinDialogTournamentId!;
|
||||
this.closeJoinDialog();
|
||||
this.tournamentService.get(tid)
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe(updated => {
|
||||
this.created = this.created.map(x => x.id === tid ? updated : x);
|
||||
this.started = this.started.map(x => x.id === tid ? updated : x);
|
||||
if (this.selectedTournament?.id === tid) this.selectedTournament = updated;
|
||||
});
|
||||
},
|
||||
error: err => {
|
||||
this.joiningBotId = null;
|
||||
this.joinError = err.error?.message ?? err.error?.error ?? 'Failed to join tournament.';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -7,11 +7,16 @@ import { Bot, BotWithToken } from '../models/bot.models';
|
||||
export class BotService {
|
||||
private readonly http = inject(HttpClient);
|
||||
private readonly base = '/api/account/bots';
|
||||
private readonly officialBase = '/api/account/official-bots';
|
||||
|
||||
list(): Observable<Bot[]> {
|
||||
return this.http.get<Bot[]>(this.base);
|
||||
}
|
||||
|
||||
listOfficial(): Observable<Bot[]> {
|
||||
return this.http.get<Bot[]>(this.officialBase);
|
||||
}
|
||||
|
||||
create(name: string): Observable<BotWithToken> {
|
||||
return this.http.post<BotWithToken>(this.base, { name });
|
||||
}
|
||||
|
||||
@@ -40,10 +40,8 @@ export class TournamentService {
|
||||
return this.http.post<Tournament>(`${this.base}/${id}/start`, null);
|
||||
}
|
||||
|
||||
joinWithBotToken(id: string, botToken: string): Observable<void> {
|
||||
return this.http.post<void>(`${this.base}/${id}/join`, null, {
|
||||
headers: new HttpHeaders({ Authorization: `Bearer ${botToken}` })
|
||||
});
|
||||
join(id: string, botId: string, botName: string): Observable<void> {
|
||||
return this.http.post<void>(`${this.base}/${id}/join`, { botId, botName });
|
||||
}
|
||||
|
||||
roundPairings(id: string, round: number): Observable<RoundPairings> {
|
||||
|
||||
Reference in New Issue
Block a user