UNPKG

mcp-quiz-server

Version:

🧠 AI-Powered Quiz Management via Model Context Protocol (MCP) - Create, manage, and take quizzes directly from VS Code, Claude, and other AI agents.

185 lines (184 loc) • 5.45 kB
"use strict"; /** * @fileoverview Quiz Completed Domain Event * @version 1.0.0 * @since 2025-07-29 * @lastUpdated 2025-07-29 * @module QuizCompletedEvent Domain Event * @description Domain event fired when a user completes a quiz * @contributors Claude Code Agent * @dependencies DomainEvent base class * @requirements REQ-ARCH-001 (Clean Architecture Domain Layer) * @testCoverage Unit tests for event creation and serialization */ Object.defineProperty(exports, "__esModule", { value: true }); exports.QuizCompletedEvent = void 0; const DomainEvent_1 = require("./DomainEvent"); /** * Quiz Completed Event * * @description Domain event that signals a user has completed a quiz. * This event can trigger score calculations, analytics updates, * achievements, notifications, or leaderboard updates. * * @example * ```typescript * const event = new QuizCompletedEvent( * 'quiz-123', * 'user-456', * 8, * 10, * 80.0, * { 'q1': 'answer1', 'q2': 'answer2' } * ); * ``` * * @since 2025-07-29 * @author Claude Code Agent * @requirements REQ-ARCH-001 (Clean Architecture Domain Layer) */ class QuizCompletedEvent extends DomainEvent_1.DomainEvent { constructor(quizId, userId, score, totalQuestions, percentage, answers, completionTimeMs) { super('QuizCompleted', 1); this.quizId = quizId; this.userId = userId; this.score = score; this.totalQuestions = totalQuestions; this.percentage = percentage; this.answers = answers; this.completionTimeMs = completionTimeMs; } /** * Get the aggregate ID (Quiz ID) that this event relates to */ getAggregateId() { return this.quizId; } /** * Get event payload for serialization */ getEventData() { return { quizId: this.quizId, userId: this.userId, score: this.score, totalQuestions: this.totalQuestions, percentage: this.percentage, answersCount: Object.keys(this.answers).length, completionTimeMs: this.completionTimeMs, // Note: We don't include actual answers for privacy/security answerIds: Object.keys(this.answers), }; } /** * Business Logic Methods */ /** * Check if this is a perfect score */ get isPerfectScore() { return this.score === this.totalQuestions; } /** * Check if this is a passing score (>= 70%) */ get isPassingScore() { return this.percentage >= 70; } /** * Check if this is a high score (>= 90%) */ get isHighScore() { return this.percentage >= 90; } /** * Get performance level */ get performanceLevel() { if (this.percentage >= 90) return 'excellent'; if (this.percentage >= 80) return 'good'; if (this.percentage >= 70) return 'average'; return 'needs_improvement'; } /** * Get grade letter based on percentage */ get letterGrade() { if (this.percentage >= 90) return 'A'; if (this.percentage >= 80) return 'B'; if (this.percentage >= 70) return 'C'; if (this.percentage >= 60) return 'D'; return 'F'; } /** * Check if all questions were answered */ get areAllQuestionsAnswered() { return Object.keys(this.answers).length === this.totalQuestions; } /** * Get completion rate as a decimal (0-1) */ get completionRate() { return Object.keys(this.answers).length / this.totalQuestions; } /** * Check if completion was fast (if time data available) */ get isFastCompletion() { if (!this.completionTimeMs) return false; // Business rule: Less than 30 seconds per question is considered fast const averageTimePerQuestion = this.completionTimeMs / this.totalQuestions; return averageTimePerQuestion < 30000; // 30 seconds in ms } /** * Get achievement triggers based on performance */ get achievements() { const achievements = []; if (this.isPerfectScore) achievements.push('perfect_score'); if (this.isHighScore) achievements.push('high_score'); if (this.areAllQuestionsAnswered) achievements.push('completionist'); if (this.isFastCompletion) achievements.push('speed_demon'); if (this.isPassingScore) achievements.push('passed'); return achievements; } /** * Check if this result should trigger notifications */ get shouldNotify() { return this.isPerfectScore || this.isHighScore || !this.isPassingScore; } /** * Get notification priority level */ get notificationPriority() { if (this.isPerfectScore) return 'high'; if (this.isHighScore) return 'medium'; if (!this.isPassingScore) return 'medium'; return 'low'; } /** * String representation for logging */ toString() { return `QuizCompleted: User ${this.userId} scored ${this.score}/${this.totalQuestions} (${this.percentage}%) on quiz ${this.quizId}`; } } exports.QuizCompletedEvent = QuizCompletedEvent;