Skip to content

Commit

Permalink
289 fix ranking api not working (#291)
Browse files Browse the repository at this point in the history
* querybuilder를 이용한, 제대로 된 ranking api 구현, 버그 수정 완료. 아직은 미완성

* filter out duplicate AC submissions
  • Loading branch information
vimkim authored Mar 14, 2024
1 parent b29dd94 commit 9eee0c4
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 2 deletions.
5 changes: 4 additions & 1 deletion server/src/entities/submission.entity.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Status } from '../const/boj-results';
import {
BaseEntity,
Column,
Entity,
ManyToOne,
PrimaryGeneratedColumn,
} from 'typeorm';
import { Status } from '../const/boj-results';
import Problem from './problem.entity';
import Room from './room.entity';
import User from './user.entity';
Expand Down Expand Up @@ -37,4 +37,7 @@ export default class Submission extends BaseEntity {

@ManyToOne(() => Problem, (problem) => problem.submissions, { cascade: true })
problem?: Problem;

@Column()
alreadyAccepted!: boolean;
}
7 changes: 7 additions & 0 deletions server/src/room/room-code/room-code.pipe.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { RoomCodePipe } from './room-code.pipe';

describe('RoomCodePipe', () => {
it('should be defined', () => {
expect(new RoomCodePipe()).toBeDefined();
});
});
19 changes: 19 additions & 0 deletions server/src/room/room-code/room-code.pipe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {
ArgumentMetadata,
BadRequestException,
Injectable,
PipeTransform,
} from '@nestjs/common';

@Injectable()
export class RoomCodePipe implements PipeTransform {
transform(value: any, _metadata: ArgumentMetadata) {
const hexRegExp = /^[0-9a-fA-F]{6}$/;

if (!hexRegExp.test(value)) {
throw new BadRequestException('Invalid room code');
}

return value;
}
}
7 changes: 7 additions & 0 deletions server/src/room/room.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Request } from 'express';
import { SessionAuthGuard } from '../auth/auth.guard';
import User from '../entities/user.entity';
import { RoomUserService } from '../room-user/room-user.service';
import { RoomCodePipe } from './room-code/room-code.pipe';
import { RoomService } from './room.service';

@Controller('room')
Expand Down Expand Up @@ -69,4 +70,10 @@ export class RoomController {
async getRoomUsers(@Param('code') code: string) {
return await this.roomUserService.findUsersByRoomCode(code);
}

@Get('/:code/rankings')
@HttpCode(HttpStatus.OK)
async getRoomRankings(@Param('code', RoomCodePipe) code: string) {
return await this.roomService.getRoomRankings(code);
}
}
36 changes: 35 additions & 1 deletion server/src/room/room.service.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import {
BadRequestException,
forwardRef,
Inject,
Injectable,
InternalServerErrorException,
Logger,
forwardRef,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import * as crypto from 'crypto';
import { isNil } from 'src/common/utils';
import { SubmissionService } from 'src/submission/submission.service';
import { Repository } from 'typeorm';
import { Status } from '../const/boj-results';
import Room from '../entities/room.entity';
import Submission from '../entities/submission.entity';
import User from '../entities/user.entity';
import RoomUser from '../room-user/room-user.entity';
import { RoomUserService } from '../room-user/room-user.service';
Expand Down Expand Up @@ -130,4 +132,36 @@ export class RoomService {
}
return room;
}

/**
* returns an array of user id, username, and the number of accepted problems of the user, sorted by the number of accepted problems
* @param code
*/
async getRoomRankings(code: string) {
Submission;
User;
const qb = this.roomRepository
.createQueryBuilder('room')
.where('room.code = :code', { code })
.innerJoin('room.joinedUsers', 'roomUser')
.innerJoin('roomUser.user', 'user')
.innerJoin(
'room.submissions',
'submission',
'submission.status = :status AND submission.user_id = user.id AND submission.alreadyAccepted = false',
{
status: Status.ACCEPTED,
},
)
.select('user.id', 'userId')
.addSelect('user.username', 'username')
.addSelect('COUNT(submission.id)', 'acceptedCount')
.addSelect('MAX(submission.submittedAt)', 'lastAcceptedAt')
.groupBy('user.id')
.orderBy('acceptedCount', 'DESC')
.addOrderBy('lastAcceptedAt', 'ASC');

const data = await qb.getRawMany();
return { data };
}
}
10 changes: 10 additions & 0 deletions server/src/submission/submission.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,23 @@ export class SubmissionService {
status,
);

const alreadyAccepted = await this.submissionRepository.exist({
where: {
user: { id: user.id },
problem: { id: problem.id },
room: { id: room.id },
status: Status.ACCEPTED,
},
});

return await this.submissionRepository
.create({
status,
user,
room,
problem,
submittedAt,
alreadyAccepted,
})
.save();
}
Expand Down

0 comments on commit 9eee0c4

Please sign in to comment.