1
- import type { ReactNode } from "react"
2
1
import React from "react"
3
- import { CheckCircle2 , Loader2 , MinusCircleIcon , XCircle } from "lucide-react"
4
2
5
- import type { PlayerGameSession } from "~/lib/games/types"
6
- import { type ProgrammingQuestionWithTestCases } from "~/lib/games/types"
3
+ import type { ClientQuestionStrategy } from "~/lib/games/question-types/base"
7
4
import { api } from "~/lib/trpc/react"
8
5
import { Skeleton } from "../ui/skeleton"
9
6
import { useGameManager } from "./GameManagerProvider"
10
7
11
- function QuestionTestCaseResults ( props : {
12
- question : ProgrammingQuestionWithTestCases
13
- testState : PlayerGameSession [ "testState" ]
14
- } ) {
15
- const testResultByTestCaseId = Object . fromEntries (
16
- props . testState ?. programmingResults . map ( ( result ) => [
17
- `${ result . programming_question_test_case_id } ` ,
18
- result ,
19
- ] ) ?? [ ] ,
20
- )
21
-
22
- const correctTestCases = props . question . programmingQuestion . testCases . filter ( ( tc ) => {
23
- const result = testResultByTestCaseId [ tc . id ]
24
- return result ?. status === "success" && result . is_correct
25
- } )
26
-
27
- const incorrectTestCases = props . question . programmingQuestion . testCases . filter ( ( tc ) => {
28
- const result = testResultByTestCaseId [ tc . id ]
29
- return result && ( result . status === "error" || ! result . is_correct )
30
- } )
31
-
32
- const unsubmittedTestCases = props . question . programmingQuestion . testCases . filter ( ( tc ) => {
33
- return ! testResultByTestCaseId [ tc . id ]
34
- } )
35
-
36
- const sortedTestCases = [ ...unsubmittedTestCases , ...incorrectTestCases , ...correctTestCases ]
37
-
38
- return (
39
- < div className = "flex flex-col space-y-6 text-sm" >
40
- { sortedTestCases . map ( ( testCase , i ) => {
41
- const result = props . testState ?. programmingResults . find (
42
- ( result ) => result . programming_question_test_case_id === testCase . id ,
43
- )
44
-
45
- let testEmoji : ReactNode
46
- if ( props . testState ?. status === "running" ) {
47
- testEmoji = (
48
- < span title = "Running test" >
49
- < Loader2 className = "animate-spin sq-6" />
50
- </ span >
51
- )
52
- } else if ( result ) {
53
- testEmoji = (
54
- < span title = { result . status === "success" ? "Test passed" : "Test failed" } >
55
- { result . status === "success" && result . is_correct ? (
56
- < CheckCircle2 className = "s q-6 rounded-full bg-primary text-black" />
57
- ) : (
58
- < XCircle className = "rounded-full bg-red-500 text-black sq-6" />
59
- ) }
60
- </ span >
61
- )
62
- } else {
63
- testEmoji = (
64
- < span className = "grayscale" title = "No tests run" >
65
- < MinusCircleIcon className = "rounded-full bg-primary text-black sq-6" />
66
- </ span >
67
- )
68
- }
69
- return (
70
- < div key = { i } className = "whitespace-pre-wrap font-mono" >
71
- < div className = "flex items-center gap-2" >
72
- < span className = "justify-self-center" > { testEmoji } </ span >
73
- < span >
74
- solution({ testCase . args . map ( ( a ) => JSON . stringify ( a ) ) . join ( ", " ) } ) =={ " " }
75
- { JSON . stringify ( testCase . expectedOutput ) }
76
- </ span >
77
- </ div >
78
- { result ?. status === "success" && ! result . is_correct && (
79
- < div className = "mt-3 whitespace-pre-wrap rounded-xl bg-red-500/20 p-4 text-red-500 bg-blend-color-burn" >
80
- Output: { JSON . stringify ( result . result ) }
81
- </ div >
82
- ) }
83
- { result ?. status === "error" && (
84
- < div className = "mt-3 whitespace-pre-wrap rounded-xl bg-red-500/20 p-4 text-red-500 bg-blend-color-burn" >
85
- { result . reason }
86
- </ div >
87
- ) }
88
- </ div >
89
- )
90
- } ) }
91
- </ div >
92
- )
93
- }
94
-
95
- export default function CodeRunning ( ) {
96
- const { gameInfo, gameSessionInfo, submitCodeMutation } = useGameManager ( )
8
+ export default function CodeRunning ( props : { questionStrategy : ClientQuestionStrategy } ) {
9
+ const { gameSessionInfo, submitCodeMutation } = useGameManager ( )
97
10
const submisisonMetricsQuery = api . games . getSubmissionMetrics . useQuery ( {
98
11
game_id : gameSessionInfo . game_id ,
99
12
} )
@@ -107,10 +20,7 @@ export default function CodeRunning() {
107
20
< div className = "relative flex flex-col" >
108
21
< div className = "flex-1" >
109
22
< div className = "mb-4 flex items-center pb-2" >
110
- < h3 className = "flex-1 text-left text-lg font-bold" >
111
- Test
112
- < br /> Cases
113
- </ h3 >
23
+ < h3 className = "flex-1 text-left text-lg font-bold" > Results</ h3 >
114
24
< p className = "text-right text-xs opacity-50" >
115
25
{ gameSessionInfo . submission_state_id ? (
116
26
< >
@@ -146,12 +56,7 @@ export default function CodeRunning() {
146
56
) }
147
57
</ p >
148
58
</ div >
149
- { gameInfo . question ?. programmingQuestion ? (
150
- < QuestionTestCaseResults
151
- question = { gameInfo . question }
152
- testState = { gameSessionInfo . testState }
153
- />
154
- ) : null }
59
+ { props . questionStrategy . results ( gameSessionInfo . testState ) }
155
60
</ div >
156
61
</ div >
157
62
)
0 commit comments