Skip to content

Commit

Permalink
fix: fix minor bugs in contest page and api (#1349)
Browse files Browse the repository at this point in the history
* fix(be): return contest problems in order

* fix(be): connect announcement to contest

* fix(be): get announcements by contest id

* test(be): add missing test for announcement controller

* fix(fe): show related problem in announcement page

* 연결된 problem이 존재할 경우 problem id를 표시합니다.
* announcement 작성 시각을 분 단위까지만 표기합니다.

* fix(fe): show alphabetical problem id in contest problem list

* fix(fe): rename clarification into announcement

* chore(fe): show accepted rate with fixing-point notation of two digits

* feat(fe): remove card list if no data is found
  • Loading branch information
aintbe authored Feb 15, 2024
1 parent aaaeb15 commit 199d457
Show file tree
Hide file tree
Showing 23 changed files with 208 additions and 229 deletions.
18 changes: 8 additions & 10 deletions backend/apps/admin/src/problem/problem.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -550,20 +550,18 @@ export class ProblemService {
where: { id: contestId, groupId }
})

const contestProblemsToBeUpdated =
await this.prisma.contestProblem.findMany({
where: { contestId }
})
const contestProblems = await this.prisma.contestProblem.findMany({
where: { contestId }
})

if (orders.length !== contestProblemsToBeUpdated.length) {
if (orders.length !== contestProblems.length) {
throw new UnprocessableDataException(
'the len of orders and the len of contestProblem are not equal.'
'the length of orders and the length of contestProblem are not equal.'
)
}
//problemId 기준으로 오름차순 정렬
contestProblemsToBeUpdated.sort((a, b) => a.problemId - b.problemId)
const queries = contestProblemsToBeUpdated.map((record) => {
const newOrder = orders.indexOf(record.problemId) + 1

const queries = contestProblems.map((record) => {
const newOrder = orders.indexOf(record.problemId)
return this.prisma.contestProblem.update({
where: {
// eslint-disable-next-line @typescript-eslint/naming-convention
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Test, type TestingModule } from '@nestjs/testing'
import { expect } from 'chai'
import { RolesService } from '@libs/auth'
import { AnnouncementController } from './announcement.controller'
import { AnnouncementService } from './announcement.service'

describe('AnnouncementController', () => {
let controller: AnnouncementController

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [AnnouncementController],
providers: [
{ provide: AnnouncementService, useValue: {} },
{ provide: RolesService, useValue: {} }
]
}).compile()

controller = module.get<AnnouncementController>(AnnouncementController)
})

it('should be defined', () => {
expect(controller).to.be.ok
})
})
13 changes: 5 additions & 8 deletions backend/apps/client/src/announcement/announcement.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ import {
Get,
Logger,
InternalServerErrorException,
Query,
BadRequestException
Query
} from '@nestjs/common'
import { AuthNotNeededIfOpenSpace } from '@libs/auth'
import { EntityNotExistException } from '@libs/exception'
import { GroupIDPipe, IDValidationPipe } from '@libs/pipe'
import { GroupIDPipe, IDValidationPipe, RequiredIntPipe } from '@libs/pipe'
import { AnnouncementService } from './announcement.service'

@Controller('announcement')
Expand All @@ -21,16 +20,17 @@ export class AnnouncementController {
@Get()
async getAnnouncements(
@Query('problemId', IDValidationPipe) problemId: number | null,
@Query('contestId', IDValidationPipe) contestId: number | null,
@Query('contestId', RequiredIntPipe) contestId: number,
@Query('groupId', GroupIDPipe) groupId: number
) {
try {
if (problemId) {
return await this.announcementService.getProblemAnnouncements(
problemId,
contestId,
groupId
)
} else if (contestId) {
} else {
return await this.announcementService.getContestAnnouncements(
contestId,
groupId
Expand All @@ -43,8 +43,5 @@ export class AnnouncementController {
this.logger.error(error)
throw new InternalServerErrorException()
}
throw new BadRequestException(
'Both problemId and contestId are not entered'
)
}
}
126 changes: 18 additions & 108 deletions backend/apps/client/src/announcement/announcement.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,126 +24,36 @@ describe('AnnouncementService', () => {

describe('getProblemAnnouncements', () => {
it('should return problem announcements', async () => {
const res = await service.getProblemAnnouncements(1, 1)
const res = await service.getProblemAnnouncements(1, 1, 1)
expect(res)
.excluding(['createTime', 'updateTime'])
.excluding(['createTime', 'updateTime', 'content'])
.to.deep.equal([
{
id: 6,
content: 'Announcement_1_0',
problemId: 1,
createTime: '2024-01-17T06:44:33.211Z',
updateTime: '2024-01-17T06:44:33.211Z'
},
{
id: 1,
content: 'Announcement_0_0',
problemId: 1,
createTime: '2024-01-17T06:44:33.207Z',
updateTime: '2024-01-17T06:44:33.207Z'
contestId: 1,
problemId: 1
}
])
})

it('should return empty array when the problem announcement does not exist', async () => {
const res = await service.getProblemAnnouncements(100, 2)
expect(res).to.deep.equal([])
})
})

describe('getContestAnnouncements', () => {
it('should return multiple contest announcements', async () => {
/*
pnpm test 실행 전 prisma migrate reset 실행하며 새롭게 seeding됨
이 과정에서 Announcement간 순서 섞이기 때문에 정렬 후 비교 필요
*/
const res = (await service.getContestAnnouncements(1, 1)).sort((x, y) => {
return x.problemId - y.problemId
})

const res = await service.getContestAnnouncements(1, 1)
expect(res)
.excluding(['createTime', 'updateTime', 'id', 'content'])
.to.deep.equal(
[
{
id: 10,
content: 'Announcement_1_4',
problemId: 5,
createTime: '2024-01-26T09:39:30.978Z',
updateTime: '2024-01-26T09:39:30.978Z'
},
{
id: 6,
content: 'Announcement_1_0',
problemId: 1,
createTime: '2024-01-26T09:39:30.977Z',
updateTime: '2024-01-26T09:39:30.977Z'
},
{
id: 7,
content: 'Announcement_1_1',
problemId: 2,
createTime: '2024-01-26T09:39:30.977Z',
updateTime: '2024-01-26T09:39:30.977Z'
},
{
id: 8,
content: 'Announcement_1_2',
problemId: 3,
createTime: '2024-01-26T09:39:30.977Z',
updateTime: '2024-01-26T09:39:30.977Z'
},
{
id: 9,
content: 'Announcement_1_3',
problemId: 4,
createTime: '2024-01-26T09:39:30.977Z',
updateTime: '2024-01-26T09:39:30.977Z'
},
{
id: 3,
content: 'Announcement_0_2',
problemId: 3,
createTime: '2024-01-26T09:39:30.976Z',
updateTime: '2024-01-26T09:39:30.976Z'
},
{
id: 4,
content: 'Announcement_0_3',
problemId: 4,
createTime: '2024-01-26T09:39:30.976Z',
updateTime: '2024-01-26T09:39:30.976Z'
},
{
id: 5,
content: 'Announcement_0_4',
problemId: 5,
createTime: '2024-01-26T09:39:30.976Z',
updateTime: '2024-01-26T09:39:30.976Z'
},
{
id: 1,
content: 'Announcement_0_0',
problemId: 1,
createTime: '2024-01-26T09:39:30.975Z',
updateTime: '2024-01-26T09:39:30.975Z'
},
{
id: 2,
content: 'Announcement_0_1',
problemId: 2,
createTime: '2024-01-26T09:39:30.975Z',
updateTime: '2024-01-26T09:39:30.975Z'
}
].sort((x, y) => {
return x.problemId - y.problemId
})
)
})

it('should return empty array when the contest announcement does not exist', async () => {
const res = await service.getContestAnnouncements(99999, 1)
expect(res).to.deep.equal([])
.excluding(['createTime', 'updateTime', 'content'])
.to.deep.equal([
{
id: 6,
contestId: 1,
problemId: 0
},
{
id: 1,
contestId: 1,
problemId: null
}
])
})
})
})
47 changes: 27 additions & 20 deletions backend/apps/client/src/announcement/announcement.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,48 @@ import { PrismaService } from '@libs/prisma'
export class AnnouncementService {
constructor(private readonly prisma: PrismaService) {}

async getProblemAnnouncements(
problemId: number,
async getContestAnnouncements(
contestId: number,
groupId: number
): Promise<Announcement[]> {
const result = await this.prisma.announcement.findMany({
where: {
problem: {
id: problemId,
const { contestProblem, announcement } =
await this.prisma.contest.findUniqueOrThrow({
where: {
id: contestId,
groupId
},
select: {
contestProblem: true,
announcement: {
orderBy: { updateTime: 'desc' }
}
}
},
orderBy: { updateTime: 'desc' }
})
})

return result
return announcement.map((announcement) => {
if (announcement.problemId !== null) {
announcement.problemId = contestProblem.find(
(problem) => announcement.problemId === problem.problemId
)!.order
}
return announcement
})
}

async getContestAnnouncements(
async getProblemAnnouncements(
contestId: number,
problemId: number,
groupId: number
): Promise<Announcement[]> {
const result = await this.prisma.announcement.findMany({
return await this.prisma.announcement.findMany({
where: {
problem: {
contestProblem: {
some: {
contestId
}
},
problemId,
contest: {
id: contestId,
groupId
}
},
orderBy: { updateTime: 'desc' }
})

return result
}
}
1 change: 1 addition & 0 deletions backend/apps/client/src/problem/problem.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ export class ProblemRepository {
return await this.prisma.contestProblem.findMany({
...paginator,
take,
orderBy: { order: 'asc' },
where: {
contestId,
problem: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
Warnings:
- Added the required column `contest_id` to the `announcement` table without a default value. This is not possible if the table is not empty.
*/
-- DropForeignKey
ALTER TABLE "announcement" DROP CONSTRAINT "announcement_problem_id_fkey";

-- AlterTable
ALTER TABLE "announcement" ADD COLUMN "contest_id" INTEGER NOT NULL,
ALTER COLUMN "problem_id" DROP NOT NULL;

-- AddForeignKey
ALTER TABLE "announcement" ADD CONSTRAINT "announcement_contest_id_fkey" FOREIGN KEY ("contest_id") REFERENCES "contest"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "announcement" ADD CONSTRAINT "announcement_problem_id_fkey" FOREIGN KEY ("problem_id") REFERENCES "problem"("id") ON DELETE SET NULL ON UPDATE CASCADE;
10 changes: 6 additions & 4 deletions backend/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ model Problem {
workbookProblem WorkbookProblem[]
submission Submission[]
announcement Announcement[]
CodeDraft CodeDraft[]
codeDraft CodeDraft[]
@@map("problem")
}
Expand Down Expand Up @@ -259,7 +259,7 @@ model Contest {
contestProblem ContestProblem[]
contestRecord ContestRecord[]
submission Submission[]
// contestAnnouncement ContestAnnouncement[]
announcement Announcement[]
@@map("contest")
}
Expand All @@ -282,8 +282,10 @@ model ContestProblem {
model Announcement {
id Int @id @default(autoincrement())
content String
problem Problem @relation(fields: [problemId], references: [id])
problemId Int @map("problem_id")
contest Contest @relation(fields: [contestId], references: [id])
contestId Int @map("contest_id")
problem Problem? @relation(fields: [problemId], references: [id])
problemId Int? @map("problem_id")
createTime DateTime @default(now()) @map("create_time")
updateTime DateTime @updatedAt @map("update_time")
Expand Down
Loading

0 comments on commit 199d457

Please sign in to comment.