@telebort/question-banks 2.2.0 → 2.4.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.
- package/README.md +194 -27
- package/dist/{assessment-DnV2240e.d.cts → assessment-BhkjdWy1.d.cts} +38 -5
- package/dist/{assessment-DnV2240e.d.ts → assessment-BhkjdWy1.d.ts} +38 -5
- package/dist/cli/index.cjs +273 -72
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +273 -72
- package/dist/cli/index.js.map +1 -1
- package/dist/{course-CkP2VX_5.d.cts → course-DD94UGiI.d.cts} +329 -139
- package/dist/{course-CkP2VX_5.d.ts → course-DD94UGiI.d.ts} +329 -139
- package/dist/{index-DRVgW8qc.d.ts → index-B1r6pY_k.d.ts} +1 -1
- package/dist/{index-B-16Gs9R.d.cts → index-jb328lpu.d.cts} +1 -1
- package/dist/index.cjs +256 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -34
- package/dist/index.d.ts +61 -34
- package/dist/index.js +255 -60
- package/dist/index.js.map +1 -1
- package/dist/premium/index.d.cts +3 -3
- package/dist/premium/index.d.ts +3 -3
- package/dist/schemas/index.cjs +120 -58
- package/dist/schemas/index.cjs.map +1 -1
- package/dist/schemas/index.d.cts +2 -2
- package/dist/schemas/index.d.ts +2 -2
- package/dist/schemas/index.js +120 -59
- package/dist/schemas/index.js.map +1 -1
- package/dist/validation/index.cjs +119 -58
- package/dist/validation/index.cjs.map +1 -1
- package/dist/validation/index.d.cts +1 -1
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.js +119 -58
- package/dist/validation/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/schemas/question.ts","../../src/schemas/course.ts","../../src/schemas/assessment.ts","../../src/schemas/certification.ts"],"names":["z"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from 'zod'\n\n// ============================================================================\n// Feedback Schema (v1.1 enhancement)\n// ============================================================================\n\n/**\n * Structured feedback following the \"Not Yet\" protocol\n * - short: Brief acknowledgment (1 sentence)\n * - detailed: Full explanation of the misconception\n * - socraticHint: Optional guiding question for discovery learning\n */\nexport const FeedbackSchema = z.object({\n short: z.string().min(1).max(200),\n detailed: z.string().min(1).max(1000),\n socraticHint: z.string().max(300).optional(),\n})\n\nexport type Feedback = z.infer<typeof FeedbackSchema>\n\n// ============================================================================\n// Option Schema\n// ============================================================================\n\nexport const OptionKeySchema = z.enum(['A', 'B', 'C', 'D'])\n\nexport type OptionKey = z.infer<typeof OptionKeySchema>\n\n/**\n * Answer option with optional misconception tracking (v1.1)\n */\nexport const OptionSchema = z.object({\n key: OptionKeySchema,\n text: z.string().min(1),\n isCorrect: z.boolean(),\n // v1.1 fields - optional for backward compatibility\n misconceptionId: z.string().optional(),\n feedback: FeedbackSchema.optional(),\n})\n\nexport type Option = z.infer<typeof OptionSchema>\n\n// ============================================================================\n// Question Type Enums\n// ============================================================================\n\nexport const QuestionTypeSchema = z.enum([\n 'vocabulary',\n 'code_understanding',\n 'problem_solving',\n 'application',\n 'reflection',\n])\n\nexport type QuestionType = z.infer<typeof QuestionTypeSchema>\n\n/**\n * Question archetype for pedagogical classification\n * - vocabulary: Definition/terminology questions\n * - trace: Code tracing (mental execution)\n * - bebras: Logic-first, computational thinking\n * - blockmodel: Surface/flow/purpose analysis\n * - parsons: Code block reordering (future)\n */\nexport const QuestionArchetypeSchema = z.enum([\n 'vocabulary',\n 'trace',\n 'bebras',\n 'blockmodel',\n 'parsons',\n])\n\nexport type QuestionArchetype = z.infer<typeof QuestionArchetypeSchema>\n\nexport const DifficultySchema = z.enum(['easy', 'medium', 'hard', 'challenge'])\n\nexport type Difficulty = z.infer<typeof DifficultySchema>\n\nexport const BloomsTaxonomySchema = z.enum([\n 'remember',\n 'understand',\n 'apply',\n 'analyze',\n 'evaluate',\n 'create',\n])\n\nexport type BloomsTaxonomy = z.infer<typeof BloomsTaxonomySchema>\n\n// ============================================================================\n// Question Metadata Schema\n// ============================================================================\n\nexport const QuestionMetadataSchema = z.object({\n difficulty: DifficultySchema,\n estimatedTime: z.number().int().positive(), // seconds\n bloomsTaxonomy: BloomsTaxonomySchema,\n tags: z.array(z.string()),\n source: z.string().default('exit-ticket'),\n version: z.string().default('1.1'),\n createdDate: z.string().optional(),\n lastModified: z.string().optional(),\n})\n\nexport type QuestionMetadata = z.infer<typeof QuestionMetadataSchema>\n\n// ============================================================================\n// Question Schema (v1.1)\n// ============================================================================\n\n/**\n * Full question schema with v1.1 enhancements:\n * - questionArchetype: Pedagogical classification\n * - misconceptionTargets: Expected misconceptions this question probes\n * - options with misconceptionId and structured feedback\n */\nexport const QuestionSchema = z.object({\n // Identifiers\n questionId: z.string().regex(/^[a-z0-9-]+-l\\d+-q\\d+$/),\n globalId: z.string().regex(/^exit-ticket-\\d{4}$/),\n questionNumber: z.number().int().positive().max(5),\n\n // Classification\n questionType: QuestionTypeSchema,\n questionTypeLabel: z.string(),\n questionArchetype: QuestionArchetypeSchema.optional(), // v1.1\n\n // Content\n prompt: z.string().min(10),\n hasCodeBlock: z.boolean(),\n codeLanguage: z.string().nullable(),\n codeContent: z.string().nullable(),\n\n // Misconception targeting (v1.1)\n misconceptionTargets: z.array(z.string()).optional(),\n\n // Answer options (exactly 4)\n options: z.array(OptionSchema).length(4),\n\n // Correct answer\n correctAnswer: OptionKeySchema,\n correctAnswerText: z.string(),\n\n // Metadata\n metadata: QuestionMetadataSchema,\n})\n\nexport type Question = z.infer<typeof QuestionSchema>\n\n// ============================================================================\n// Question without answer (for Standard tier - no answer leakage)\n// ============================================================================\n\nexport const QuestionWithoutAnswerSchema = QuestionSchema.omit({\n correctAnswer: true,\n correctAnswerText: true,\n}).extend({\n options: z.array(\n OptionSchema.omit({\n isCorrect: true,\n feedback: true,\n misconceptionId: true,\n })\n ).length(4),\n})\n\nexport type QuestionWithoutAnswer = z.infer<typeof QuestionWithoutAnswerSchema>\n","import { z } from 'zod'\nimport { QuestionSchema } from './question'\n\n// ============================================================================\n// Course Domain & Tier\n// ============================================================================\n\nexport const CourseDomainSchema = z.enum([\n // AI & Data Science\n 'ai_data_science',\n 'ai_ml_cv',\n 'ai_generative',\n 'ai_advanced',\n // Web Development\n 'web_development',\n // Mobile Development\n 'mobile_development',\n 'mobile',\n // Block-based Programming\n 'block_based',\n 'python_programming',\n 'design',\n // Foundation\n 'foundation',\n 'creative_computing',\n])\n\nexport type CourseDomain = z.infer<typeof CourseDomainSchema>\n\nexport const CourseTierSchema = z.enum([\n 'foundation',\n 'intermediate',\n 'advanced',\n])\n\nexport type CourseTier = z.infer<typeof CourseTierSchema>\n\n// ============================================================================\n// Lesson Schema\n// ============================================================================\n\nexport const LessonSchema = z.object({\n lessonId: z.string(), // e.g., \"ai-1-lesson-1\"\n lessonNumber: z.number().int().positive(),\n lessonTitle: z.string(),\n lessonSlug: z.string().optional(),\n totalQuestions: z.number().int().positive().default(5),\n questions: z.array(QuestionSchema),\n})\n\nexport type Lesson = z.infer<typeof LessonSchema>\n\n// ============================================================================\n// Course Schema\n// ============================================================================\n\nexport const CourseSchema = z.object({\n courseId: z.string(), // e.g., \"ai-1\"\n courseName: z.string(), // e.g., \"AI-1 Data Analysis and Data Science\"\n courseCode: z.string(), // e.g., \"AI1\"\n domain: CourseDomainSchema,\n tier: CourseTierSchema,\n difficulty: z.number().int().min(1).max(5),\n totalLessons: z.number().int().positive(),\n totalQuestions: z.number().int().positive(),\n sourceFile: z.string().optional(),\n lessons: z.array(LessonSchema),\n})\n\nexport type Course = z.infer<typeof CourseSchema>\n\n// ============================================================================\n// Course Summary (without questions - for listing)\n// ============================================================================\n\nexport const CourseSummarySchema = CourseSchema.omit({ lessons: true }).extend({\n lessons: z.array(\n LessonSchema.omit({ questions: true })\n ).optional(),\n})\n\nexport type CourseSummary = z.infer<typeof CourseSummarySchema>\n","import { z } from 'zod'\nimport { OptionKeySchema, FeedbackSchema } from './question'\n\n// ============================================================================\n// User Response Schema\n// ============================================================================\n\n/**\n * A single user response to a question\n */\nexport const UserResponseSchema = z.object({\n questionId: z.string(),\n selectedAnswer: OptionKeySchema,\n timeSpent: z.number().int().nonnegative().optional(), // milliseconds\n submittedAt: z.string().datetime().optional(),\n})\n\nexport type UserResponse = z.infer<typeof UserResponseSchema>\n\n// ============================================================================\n// Assessment Submission Schema\n// ============================================================================\n\n/**\n * An assessment submission containing multiple responses\n */\nexport const AssessmentSubmissionSchema = z.object({\n assessmentId: z.string().uuid().optional(), // Generated if not provided\n userId: z.string().optional(), // For authenticated users\n sessionId: z.string().optional(), // For anonymous sessions\n courseId: z.string(),\n lessonId: z.string().optional(),\n responses: z.array(UserResponseSchema).min(1),\n submittedAt: z.string().datetime(),\n metadata: z.record(z.unknown()).optional(), // Custom metadata\n})\n\nexport type AssessmentSubmission = z.infer<typeof AssessmentSubmissionSchema>\n\n// ============================================================================\n// Graded Response Schema (Premium tier)\n// ============================================================================\n\n/**\n * Result of grading a single response\n */\nexport const GradedResponseSchema = z.object({\n questionId: z.string(),\n selectedAnswer: OptionKeySchema,\n correctAnswer: OptionKeySchema,\n isCorrect: z.boolean(),\n misconceptionId: z.string().nullable(), // For incorrect answers\n feedback: FeedbackSchema.optional(),\n timeSpent: z.number().int().nonnegative().optional(),\n})\n\nexport type GradedResponse = z.infer<typeof GradedResponseSchema>\n\n// ============================================================================\n// Misconception Report Schema (Premium tier)\n// ============================================================================\n\n/**\n * Aggregated misconception analysis for an assessment\n */\nexport const MisconceptionReportSchema = z.object({\n misconceptionId: z.string(),\n count: z.number().int().positive(),\n percentage: z.number().min(0).max(100),\n questionIds: z.array(z.string()),\n description: z.string().optional(),\n})\n\nexport type MisconceptionReport = z.infer<typeof MisconceptionReportSchema>\n\n// ============================================================================\n// Graded Assessment Schema (Premium tier)\n// ============================================================================\n\n/**\n * Complete graded assessment with scores and misconception analysis\n */\nexport const GradedAssessmentSchema = z.object({\n assessmentId: z.string().uuid(),\n userId: z.string().optional(),\n courseId: z.string(),\n lessonId: z.string().optional(),\n\n // Scores\n totalQuestions: z.number().int().positive(),\n correctCount: z.number().int().nonnegative(),\n incorrectCount: z.number().int().nonnegative(),\n score: z.number().min(0).max(100), // Percentage\n passed: z.boolean(), // Based on threshold (default 70%)\n\n // Detailed results\n responses: z.array(GradedResponseSchema),\n\n // Misconception analysis (v1.1 feature)\n misconceptions: z.array(MisconceptionReportSchema).optional(),\n topMisconceptions: z.array(z.string()).max(3).optional(),\n\n // Timing\n totalTimeSpent: z.number().int().nonnegative().optional(), // milliseconds\n averageTimePerQuestion: z.number().nonnegative().optional(),\n submittedAt: z.string().datetime(),\n gradedAt: z.string().datetime(),\n})\n\nexport type GradedAssessment = z.infer<typeof GradedAssessmentSchema>\n\n// ============================================================================\n// Validation Result Schema (Standard tier - no answer leakage)\n// ============================================================================\n\n/**\n * Result of validating an assessment submission\n * Does NOT reveal correct answers - only schema compliance\n */\nexport const ValidationResultSchema = z.object({\n valid: z.boolean(),\n errors: z.array(z.object({\n path: z.array(z.union([z.string(), z.number()])),\n message: z.string(),\n code: z.string().optional(),\n })).optional(),\n isComplete: z.boolean(), // All questions answered\n questionCount: z.number().int(),\n answeredCount: z.number().int(),\n})\n\nexport type ValidationResult = z.infer<typeof ValidationResultSchema>\n","import { z } from 'zod'\n\n// ============================================================================\n// Certification Metadata Schema (v1.2)\n// Used for Academic Transcript and Course Certification\n// ============================================================================\n\n/**\n * Certification Project Schema\n * Represents a project in a course for certification tracking\n */\nexport const CertificationProjectSchema = z.object({\n projectNumber: z.number().int().positive(),\n projectName: z.string(),\n sessionNumber: z.number().int().positive(),\n})\n\nexport type CertificationProject = z.infer<typeof CertificationProjectSchema>\n\n/**\n * Certification Metadata Schema (v1.2)\n *\n * Contains course metadata for generating:\n * - Academic Transcripts (topics list)\n * - Course Certifications (completion requirements)\n *\n * Extracted from course Welcome Note.mdx session tables.\n */\nexport const CertificationMetadataSchema = z.object({\n // Course identification\n courseId: z.string(), // e.g., \"bbp\"\n courseName: z.string(), // e.g., \"BBP: Block-based Python\"\n courseCode: z.string(), // e.g., \"BBP\"\n domain: z.string(), // e.g., \"block_based\"\n tier: z.string(), // e.g., \"foundation\"\n\n // Schema version\n schemaVersion: z.literal('1.2.0'),\n lastUpdated: z.string(), // ISO date string, e.g., \"2025-12-27\"\n\n // Academic Transcript content\n topics: z.array(z.string()), // Lesson names for transcript listing\n projects: z.array(CertificationProjectSchema),\n\n // Summary counts\n totalSessions: z.number().int().nonnegative(),\n totalTopics: z.number().int().nonnegative(),\n totalProjects: z.number().int().nonnegative(),\n})\n\nexport type CertificationMetadata = z.infer<typeof CertificationMetadataSchema>\n\n/**\n * Certification Index Schema\n * Lists all available courses with certification metadata\n */\nexport const CertificationIndexSchema = z.object({\n schemaVersion: z.string(),\n lastUpdated: z.string(),\n totalCourses: z.number().int().nonnegative(),\n courses: z.array(\n z.object({\n courseCode: z.string(),\n dataFile: z.string(),\n })\n ),\n cdnBaseUrl: z.string().url(),\n})\n\nexport type CertificationIndex = z.infer<typeof CertificationIndexSchema>\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/schemas/question.ts","../../src/schemas/assessment.ts","../../src/schemas/course.ts","../../src/schemas/certification.ts"],"names":["z"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from 'zod'\n\n// ============================================================================\n// Feedback Schema (v1.1 enhancement)\n// ============================================================================\n\n/**\n * Structured feedback following the \"Not Yet\" protocol\n * - short: Brief acknowledgment (1 sentence)\n * - detailed: Full explanation of the misconception\n * - socraticHint: Optional guiding question for discovery learning\n */\nexport const FeedbackSchema = z.object({\n short: z.string().min(1).max(200),\n detailed: z.string().min(1).max(1000),\n socraticHint: z.string().max(300).optional(),\n})\n\nexport type Feedback = z.infer<typeof FeedbackSchema>\n\n// ============================================================================\n// Option Schema\n// ============================================================================\n\nexport const OptionKeySchema = z.enum(['A', 'B', 'C', 'D'])\n\nexport type OptionKey = z.infer<typeof OptionKeySchema>\n\n/**\n * Answer option with optional misconception tracking (v1.1)\n */\nexport const OptionSchema = z.object({\n key: OptionKeySchema,\n text: z.string().min(1),\n isCorrect: z.boolean(),\n // v1.1 fields - optional for backward compatibility\n misconceptionId: z.string().nullish(),\n feedback: FeedbackSchema.optional(),\n})\n\nexport type Option = z.infer<typeof OptionSchema>\n\n// ============================================================================\n// Question Type Enums\n// ============================================================================\n\nexport const QuestionTypeSchema = z.enum([\n // Core assessment types (original v1.0)\n 'vocabulary',\n 'code_understanding',\n 'problem_solving',\n 'application',\n 'reflection',\n // Code-focused types\n 'debugging',\n 'trace',\n 'predict',\n // Higher-order thinking\n 'analyze',\n 'evaluation',\n 'synthesis',\n 'design',\n 'conceptual',\n 'explain',\n // Domain-specific\n 'bebras',\n 'blockmodel',\n 'ethical_reasoning',\n])\n\nexport type QuestionType = z.infer<typeof QuestionTypeSchema>\n\n/**\n * Question archetype for pedagogical classification\n * - vocabulary: Definition/terminology questions\n * - trace: Code tracing (mental execution)\n * - bebras: Logic-first, computational thinking\n * - blockmodel: Surface/flow/purpose analysis\n * - parsons: Code block reordering (future)\n * - predict: PRIMM predict phase\n * - explain: PRIMM explain phase\n * - debugging: Find/fix errors\n * - application: Apply concept to scenario\n * - problem_solving: Solve novel problems\n * - evaluation: Judge/compare approaches\n * - reflection: Meta-cognitive self-assessment\n * - conceptual: Pure concept understanding\n * - analysis: Compare/decompose\n * - design: System/solution design\n * - synthesis: Combine ideas to create\n * - code: Code-focused analysis\n */\nexport const QuestionArchetypeSchema = z.enum([\n // Original archetypes (v1.1)\n 'vocabulary',\n 'trace',\n 'bebras',\n 'blockmodel',\n 'parsons',\n // Assessment patterns\n 'application',\n 'problem_solving',\n 'debugging',\n 'predict',\n 'explain',\n 'evaluation',\n 'reflection',\n 'conceptual',\n 'analysis',\n 'design',\n 'synthesis',\n 'code',\n])\n\nexport type QuestionArchetype = z.infer<typeof QuestionArchetypeSchema>\n\nexport const DifficultySchema = z.enum(['easy', 'medium', 'hard', 'challenge'])\n\nexport type Difficulty = z.infer<typeof DifficultySchema>\n\nexport const BloomsTaxonomySchema = z.enum([\n 'remember',\n 'understand',\n 'apply',\n 'analyze',\n 'evaluate',\n 'create',\n])\n\nexport type BloomsTaxonomy = z.infer<typeof BloomsTaxonomySchema>\n\n// ============================================================================\n// Question Metadata Schema\n// ============================================================================\n\nexport const QuestionMetadataSchema = z.object({\n difficulty: DifficultySchema,\n estimatedTime: z.number().int().positive(), // seconds\n bloomsTaxonomy: BloomsTaxonomySchema,\n tags: z.array(z.string()),\n conceptTags: z.array(z.string()).optional(), // mastery-relevant concept tags\n metaTags: z.array(z.string()).optional(), // Bloom's types, course codes, internal\n source: z.string().default('exit-ticket'),\n version: z.string().default('1.1'),\n createdDate: z.string().optional(),\n lastModified: z.string().optional(),\n})\n\nexport type QuestionMetadata = z.infer<typeof QuestionMetadataSchema>\n\n// ============================================================================\n// Question Schema (v1.1)\n// ============================================================================\n\n/**\n * Full question schema with v1.1 enhancements:\n * - questionArchetype: Pedagogical classification\n * - misconceptionTargets: Expected misconceptions this question probes\n * - options with misconceptionId and structured feedback\n */\nexport const QuestionSchema = z.object({\n // Identifiers\n questionId: z.string().regex(/^[a-z0-9][-a-z0-9]*-(?:l\\d+-)?q\\d+$/),\n globalId: z.string().regex(/^exit-ticket-[a-z0-9][-a-z0-9]*$/),\n questionNumber: z.number().int().positive().max(5),\n\n // Classification\n questionType: QuestionTypeSchema,\n questionTypeLabel: z.string(),\n questionArchetype: QuestionArchetypeSchema.optional(), // v1.1\n\n // Content\n prompt: z.string().min(10),\n hasCodeBlock: z.boolean(),\n codeLanguage: z.string().nullable(),\n codeContent: z.string().nullable(),\n\n // Misconception targeting (v1.1)\n misconceptionTargets: z.array(z.string()).optional(),\n\n // Answer options (exactly 4)\n options: z.array(OptionSchema).length(4),\n\n // Correct answer\n correctAnswer: OptionKeySchema,\n correctAnswerText: z.string(),\n\n // Metadata\n metadata: QuestionMetadataSchema,\n})\n\nexport type Question = z.infer<typeof QuestionSchema>\n\n// ============================================================================\n// Question without answer (for Standard tier - no answer leakage)\n// ============================================================================\n\nexport const QuestionWithoutAnswerSchema = QuestionSchema.omit({\n correctAnswer: true,\n correctAnswerText: true,\n}).extend({\n options: z.array(\n OptionSchema.omit({\n isCorrect: true,\n feedback: true,\n misconceptionId: true,\n })\n ).length(4),\n})\n\nexport type QuestionWithoutAnswer = z.infer<typeof QuestionWithoutAnswerSchema>\n","import { z } from 'zod'\nimport { OptionKeySchema, FeedbackSchema } from './question'\n\n// ============================================================================\n// Assessment Blueprint Schema (for course-level summative assessments)\n// ============================================================================\n\n/**\n * Defines a summative assessment (quiz) that covers multiple lessons.\n * Stored in CDN course exports and used by the assessment module to build quizzes.\n */\nexport const AssessmentBlueprintSchema = z.object({\n assessmentId: z.string(), // e.g., \"cs1-quiz-1\"\n title: z.string(), // e.g., \"Quiz 1\"\n description: z.string(),\n lessonRange: z.tuple([z.number().int().positive(), z.number().int().positive()])\n .refine(([start, end]) => start <= end, { message: 'lessonRange start must be <= end' }),\n questionCount: z.number().int().positive(),\n passingScore: z.number().min(0).max(100),\n timeLimitMinutes: z.number().int().positive().nullable(),\n tags: z.array(z.string()).optional(),\n})\n\nexport type AssessmentBlueprint = z.infer<typeof AssessmentBlueprintSchema>\n\n// ============================================================================\n// User Response Schema\n// ============================================================================\n\n/**\n * A single user response to a question\n */\nexport const UserResponseSchema = z.object({\n questionId: z.string(),\n selectedAnswer: OptionKeySchema,\n timeSpent: z.number().int().nonnegative().optional(), // milliseconds\n submittedAt: z.string().datetime().optional(),\n})\n\nexport type UserResponse = z.infer<typeof UserResponseSchema>\n\n// ============================================================================\n// Assessment Submission Schema\n// ============================================================================\n\n/**\n * An assessment submission containing multiple responses\n */\nexport const AssessmentSubmissionSchema = z.object({\n assessmentId: z.string().uuid().optional(), // Generated if not provided\n userId: z.string().optional(), // For authenticated users\n sessionId: z.string().optional(), // For anonymous sessions\n courseId: z.string(),\n lessonId: z.string().optional(),\n responses: z.array(UserResponseSchema).min(1),\n submittedAt: z.string().datetime(),\n metadata: z.record(z.unknown()).optional(), // Custom metadata\n})\n\nexport type AssessmentSubmission = z.infer<typeof AssessmentSubmissionSchema>\n\n// ============================================================================\n// Graded Response Schema (Premium tier)\n// ============================================================================\n\n/**\n * Result of grading a single response\n */\nexport const GradedResponseSchema = z.object({\n questionId: z.string(),\n selectedAnswer: OptionKeySchema,\n correctAnswer: OptionKeySchema,\n isCorrect: z.boolean(),\n misconceptionId: z.string().nullable(), // For incorrect answers\n feedback: FeedbackSchema.optional(),\n timeSpent: z.number().int().nonnegative().optional(),\n})\n\nexport type GradedResponse = z.infer<typeof GradedResponseSchema>\n\n// ============================================================================\n// Misconception Report Schema (Premium tier)\n// ============================================================================\n\n/**\n * Aggregated misconception analysis for an assessment\n */\nexport const MisconceptionReportSchema = z.object({\n misconceptionId: z.string(),\n count: z.number().int().positive(),\n percentage: z.number().min(0).max(100),\n questionIds: z.array(z.string()),\n description: z.string().optional(),\n})\n\nexport type MisconceptionReport = z.infer<typeof MisconceptionReportSchema>\n\n// ============================================================================\n// Graded Assessment Schema (Premium tier)\n// ============================================================================\n\n/**\n * Complete graded assessment with scores and misconception analysis\n */\nexport const GradedAssessmentSchema = z.object({\n assessmentId: z.string(),\n userId: z.string().optional(),\n courseId: z.string(),\n lessonId: z.string().optional(),\n\n // Scores\n totalQuestions: z.number().int().positive(),\n correctCount: z.number().int().nonnegative(),\n incorrectCount: z.number().int().nonnegative(),\n score: z.number().min(0).max(100), // Percentage\n passed: z.boolean(), // Based on threshold (default 70%)\n\n // Detailed results\n responses: z.array(GradedResponseSchema),\n\n // Misconception analysis (v1.1 feature)\n misconceptions: z.array(MisconceptionReportSchema).optional(),\n topMisconceptions: z.array(z.string()).max(3).optional(),\n\n // Timing\n totalTimeSpent: z.number().int().nonnegative().optional(), // milliseconds\n averageTimePerQuestion: z.number().nonnegative().optional(),\n submittedAt: z.string().datetime(),\n gradedAt: z.string().datetime(),\n})\n\nexport type GradedAssessment = z.infer<typeof GradedAssessmentSchema>\n\n// ============================================================================\n// Validation Result Schema (Standard tier - no answer leakage)\n// ============================================================================\n\n/**\n * Result of validating an assessment submission\n * Does NOT reveal correct answers - only schema compliance\n */\nexport const ValidationResultSchema = z.object({\n valid: z.boolean(),\n errors: z.array(z.object({\n path: z.array(z.union([z.string(), z.number()])),\n message: z.string(),\n code: z.string().optional(),\n })).optional(),\n isComplete: z.boolean(), // All questions answered\n questionCount: z.number().int(),\n answeredCount: z.number().int(),\n})\n\nexport type ValidationResult = z.infer<typeof ValidationResultSchema>\n","import { z } from 'zod'\nimport { QuestionSchema } from './question'\nimport { AssessmentBlueprintSchema } from './assessment'\n\n// ============================================================================\n// Course Domain & Tier\n// ============================================================================\n\nexport const CourseDomainSchema = z.enum([\n // AI & Data Science\n 'ai_data_science',\n 'ai_ml_cv',\n 'ai_generative',\n 'ai_advanced',\n 'ai', // Prompt Engineering (general AI)\n // Web Development\n 'web_development',\n // Mobile Development\n 'mobile_development',\n 'mobile',\n // Block-based Programming\n 'block_based',\n 'python_programming',\n 'design',\n 'artificial_intelligence', // Block-based AI courses (BBAI)\n // Computer Science\n 'cs_foundations', // CS1-CS4 courses\n // Foundation\n 'foundation',\n 'creative_computing',\n // Utility / Tools\n 'tools', // IDE Setup, Git, Vibe Coding\n])\n\nexport type CourseDomain = z.infer<typeof CourseDomainSchema>\n\nexport const CourseTierSchema = z.enum([\n 'beginner', // Block-based courses (BBW, BBP, BBD, BBAI)\n 'foundation',\n 'intermediate',\n 'advanced',\n])\n\nexport type CourseTier = z.infer<typeof CourseTierSchema>\n\n// ============================================================================\n// Lesson Schema\n// ============================================================================\n\nexport const LessonSchema = z.object({\n lessonId: z.string(), // e.g., \"ai-1-lesson-1\"\n lessonNumber: z.number().int().positive(),\n lessonTitle: z.string(),\n lessonSlug: z.string().optional(),\n totalQuestions: z.number().int().positive().default(5),\n questions: z.array(QuestionSchema),\n})\n\nexport type Lesson = z.infer<typeof LessonSchema>\n\n// ============================================================================\n// Course Schema\n// ============================================================================\n\nexport const CourseSchema = z.object({\n courseId: z.string(), // e.g., \"ai-1\"\n courseName: z.string(), // e.g., \"AI-1 Data Analysis and Data Science\"\n courseCode: z.string(), // e.g., \"AI1\"\n domain: CourseDomainSchema,\n tier: CourseTierSchema,\n difficulty: z.number().int().min(1).max(5),\n totalLessons: z.number().int().positive(),\n totalQuestions: z.number().int().positive(),\n sourceFile: z.string().optional(),\n lessons: z.array(LessonSchema),\n assessments: z.array(AssessmentBlueprintSchema).optional(),\n})\n\nexport type Course = z.infer<typeof CourseSchema>\n\n// ============================================================================\n// Course Summary (without questions - for listing)\n// ============================================================================\n\nexport const CourseSummarySchema = CourseSchema.omit({ lessons: true }).extend({\n lessons: z.array(\n LessonSchema.omit({ questions: true })\n ).optional(),\n})\n\nexport type CourseSummary = z.infer<typeof CourseSummarySchema>\n","import { z } from 'zod'\n\n// ============================================================================\n// Certification Metadata Schema (v1.2)\n// Used for Academic Transcript and Course Certification\n// ============================================================================\n\n/**\n * Certification Project Schema\n * Represents a project in a course for certification tracking\n */\nexport const CertificationProjectSchema = z.object({\n projectNumber: z.number().int().positive(),\n projectName: z.string(),\n sessionNumber: z.number().int().positive(),\n})\n\nexport type CertificationProject = z.infer<typeof CertificationProjectSchema>\n\n/**\n * Certification Metadata Schema (v1.2)\n *\n * Contains course metadata for generating:\n * - Academic Transcripts (topics list)\n * - Course Certifications (completion requirements)\n *\n * Extracted from course Welcome Note.mdx session tables.\n */\nexport const CertificationMetadataSchema = z.object({\n // Course identification\n courseId: z.string(), // e.g., \"bbp\"\n courseName: z.string(), // e.g., \"BBP: Block-based Python\"\n courseCode: z.string(), // e.g., \"BBP\"\n domain: z.string(), // e.g., \"block_based\"\n tier: z.string(), // e.g., \"foundation\"\n\n // Schema version\n schemaVersion: z.literal('1.2.0'),\n lastUpdated: z.string(), // ISO date string, e.g., \"2025-12-27\"\n\n // Academic Transcript content\n topics: z.array(z.string()), // Lesson names for transcript listing\n projects: z.array(CertificationProjectSchema),\n\n // Summary counts\n totalSessions: z.number().int().nonnegative(),\n totalTopics: z.number().int().nonnegative(),\n totalProjects: z.number().int().nonnegative(),\n})\n\nexport type CertificationMetadata = z.infer<typeof CertificationMetadataSchema>\n\n/**\n * Certification Index Schema\n * Lists all available courses with certification metadata\n */\nexport const CertificationIndexSchema = z.object({\n schemaVersion: z.string(),\n lastUpdated: z.string(),\n totalCourses: z.number().int().nonnegative(),\n courses: z.array(\n z.object({\n courseCode: z.string(),\n dataFile: z.string(),\n })\n ),\n cdnBaseUrl: z.string().url(),\n})\n\nexport type CertificationIndex = z.infer<typeof CertificationIndexSchema>\n"]}
|
|
@@ -14,22 +14,52 @@ var OptionSchema = zod.z.object({
|
|
|
14
14
|
text: zod.z.string().min(1),
|
|
15
15
|
isCorrect: zod.z.boolean(),
|
|
16
16
|
// v1.1 fields - optional for backward compatibility
|
|
17
|
-
misconceptionId: zod.z.string().
|
|
17
|
+
misconceptionId: zod.z.string().nullish(),
|
|
18
18
|
feedback: FeedbackSchema.optional()
|
|
19
19
|
});
|
|
20
20
|
var QuestionTypeSchema = zod.z.enum([
|
|
21
|
+
// Core assessment types (original v1.0)
|
|
21
22
|
"vocabulary",
|
|
22
23
|
"code_understanding",
|
|
23
24
|
"problem_solving",
|
|
24
25
|
"application",
|
|
25
|
-
"reflection"
|
|
26
|
+
"reflection",
|
|
27
|
+
// Code-focused types
|
|
28
|
+
"debugging",
|
|
29
|
+
"trace",
|
|
30
|
+
"predict",
|
|
31
|
+
// Higher-order thinking
|
|
32
|
+
"analyze",
|
|
33
|
+
"evaluation",
|
|
34
|
+
"synthesis",
|
|
35
|
+
"design",
|
|
36
|
+
"conceptual",
|
|
37
|
+
"explain",
|
|
38
|
+
// Domain-specific
|
|
39
|
+
"bebras",
|
|
40
|
+
"blockmodel",
|
|
41
|
+
"ethical_reasoning"
|
|
26
42
|
]);
|
|
27
43
|
var QuestionArchetypeSchema = zod.z.enum([
|
|
44
|
+
// Original archetypes (v1.1)
|
|
28
45
|
"vocabulary",
|
|
29
46
|
"trace",
|
|
30
47
|
"bebras",
|
|
31
48
|
"blockmodel",
|
|
32
|
-
"parsons"
|
|
49
|
+
"parsons",
|
|
50
|
+
// Assessment patterns
|
|
51
|
+
"application",
|
|
52
|
+
"problem_solving",
|
|
53
|
+
"debugging",
|
|
54
|
+
"predict",
|
|
55
|
+
"explain",
|
|
56
|
+
"evaluation",
|
|
57
|
+
"reflection",
|
|
58
|
+
"conceptual",
|
|
59
|
+
"analysis",
|
|
60
|
+
"design",
|
|
61
|
+
"synthesis",
|
|
62
|
+
"code"
|
|
33
63
|
]);
|
|
34
64
|
var DifficultySchema = zod.z.enum(["easy", "medium", "hard", "challenge"]);
|
|
35
65
|
var BloomsTaxonomySchema = zod.z.enum([
|
|
@@ -46,6 +76,10 @@ var QuestionMetadataSchema = zod.z.object({
|
|
|
46
76
|
// seconds
|
|
47
77
|
bloomsTaxonomy: BloomsTaxonomySchema,
|
|
48
78
|
tags: zod.z.array(zod.z.string()),
|
|
79
|
+
conceptTags: zod.z.array(zod.z.string()).optional(),
|
|
80
|
+
// mastery-relevant concept tags
|
|
81
|
+
metaTags: zod.z.array(zod.z.string()).optional(),
|
|
82
|
+
// Bloom's types, course codes, internal
|
|
49
83
|
source: zod.z.string().default("exit-ticket"),
|
|
50
84
|
version: zod.z.string().default("1.1"),
|
|
51
85
|
createdDate: zod.z.string().optional(),
|
|
@@ -53,8 +87,8 @@ var QuestionMetadataSchema = zod.z.object({
|
|
|
53
87
|
});
|
|
54
88
|
var QuestionSchema = zod.z.object({
|
|
55
89
|
// Identifiers
|
|
56
|
-
questionId: zod.z.string().regex(/^[a-z0-9-]
|
|
57
|
-
globalId: zod.z.string().regex(/^exit-ticket
|
|
90
|
+
questionId: zod.z.string().regex(/^[a-z0-9][-a-z0-9]*-(?:l\d+-)?q\d+$/),
|
|
91
|
+
globalId: zod.z.string().regex(/^exit-ticket-[a-z0-9][-a-z0-9]*$/),
|
|
58
92
|
questionNumber: zod.z.number().int().positive().max(5),
|
|
59
93
|
// Classification
|
|
60
94
|
questionType: QuestionTypeSchema,
|
|
@@ -88,58 +122,17 @@ QuestionSchema.omit({
|
|
|
88
122
|
})
|
|
89
123
|
).length(4)
|
|
90
124
|
});
|
|
91
|
-
var
|
|
92
|
-
|
|
93
|
-
"
|
|
94
|
-
|
|
95
|
-
"
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
// Block-based Programming
|
|
103
|
-
"block_based",
|
|
104
|
-
"python_programming",
|
|
105
|
-
"design",
|
|
106
|
-
// Foundation
|
|
107
|
-
"foundation",
|
|
108
|
-
"creative_computing"
|
|
109
|
-
]);
|
|
110
|
-
var CourseTierSchema = zod.z.enum([
|
|
111
|
-
"foundation",
|
|
112
|
-
"intermediate",
|
|
113
|
-
"advanced"
|
|
114
|
-
]);
|
|
115
|
-
var LessonSchema = zod.z.object({
|
|
116
|
-
lessonId: zod.z.string(),
|
|
117
|
-
// e.g., "ai-1-lesson-1"
|
|
118
|
-
lessonNumber: zod.z.number().int().positive(),
|
|
119
|
-
lessonTitle: zod.z.string(),
|
|
120
|
-
lessonSlug: zod.z.string().optional(),
|
|
121
|
-
totalQuestions: zod.z.number().int().positive().default(5),
|
|
122
|
-
questions: zod.z.array(QuestionSchema)
|
|
123
|
-
});
|
|
124
|
-
var CourseSchema = zod.z.object({
|
|
125
|
-
courseId: zod.z.string(),
|
|
126
|
-
// e.g., "ai-1"
|
|
127
|
-
courseName: zod.z.string(),
|
|
128
|
-
// e.g., "AI-1 Data Analysis and Data Science"
|
|
129
|
-
courseCode: zod.z.string(),
|
|
130
|
-
// e.g., "AI1"
|
|
131
|
-
domain: CourseDomainSchema,
|
|
132
|
-
tier: CourseTierSchema,
|
|
133
|
-
difficulty: zod.z.number().int().min(1).max(5),
|
|
134
|
-
totalLessons: zod.z.number().int().positive(),
|
|
135
|
-
totalQuestions: zod.z.number().int().positive(),
|
|
136
|
-
sourceFile: zod.z.string().optional(),
|
|
137
|
-
lessons: zod.z.array(LessonSchema)
|
|
138
|
-
});
|
|
139
|
-
CourseSchema.omit({ lessons: true }).extend({
|
|
140
|
-
lessons: zod.z.array(
|
|
141
|
-
LessonSchema.omit({ questions: true })
|
|
142
|
-
).optional()
|
|
125
|
+
var AssessmentBlueprintSchema = zod.z.object({
|
|
126
|
+
assessmentId: zod.z.string(),
|
|
127
|
+
// e.g., "cs1-quiz-1"
|
|
128
|
+
title: zod.z.string(),
|
|
129
|
+
// e.g., "Quiz 1"
|
|
130
|
+
description: zod.z.string(),
|
|
131
|
+
lessonRange: zod.z.tuple([zod.z.number().int().positive(), zod.z.number().int().positive()]).refine(([start, end]) => start <= end, { message: "lessonRange start must be <= end" }),
|
|
132
|
+
questionCount: zod.z.number().int().positive(),
|
|
133
|
+
passingScore: zod.z.number().min(0).max(100),
|
|
134
|
+
timeLimitMinutes: zod.z.number().int().positive().nullable(),
|
|
135
|
+
tags: zod.z.array(zod.z.string()).optional()
|
|
143
136
|
});
|
|
144
137
|
var UserResponseSchema = zod.z.object({
|
|
145
138
|
questionId: zod.z.string(),
|
|
@@ -180,7 +173,7 @@ var MisconceptionReportSchema = zod.z.object({
|
|
|
180
173
|
description: zod.z.string().optional()
|
|
181
174
|
});
|
|
182
175
|
zod.z.object({
|
|
183
|
-
assessmentId: zod.z.string()
|
|
176
|
+
assessmentId: zod.z.string(),
|
|
184
177
|
userId: zod.z.string().optional(),
|
|
185
178
|
courseId: zod.z.string(),
|
|
186
179
|
lessonId: zod.z.string().optional(),
|
|
@@ -216,6 +209,74 @@ zod.z.object({
|
|
|
216
209
|
questionCount: zod.z.number().int(),
|
|
217
210
|
answeredCount: zod.z.number().int()
|
|
218
211
|
});
|
|
212
|
+
|
|
213
|
+
// src/schemas/course.ts
|
|
214
|
+
var CourseDomainSchema = zod.z.enum([
|
|
215
|
+
// AI & Data Science
|
|
216
|
+
"ai_data_science",
|
|
217
|
+
"ai_ml_cv",
|
|
218
|
+
"ai_generative",
|
|
219
|
+
"ai_advanced",
|
|
220
|
+
"ai",
|
|
221
|
+
// Prompt Engineering (general AI)
|
|
222
|
+
// Web Development
|
|
223
|
+
"web_development",
|
|
224
|
+
// Mobile Development
|
|
225
|
+
"mobile_development",
|
|
226
|
+
"mobile",
|
|
227
|
+
// Block-based Programming
|
|
228
|
+
"block_based",
|
|
229
|
+
"python_programming",
|
|
230
|
+
"design",
|
|
231
|
+
"artificial_intelligence",
|
|
232
|
+
// Block-based AI courses (BBAI)
|
|
233
|
+
// Computer Science
|
|
234
|
+
"cs_foundations",
|
|
235
|
+
// CS1-CS4 courses
|
|
236
|
+
// Foundation
|
|
237
|
+
"foundation",
|
|
238
|
+
"creative_computing",
|
|
239
|
+
// Utility / Tools
|
|
240
|
+
"tools"
|
|
241
|
+
// IDE Setup, Git, Vibe Coding
|
|
242
|
+
]);
|
|
243
|
+
var CourseTierSchema = zod.z.enum([
|
|
244
|
+
"beginner",
|
|
245
|
+
// Block-based courses (BBW, BBP, BBD, BBAI)
|
|
246
|
+
"foundation",
|
|
247
|
+
"intermediate",
|
|
248
|
+
"advanced"
|
|
249
|
+
]);
|
|
250
|
+
var LessonSchema = zod.z.object({
|
|
251
|
+
lessonId: zod.z.string(),
|
|
252
|
+
// e.g., "ai-1-lesson-1"
|
|
253
|
+
lessonNumber: zod.z.number().int().positive(),
|
|
254
|
+
lessonTitle: zod.z.string(),
|
|
255
|
+
lessonSlug: zod.z.string().optional(),
|
|
256
|
+
totalQuestions: zod.z.number().int().positive().default(5),
|
|
257
|
+
questions: zod.z.array(QuestionSchema)
|
|
258
|
+
});
|
|
259
|
+
var CourseSchema = zod.z.object({
|
|
260
|
+
courseId: zod.z.string(),
|
|
261
|
+
// e.g., "ai-1"
|
|
262
|
+
courseName: zod.z.string(),
|
|
263
|
+
// e.g., "AI-1 Data Analysis and Data Science"
|
|
264
|
+
courseCode: zod.z.string(),
|
|
265
|
+
// e.g., "AI1"
|
|
266
|
+
domain: CourseDomainSchema,
|
|
267
|
+
tier: CourseTierSchema,
|
|
268
|
+
difficulty: zod.z.number().int().min(1).max(5),
|
|
269
|
+
totalLessons: zod.z.number().int().positive(),
|
|
270
|
+
totalQuestions: zod.z.number().int().positive(),
|
|
271
|
+
sourceFile: zod.z.string().optional(),
|
|
272
|
+
lessons: zod.z.array(LessonSchema),
|
|
273
|
+
assessments: zod.z.array(AssessmentBlueprintSchema).optional()
|
|
274
|
+
});
|
|
275
|
+
CourseSchema.omit({ lessons: true }).extend({
|
|
276
|
+
lessons: zod.z.array(
|
|
277
|
+
LessonSchema.omit({ questions: true })
|
|
278
|
+
).optional()
|
|
279
|
+
});
|
|
219
280
|
var CertificationProjectSchema = zod.z.object({
|
|
220
281
|
projectNumber: zod.z.number().int().positive(),
|
|
221
282
|
projectName: zod.z.string(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/schemas/question.ts","../../src/schemas/course.ts","../../src/schemas/assessment.ts","../../src/schemas/certification.ts","../../src/validation/client.ts"],"names":["z"],"mappings":"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","file":"index.cjs","sourcesContent":["import { z } from 'zod'\n\n// ============================================================================\n// Feedback Schema (v1.1 enhancement)\n// ============================================================================\n\n/**\n * Structured feedback following the \"Not Yet\" protocol\n * - short: Brief acknowledgment (1 sentence)\n * - detailed: Full explanation of the misconception\n * - socraticHint: Optional guiding question for discovery learning\n */\nexport const FeedbackSchema = z.object({\n short: z.string().min(1).max(200),\n detailed: z.string().min(1).max(1000),\n socraticHint: z.string().max(300).optional(),\n})\n\nexport type Feedback = z.infer<typeof FeedbackSchema>\n\n// ============================================================================\n// Option Schema\n// ============================================================================\n\nexport const OptionKeySchema = z.enum(['A', 'B', 'C', 'D'])\n\nexport type OptionKey = z.infer<typeof OptionKeySchema>\n\n/**\n * Answer option with optional misconception tracking (v1.1)\n */\nexport const OptionSchema = z.object({\n key: OptionKeySchema,\n text: z.string().min(1),\n isCorrect: z.boolean(),\n // v1.1 fields - optional for backward compatibility\n misconceptionId: z.string().optional(),\n feedback: FeedbackSchema.optional(),\n})\n\nexport type Option = z.infer<typeof OptionSchema>\n\n// ============================================================================\n// Question Type Enums\n// ============================================================================\n\nexport const QuestionTypeSchema = z.enum([\n 'vocabulary',\n 'code_understanding',\n 'problem_solving',\n 'application',\n 'reflection',\n])\n\nexport type QuestionType = z.infer<typeof QuestionTypeSchema>\n\n/**\n * Question archetype for pedagogical classification\n * - vocabulary: Definition/terminology questions\n * - trace: Code tracing (mental execution)\n * - bebras: Logic-first, computational thinking\n * - blockmodel: Surface/flow/purpose analysis\n * - parsons: Code block reordering (future)\n */\nexport const QuestionArchetypeSchema = z.enum([\n 'vocabulary',\n 'trace',\n 'bebras',\n 'blockmodel',\n 'parsons',\n])\n\nexport type QuestionArchetype = z.infer<typeof QuestionArchetypeSchema>\n\nexport const DifficultySchema = z.enum(['easy', 'medium', 'hard', 'challenge'])\n\nexport type Difficulty = z.infer<typeof DifficultySchema>\n\nexport const BloomsTaxonomySchema = z.enum([\n 'remember',\n 'understand',\n 'apply',\n 'analyze',\n 'evaluate',\n 'create',\n])\n\nexport type BloomsTaxonomy = z.infer<typeof BloomsTaxonomySchema>\n\n// ============================================================================\n// Question Metadata Schema\n// ============================================================================\n\nexport const QuestionMetadataSchema = z.object({\n difficulty: DifficultySchema,\n estimatedTime: z.number().int().positive(), // seconds\n bloomsTaxonomy: BloomsTaxonomySchema,\n tags: z.array(z.string()),\n source: z.string().default('exit-ticket'),\n version: z.string().default('1.1'),\n createdDate: z.string().optional(),\n lastModified: z.string().optional(),\n})\n\nexport type QuestionMetadata = z.infer<typeof QuestionMetadataSchema>\n\n// ============================================================================\n// Question Schema (v1.1)\n// ============================================================================\n\n/**\n * Full question schema with v1.1 enhancements:\n * - questionArchetype: Pedagogical classification\n * - misconceptionTargets: Expected misconceptions this question probes\n * - options with misconceptionId and structured feedback\n */\nexport const QuestionSchema = z.object({\n // Identifiers\n questionId: z.string().regex(/^[a-z0-9-]+-l\\d+-q\\d+$/),\n globalId: z.string().regex(/^exit-ticket-\\d{4}$/),\n questionNumber: z.number().int().positive().max(5),\n\n // Classification\n questionType: QuestionTypeSchema,\n questionTypeLabel: z.string(),\n questionArchetype: QuestionArchetypeSchema.optional(), // v1.1\n\n // Content\n prompt: z.string().min(10),\n hasCodeBlock: z.boolean(),\n codeLanguage: z.string().nullable(),\n codeContent: z.string().nullable(),\n\n // Misconception targeting (v1.1)\n misconceptionTargets: z.array(z.string()).optional(),\n\n // Answer options (exactly 4)\n options: z.array(OptionSchema).length(4),\n\n // Correct answer\n correctAnswer: OptionKeySchema,\n correctAnswerText: z.string(),\n\n // Metadata\n metadata: QuestionMetadataSchema,\n})\n\nexport type Question = z.infer<typeof QuestionSchema>\n\n// ============================================================================\n// Question without answer (for Standard tier - no answer leakage)\n// ============================================================================\n\nexport const QuestionWithoutAnswerSchema = QuestionSchema.omit({\n correctAnswer: true,\n correctAnswerText: true,\n}).extend({\n options: z.array(\n OptionSchema.omit({\n isCorrect: true,\n feedback: true,\n misconceptionId: true,\n })\n ).length(4),\n})\n\nexport type QuestionWithoutAnswer = z.infer<typeof QuestionWithoutAnswerSchema>\n","import { z } from 'zod'\nimport { QuestionSchema } from './question'\n\n// ============================================================================\n// Course Domain & Tier\n// ============================================================================\n\nexport const CourseDomainSchema = z.enum([\n // AI & Data Science\n 'ai_data_science',\n 'ai_ml_cv',\n 'ai_generative',\n 'ai_advanced',\n // Web Development\n 'web_development',\n // Mobile Development\n 'mobile_development',\n 'mobile',\n // Block-based Programming\n 'block_based',\n 'python_programming',\n 'design',\n // Foundation\n 'foundation',\n 'creative_computing',\n])\n\nexport type CourseDomain = z.infer<typeof CourseDomainSchema>\n\nexport const CourseTierSchema = z.enum([\n 'foundation',\n 'intermediate',\n 'advanced',\n])\n\nexport type CourseTier = z.infer<typeof CourseTierSchema>\n\n// ============================================================================\n// Lesson Schema\n// ============================================================================\n\nexport const LessonSchema = z.object({\n lessonId: z.string(), // e.g., \"ai-1-lesson-1\"\n lessonNumber: z.number().int().positive(),\n lessonTitle: z.string(),\n lessonSlug: z.string().optional(),\n totalQuestions: z.number().int().positive().default(5),\n questions: z.array(QuestionSchema),\n})\n\nexport type Lesson = z.infer<typeof LessonSchema>\n\n// ============================================================================\n// Course Schema\n// ============================================================================\n\nexport const CourseSchema = z.object({\n courseId: z.string(), // e.g., \"ai-1\"\n courseName: z.string(), // e.g., \"AI-1 Data Analysis and Data Science\"\n courseCode: z.string(), // e.g., \"AI1\"\n domain: CourseDomainSchema,\n tier: CourseTierSchema,\n difficulty: z.number().int().min(1).max(5),\n totalLessons: z.number().int().positive(),\n totalQuestions: z.number().int().positive(),\n sourceFile: z.string().optional(),\n lessons: z.array(LessonSchema),\n})\n\nexport type Course = z.infer<typeof CourseSchema>\n\n// ============================================================================\n// Course Summary (without questions - for listing)\n// ============================================================================\n\nexport const CourseSummarySchema = CourseSchema.omit({ lessons: true }).extend({\n lessons: z.array(\n LessonSchema.omit({ questions: true })\n ).optional(),\n})\n\nexport type CourseSummary = z.infer<typeof CourseSummarySchema>\n","import { z } from 'zod'\nimport { OptionKeySchema, FeedbackSchema } from './question'\n\n// ============================================================================\n// User Response Schema\n// ============================================================================\n\n/**\n * A single user response to a question\n */\nexport const UserResponseSchema = z.object({\n questionId: z.string(),\n selectedAnswer: OptionKeySchema,\n timeSpent: z.number().int().nonnegative().optional(), // milliseconds\n submittedAt: z.string().datetime().optional(),\n})\n\nexport type UserResponse = z.infer<typeof UserResponseSchema>\n\n// ============================================================================\n// Assessment Submission Schema\n// ============================================================================\n\n/**\n * An assessment submission containing multiple responses\n */\nexport const AssessmentSubmissionSchema = z.object({\n assessmentId: z.string().uuid().optional(), // Generated if not provided\n userId: z.string().optional(), // For authenticated users\n sessionId: z.string().optional(), // For anonymous sessions\n courseId: z.string(),\n lessonId: z.string().optional(),\n responses: z.array(UserResponseSchema).min(1),\n submittedAt: z.string().datetime(),\n metadata: z.record(z.unknown()).optional(), // Custom metadata\n})\n\nexport type AssessmentSubmission = z.infer<typeof AssessmentSubmissionSchema>\n\n// ============================================================================\n// Graded Response Schema (Premium tier)\n// ============================================================================\n\n/**\n * Result of grading a single response\n */\nexport const GradedResponseSchema = z.object({\n questionId: z.string(),\n selectedAnswer: OptionKeySchema,\n correctAnswer: OptionKeySchema,\n isCorrect: z.boolean(),\n misconceptionId: z.string().nullable(), // For incorrect answers\n feedback: FeedbackSchema.optional(),\n timeSpent: z.number().int().nonnegative().optional(),\n})\n\nexport type GradedResponse = z.infer<typeof GradedResponseSchema>\n\n// ============================================================================\n// Misconception Report Schema (Premium tier)\n// ============================================================================\n\n/**\n * Aggregated misconception analysis for an assessment\n */\nexport const MisconceptionReportSchema = z.object({\n misconceptionId: z.string(),\n count: z.number().int().positive(),\n percentage: z.number().min(0).max(100),\n questionIds: z.array(z.string()),\n description: z.string().optional(),\n})\n\nexport type MisconceptionReport = z.infer<typeof MisconceptionReportSchema>\n\n// ============================================================================\n// Graded Assessment Schema (Premium tier)\n// ============================================================================\n\n/**\n * Complete graded assessment with scores and misconception analysis\n */\nexport const GradedAssessmentSchema = z.object({\n assessmentId: z.string().uuid(),\n userId: z.string().optional(),\n courseId: z.string(),\n lessonId: z.string().optional(),\n\n // Scores\n totalQuestions: z.number().int().positive(),\n correctCount: z.number().int().nonnegative(),\n incorrectCount: z.number().int().nonnegative(),\n score: z.number().min(0).max(100), // Percentage\n passed: z.boolean(), // Based on threshold (default 70%)\n\n // Detailed results\n responses: z.array(GradedResponseSchema),\n\n // Misconception analysis (v1.1 feature)\n misconceptions: z.array(MisconceptionReportSchema).optional(),\n topMisconceptions: z.array(z.string()).max(3).optional(),\n\n // Timing\n totalTimeSpent: z.number().int().nonnegative().optional(), // milliseconds\n averageTimePerQuestion: z.number().nonnegative().optional(),\n submittedAt: z.string().datetime(),\n gradedAt: z.string().datetime(),\n})\n\nexport type GradedAssessment = z.infer<typeof GradedAssessmentSchema>\n\n// ============================================================================\n// Validation Result Schema (Standard tier - no answer leakage)\n// ============================================================================\n\n/**\n * Result of validating an assessment submission\n * Does NOT reveal correct answers - only schema compliance\n */\nexport const ValidationResultSchema = z.object({\n valid: z.boolean(),\n errors: z.array(z.object({\n path: z.array(z.union([z.string(), z.number()])),\n message: z.string(),\n code: z.string().optional(),\n })).optional(),\n isComplete: z.boolean(), // All questions answered\n questionCount: z.number().int(),\n answeredCount: z.number().int(),\n})\n\nexport type ValidationResult = z.infer<typeof ValidationResultSchema>\n","import { z } from 'zod'\n\n// ============================================================================\n// Certification Metadata Schema (v1.2)\n// Used for Academic Transcript and Course Certification\n// ============================================================================\n\n/**\n * Certification Project Schema\n * Represents a project in a course for certification tracking\n */\nexport const CertificationProjectSchema = z.object({\n projectNumber: z.number().int().positive(),\n projectName: z.string(),\n sessionNumber: z.number().int().positive(),\n})\n\nexport type CertificationProject = z.infer<typeof CertificationProjectSchema>\n\n/**\n * Certification Metadata Schema (v1.2)\n *\n * Contains course metadata for generating:\n * - Academic Transcripts (topics list)\n * - Course Certifications (completion requirements)\n *\n * Extracted from course Welcome Note.mdx session tables.\n */\nexport const CertificationMetadataSchema = z.object({\n // Course identification\n courseId: z.string(), // e.g., \"bbp\"\n courseName: z.string(), // e.g., \"BBP: Block-based Python\"\n courseCode: z.string(), // e.g., \"BBP\"\n domain: z.string(), // e.g., \"block_based\"\n tier: z.string(), // e.g., \"foundation\"\n\n // Schema version\n schemaVersion: z.literal('1.2.0'),\n lastUpdated: z.string(), // ISO date string, e.g., \"2025-12-27\"\n\n // Academic Transcript content\n topics: z.array(z.string()), // Lesson names for transcript listing\n projects: z.array(CertificationProjectSchema),\n\n // Summary counts\n totalSessions: z.number().int().nonnegative(),\n totalTopics: z.number().int().nonnegative(),\n totalProjects: z.number().int().nonnegative(),\n})\n\nexport type CertificationMetadata = z.infer<typeof CertificationMetadataSchema>\n\n/**\n * Certification Index Schema\n * Lists all available courses with certification metadata\n */\nexport const CertificationIndexSchema = z.object({\n schemaVersion: z.string(),\n lastUpdated: z.string(),\n totalCourses: z.number().int().nonnegative(),\n courses: z.array(\n z.object({\n courseCode: z.string(),\n dataFile: z.string(),\n })\n ),\n cdnBaseUrl: z.string().url(),\n})\n\nexport type CertificationIndex = z.infer<typeof CertificationIndexSchema>\n","import { AssessmentSubmissionSchema, type AssessmentSubmission, type ValidationResult } from '../schemas'\nimport type { ValidationClientConfig, ValidationClientResult, ValidationApiError } from './types'\n\n/**\n * Standard Tier - Validation Client\n *\n * Validates assessment submissions against schemas\n * Does NOT reveal correct answers - only schema compliance\n */\nexport class ValidationClient {\n private apiKey: string\n private baseUrl: string\n private timeout: number\n\n constructor(config: ValidationClientConfig) {\n this.apiKey = config.apiKey\n this.baseUrl = config.baseUrl ?? 'https://api.telebort.com/question-banks/v1'\n this.timeout = config.timeout ?? 30000\n }\n\n /**\n * Validate an assessment submission\n *\n * @param assessment - The assessment to validate\n * @returns Validation result (no correct answers revealed)\n */\n async validateAssessment(assessment: AssessmentSubmission): Promise<ValidationClientResult> {\n // First, validate locally with Zod schema\n const localResult = AssessmentSubmissionSchema.safeParse(assessment)\n\n if (!localResult.success) {\n return {\n valid: false,\n errors: localResult.error.issues.map(issue => ({\n path: issue.path,\n message: issue.message,\n code: issue.code,\n })),\n isComplete: false,\n questionCount: 0,\n answeredCount: assessment.responses?.length ?? 0,\n }\n }\n\n // If API key is provided, also validate with server\n if (this.apiKey && this.apiKey !== 'offline') {\n try {\n const response = await fetch(`${this.baseUrl}/validate`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-API-Key': this.apiKey,\n },\n body: JSON.stringify(assessment),\n signal: AbortSignal.timeout(this.timeout),\n })\n\n if (!response.ok) {\n // Safely parse error response (may not be JSON)\n let errorMessage = `HTTP ${response.status}: ${response.statusText}`\n try {\n const error = await response.json() as ValidationApiError\n errorMessage = error.message || errorMessage\n } catch {\n // Response wasn't JSON, use status message\n }\n throw new Error(`API Error: ${errorMessage}`)\n }\n\n return await response.json() as ValidationClientResult\n } catch (error) {\n // Fall back to local validation if API fails\n console.warn('API validation failed, using local validation:', error)\n }\n }\n\n // Return local validation result\n return {\n valid: true,\n isComplete: true, // Assume complete for local validation\n questionCount: assessment.responses.length,\n answeredCount: assessment.responses.length,\n }\n }\n\n /**\n * Validate assessment offline (no API call)\n * Uses only Zod schemas\n */\n validateOffline(assessment: unknown): ValidationResult {\n const result = AssessmentSubmissionSchema.safeParse(assessment)\n\n if (!result.success) {\n return {\n valid: false,\n errors: result.error.issues.map(issue => ({\n path: issue.path,\n message: issue.message,\n code: issue.code,\n })),\n isComplete: false,\n questionCount: 0,\n answeredCount: 0,\n }\n }\n\n return {\n valid: true,\n isComplete: true,\n questionCount: result.data.responses.length,\n answeredCount: result.data.responses.length,\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/schemas/question.ts","../../src/schemas/assessment.ts","../../src/schemas/course.ts","../../src/schemas/certification.ts","../../src/validation/client.ts"],"names":["z"],"mappings":"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","file":"index.cjs","sourcesContent":["import { z } from 'zod'\n\n// ============================================================================\n// Feedback Schema (v1.1 enhancement)\n// ============================================================================\n\n/**\n * Structured feedback following the \"Not Yet\" protocol\n * - short: Brief acknowledgment (1 sentence)\n * - detailed: Full explanation of the misconception\n * - socraticHint: Optional guiding question for discovery learning\n */\nexport const FeedbackSchema = z.object({\n short: z.string().min(1).max(200),\n detailed: z.string().min(1).max(1000),\n socraticHint: z.string().max(300).optional(),\n})\n\nexport type Feedback = z.infer<typeof FeedbackSchema>\n\n// ============================================================================\n// Option Schema\n// ============================================================================\n\nexport const OptionKeySchema = z.enum(['A', 'B', 'C', 'D'])\n\nexport type OptionKey = z.infer<typeof OptionKeySchema>\n\n/**\n * Answer option with optional misconception tracking (v1.1)\n */\nexport const OptionSchema = z.object({\n key: OptionKeySchema,\n text: z.string().min(1),\n isCorrect: z.boolean(),\n // v1.1 fields - optional for backward compatibility\n misconceptionId: z.string().nullish(),\n feedback: FeedbackSchema.optional(),\n})\n\nexport type Option = z.infer<typeof OptionSchema>\n\n// ============================================================================\n// Question Type Enums\n// ============================================================================\n\nexport const QuestionTypeSchema = z.enum([\n // Core assessment types (original v1.0)\n 'vocabulary',\n 'code_understanding',\n 'problem_solving',\n 'application',\n 'reflection',\n // Code-focused types\n 'debugging',\n 'trace',\n 'predict',\n // Higher-order thinking\n 'analyze',\n 'evaluation',\n 'synthesis',\n 'design',\n 'conceptual',\n 'explain',\n // Domain-specific\n 'bebras',\n 'blockmodel',\n 'ethical_reasoning',\n])\n\nexport type QuestionType = z.infer<typeof QuestionTypeSchema>\n\n/**\n * Question archetype for pedagogical classification\n * - vocabulary: Definition/terminology questions\n * - trace: Code tracing (mental execution)\n * - bebras: Logic-first, computational thinking\n * - blockmodel: Surface/flow/purpose analysis\n * - parsons: Code block reordering (future)\n * - predict: PRIMM predict phase\n * - explain: PRIMM explain phase\n * - debugging: Find/fix errors\n * - application: Apply concept to scenario\n * - problem_solving: Solve novel problems\n * - evaluation: Judge/compare approaches\n * - reflection: Meta-cognitive self-assessment\n * - conceptual: Pure concept understanding\n * - analysis: Compare/decompose\n * - design: System/solution design\n * - synthesis: Combine ideas to create\n * - code: Code-focused analysis\n */\nexport const QuestionArchetypeSchema = z.enum([\n // Original archetypes (v1.1)\n 'vocabulary',\n 'trace',\n 'bebras',\n 'blockmodel',\n 'parsons',\n // Assessment patterns\n 'application',\n 'problem_solving',\n 'debugging',\n 'predict',\n 'explain',\n 'evaluation',\n 'reflection',\n 'conceptual',\n 'analysis',\n 'design',\n 'synthesis',\n 'code',\n])\n\nexport type QuestionArchetype = z.infer<typeof QuestionArchetypeSchema>\n\nexport const DifficultySchema = z.enum(['easy', 'medium', 'hard', 'challenge'])\n\nexport type Difficulty = z.infer<typeof DifficultySchema>\n\nexport const BloomsTaxonomySchema = z.enum([\n 'remember',\n 'understand',\n 'apply',\n 'analyze',\n 'evaluate',\n 'create',\n])\n\nexport type BloomsTaxonomy = z.infer<typeof BloomsTaxonomySchema>\n\n// ============================================================================\n// Question Metadata Schema\n// ============================================================================\n\nexport const QuestionMetadataSchema = z.object({\n difficulty: DifficultySchema,\n estimatedTime: z.number().int().positive(), // seconds\n bloomsTaxonomy: BloomsTaxonomySchema,\n tags: z.array(z.string()),\n conceptTags: z.array(z.string()).optional(), // mastery-relevant concept tags\n metaTags: z.array(z.string()).optional(), // Bloom's types, course codes, internal\n source: z.string().default('exit-ticket'),\n version: z.string().default('1.1'),\n createdDate: z.string().optional(),\n lastModified: z.string().optional(),\n})\n\nexport type QuestionMetadata = z.infer<typeof QuestionMetadataSchema>\n\n// ============================================================================\n// Question Schema (v1.1)\n// ============================================================================\n\n/**\n * Full question schema with v1.1 enhancements:\n * - questionArchetype: Pedagogical classification\n * - misconceptionTargets: Expected misconceptions this question probes\n * - options with misconceptionId and structured feedback\n */\nexport const QuestionSchema = z.object({\n // Identifiers\n questionId: z.string().regex(/^[a-z0-9][-a-z0-9]*-(?:l\\d+-)?q\\d+$/),\n globalId: z.string().regex(/^exit-ticket-[a-z0-9][-a-z0-9]*$/),\n questionNumber: z.number().int().positive().max(5),\n\n // Classification\n questionType: QuestionTypeSchema,\n questionTypeLabel: z.string(),\n questionArchetype: QuestionArchetypeSchema.optional(), // v1.1\n\n // Content\n prompt: z.string().min(10),\n hasCodeBlock: z.boolean(),\n codeLanguage: z.string().nullable(),\n codeContent: z.string().nullable(),\n\n // Misconception targeting (v1.1)\n misconceptionTargets: z.array(z.string()).optional(),\n\n // Answer options (exactly 4)\n options: z.array(OptionSchema).length(4),\n\n // Correct answer\n correctAnswer: OptionKeySchema,\n correctAnswerText: z.string(),\n\n // Metadata\n metadata: QuestionMetadataSchema,\n})\n\nexport type Question = z.infer<typeof QuestionSchema>\n\n// ============================================================================\n// Question without answer (for Standard tier - no answer leakage)\n// ============================================================================\n\nexport const QuestionWithoutAnswerSchema = QuestionSchema.omit({\n correctAnswer: true,\n correctAnswerText: true,\n}).extend({\n options: z.array(\n OptionSchema.omit({\n isCorrect: true,\n feedback: true,\n misconceptionId: true,\n })\n ).length(4),\n})\n\nexport type QuestionWithoutAnswer = z.infer<typeof QuestionWithoutAnswerSchema>\n","import { z } from 'zod'\nimport { OptionKeySchema, FeedbackSchema } from './question'\n\n// ============================================================================\n// Assessment Blueprint Schema (for course-level summative assessments)\n// ============================================================================\n\n/**\n * Defines a summative assessment (quiz) that covers multiple lessons.\n * Stored in CDN course exports and used by the assessment module to build quizzes.\n */\nexport const AssessmentBlueprintSchema = z.object({\n assessmentId: z.string(), // e.g., \"cs1-quiz-1\"\n title: z.string(), // e.g., \"Quiz 1\"\n description: z.string(),\n lessonRange: z.tuple([z.number().int().positive(), z.number().int().positive()])\n .refine(([start, end]) => start <= end, { message: 'lessonRange start must be <= end' }),\n questionCount: z.number().int().positive(),\n passingScore: z.number().min(0).max(100),\n timeLimitMinutes: z.number().int().positive().nullable(),\n tags: z.array(z.string()).optional(),\n})\n\nexport type AssessmentBlueprint = z.infer<typeof AssessmentBlueprintSchema>\n\n// ============================================================================\n// User Response Schema\n// ============================================================================\n\n/**\n * A single user response to a question\n */\nexport const UserResponseSchema = z.object({\n questionId: z.string(),\n selectedAnswer: OptionKeySchema,\n timeSpent: z.number().int().nonnegative().optional(), // milliseconds\n submittedAt: z.string().datetime().optional(),\n})\n\nexport type UserResponse = z.infer<typeof UserResponseSchema>\n\n// ============================================================================\n// Assessment Submission Schema\n// ============================================================================\n\n/**\n * An assessment submission containing multiple responses\n */\nexport const AssessmentSubmissionSchema = z.object({\n assessmentId: z.string().uuid().optional(), // Generated if not provided\n userId: z.string().optional(), // For authenticated users\n sessionId: z.string().optional(), // For anonymous sessions\n courseId: z.string(),\n lessonId: z.string().optional(),\n responses: z.array(UserResponseSchema).min(1),\n submittedAt: z.string().datetime(),\n metadata: z.record(z.unknown()).optional(), // Custom metadata\n})\n\nexport type AssessmentSubmission = z.infer<typeof AssessmentSubmissionSchema>\n\n// ============================================================================\n// Graded Response Schema (Premium tier)\n// ============================================================================\n\n/**\n * Result of grading a single response\n */\nexport const GradedResponseSchema = z.object({\n questionId: z.string(),\n selectedAnswer: OptionKeySchema,\n correctAnswer: OptionKeySchema,\n isCorrect: z.boolean(),\n misconceptionId: z.string().nullable(), // For incorrect answers\n feedback: FeedbackSchema.optional(),\n timeSpent: z.number().int().nonnegative().optional(),\n})\n\nexport type GradedResponse = z.infer<typeof GradedResponseSchema>\n\n// ============================================================================\n// Misconception Report Schema (Premium tier)\n// ============================================================================\n\n/**\n * Aggregated misconception analysis for an assessment\n */\nexport const MisconceptionReportSchema = z.object({\n misconceptionId: z.string(),\n count: z.number().int().positive(),\n percentage: z.number().min(0).max(100),\n questionIds: z.array(z.string()),\n description: z.string().optional(),\n})\n\nexport type MisconceptionReport = z.infer<typeof MisconceptionReportSchema>\n\n// ============================================================================\n// Graded Assessment Schema (Premium tier)\n// ============================================================================\n\n/**\n * Complete graded assessment with scores and misconception analysis\n */\nexport const GradedAssessmentSchema = z.object({\n assessmentId: z.string(),\n userId: z.string().optional(),\n courseId: z.string(),\n lessonId: z.string().optional(),\n\n // Scores\n totalQuestions: z.number().int().positive(),\n correctCount: z.number().int().nonnegative(),\n incorrectCount: z.number().int().nonnegative(),\n score: z.number().min(0).max(100), // Percentage\n passed: z.boolean(), // Based on threshold (default 70%)\n\n // Detailed results\n responses: z.array(GradedResponseSchema),\n\n // Misconception analysis (v1.1 feature)\n misconceptions: z.array(MisconceptionReportSchema).optional(),\n topMisconceptions: z.array(z.string()).max(3).optional(),\n\n // Timing\n totalTimeSpent: z.number().int().nonnegative().optional(), // milliseconds\n averageTimePerQuestion: z.number().nonnegative().optional(),\n submittedAt: z.string().datetime(),\n gradedAt: z.string().datetime(),\n})\n\nexport type GradedAssessment = z.infer<typeof GradedAssessmentSchema>\n\n// ============================================================================\n// Validation Result Schema (Standard tier - no answer leakage)\n// ============================================================================\n\n/**\n * Result of validating an assessment submission\n * Does NOT reveal correct answers - only schema compliance\n */\nexport const ValidationResultSchema = z.object({\n valid: z.boolean(),\n errors: z.array(z.object({\n path: z.array(z.union([z.string(), z.number()])),\n message: z.string(),\n code: z.string().optional(),\n })).optional(),\n isComplete: z.boolean(), // All questions answered\n questionCount: z.number().int(),\n answeredCount: z.number().int(),\n})\n\nexport type ValidationResult = z.infer<typeof ValidationResultSchema>\n","import { z } from 'zod'\nimport { QuestionSchema } from './question'\nimport { AssessmentBlueprintSchema } from './assessment'\n\n// ============================================================================\n// Course Domain & Tier\n// ============================================================================\n\nexport const CourseDomainSchema = z.enum([\n // AI & Data Science\n 'ai_data_science',\n 'ai_ml_cv',\n 'ai_generative',\n 'ai_advanced',\n 'ai', // Prompt Engineering (general AI)\n // Web Development\n 'web_development',\n // Mobile Development\n 'mobile_development',\n 'mobile',\n // Block-based Programming\n 'block_based',\n 'python_programming',\n 'design',\n 'artificial_intelligence', // Block-based AI courses (BBAI)\n // Computer Science\n 'cs_foundations', // CS1-CS4 courses\n // Foundation\n 'foundation',\n 'creative_computing',\n // Utility / Tools\n 'tools', // IDE Setup, Git, Vibe Coding\n])\n\nexport type CourseDomain = z.infer<typeof CourseDomainSchema>\n\nexport const CourseTierSchema = z.enum([\n 'beginner', // Block-based courses (BBW, BBP, BBD, BBAI)\n 'foundation',\n 'intermediate',\n 'advanced',\n])\n\nexport type CourseTier = z.infer<typeof CourseTierSchema>\n\n// ============================================================================\n// Lesson Schema\n// ============================================================================\n\nexport const LessonSchema = z.object({\n lessonId: z.string(), // e.g., \"ai-1-lesson-1\"\n lessonNumber: z.number().int().positive(),\n lessonTitle: z.string(),\n lessonSlug: z.string().optional(),\n totalQuestions: z.number().int().positive().default(5),\n questions: z.array(QuestionSchema),\n})\n\nexport type Lesson = z.infer<typeof LessonSchema>\n\n// ============================================================================\n// Course Schema\n// ============================================================================\n\nexport const CourseSchema = z.object({\n courseId: z.string(), // e.g., \"ai-1\"\n courseName: z.string(), // e.g., \"AI-1 Data Analysis and Data Science\"\n courseCode: z.string(), // e.g., \"AI1\"\n domain: CourseDomainSchema,\n tier: CourseTierSchema,\n difficulty: z.number().int().min(1).max(5),\n totalLessons: z.number().int().positive(),\n totalQuestions: z.number().int().positive(),\n sourceFile: z.string().optional(),\n lessons: z.array(LessonSchema),\n assessments: z.array(AssessmentBlueprintSchema).optional(),\n})\n\nexport type Course = z.infer<typeof CourseSchema>\n\n// ============================================================================\n// Course Summary (without questions - for listing)\n// ============================================================================\n\nexport const CourseSummarySchema = CourseSchema.omit({ lessons: true }).extend({\n lessons: z.array(\n LessonSchema.omit({ questions: true })\n ).optional(),\n})\n\nexport type CourseSummary = z.infer<typeof CourseSummarySchema>\n","import { z } from 'zod'\n\n// ============================================================================\n// Certification Metadata Schema (v1.2)\n// Used for Academic Transcript and Course Certification\n// ============================================================================\n\n/**\n * Certification Project Schema\n * Represents a project in a course for certification tracking\n */\nexport const CertificationProjectSchema = z.object({\n projectNumber: z.number().int().positive(),\n projectName: z.string(),\n sessionNumber: z.number().int().positive(),\n})\n\nexport type CertificationProject = z.infer<typeof CertificationProjectSchema>\n\n/**\n * Certification Metadata Schema (v1.2)\n *\n * Contains course metadata for generating:\n * - Academic Transcripts (topics list)\n * - Course Certifications (completion requirements)\n *\n * Extracted from course Welcome Note.mdx session tables.\n */\nexport const CertificationMetadataSchema = z.object({\n // Course identification\n courseId: z.string(), // e.g., \"bbp\"\n courseName: z.string(), // e.g., \"BBP: Block-based Python\"\n courseCode: z.string(), // e.g., \"BBP\"\n domain: z.string(), // e.g., \"block_based\"\n tier: z.string(), // e.g., \"foundation\"\n\n // Schema version\n schemaVersion: z.literal('1.2.0'),\n lastUpdated: z.string(), // ISO date string, e.g., \"2025-12-27\"\n\n // Academic Transcript content\n topics: z.array(z.string()), // Lesson names for transcript listing\n projects: z.array(CertificationProjectSchema),\n\n // Summary counts\n totalSessions: z.number().int().nonnegative(),\n totalTopics: z.number().int().nonnegative(),\n totalProjects: z.number().int().nonnegative(),\n})\n\nexport type CertificationMetadata = z.infer<typeof CertificationMetadataSchema>\n\n/**\n * Certification Index Schema\n * Lists all available courses with certification metadata\n */\nexport const CertificationIndexSchema = z.object({\n schemaVersion: z.string(),\n lastUpdated: z.string(),\n totalCourses: z.number().int().nonnegative(),\n courses: z.array(\n z.object({\n courseCode: z.string(),\n dataFile: z.string(),\n })\n ),\n cdnBaseUrl: z.string().url(),\n})\n\nexport type CertificationIndex = z.infer<typeof CertificationIndexSchema>\n","import { AssessmentSubmissionSchema, type AssessmentSubmission, type ValidationResult } from '../schemas'\nimport type { ValidationClientConfig, ValidationClientResult, ValidationApiError } from './types'\n\n/**\n * Standard Tier - Validation Client\n *\n * Validates assessment submissions against schemas\n * Does NOT reveal correct answers - only schema compliance\n */\nexport class ValidationClient {\n private apiKey: string\n private baseUrl: string\n private timeout: number\n\n constructor(config: ValidationClientConfig) {\n this.apiKey = config.apiKey\n this.baseUrl = config.baseUrl ?? 'https://api.telebort.com/question-banks/v1'\n this.timeout = config.timeout ?? 30000\n }\n\n /**\n * Validate an assessment submission\n *\n * @param assessment - The assessment to validate\n * @returns Validation result (no correct answers revealed)\n */\n async validateAssessment(assessment: AssessmentSubmission): Promise<ValidationClientResult> {\n // First, validate locally with Zod schema\n const localResult = AssessmentSubmissionSchema.safeParse(assessment)\n\n if (!localResult.success) {\n return {\n valid: false,\n errors: localResult.error.issues.map(issue => ({\n path: issue.path,\n message: issue.message,\n code: issue.code,\n })),\n isComplete: false,\n questionCount: 0,\n answeredCount: assessment.responses?.length ?? 0,\n }\n }\n\n // If API key is provided, also validate with server\n if (this.apiKey && this.apiKey !== 'offline') {\n try {\n const response = await fetch(`${this.baseUrl}/validate`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-API-Key': this.apiKey,\n },\n body: JSON.stringify(assessment),\n signal: AbortSignal.timeout(this.timeout),\n })\n\n if (!response.ok) {\n // Safely parse error response (may not be JSON)\n let errorMessage = `HTTP ${response.status}: ${response.statusText}`\n try {\n const error = await response.json() as ValidationApiError\n errorMessage = error.message || errorMessage\n } catch {\n // Response wasn't JSON, use status message\n }\n throw new Error(`API Error: ${errorMessage}`)\n }\n\n return await response.json() as ValidationClientResult\n } catch (error) {\n // Fall back to local validation if API fails\n console.warn('API validation failed, using local validation:', error)\n }\n }\n\n // Return local validation result\n return {\n valid: true,\n isComplete: true, // Assume complete for local validation\n questionCount: assessment.responses.length,\n answeredCount: assessment.responses.length,\n }\n }\n\n /**\n * Validate assessment offline (no API call)\n * Uses only Zod schemas\n */\n validateOffline(assessment: unknown): ValidationResult {\n const result = AssessmentSubmissionSchema.safeParse(assessment)\n\n if (!result.success) {\n return {\n valid: false,\n errors: result.error.issues.map(issue => ({\n path: issue.path,\n message: issue.message,\n code: issue.code,\n })),\n isComplete: false,\n questionCount: 0,\n answeredCount: 0,\n }\n }\n\n return {\n valid: true,\n isComplete: true,\n questionCount: result.data.responses.length,\n answeredCount: result.data.responses.length,\n }\n }\n}\n"]}
|