Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(be): add admin submission module #1924

Merged
merged 11 commits into from
Aug 19, 2024
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 ContestSubmissionOverall {
@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 GetContestSubmissionOverallInput {
@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 { ContestSubmissionOverall } from './model/contest-submission-overall.model'
import { GetContestSubmissionOverallInput } from './model/get-contest-submission-overall.input'
import { SubmissionService } from './submission.service'

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

@Query(() => [ContestSubmissionOverall])
async getContestSubmissionOveralls(
@Args('input', {
nullable: false,
type: () => GetContestSubmissionOverallInput
})
input: GetContestSubmissionOverallInput,
@Args('cursor', { nullable: true, type: () => Int }, CursorValidationPipe)
cursor: number | null,
@Args('take', { nullable: true, defaultValue: 10, type: () => Int })
take: number
): Promise<ContestSubmissionOverall[]> {
try {
return await this.submissionService.getContestSubmissionOveralls(
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 { GetContestSubmissionOverallInput } from './model/get-contest-submission-overall.input'

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

async getContestSubmissionOveralls(
input: GetContestSubmissionOverallInput,
take: number,
cursor: number | null
) {
const pagenator = this.prisma.getPaginator(cursor)
jimin9038 marked this conversation as resolved.
Show resolved Hide resolved

const { contestId, problemId } = input
const contestSubmissions = await this.prisma.submission.findMany({
...pagenator,
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 as string,
realname: c.user?.userProfile?.realName as string,
username: c.user?.username as string,
result: c.result as ResultStatus,
language: c.language as Language,
submissionTime: c.createTime,
codeSize: c.codeSize ?? null,
ip: c.userIp
}
})

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 GetContestSubmissionSummaries(
$input: GetContestSubmissionSummaryInput!,
$cursor: Int,
$take: Int
) {
getContestSubmissionSummaries(
input: $input,
cursor: $cursor,
take: $take
) {
title
studentId
realname
username
result
language
submissionTime
codeSize
ip
}
}
}

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