@kensai/quiz-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +99 -0
  3. package/dist/evaluate.d.ts +47 -0
  4. package/dist/evaluate.d.ts.map +1 -0
  5. package/dist/evaluate.js +149 -0
  6. package/dist/evaluate.js.map +1 -0
  7. package/dist/events.d.ts +10 -0
  8. package/dist/events.d.ts.map +1 -0
  9. package/dist/events.js +26 -0
  10. package/dist/events.js.map +1 -0
  11. package/dist/index.d.ts +26 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +19 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/load.d.ts +22 -0
  16. package/dist/load.d.ts.map +1 -0
  17. package/dist/load.js +31 -0
  18. package/dist/load.js.map +1 -0
  19. package/dist/resolve.d.ts +9 -0
  20. package/dist/resolve.d.ts.map +1 -0
  21. package/dist/resolve.js +22 -0
  22. package/dist/resolve.js.map +1 -0
  23. package/dist/runtime.d.ts +118 -0
  24. package/dist/runtime.d.ts.map +1 -0
  25. package/dist/runtime.js +245 -0
  26. package/dist/runtime.js.map +1 -0
  27. package/dist/schema.generated.d.ts +503 -0
  28. package/dist/schema.generated.d.ts.map +1 -0
  29. package/dist/schema.generated.js +626 -0
  30. package/dist/schema.generated.js.map +1 -0
  31. package/dist/settings.d.ts +19 -0
  32. package/dist/settings.d.ts.map +1 -0
  33. package/dist/settings.js +32 -0
  34. package/dist/settings.js.map +1 -0
  35. package/dist/stats.d.ts +33 -0
  36. package/dist/stats.d.ts.map +1 -0
  37. package/dist/stats.js +79 -0
  38. package/dist/stats.js.map +1 -0
  39. package/dist/text.d.ts +5 -0
  40. package/dist/text.d.ts.map +1 -0
  41. package/dist/text.js +11 -0
  42. package/dist/text.js.map +1 -0
  43. package/dist/types.d.ts +136 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +9 -0
  46. package/dist/types.js.map +1 -0
  47. package/dist/validate.d.ts +28 -0
  48. package/dist/validate.d.ts.map +1 -0
  49. package/dist/validate.js +170 -0
  50. package/dist/validate.js.map +1 -0
  51. package/package.json +60 -0
