Commit eb400dd2 authored by nanahira's avatar nanahira

add clear-participants and upload-ydk

parent d9fe1a1c
...@@ -28,7 +28,8 @@ ...@@ -28,7 +28,8 @@
"reflect-metadata": "^0.2.2", "reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",
"typeorm": "^0.3.22", "typeorm": "^0.3.22",
"yaml": "^2.7.1" "yaml": "^2.7.1",
"ygopro-deck-encode": "^1.0.6"
}, },
"devDependencies": { "devDependencies": {
"@eslint/eslintrc": "^3.2.0", "@eslint/eslintrc": "^3.2.0",
...@@ -38,14 +39,16 @@ ...@@ -38,14 +39,16 @@
"@nestjs/testing": "^11.0.1", "@nestjs/testing": "^11.0.1",
"@swc/cli": "^0.6.0", "@swc/cli": "^0.6.0",
"@swc/core": "^1.10.7", "@swc/core": "^1.10.7",
"@types/express": "^5.0.1", "@types/express": "^5.0.2",
"@types/jest": "^29.5.14", "@types/jest": "^29.5.14",
"@types/lodash": "^4.17.16", "@types/lodash": "^4.17.16",
"@types/multer": "^1.4.12",
"@types/node": "^22.10.7", "@types/node": "^22.10.7",
"@types/supertest": "^6.0.2", "@types/supertest": "^6.0.2",
"eslint": "^9.25.1", "eslint": "^9.25.1",
"eslint-config-prettier": "^10.0.1", "eslint-config-prettier": "^10.0.1",
"eslint-plugin-prettier": "^5.2.2", "eslint-plugin-prettier": "^5.2.2",
"express": "^5.1.0",
"globals": "^16.0.0", "globals": "^16.0.0",
"jest": "^29.7.0", "jest": "^29.7.0",
"prettier": "^3.4.2", "prettier": "^3.4.2",
...@@ -3317,9 +3320,9 @@ ...@@ -3317,9 +3320,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/express": { "node_modules/@types/express": {
"version": "5.0.1", "version": "5.0.2",
"resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.1.tgz", "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.2.tgz",
"integrity": "sha512-UZUw8vjpWFXuDnjFTh7/5c2TWDlQqeXHi6hcN7F2XSVT5P+WmUnnbFS3KA6Jnc6IsEqI2qCVu2bK0R0J4A8ZQQ==", "integrity": "sha512-BtjL3ZwbCQriyb0DGw+Rt12qAXPiBTPs815lsUvtt1Grk0vLRMZNMUZ741d5rjk+UQOxfDiBZ3dxpX00vSkK3g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
...@@ -3431,6 +3434,16 @@ ...@@ -3431,6 +3434,16 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/multer": {
"version": "1.4.12",
"resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.12.tgz",
"integrity": "sha512-pQ2hoqvXiJt2FP9WQVLPRO+AmiIm/ZYkavPlIQnx282u4ZrVdztx0pkh3jjpQt0Kz+YI0YhSG264y08UJKoUQg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/express": "*"
}
},
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "22.14.1", "version": "22.14.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz",
...@@ -12551,6 +12564,12 @@ ...@@ -12551,6 +12564,12 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/ygopro-deck-encode": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/ygopro-deck-encode/-/ygopro-deck-encode-1.0.6.tgz",
"integrity": "sha512-oG86JI1So7zIVmgXujGPHay95sl2zDF24W2DVVTxnnmxzi0JMmq1AkBuR7B74Ofx/vpuvLe60OzrprbXtM+LwQ==",
"license": "MIT"
},
"node_modules/yn": { "node_modules/yn": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
......
import { ApiProperty } from '@nestjs/swagger';
export class FilesUploadDto {
@ApiProperty({ type: 'array', items: { type: 'string', format: 'binary' } })
files: any[];
}
import { Controller, HttpCode, Post } from '@nestjs/common'; import {
Controller,
HttpCode,
Post,
UploadedFiles,
UseInterceptors,
} from '@nestjs/common';
import { TournamentService } from './tournament.service'; import { TournamentService } from './tournament.service';
import { ApiError, BlankReturnMessageDto, RestfulFactory } from 'nicot'; import { ApiError, BlankReturnMessageDto, RestfulFactory } from 'nicot';
import { Tournament } from './entities/Tournament.entity'; import { Tournament } from './entities/Tournament.entity';
import { ApiMycardUser, MycardUser, PutMycardUser } from 'nestjs-mycard'; import { ApiMycardUser, MycardUser, PutMycardUser } from 'nestjs-mycard';
import { import {
ApiBody,
ApiConsumes,
ApiOkResponse, ApiOkResponse,
ApiOperation, ApiOperation,
ApiParam, ApiParam,
ApiTags, ApiTags,
} from '@nestjs/swagger'; } from '@nestjs/swagger';
import { FilesUploadDto } from '../dto/file-upload.dto';
import { Participant } from '../participant/entities/participant.entity';
import { ParticipantService } from '../participant/participant.service';
import { FilesInterceptor } from '@nestjs/platform-express';
import { multerToParticipant } from '../utility/multer-to-participant';
const factory = new RestfulFactory(Tournament, { const factory = new RestfulFactory(Tournament, {
relations: [ relations: [
...@@ -43,7 +56,10 @@ class UpdateTournamentDto extends factory.updateDto {} ...@@ -43,7 +56,10 @@ class UpdateTournamentDto extends factory.updateDto {}
@ApiError(404, '相关资源未找到') @ApiError(404, '相关资源未找到')
@ApiError(403, '无法操作,弹 Toast 即可') @ApiError(403, '无法操作,弹 Toast 即可')
export class TournamentController { export class TournamentController {
constructor(private readonly tournamentService: TournamentService) {} constructor(
private readonly tournamentService: TournamentService,
private readonly participantService: ParticipantService,
) {}
@factory.create() @factory.create()
async create( async create(
...@@ -121,4 +137,40 @@ export class TournamentController { ...@@ -121,4 +137,40 @@ export class TournamentController {
) { ) {
return this.tournamentService.endTournament(id, user); return this.tournamentService.endTournament(id, user);
} }
@Post(':id/clear-participants')
@HttpCode(200)
@ApiOperation({ summary: '清空比赛选手' })
@ApiParam({ name: 'id', description: 'Tournament ID' })
@ApiOkResponse({ type: BlankReturnMessageDto })
async clearParticipants(
@factory.idParam() id: number,
@PutMycardUser() user: MycardUser,
) {
return this.tournamentService.clearTournamentParticipants(id, user);
}
@Post(':id/upload-ydk')
@HttpCode(200)
@ApiConsumes('multipart/form-data')
@ApiOperation({ summary: '上传 YDK 文件(创建选手)' })
@ApiParam({ name: 'id', description: 'Tournament ID' })
@ApiBody({
type: FilesUploadDto,
})
@ApiOkResponse({
type: new RestfulFactory(Participant, {
relations: [],
}).importReturnMessageDto,
})
@UseInterceptors(FilesInterceptor('files'))
async uploadYdk(
@factory.idParam() id: number,
@PutMycardUser() user: MycardUser,
@UploadedFiles() files: Array<Express.Multer.File>,
) {
return this.participantService.importParticipants(
files.map((f) => multerToParticipant(f, id)),
user,
);
}
} }
import { Participant } from '../participant/entities/participant.entity';
import YGOProDeck from 'ygopro-deck-encode';
export const multerToParticipant = (
multerFile: Express.Multer.File,
tournamentId: number,
) => {
const participant = new Participant();
participant.quit = false;
participant.name = multerFile.originalname.replace(/(\.ydk)+$/i, '');
participant.tournamentId = tournamentId;
participant.deckbuf = Buffer.from(
YGOProDeck.fromYdkString(
multerFile.buffer.toString('utf-8'),
).toUpdateDeckPayload(),
).toString('base64');
return participant;
};
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