Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 69 additions & 8 deletions backend/src/modules/quiz/quiz-generator.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
import { Injectable, Logger } from '@nestjs/common';
import { AiService } from '../ai/ai.service';

export type QuestionType = 'multiple_choice' | 'true_false' | 'short_answer' | 'fill_blank';
export type QuestionType =
| 'multiple_choice'
| 'true_false'
| 'short_answer'
| 'fill_blank'
| 'matching'
| 'ordering'
| 'coding'
| 'essay';

export interface MatchingPair {
left: string;
right: string;
}

export interface CodingTestCase {
input: string;
expected: string;
}

export interface GeneratedQuestion {
type: QuestionType;
Expand All @@ -10,6 +28,20 @@ export interface GeneratedQuestion {
correctAnswer: string;
explanation: string;
difficulty: 'easy' | 'medium' | 'hard';
/** For matching questions: pairs of left-right items */
pairs?: MatchingPair[];
/** For ordering questions: items to order */
items?: string[];
/** For ordering questions: correct order as indices */
correctOrder?: number[];
/** For coding questions: programming language */
language?: string;
/** For coding questions: test cases */
testCases?: CodingTestCase[];
/** For essay questions: grading rubric */
rubric?: string;
/** For essay questions: maximum word count */
maxWords?: number;
}

export interface GenerateQuizOptions {
Expand Down Expand Up @@ -52,15 +84,36 @@ Return the questions in this exact JSON format:
{
"questions": [
{
"type": "multiple_choice" | "true_false" | "short_answer" | "fill_blank",
"type": "multiple_choice" | "true_false" | "short_answer" | "fill_blank" | "matching" | "ordering" | "coding" | "essay",
"question": "The question text",
"options": ["A", "B", "C", "D"], // only for multiple_choice
"correctAnswer": "The correct answer",
"correctAnswer": "The correct answer", // for multiple_choice, true_false, short_answer, fill_blank
"explanation": "Why this is correct",
"difficulty": "easy" | "medium" | "hard"
"difficulty": "easy" | "medium" | "hard",

// For matching questions only:
"pairs": [{"left": "Term", "right": "Definition"}, ...], // 4-6 pairs to match

// For ordering questions only:
"items": ["Step 1", "Step 2", "Step 3"], // items in correct order
"correctOrder": [0, 1, 2], // indices representing the correct sequence

// For coding questions only:
"language": "python", // programming language
"testCases": [{"input": "...", "expected": "..."}], // test cases for validation

// For essay questions only:
"rubric": "Key points: X, Y, Z", // grading criteria
"maxWords": 500 // maximum word count
}
]
}`;
}

Important type-specific rules:
- matching: Always include "pairs" array with 4-6 items. Set "correctAnswer" to JSON string of the pairs array.
- ordering: Always include "items" and "correctOrder". Set "correctAnswer" to JSON string of correctOrder array.
- coding: Always include "language", "testCases" with at least 2 test cases. Set "correctAnswer" to a sample solution.
- essay: Always include "rubric" and "maxWords". Set "correctAnswer" to key points expected.`;

const userPrompt = `Study Material:
${content}
Expand Down Expand Up @@ -123,15 +176,23 @@ Return the questions in this exact JSON format:
{
"questions": [
{
"type": "multiple_choice" | "true_false" | "short_answer",
"type": "multiple_choice" | "true_false" | "short_answer" | "fill_blank" | "matching" | "ordering" | "coding" | "essay",
"question": "The question text",
"options": ["A", "B", "C", "D"],
"correctAnswer": "The correct answer",
"explanation": "Why this is correct",
"difficulty": "${difficulty}"
"difficulty": "${difficulty}",
"pairs": [{"left": "Term", "right": "Definition"}, ...],
"items": ["Step 1", "Step 2", "Step 3"],
"correctOrder": [0, 1, 2],
"language": "python",
"testCases": [{"input": "...", "expected": "..."}],
"rubric": "Key points: X, Y, Z",
"maxWords": 500
}
]
}`;
}
Include only the fields relevant to each question type.`;

const response = await this.aiService.completeJson<{ questions: GeneratedQuestion[] }>(
[
Expand Down
3 changes: 2 additions & 1 deletion backend/src/modules/quiz/quiz.module.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { Module } from '@nestjs/common';
import { AuthModule } from '../auth/auth.module';
import { NotificationsModule } from '../notifications/notifications.module';
import { CodeSandboxModule } from '../code-sandbox/code-sandbox.module';
import { QuizService } from './quiz.service';
import { QuizController } from './quiz.controller';
import { QuizGeneratorService } from './quiz-generator.service';
import { LiveQuizService } from './live-quiz.service';
import { LiveQuizGateway } from './live-quiz.gateway';

@Module({
imports: [AuthModule, NotificationsModule],
imports: [AuthModule, NotificationsModule, CodeSandboxModule],
controllers: [QuizController],
providers: [QuizService, QuizGeneratorService, LiveQuizService, LiveQuizGateway],
exports: [QuizService, QuizGeneratorService, LiveQuizService],
Expand Down
Loading
Loading