Skip to content

Commit

Permalink
feat(be): add admin submission module (#1924)
Browse files Browse the repository at this point in the history
* feat(be): add admin submission module

* feat(be): use user-ip

* chore(be): handle exceptions

* fix(be): add type

* fix(be): typo

* fix(be): rename into getcontestsubmissions

---------

Co-authored-by: Jimin Ha <[email protected]>
  • Loading branch information
Jaehyeon1020 and jimin9038 authored Aug 19, 2024
1 parent 2ac9786 commit 46525d8
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 0 deletions.
2 changes: 2 additions & 0 deletions apps/backend/apps/admin/src/admin.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { ContestModule } from './contest/contest.module'
import { GroupModule } from './group/group.module'
import { ProblemModule } from './problem/problem.module'
import { StorageModule } from './storage/storage.module'
import { SubmissionModule } from './submission/submission.module'
import { UserModule } from './user/user.module'

@Module({
Expand Down Expand Up @@ -55,6 +56,7 @@ import { UserModule } from './user/user.module'
UserModule,
AnnouncementModule,
NoticeModule,
SubmissionModule,
LoggerModule.forRoot(pinoLoggerModuleOption)
],
controllers: [AdminController],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Field, Int, ObjectType } from '@nestjs/graphql'
import { Language, ResultStatus } from '@admin/@generated'

@ObjectType({ description: 'contestSubmissionOverall' })
export class ContestSubmission {
@Field(() => String, { nullable: false })
title!: string // 문제 title

@Field(() => String, { nullable: false })
studentId!: string // 학번

@Field(() => String, { nullable: true })
realname?: string // 실명

@Field(() => String, { nullable: false })
username!: string

@Field(() => ResultStatus, { nullable: false })
result!: ResultStatus // Accepted, WrongAnswer ...

@Field(() => Language, { nullable: false })
language!: Language

@Field(() => String, { nullable: false })
submissionTime!: Date // 제출 시각

@Field(() => Int, { nullable: true })
codeSize: number | null

@Field(() => String, { nullable: true })
ip: string | null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Field, InputType, Int } from '@nestjs/graphql'

@InputType()
export class GetContestSubmissionsInput {
@Field(() => Int, { nullable: false })
contestId!: number

@Field(() => Int, { nullable: true })
problemId?: number
}
8 changes: 8 additions & 0 deletions apps/backend/apps/admin/src/submission/submission.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Module } from '@nestjs/common'
import { SubmissionResolver } from './submission.resolver'
import { SubmissionService } from './submission.service'

@Module({
providers: [SubmissionResolver, SubmissionService]
})
export class SubmissionModule {}
37 changes: 37 additions & 0 deletions apps/backend/apps/admin/src/submission/submission.resolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { InternalServerErrorException, Logger } from '@nestjs/common'
import { Args, Int, Query, Resolver } from '@nestjs/graphql'
import { CursorValidationPipe } from '@libs/pipe'
import { Submission } from '@admin/@generated'
import { ContestSubmission } from './model/contest-submission.model'
import { GetContestSubmissionsInput } from './model/get-contest-submission.input'
import { SubmissionService } from './submission.service'

@Resolver(() => Submission)
export class SubmissionResolver {
private readonly logger = new Logger(SubmissionResolver.name)
constructor(private readonly submissionService: SubmissionService) {}

@Query(() => [ContestSubmission])
async getContestSubmissions(
@Args('input', {
nullable: false,
type: () => GetContestSubmissionsInput
})
input: GetContestSubmissionsInput,
@Args('cursor', { nullable: true, type: () => Int }, CursorValidationPipe)
cursor: number | null,
@Args('take', { nullable: true, defaultValue: 10, type: () => Int })
take: number
): Promise<ContestSubmission[]> {
try {
return await this.submissionService.getContestSubmissions(
input,
take,
cursor
)
} catch (error) {
this.logger.error(error.error)
throw new InternalServerErrorException()
}
}
}
62 changes: 62 additions & 0 deletions apps/backend/apps/admin/src/submission/submission.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Injectable } from '@nestjs/common'
import { PrismaService } from '@libs/prisma'
import type { Language, ResultStatus } from '@admin/@generated'
import type { GetContestSubmissionsInput } from './model/get-contest-submission.input'

@Injectable()
export class SubmissionService {
constructor(private readonly prisma: PrismaService) {}

async getContestSubmissions(
input: GetContestSubmissionsInput,
take: number,
cursor: number | null
) {
const paginator = this.prisma.getPaginator(cursor)

const { contestId, problemId } = input
const contestSubmissions = await this.prisma.submission.findMany({
...paginator,
take,
where: {
contestId,
problemId
},
include: {
user: {
select: {
id: true,
username: true,
studentId: true,
userProfile: {
select: {
realName: true
}
}
}
},
problem: {
select: {
title: true
}
}
}
})

const results = contestSubmissions.map((c) => {
return {
title: c.problem.title,
studentId: c.user?.studentId ?? 'Unknown',
realname: c.user?.userProfile?.realName ?? 'Unknown',
username: c.user?.username ?? 'Unknown',
result: c.result as ResultStatus,
language: c.language as Language,
submissionTime: c.createTime,
codeSize: c.codeSize ?? null,
ip: c.userIp ?? 'Unknown'
}
})

return results
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
meta {
name: Succeed
type: graphql
seq: 1
}

post {
url: {{gqlUrl}}
body: graphql
auth: none
}

body:graphql {
query GetContestSubmissions(
$input: GetContestSubmissionsInput!,
$cursor: Int,
$take: Int
) {
getContestSubmissions(
input: $input,
cursor: $cursor,
take: $take
) {
title
studentId
realname
username
result
language
submissionTime
codeSize
ip
}
}
}

body:graphql:vars {
{
"input": {
"contestId": 1
},
"take": 10
}
}

0 comments on commit 46525d8

Please sign in to comment.