diff --git a/app/(app)/challenges/[id]/_components/header/index.tsx b/app/(app)/challenges/[id]/_components/header/index.tsx index 2835939..60eb82a 100644 --- a/app/(app)/challenges/[id]/_components/header/index.tsx +++ b/app/(app)/challenges/[id]/_components/header/index.tsx @@ -1,8 +1,10 @@ "use client"; +import ColoredRate from "@/components/colored-rate"; import DifficultyBadge from "@/components/question/difficulty-badge"; import SolvedStatusBadge from "@/components/question/solved-status-badge"; import { Badge } from "@/components/ui/badge"; +import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; import { graphql } from "@/gql"; import { getQuestionSolvedStatus } from "@/lib/solved-status"; import { useSuspenseQuery } from "@apollo/client/react"; @@ -15,6 +17,13 @@ export const QUESTION_HEADER = graphql(` difficulty category + statistics { + passedUsers + attemptedUsers + correctSubmissionCount + submissionCount + } + ...QuestionSolvedStatus } } @@ -22,7 +31,12 @@ export const QUESTION_HEADER = graphql(` export default function Header({ id }: { id: string }) { const { data } = useSuspenseQuery(QUESTION_HEADER, { variables: { id } }); - const { title, difficulty, category } = data.question; + const { title, difficulty, category, statistics } = data.question; + + const passedRate = statistics.attemptedUsers ? statistics.passedUsers / statistics.attemptedUsers : 0; + const correctSubmissionRate = statistics.submissionCount + ? statistics.correctSubmissionCount / statistics.submissionCount + : 0; const solvedStatus = getQuestionSolvedStatus(data.question); @@ -30,14 +44,44 @@ export default function Header({ id }: { id: string }) {
{/* Header */}
-
{title}
-
+
+ {title} +
+
{category}
+ +
+ + + + 通過率 + + + + 共有 {statistics.attemptedUsers} 人嘗試這題,其中 {statistics.passedUsers} 人通過。 + + + + + + + 正確率 + + + + 共有 {statistics.submissionCount} 次提交,其中 {statistics.correctSubmissionCount} 次正確。 + + +
); } + +function Separator() { + return
; +} diff --git a/components/colored-rate.tsx b/components/colored-rate.tsx new file mode 100644 index 0000000..5661f89 --- /dev/null +++ b/components/colored-rate.tsx @@ -0,0 +1,24 @@ +import { cn } from "@/lib/utils"; + +export interface ColoredRateProps extends React.ComponentPropsWithoutRef<"span"> { + rate: number; // float +} + +export default function ColoredRate({ + rate, + className, + ...props +}: ColoredRateProps) { + const color = rate > 0.8 + ? "text-green-800" + : rate > 0.5 + ? "text-yellow-800" + : "text-red-800"; + const roundedRate = Math.round(rate * 100); + + return ( + + {roundedRate}% + + ); +} diff --git a/components/question/question-card.tsx b/components/question/question-card.tsx index 0b705ca..89a94ed 100644 --- a/components/question/question-card.tsx +++ b/components/question/question-card.tsx @@ -4,6 +4,7 @@ import { getQuestionSolvedStatus } from "@/lib/solved-status"; import { SwordIcon } from "lucide-react"; import Link from "next/link"; import { Remark } from "react-remark"; +import ColoredRate from "../colored-rate"; import DifficultyBadge from "./difficulty-badge"; import SolvedStatusBadge from "./solved-status-badge"; @@ -15,6 +16,11 @@ const QUESTION_CARD_FRAGMENT = graphql(` difficulty category + statistics { + passedUsers + attemptedUsers + } + ...QuestionSolvedStatus } `); @@ -28,6 +34,10 @@ export default function QuestionCard({ const descriptionFirstLine = question.description.split("\n")[0]; const solvedStatus = getQuestionSolvedStatus(question); + const passedRate = question.statistics.attemptedUsers + ? question.statistics.passedUsers / question.statistics.attemptedUsers + : 0; + return (
{/* Question Body */} @@ -42,6 +52,9 @@ export default function QuestionCard({ {question.category} + + 通過率 +
diff --git a/gql/gql.ts b/gql/gql.ts index 4c2a927..0c9a7bf 100644 --- a/gql/gql.ts +++ b/gql/gql.ts @@ -14,7 +14,7 @@ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document- * Learn more about it here: https://the-guild.dev/graphql/codegen/plugins/presets/preset-client#reducing-bundle-size */ type Documents = { - "\n query QuestionHeader($id: ID!) {\n question(id: $id) {\n id\n title\n difficulty\n category\n\n ...QuestionSolvedStatus\n }\n }\n": typeof types.QuestionHeaderDocument, + "\n query QuestionHeader($id: ID!) {\n question(id: $id) {\n id\n title\n difficulty\n category\n\n statistics {\n passedUsers\n attemptedUsers\n correctSubmissionCount\n submissionCount\n }\n\n ...QuestionSolvedStatus\n }\n }\n": typeof types.QuestionHeaderDocument, "\n query CompareAnswer($id: ID!) {\n question(id: $id) {\n id\n referenceAnswerResult {\n columns\n rows\n }\n lastSubmission {\n id\n status\n queryResult {\n columns\n rows\n }\n error\n }\n }\n }\n": typeof types.CompareAnswerDocument, "\n query CorrectAnswer($id: ID!) {\n question(id: $id) {\n id\n referenceAnswerResult {\n columns\n rows\n }\n }\n }\n": typeof types.CorrectAnswerDocument, "\n query DatabaseRelationship($id: ID!) {\n question(id: $id) {\n database {\n id\n slug\n relationFigure\n }\n }\n }\n": typeof types.DatabaseRelationshipDocument, @@ -40,12 +40,12 @@ type Documents = { "\n fragment QuestionInfoFragment on Question {\n id\n title\n description\n difficulty\n category\n }\n": typeof types.QuestionInfoFragmentFragmentDoc, "\n query UserAnswerResult($id: ID!) {\n question(id: $id) {\n id\n lastSubmission {\n id\n submittedCode\n status\n queryResult {\n columns\n rows\n }\n error\n }\n }\n }\n": typeof types.UserAnswerResultDocument, "\n query QuestionSchema($id: ID!) {\n question(id: $id) {\n id\n database {\n id\n structure {\n tables {\n columns\n name\n }\n }\n }\n }\n }": typeof types.QuestionSchemaDocument, - "\n fragment QuestionCard on Question {\n id\n title\n description\n difficulty\n category\n\n ...QuestionSolvedStatus\n }\n": typeof types.QuestionCardFragmentDoc, + "\n fragment QuestionCard on Question {\n id\n title\n description\n difficulty\n category\n\n statistics {\n passedUsers\n attemptedUsers\n }\n\n ...QuestionSolvedStatus\n }\n": typeof types.QuestionCardFragmentDoc, "\n fragment QuestionSolvedStatus on Question {\n solved\n attempted\n }\n": typeof types.QuestionSolvedStatusFragmentDoc, "\n query BasicUserInfo {\n me {\n id\n name\n email\n avatar\n\n group {\n name\n }\n }\n }\n": typeof types.BasicUserInfoDocument, }; const documents: Documents = { - "\n query QuestionHeader($id: ID!) {\n question(id: $id) {\n id\n title\n difficulty\n category\n\n ...QuestionSolvedStatus\n }\n }\n": types.QuestionHeaderDocument, + "\n query QuestionHeader($id: ID!) {\n question(id: $id) {\n id\n title\n difficulty\n category\n\n statistics {\n passedUsers\n attemptedUsers\n correctSubmissionCount\n submissionCount\n }\n\n ...QuestionSolvedStatus\n }\n }\n": types.QuestionHeaderDocument, "\n query CompareAnswer($id: ID!) {\n question(id: $id) {\n id\n referenceAnswerResult {\n columns\n rows\n }\n lastSubmission {\n id\n status\n queryResult {\n columns\n rows\n }\n error\n }\n }\n }\n": types.CompareAnswerDocument, "\n query CorrectAnswer($id: ID!) {\n question(id: $id) {\n id\n referenceAnswerResult {\n columns\n rows\n }\n }\n }\n": types.CorrectAnswerDocument, "\n query DatabaseRelationship($id: ID!) {\n question(id: $id) {\n database {\n id\n slug\n relationFigure\n }\n }\n }\n": types.DatabaseRelationshipDocument, @@ -71,7 +71,7 @@ const documents: Documents = { "\n fragment QuestionInfoFragment on Question {\n id\n title\n description\n difficulty\n category\n }\n": types.QuestionInfoFragmentFragmentDoc, "\n query UserAnswerResult($id: ID!) {\n question(id: $id) {\n id\n lastSubmission {\n id\n submittedCode\n status\n queryResult {\n columns\n rows\n }\n error\n }\n }\n }\n": types.UserAnswerResultDocument, "\n query QuestionSchema($id: ID!) {\n question(id: $id) {\n id\n database {\n id\n structure {\n tables {\n columns\n name\n }\n }\n }\n }\n }": types.QuestionSchemaDocument, - "\n fragment QuestionCard on Question {\n id\n title\n description\n difficulty\n category\n\n ...QuestionSolvedStatus\n }\n": types.QuestionCardFragmentDoc, + "\n fragment QuestionCard on Question {\n id\n title\n description\n difficulty\n category\n\n statistics {\n passedUsers\n attemptedUsers\n }\n\n ...QuestionSolvedStatus\n }\n": types.QuestionCardFragmentDoc, "\n fragment QuestionSolvedStatus on Question {\n solved\n attempted\n }\n": types.QuestionSolvedStatusFragmentDoc, "\n query BasicUserInfo {\n me {\n id\n name\n email\n avatar\n\n group {\n name\n }\n }\n }\n": types.BasicUserInfoDocument, }; @@ -93,7 +93,7 @@ export function graphql(source: string): unknown; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n query QuestionHeader($id: ID!) {\n question(id: $id) {\n id\n title\n difficulty\n category\n\n ...QuestionSolvedStatus\n }\n }\n"): (typeof documents)["\n query QuestionHeader($id: ID!) {\n question(id: $id) {\n id\n title\n difficulty\n category\n\n ...QuestionSolvedStatus\n }\n }\n"]; +export function graphql(source: "\n query QuestionHeader($id: ID!) {\n question(id: $id) {\n id\n title\n difficulty\n category\n\n statistics {\n passedUsers\n attemptedUsers\n correctSubmissionCount\n submissionCount\n }\n\n ...QuestionSolvedStatus\n }\n }\n"): (typeof documents)["\n query QuestionHeader($id: ID!) {\n question(id: $id) {\n id\n title\n difficulty\n category\n\n statistics {\n passedUsers\n attemptedUsers\n correctSubmissionCount\n submissionCount\n }\n\n ...QuestionSolvedStatus\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ @@ -197,7 +197,7 @@ export function graphql(source: "\n query QuestionSchema($id: ID!) {\n quest /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n fragment QuestionCard on Question {\n id\n title\n description\n difficulty\n category\n\n ...QuestionSolvedStatus\n }\n"): (typeof documents)["\n fragment QuestionCard on Question {\n id\n title\n description\n difficulty\n category\n\n ...QuestionSolvedStatus\n }\n"]; +export function graphql(source: "\n fragment QuestionCard on Question {\n id\n title\n description\n difficulty\n category\n\n statistics {\n passedUsers\n attemptedUsers\n }\n\n ...QuestionSolvedStatus\n }\n"): (typeof documents)["\n fragment QuestionCard on Question {\n id\n title\n description\n difficulty\n category\n\n statistics {\n passedUsers\n attemptedUsers\n }\n\n ...QuestionSolvedStatus\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/gql/graphql.ts b/gql/graphql.ts index bd1f8b6..98f3f96 100644 --- a/gql/graphql.ts +++ b/gql/graphql.ts @@ -834,6 +834,8 @@ export type Question = Node & { referenceAnswerResult: SqlExecutionResult; /** Have you solved the question? */ solved: Scalars['Boolean']['output']; + /** The statistics of the question, e.g. pass rate. */ + statistics: QuestionStatistics; submissions: SubmissionConnection; /** Question title */ title: Scalars['String']['output']; @@ -893,6 +895,18 @@ export enum QuestionOrderField { Difficulty = 'DIFFICULTY' } +export type QuestionStatistics = { + __typename?: 'QuestionStatistics'; + /** 嘗試人數 */ + attemptedUsers: Scalars['Int']['output']; + /** 答案正確的提交數 */ + correctSubmissionCount: Scalars['Int']['output']; + /** 通過的學生數 */ + passedUsers: Scalars['Int']['output']; + /** 所有提交數 */ + submissionCount: Scalars['Int']['output']; +}; + /** * QuestionWhereInput is used for filtering Question objects. * Input was generated by ent. @@ -1518,7 +1532,7 @@ export type QuestionHeaderQueryVariables = Exact<{ export type QuestionHeaderQuery = { __typename?: 'Query', question: ( - { __typename?: 'Question', id: string, title: string, difficulty: QuestionDifficulty, category: string } + { __typename?: 'Question', id: string, title: string, difficulty: QuestionDifficulty, category: string, statistics: { __typename?: 'QuestionStatistics', passedUsers: number, attemptedUsers: number, correctSubmissionCount: number, submissionCount: number } } & { ' $fragmentRefs'?: { 'QuestionSolvedStatusFragment': QuestionSolvedStatusFragment } } ) }; @@ -1683,7 +1697,7 @@ export type QuestionSchemaQueryVariables = Exact<{ export type QuestionSchemaQuery = { __typename?: 'Query', question: { __typename?: 'Question', id: string, database: { __typename?: 'Database', id: string, structure: { __typename?: 'DatabaseStructure', tables: Array<{ __typename?: 'DatabaseTable', columns: Array, name: string }> } } } }; export type QuestionCardFragment = ( - { __typename?: 'Question', id: string, title: string, description: string, difficulty: QuestionDifficulty, category: string } + { __typename?: 'Question', id: string, title: string, description: string, difficulty: QuestionDifficulty, category: string, statistics: { __typename?: 'QuestionStatistics', passedUsers: number, attemptedUsers: number } } & { ' $fragmentRefs'?: { 'QuestionSolvedStatusFragment': QuestionSolvedStatusFragment } } ) & { ' $fragmentName'?: 'QuestionCardFragment' }; @@ -1699,8 +1713,8 @@ export const MaterialsSchemaCardFragmentDoc = {"kind":"Document","definitions":[ export const PointFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"PointFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Point"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"points"}}]}}]} as unknown as DocumentNode; export const QuestionInfoFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"QuestionInfoFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Question"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"difficulty"}},{"kind":"Field","name":{"kind":"Name","value":"category"}}]}}]} as unknown as DocumentNode; export const QuestionSolvedStatusFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"QuestionSolvedStatus"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Question"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"solved"}},{"kind":"Field","name":{"kind":"Name","value":"attempted"}}]}}]} as unknown as DocumentNode; -export const QuestionCardFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"QuestionCard"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Question"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"difficulty"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"QuestionSolvedStatus"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"QuestionSolvedStatus"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Question"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"solved"}},{"kind":"Field","name":{"kind":"Name","value":"attempted"}}]}}]} as unknown as DocumentNode; -export const QuestionHeaderDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"QuestionHeader"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"question"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"difficulty"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"QuestionSolvedStatus"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"QuestionSolvedStatus"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Question"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"solved"}},{"kind":"Field","name":{"kind":"Name","value":"attempted"}}]}}]} as unknown as DocumentNode; +export const QuestionCardFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"QuestionCard"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Question"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"difficulty"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"statistics"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"passedUsers"}},{"kind":"Field","name":{"kind":"Name","value":"attemptedUsers"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"QuestionSolvedStatus"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"QuestionSolvedStatus"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Question"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"solved"}},{"kind":"Field","name":{"kind":"Name","value":"attempted"}}]}}]} as unknown as DocumentNode; +export const QuestionHeaderDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"QuestionHeader"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"question"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"difficulty"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"statistics"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"passedUsers"}},{"kind":"Field","name":{"kind":"Name","value":"attemptedUsers"}},{"kind":"Field","name":{"kind":"Name","value":"correctSubmissionCount"}},{"kind":"Field","name":{"kind":"Name","value":"submissionCount"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"QuestionSolvedStatus"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"QuestionSolvedStatus"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Question"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"solved"}},{"kind":"Field","name":{"kind":"Name","value":"attempted"}}]}}]} as unknown as DocumentNode; export const CompareAnswerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"CompareAnswer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"question"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"referenceAnswerResult"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"columns"}},{"kind":"Field","name":{"kind":"Name","value":"rows"}}]}},{"kind":"Field","name":{"kind":"Name","value":"lastSubmission"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"queryResult"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"columns"}},{"kind":"Field","name":{"kind":"Name","value":"rows"}}]}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}}]}}]}}]} as unknown as DocumentNode; export const CorrectAnswerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"CorrectAnswer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"question"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"referenceAnswerResult"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"columns"}},{"kind":"Field","name":{"kind":"Name","value":"rows"}}]}}]}}]}}]} as unknown as DocumentNode; export const DatabaseRelationshipDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"DatabaseRelationship"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"question"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"database"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"relationFigure"}}]}}]}}]}}]} as unknown as DocumentNode; @@ -1711,7 +1725,7 @@ export const SqlEditorContextDocument = {"kind":"Document","definitions":[{"kind export const SubmissionHistoryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"SubmissionHistory"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"question"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"userSubmissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"submittedCode"}},{"kind":"Field","name":{"kind":"Name","value":"submittedAt"}}]}}]}}]}}]} as unknown as DocumentNode; export const TagFilterSectionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"TagFilterSection"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"questionCategories"}}]}}]} as unknown as DocumentNode; export const ChallengeStatisticsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ChallengeStatistics"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"me"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"submissionStatistics"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalQuestions"}},{"kind":"Field","name":{"kind":"Name","value":"solvedQuestions"}},{"kind":"Field","name":{"kind":"Name","value":"attemptedQuestions"}}]}}]}}]}}]} as unknown as DocumentNode; -export const ListQuestionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ListQuestions"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"where"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"QuestionWhereInput"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"after"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Cursor"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"questions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"where"},"value":{"kind":"Variable","name":{"kind":"Name","value":"where"}}},{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"10"}},{"kind":"Argument","name":{"kind":"Name","value":"after"},"value":{"kind":"Variable","name":{"kind":"Name","value":"after"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"QuestionCard"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"QuestionSolvedStatus"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"QuestionSolvedStatus"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Question"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"solved"}},{"kind":"Field","name":{"kind":"Name","value":"attempted"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"QuestionCard"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Question"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"difficulty"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"QuestionSolvedStatus"}}]}}]} as unknown as DocumentNode; +export const ListQuestionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ListQuestions"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"where"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"QuestionWhereInput"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"after"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Cursor"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"questions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"where"},"value":{"kind":"Variable","name":{"kind":"Name","value":"where"}}},{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"10"}},{"kind":"Argument","name":{"kind":"Name","value":"after"},"value":{"kind":"Variable","name":{"kind":"Name","value":"after"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"QuestionCard"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"QuestionSolvedStatus"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"QuestionSolvedStatus"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Question"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"solved"}},{"kind":"Field","name":{"kind":"Name","value":"attempted"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"QuestionCard"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Question"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"difficulty"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"statistics"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"passedUsers"}},{"kind":"Field","name":{"kind":"Name","value":"attemptedUsers"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"QuestionSolvedStatus"}}]}}]} as unknown as DocumentNode; export const MaterialsSchemaContentDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"MaterialsSchemaContent"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"database"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}}]}}]}}]} as unknown as DocumentNode; export const MaterialsSchemaDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"MaterialsSchema"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"databases"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"MaterialsSchemaCard"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"MaterialsSchemaCard"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Database"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"description"}}]}}]} as unknown as DocumentNode; export const CompletedQuestionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"CompletedQuestions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"me"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"submissionStatistics"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalQuestions"}},{"kind":"Field","name":{"kind":"Name","value":"solvedQuestions"}}]}}]}}]}}]} as unknown as DocumentNode; diff --git a/schema.graphql b/schema.graphql index 5c438c9..3d98a06 100644 --- a/schema.graphql +++ b/schema.graphql @@ -703,6 +703,8 @@ type Question implements Node { referenceAnswerResult: SQLExecutionResult! """Have you solved the question?""" solved: Boolean! + """The statistics of the question, e.g. pass rate.""" + statistics: QuestionStatistics! submissions( """Returns the elements in the list that come after the specified cursor.""" after: Cursor @@ -767,6 +769,17 @@ enum QuestionOrderField { DIFFICULTY } +type QuestionStatistics { + """嘗試人數""" + attemptedUsers: Int! + """答案正確的提交數""" + correctSubmissionCount: Int! + """通過的學生數""" + passedUsers: Int! + """所有提交數""" + submissionCount: Int! +} + """ QuestionWhereInput is used for filtering Question objects. Input was generated by ent.