Commit c445ea24 authored by nanahira's avatar nanahira

add .cleanzombie

parent 9245ea30
......@@ -38,6 +38,11 @@ export class MatchWrapper {
(this.match.scores_csv?.length || 0) < 3
);
}
isNotStarted() {
return !this.match.scores_csv && this.match.state !== 'complete';
}
getPlayerIds() {
return [this.match.player1_id, this.match.player2_id];
}
......@@ -45,6 +50,12 @@ export class MatchWrapper {
hasPlayer(id: number) {
return this.getPlayerIds().includes(id);
}
getDisplayLine(player1Name: string, player2Name: string) {
return `${player1Name} ${
this.match.scores_csv || '未开始'
} ${player2Name}`;
}
}
export class Participant {
......@@ -196,4 +207,19 @@ export class TournamentWrapper {
}
return allRelatedMatches[allRelatedMatches.length - 1];
}
displayMatch(match: MatchWrapper) {
const currentMatchInfo = match.match;
const player1Name = this.getParticipantFromParticipantId(
currentMatchInfo.player1_id,
).participant.name;
const player2Name = this.getParticipantFromParticipantId(
currentMatchInfo.player2_id,
).participant.name;
return match.getDisplayLine(player1Name, player2Name);
}
getZombieMatches() {
return this.tournament.matches.filter((m) => m.isNotStarted());
}
}
......@@ -5,7 +5,7 @@ import {
YGOTournamentPluginConfigLike,
} from './config';
import { classToPlain, plainToClass } from 'class-transformer';
import { TournamentWrapper } from './def/challonge';
import { MatchWrapper, TournamentWrapper } from './def/challonge';
import { S3Client } from '@aws-sdk/client-s3';
import { getSignedUrl } from './presign';
import { SRVProRoomInfo } from './def/srvpro';
......@@ -143,16 +143,12 @@ export class YGOTournamentPlugin {
if (!currentMatch) {
return '您没有正在进行的比赛。';
}
const currentMatchInfo = currentMatch.match;
const player1Name = tournament.getParticipantFromParticipantId(
currentMatchInfo.player1_id,
).participant.name;
const player2Name = tournament.getParticipantFromParticipantId(
currentMatchInfo.player2_id,
).participant.name;
return `您当前的对局信息:\n${player1Name}\t${
currentMatchInfo.scores_csv || '未开始'
}\t${player2Name}`;
return `您当前的对局信息:\n${tournament.displayMatch(currentMatch)}`;
}
private async fetchSRVProRoomlist() {
const rawRoomlist = await this.config.tournament.fetchRooms(this.ctx);
return plainToClass(SRVProRoomInfo, rawRoomlist);
}
private async onUserDeclareLate(userId: string) {
......@@ -182,11 +178,7 @@ export class YGOTournamentPlugin {
if (!currentMatch.isClean()) {
return '你涉及的比赛似乎已经有结果了,请联系裁判处理。';
}
const rawRoomlist = await this.config.tournament.fetchRooms(this.ctx);
if (!rawRoomlist) {
return '获取房间列表失败,请与技术人员联系。';
}
const roomlist = plainToClass(SRVProRoomInfo, rawRoomlist);
const roomlist = await this.fetchSRVProRoomlist();
const roomsWithPlayer = roomlist.searchForUser(participantName);
if (!roomsWithPlayer.length) {
return '请先进入房间并打勾确认。';
......@@ -236,6 +228,44 @@ export class YGOTournamentPlugin {
return '迟到杀成功。';
}
private async getZombieMatches() {
const tournament = await this.fetchChallongeData();
const matches = tournament.getZombieMatches();
if (!matches.length) {
return { tournament, matches };
}
const roomlist = await this.fetchSRVProRoomlist();
const zombieMatches = matches.filter((m) => {
const player1 = tournament.getParticipantFromParticipantId(
m.match.player1_id,
);
const player2 = tournament.getParticipantFromParticipantId(
m.match.player2_id,
);
const player1Name = player1.getNameMatching().userName;
const player2Name = player2.getNameMatching().userName;
const roomsWithPlayer1 = roomlist.searchForUser(player1Name);
const roomsWithPlayer2 = roomlist.searchForUser(player2Name);
return (
roomsWithPlayer1.every((r) => r.istart === 'wait') &&
roomsWithPlayer2.every((r) => r.istart === 'wait')
);
});
return { tournament, matches: zombieMatches };
}
private async cleanZombieMatch(match: MatchWrapper) {
await this.ctx.http.put(
`${this.config.tournament.getChallongeUrl()}/matches/${
match.match.id
}.json`,
{
api_key: this.config.tournament.challongeKey,
match: { scores_csv: '0-0', winner_id: 'tie' },
},
);
}
private initializeDeckFetch() {
if (!this.config.isDeckFetchEnabled()) {
return;
......@@ -378,6 +408,32 @@ export class YGOTournamentPlugin {
);
return '清理缓存成功。';
});
judgeCommand
.subcommand('.cleanzombie', '清理僵尸对局')
.usage('会清理所有没有开始的对局,统一设置为 0-0 平。')
.action(async ({ session }) => {
try {
const { tournament, matches } = await this.getZombieMatches();
if (!matches.length) {
return '未找到僵尸对局。';
}
await session.send(
`找到了 ${matches.length} 个僵尸对局:\n${matches
.map((m) => tournament.displayMatch(m))
.join('\n')}\n\n输入 yes 进行清理。`,
);
const reply = await session.prompt();
if (reply !== 'yes') {
return '清理被取消。';
}
await Promise.all(matches.map((m) => this.cleanZombieMatch(m)));
return `清理成功,清理了 ${matches.length} 个僵尸对局。`;
} catch (e) {
this.ctx
.logger('challonge')
.error(`Failed to clean zombie matches: ${e.toString()}`);
}
});
}
name = 'ygotournament-main';
......
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