@@ -59,6 +59,21 @@ export type Schema = Variant["schema"];
5959export type ClientVariant = z . infer < typeof clientVariantSchema > ;
6060export type ClientSchema = ClientVariant [ "schema" ] ;
6161
62+ export function decodeAllCorrectAnswer ( answer ?: Answer ) : string [ ] {
63+ if ( typeof answer !== "string" ) {
64+ return [ ] ;
65+ }
66+ try {
67+ return JSON . parse ( answer ) ;
68+ } catch {
69+ return [ ] ;
70+ }
71+ }
72+
73+ export function encodeAllCorrectAnswer ( value : string [ ] ) : Answer {
74+ return JSON . stringify ( value ) ;
75+ }
76+
6277export function parseAnswer ( answer : string , schema : Schema [ string ] ) : Answer {
6378 let value : Answer = answer . trim ( ) . toUpperCase ( ) ;
6479 if ( ! value ) return null ;
@@ -68,10 +83,30 @@ export function parseAnswer(answer: string, schema: Schema[string]): Answer {
6883 value = Number ( value ) ;
6984 }
7085 }
86+
87+ if ( schema . kind === "allCorrect" ) {
88+ value = encodeAllCorrectAnswer ( answer . split ( "" ) ) ;
89+ }
90+
7191 isValidAnswer ( value , schema ) ;
7292 return value ;
7393}
7494
95+ export function displayAnswer ( answer : Answer , kind : Schema [ string ] [ "kind" ] ) : string {
96+ switch ( kind ) {
97+ case "allCorrect" : {
98+ const values = decodeAllCorrectAnswer ( answer ) ;
99+ return values . join ( "" ) ;
100+ }
101+ default : {
102+ if ( answer === null ) {
103+ return "" ;
104+ }
105+ return `${ answer } ` ;
106+ }
107+ }
108+ }
109+
75110export function isValidAnswer ( answer : Answer , schema : Schema [ string ] ) {
76111 if ( answer == null ) return ;
77112 if ( schema . type === "number" && ! Number . isInteger ( answer ) ) {
@@ -86,6 +121,16 @@ export function isValidAnswer(answer: Answer, schema: Schema[string]) {
86121 break ;
87122 }
88123 case "allCorrect" : {
124+ const values = decodeAllCorrectAnswer ( answer ) ;
125+ const wrong = values . filter (
126+ ( value ) => ! schema . options . some ( ( option ) => option . value === value ) ,
127+ ) ;
128+ if ( wrong . length >= 1 ) {
129+ throw new Error ( `Opzioni non valide: ${ wrong . join ( "" ) } ` ) ;
130+ }
131+ if ( new Set ( values ) . size !== values . length ) {
132+ throw new Error ( `Opzioni ripetute: ${ values . join ( "" ) } ` ) ;
133+ }
89134 break ;
90135 }
91136 default : {
@@ -114,6 +159,20 @@ export function calcScore(student: Student, schema?: Schema) {
114159}
115160
116161export function calcProblemPoints ( problem : Schema [ string ] , answer ?: Answer ) {
162+ if ( problem . kind === "allCorrect" ) {
163+ const values = decodeAllCorrectAnswer ( answer ) ;
164+ if ( values . length === 0 ) {
165+ return 1 ; // TODO: save points in schema
166+ }
167+ const correctOptions = problem . options . filter ( ( option ) => option . points === 5 ) ;
168+ if (
169+ correctOptions . length !== values . length &&
170+ correctOptions . some ( ( option ) => ! values . some ( ( value ) => option . value === value ) )
171+ ) {
172+ return 0 ;
173+ }
174+ return 5 ;
175+ }
117176 for ( const option of problem . options ?? [ ] ) {
118177 if ( option . value === ( answer ?? null ) ) {
119178 return option . points ;
0 commit comments