@@ -0,0 +1,503 @@
1
+ export declare const quizSchema: {
2
+ readonly $schema: "https://json-schema.org/draft/2020-12/schema";
3
+ readonly $id: "https://github.com/kensai/quiz-core/spec/quiz.schema.json";
4
+ readonly title: "Kensai Quiz";
5
+ readonly description: "Specification for a single, portable, AI-authorable quiz (schema version 0.1).";
6
+ readonly type: "object";
7
+ readonly required: readonly ["schema_version", "metadata", "questions"];
8
+ readonly additionalProperties: false;
9
+ readonly properties: {
10
+ readonly schema_version: {
11
+ readonly type: "string";
12
+ readonly const: "0.1";
13
+ readonly description: "Spec version this file targets. Enables backward compatibility.";
14
+ };
15
+ readonly metadata: {
16
+ readonly $ref: "#/$defs/metadata";
17
+ };
18
+ readonly settings: {
19
+ readonly $ref: "#/$defs/settings";
20
+ };
21
+ readonly categories: {
22
+ readonly type: "array";
23
+ readonly description: "Optional registry of categories used for end-of-quiz statistics.";
24
+ readonly items: {
25
+ readonly $ref: "#/$defs/category";
26
+ };
27
+ };
28
+ readonly option_groups: {
29
+ readonly type: "object";
30
+ readonly description: "Reusable named option sets. Reference them from questions via `options_from` / `groups_from`.";
31
+ readonly additionalProperties: {
32
+ readonly type: "array";
33
+ readonly minItems: 1;
34
+ readonly items: {
35
+ readonly $ref: "#/$defs/option";
36
+ };
37
+ };
38
+ };
39
+ readonly questions: {
40
+ readonly type: "array";
41
+ readonly minItems: 1;
42
+ readonly items: {
43
+ readonly $ref: "#/$defs/question";
44
+ };
45
+ };
46
+ };
47
+ readonly $defs: {
48
+ readonly metadata: {
49
+ readonly type: "object";
50
+ readonly required: readonly ["title"];
51
+ readonly additionalProperties: false;
52
+ readonly properties: {
53
+ readonly id: {
54
+ readonly type: "string";
55
+ readonly description: "Optional stable slug.";
56
+ };
57
+ readonly title: {
58
+ readonly type: "string";
59
+ readonly description: "Human title (Markdown).";
60
+ };
61
+ readonly path: {
62
+ readonly type: "string";
63
+ readonly description: "Study-path breadcrumb, e.g. 'English / Verb system / Present tenses'.";
64
+ };
65
+ readonly description: {
66
+ readonly type: "string";
67
+ readonly description: "Optional overview (Markdown).";
68
+ };
69
+ readonly language: {
70
+ readonly type: "string";
71
+ readonly description: "BCP-47 content language tag, e.g. 'en', 'es'. Default: 'und'.";
72
+ };
73
+ readonly author: {
74
+ readonly type: "string";
75
+ };
76
+ readonly tags: {
77
+ readonly type: "array";
78
+ readonly items: {
79
+ readonly type: "string";
80
+ };
81
+ };
82
+ };
83
+ };
84
+ readonly settings: {
85
+ readonly type: "object";
86
+ readonly description: "All fields optional. Author defaults; a player may override per attempt.";
87
+ readonly additionalProperties: false;
88
+ readonly properties: {
89
+ readonly navigation: {
90
+ readonly enum: readonly ["all", "sequential"];
91
+ readonly default: "all";
92
+ readonly description: "'all' shows every question at once; 'sequential' advances one by one.";
93
+ };
94
+ readonly order: {
95
+ readonly enum: readonly ["fixed", "random"];
96
+ readonly default: "fixed";
97
+ readonly description: "Order in which questions are presented ('random' shuffles them).";
98
+ };
99
+ readonly feedback: {
100
+ readonly enum: readonly ["immediate", "on_finish"];
101
+ readonly default: "on_finish";
102
+ readonly description: "Reveal correctness/explanation per question or only at the end.";
103
+ };
104
+ readonly time_limit: {
105
+ readonly type: readonly ["number", "null"];
106
+ readonly minimum: 1;
107
+ readonly default: null;
108
+ readonly description: "Seconds allowed. null or omitted = unlimited.";
109
+ };
110
+ readonly shuffle_options: {
111
+ readonly type: "boolean";
112
+ readonly default: false;
113
+ readonly description: "Shuffle the answer-option order of choice questions, except those that set `shuffle_options: false`.";
114
+ };
115
+ readonly passing_score: {
116
+ readonly type: "number";
117
+ readonly minimum: 0;
118
+ readonly maximum: 1;
119
+ readonly description: "Pass threshold as a fraction 0..1.";
120
+ };
121
+ };
122
+ };
123
+ readonly category: {
124
+ readonly type: "object";
125
+ readonly required: readonly ["id", "label"];
126
+ readonly additionalProperties: false;
127
+ readonly properties: {
128
+ readonly id: {
129
+ readonly type: "string";
130
+ };
131
+ readonly label: {
132
+ readonly type: "string";
133
+ readonly description: "Display label (Markdown).";
134
+ };
135
+ };
136
+ };
137
+ readonly option: {
138
+ readonly type: "object";
139
+ readonly required: readonly ["id", "text"];
140
+ readonly additionalProperties: false;
141
+ readonly properties: {
142
+ readonly id: {
143
+ readonly type: "string";
144
+ readonly description: "Unique within its option list.";
145
+ };
146
+ readonly text: {
147
+ readonly type: "string";
148
+ readonly description: "Option text (Markdown).";
149
+ };
150
+ };
151
+ };
152
+ readonly group: {
153
+ readonly type: "object";
154
+ readonly required: readonly ["id", "label"];
155
+ readonly additionalProperties: false;
156
+ readonly properties: {
157
+ readonly id: {
158
+ readonly type: "string";
159
+ };
160
+ readonly label: {
161
+ readonly type: "string";
162
+ readonly description: "Bucket label (Markdown).";
163
+ };
164
+ };
165
+ };
166
+ readonly id_or_id_list: {
167
+ readonly description: "A single id or a list of ids.";
168
+ readonly oneOf: readonly [{
169
+ readonly type: "string";
170
+ }, {
171
+ readonly type: "array";
172
+ readonly minItems: 1;
173
+ readonly items: {
174
+ readonly type: "string";
175
+ };
176
+ }];
177
+ };
178
+ readonly question: {
179
+ readonly type: "object";
180
+ readonly required: readonly ["type", "prompt"];
181
+ readonly properties: {
182
+ readonly id: {
183
+ readonly type: "string";
184
+ readonly description: "Recommended: stable id for stats/resume.";
185
+ };
186
+ readonly type: {
187
+ readonly enum: readonly ["choice", "true_false", "fill_blank", "classify", "matching", "ordering", "short_answer"];
188
+ };
189
+ readonly category: {
190
+ readonly type: "string";
191
+ readonly description: "References a categories[].id, or a free-form string.";
192
+ };
193
+ readonly points: {
194
+ readonly type: "number";
195
+ readonly minimum: 0;
196
+ readonly default: 1;
197
+ };
198
+ readonly prompt: {
199
+ readonly type: "string";
200
+ readonly description: "Question text (Markdown).";
201
+ };
202
+ readonly explanation: {
203
+ readonly type: "string";
204
+ readonly description: "Optional rationale (Markdown).";
205
+ };
206
+ };
207
+ readonly oneOf: readonly [{
208
+ readonly $ref: "#/$defs/q_choice";
209
+ }, {
210
+ readonly $ref: "#/$defs/q_true_false";
211
+ }, {
212
+ readonly $ref: "#/$defs/q_fill_blank";
213
+ }, {
214
+ readonly $ref: "#/$defs/q_classify";
215
+ }, {
216
+ readonly $ref: "#/$defs/q_matching";
217
+ }, {
218
+ readonly $ref: "#/$defs/q_ordering";
219
+ }, {
220
+ readonly $ref: "#/$defs/q_short_answer";
221
+ }];
222
+ };
223
+ readonly q_choice: {
224
+ readonly properties: {
225
+ readonly type: {
226
+ readonly const: "choice";
227
+ };
228
+ readonly id: true;
229
+ readonly category: true;
230
+ readonly points: true;
231
+ readonly prompt: true;
232
+ readonly explanation: true;
233
+ readonly select: {
234
+ readonly enum: readonly ["single", "multiple"];
235
+ readonly default: "single";
236
+ };
237
+ readonly options: {
238
+ readonly type: "array";
239
+ readonly minItems: 2;
240
+ readonly items: {
241
+ readonly $ref: "#/$defs/option";
242
+ };
243
+ };
244
+ readonly options_from: {
245
+ readonly type: "string";
246
+ readonly description: "Name of an entry in option_groups.";
247
+ };
248
+ readonly answer: {
249
+ readonly $ref: "#/$defs/id_or_id_list";
250
+ };
251
+ readonly shuffle_options: {
252
+ readonly type: "boolean";
253
+ readonly default: true;
254
+ readonly description: "Whether these options may be reordered when the quiz enables option shuffling. Default true; set false to lock the order (e.g. an 'All of the above' option, or options like 'Both A and B').";
255
+ };
256
+ };
257
+ readonly required: readonly ["type", "prompt", "answer"];
258
+ readonly oneOf: readonly [{
259
+ readonly required: readonly ["options"];
260
+ readonly not: {
261
+ readonly required: readonly ["options_from"];
262
+ };
263
+ }, {
264
+ readonly required: readonly ["options_from"];
265
+ readonly not: {
266
+ readonly required: readonly ["options"];
267
+ };
268
+ }];
269
+ readonly additionalProperties: false;
270
+ };
271
+ readonly q_true_false: {
272
+ readonly properties: {
273
+ readonly type: {
274
+ readonly const: "true_false";
275
+ };
276
+ readonly id: true;
277
+ readonly category: true;
278
+ readonly points: true;
279
+ readonly prompt: true;
280
+ readonly explanation: true;
281
+ readonly answer: {
282
+ readonly type: "boolean";
283
+ };
284
+ };
285
+ readonly required: readonly ["type", "prompt", "answer"];
286
+ readonly additionalProperties: false;
287
+ };
288
+ readonly q_fill_blank: {
289
+ readonly properties: {
290
+ readonly type: {
291
+ readonly const: "fill_blank";
292
+ };
293
+ readonly id: true;
294
+ readonly category: true;
295
+ readonly points: true;
296
+ readonly prompt: true;
297
+ readonly explanation: true;
298
+ readonly blanks: {
299
+ readonly type: "object";
300
+ readonly minProperties: 1;
301
+ readonly description: "Map of placeholder id ({{id}} in prompt) to a blank definition.";
302
+ readonly additionalProperties: {
303
+ readonly $ref: "#/$defs/blank";
304
+ };
305
+ };
306
+ };
307
+ readonly required: readonly ["type", "prompt", "blanks"];
308
+ readonly additionalProperties: false;
309
+ };
310
+ readonly blank: {
311
+ readonly type: "object";
312
+ readonly description: "A blank is either free-text (accept) or a per-blank choice (options + answer).";
313
+ readonly additionalProperties: false;
314
+ readonly properties: {
315
+ readonly accept: {
316
+ readonly type: "array";
317
+ readonly minItems: 1;
318
+ readonly items: {
319
+ readonly type: "string";
320
+ };
321
+ readonly description: "Accepted free-text answers (synonyms).";
322
+ };
323
+ readonly case_sensitive: {
324
+ readonly type: "boolean";
325
+ readonly default: false;
326
+ };
327
+ readonly options: {
328
+ readonly type: "array";
329
+ readonly minItems: 2;
330
+ readonly items: {
331
+ readonly $ref: "#/$defs/option";
332
+ };
333
+ };
334
+ readonly answer: {
335
+ readonly type: "string";
336
+ readonly description: "Correct option id (choice-per-blank variant).";
337
+ };
338
+ };
339
+ readonly oneOf: readonly [{
340
+ readonly required: readonly ["accept"];
341
+ readonly not: {
342
+ readonly required: readonly ["options"];
343
+ };
344
+ }, {
345
+ readonly required: readonly ["options", "answer"];
346
+ readonly not: {
347
+ readonly required: readonly ["accept"];
348
+ };
349
+ }];
350
+ };
351
+ readonly q_classify: {
352
+ readonly properties: {
353
+ readonly type: {
354
+ readonly const: "classify";
355
+ };
356
+ readonly id: true;
357
+ readonly category: true;
358
+ readonly points: true;
359
+ readonly prompt: true;
360
+ readonly explanation: true;
361
+ readonly groups: {
362
+ readonly type: "array";
363
+ readonly minItems: 2;
364
+ readonly items: {
365
+ readonly $ref: "#/$defs/group";
366
+ };
367
+ };
368
+ readonly groups_from: {
369
+ readonly type: "string";
370
+ readonly description: "Name of an entry in option_groups (its options act as buckets: id + text).";
371
+ };
372
+ readonly items: {
373
+ readonly type: "array";
374
+ readonly minItems: 1;
375
+ readonly items: {
376
+ readonly type: "object";
377
+ readonly required: readonly ["id", "text", "answer"];
378
+ readonly additionalProperties: false;
379
+ readonly properties: {
380
+ readonly id: {
381
+ readonly type: "string";
382
+ };
383
+ readonly text: {
384
+ readonly type: "string";
385
+ readonly description: "Item text (Markdown).";
386
+ };
387
+ readonly answer: {
388
+ readonly type: "string";
389
+ readonly description: "Target group id.";
390
+ };
391
+ };
392
+ };
393
+ };
394
+ };
395
+ readonly required: readonly ["type", "prompt", "items"];
396
+ readonly oneOf: readonly [{
397
+ readonly required: readonly ["groups"];
398
+ readonly not: {
399
+ readonly required: readonly ["groups_from"];
400
+ };
401
+ }, {
402
+ readonly required: readonly ["groups_from"];
403
+ readonly not: {
404
+ readonly required: readonly ["groups"];
405
+ };
406
+ }];
407
+ readonly additionalProperties: false;
408
+ };
409
+ readonly q_matching: {
410
+ readonly properties: {
411
+ readonly type: {
412
+ readonly const: "matching";
413
+ };
414
+ readonly id: true;
415
+ readonly category: true;
416
+ readonly points: true;
417
+ readonly prompt: true;
418
+ readonly explanation: true;
419
+ readonly left: {
420
+ readonly type: "array";
421
+ readonly minItems: 1;
422
+ readonly items: {
423
+ readonly $ref: "#/$defs/option";
424
+ };
425
+ };
426
+ readonly right: {
427
+ readonly type: "array";
428
+ readonly minItems: 1;
429
+ readonly items: {
430
+ readonly $ref: "#/$defs/option";
431
+ };
432
+ };
433
+ readonly answer: {
434
+ readonly type: "object";
435
+ readonly minProperties: 1;
436
+ readonly description: "Map of left id -> right id.";
437
+ readonly additionalProperties: {
438
+ readonly type: "string";
439
+ };
440
+ };
441
+ };
442
+ readonly required: readonly ["type", "prompt", "left", "right", "answer"];
443
+ readonly additionalProperties: false;
444
+ };
445
+ readonly q_ordering: {
446
+ readonly properties: {
447
+ readonly type: {
448
+ readonly const: "ordering";
449
+ };
450
+ readonly id: true;
451
+ readonly category: true;
452
+ readonly points: true;
453
+ readonly prompt: true;
454
+ readonly explanation: true;
455
+ readonly items: {
456
+ readonly type: "array";
457
+ readonly minItems: 2;
458
+ readonly items: {
459
+ readonly $ref: "#/$defs/option";
460
+ };
461
+ };
462
+ readonly answer: {
463
+ readonly type: "array";
464
+ readonly minItems: 2;
465
+ readonly items: {
466
+ readonly type: "string";
467
+ };
468
+ readonly description: "Item ids in the correct order.";
469
+ };
470
+ };
471
+ readonly required: readonly ["type", "prompt", "items", "answer"];
472
+ readonly additionalProperties: false;
473
+ };
474
+ readonly q_short_answer: {
475
+ readonly properties: {
476
+ readonly type: {
477
+ readonly const: "short_answer";
478
+ };
479
+ readonly id: true;
480
+ readonly category: true;
481
+ readonly points: true;
482
+ readonly prompt: true;
483
+ readonly explanation: true;
484
+ readonly accept: {
485
+ readonly type: "array";
486
+ readonly minItems: 1;
487
+ readonly items: {
488
+ readonly type: "string";
489
+ };
490
+ readonly description: "Accepted answers (synonyms).";
491
+ };
492
+ readonly case_sensitive: {
493
+ readonly type: "boolean";
494
+ readonly default: false;
495
+ };
496
+ };
497
+ readonly required: readonly ["type", "prompt", "accept"];
498
+ readonly additionalProperties: false;
499
+ };
500
+ };
501
+ };
502
+ export default quizSchema;
503
+ //# sourceMappingURL=schema.generated.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.generated.d.ts","sourceRoot":"","sources":["../src/schema.generated.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6mBb,CAAC;AAEX,eAAe,UAAU,CAAC"}