Commit 8c220d79 authored by nanahira's avatar nanahira

add participant seq

parent 82191785
......@@ -95,6 +95,13 @@ export class MatchService extends CrudService(Match, {
if (dto.winnerId !== undefined) {
dto.status = MatchStatus.Finished;
}
if (
dto.player1Score === 0 &&
dto.player2Score === 0 &&
dto.winnerId === undefined
) {
dto.status = MatchStatus.Pending;
}
if (
match.status === MatchStatus.Finished &&
(dto.winnerId !== undefined ||
......@@ -114,9 +121,7 @@ export class MatchService extends CrudService(Match, {
);
}
dto.winnerId ||= null;
if (dto.player1Score === 0 && dto.player2Score === 0) {
dto.status = MatchStatus.Pending;
}
const result = await this.update(id, dto);
await this.tournamentService.afterMatchUpdate(match.tournamentId);
return result;
......
import { Entity, ManyToOne, OneToMany } from 'typeorm';
import { Entity, Index, ManyToOne, OneToMany } from 'typeorm';
import { NamedBase } from '../../utility/NamedBase.entity';
import {
BoolColumn,
IntColumn,
NotChangeable,
NotColumn,
NotQueryable,
......@@ -34,7 +35,7 @@ export class ParticipantScore {
tieBreaker: number;
}
@Entity({ orderBy: { id: 'ASC' } })
@Entity()
export class Participant extends NamedBase {
@QueryMatchBoolean()
@BoolColumn({ default: false, description: '是否已经退赛' })
......@@ -67,6 +68,14 @@ export class Participant extends NamedBase {
})
score: ParticipantScore;
@Index()
@QueryEqual()
@IntColumn('int', {
description: '该选手的排序,小号在前',
default: 1000,
})
seq: number;
getMatches() {
return this.matches1.concat(this.matches2);
}
......
......@@ -12,6 +12,8 @@ import { TournamentService } from '../tournament/tournament.service';
@Injectable()
export class ParticipantService extends CrudService(Participant, {
relations: [Inner('tournament')],
extraGetQuery: (qb) =>
qb.orderBy('participant.seq', 'ASC').addOrderBy('participant.id', 'ASC'),
}) {
constructor(
@InjectRepository(Participant) repo,
......
......@@ -256,6 +256,8 @@ export class Tournament extends DescBase {
this.participants,
(p) => -p.score.score,
(p) => -p.score.tieBreaker,
(p) => p.seq,
(p) => p.id,
);
this.participants.forEach((p, i) => {
......
......@@ -196,4 +196,16 @@ export class TournamentController {
) {
return this.tournamentService.importParticipantsFrom(id, dto, user);
}
@Post(':id/shuffle-participants')
@HttpCode(200)
@ApiOperation({ summary: '打乱比赛选手' })
@ApiParam({ name: 'id', description: 'Tournament ID' })
@ApiOkResponse({ type: BlankReturnMessageDto })
async shuffleParticipants(
@factory.idParam() id: number,
@PutMycardUser() user: MycardUser,
) {
return this.tournamentService.shuffleParticipants(id, user);
}
}
......@@ -15,6 +15,7 @@ import { filter, lastValueFrom, mergeMap, tap } from 'rxjs';
import { Readable } from 'stream';
import { parseZipStream } from '../utility/parse-zip-stream';
import YGOProDeck from 'ygopro-deck-encode';
import { shuffleArray } from '../utility/shuffle-array';
@Injectable()
export class TournamentService extends CrudService(Tournament, {
......@@ -25,6 +26,13 @@ export class TournamentService extends CrudService(Tournament, {
'matches.player2',
'matches.winner',
],
extraGetQuery: (qb) =>
qb
.addOrderBy('participants.seq', 'ASC')
.addOrderBy('participants.id', 'ASC')
.addOrderBy('matches.round', 'ASC')
.addOrderBy('matches.isThirdPlaceMatch', 'ASC')
.addOrderBy('matches.id', 'ASC'),
}) {
constructor(
@InjectRepository(Tournament) repo,
......@@ -348,4 +356,48 @@ export class TournamentService extends CrudService(Tournament, {
}
return this.participantService.importParticipants(participants, user);
}
async shuffleParticipants(id: number, user: MycardUser | number) {
const tournament = await this.checkPermissionOfTournament(
id,
user,
['status'],
['participants'],
);
if (tournament.status !== TournamentStatus.Ready) {
throw new BlankReturnMessageDto(
403,
'比赛已经开始,不能打乱参赛者。',
).toException();
}
if (!tournament.participants.length) {
throw new BlankReturnMessageDto(
404,
'没有选手,不能打乱参赛者。',
).toException();
}
const participants = [...tournament.participants];
// shuffle
shuffleArray(participants);
participants.forEach((p, i) => {
p.seq = 1000 + 100 * i;
});
const ids = participants.map((p) => p.id);
const cases = participants
.map((p) => `WHEN ${p.id} THEN ${p.seq}`)
.join('\n');
await this.repo.manager
.createQueryBuilder()
.update(Participant)
.set({
seq: () => `
CASE id
${cases}
END
`,
})
.whereInIds(ids)
.execute();
return new BlankReturnMessageDto(200, 'success');
}
}
export function shuffleArray<T>(arr: T[]): T[] {
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1)); // 0 ≤ j ≤ i
[arr[i], arr[j]] = [arr[j], arr[i]]; // swap elements
}
return arr;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment