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) • 7.29 kB
JavaScript
"use strict";
/**
* @moduleName: QuizResult Entity Model
* @version: 1.0.0
* @since: 2025-07-22
* @lastUpdated: 2025-07-22
* @projectSummary: TypeORM entity model for quiz attempt results with score calculation and timing
* @techStack: TypeORM, TypeScript, Decorators, Computed Properties
* @dependency: typeorm, reflect-metadata
* @interModuleDependency: ./Quiz, ./Result
* @requirementsTraceability:
* {@link Requirements.REQ_DATA_002} (Append-Only Results Storage)
* @briefDescription: Quiz attempt result entity with user information, scoring, timing, and individual question results
* @contributors: Jorge the Database Architect
* @vulnerabilitiesAssessment:
* - User identification stored securely
* - Score calculation methods validated
* - Timing data for analytics
* - Cascade delete for result cleanup
*/
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var QuizResult_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.QuizResult = void 0;
const typeorm_1 = require("typeorm");
const Quiz_1 = require("./Quiz");
const Result_1 = require("./Result");
let QuizResult = QuizResult_1 = class QuizResult {
// Computed properties
get percentage() {
return this.totalQuestions > 0
? Math.round((this.correctAnswers / this.totalQuestions) * 100)
: 0;
}
get averageTimePerQuestion() {
return this.totalQuestions > 0 && this.totalTimeSpent
? Math.round(this.totalTimeSpent / this.totalQuestions)
: 0;
}
get grade() {
const percentage = this.percentage;
if (percentage >= 90)
return 'A';
if (percentage >= 80)
return 'B';
if (percentage >= 70)
return 'C';
if (percentage >= 60)
return 'D';
return 'F';
}
// Helper methods
calculateScore() {
if (this.results) {
this.totalQuestions = this.results.length;
this.correctAnswers = this.results.filter(r => r.isCorrect).length;
this.incorrectAnswers = this.totalQuestions - this.correctAnswers;
this.score = this.percentage;
this.totalTimeSpent = this.results.reduce((sum, r) => sum + (r.timeSpent || 0), 0);
}
}
markCompleted() {
this.isCompleted = true;
this.status = 'completed';
this.completedAt = new Date();
this.calculateScore();
}
toJSON() {
var _a, _b;
return {
id: this.id,
quizId: this.quizId,
userId: this.userId,
userName: this.userName,
score: this.score,
totalQuestions: this.totalQuestions,
correctAnswers: this.correctAnswers,
incorrectAnswers: this.incorrectAnswers,
totalTimeSpent: this.totalTimeSpent,
isCompleted: this.isCompleted,
status: this.status,
percentage: this.percentage,
grade: this.grade,
averageTimePerQuestion: this.averageTimePerQuestion,
startedAt: this.startedAt,
completedAt: this.completedAt,
quiz: (_a = this.quiz) === null || _a === void 0 ? void 0 : _a.toJSON(),
results: (_b = this.results) === null || _b === void 0 ? void 0 : _b.map(r => r.toJSON()),
metadata: this.metadata,
};
}
// Static factory method
static create(data) {
const quizResult = new QuizResult_1();
quizResult.quizId = data.quizId;
quizResult.userId = data.userId;
quizResult.userName = data.userName;
quizResult.status = 'in_progress';
quizResult.isCompleted = false;
return quizResult;
}
};
exports.QuizResult = QuizResult;
__decorate([
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
__metadata("design:type", String)
], QuizResult.prototype, "id", void 0);
__decorate([
(0, typeorm_1.Column)({ type: 'uuid' }),
__metadata("design:type", String)
], QuizResult.prototype, "quizId", void 0);
__decorate([
(0, typeorm_1.Column)({ type: 'varchar', length: 255, nullable: true }),
__metadata("design:type", String)
], QuizResult.prototype, "userId", void 0);
__decorate([
(0, typeorm_1.Column)({ type: 'varchar', length: 255, nullable: true }),
__metadata("design:type", String)
], QuizResult.prototype, "userName", void 0);
__decorate([
(0, typeorm_1.Column)({ type: 'float', default: 0 }),
__metadata("design:type", Number)
], QuizResult.prototype, "score", void 0);
__decorate([
(0, typeorm_1.Column)({ type: 'integer', default: 0 }),
__metadata("design:type", Number)
], QuizResult.prototype, "totalQuestions", void 0);
__decorate([
(0, typeorm_1.Column)({ type: 'integer', default: 0 }),
__metadata("design:type", Number)
], QuizResult.prototype, "correctAnswers", void 0);
__decorate([
(0, typeorm_1.Column)({ type: 'integer', default: 0 }),
__metadata("design:type", Number)
], QuizResult.prototype, "incorrectAnswers", void 0);
__decorate([
(0, typeorm_1.Column)({ type: 'integer', nullable: true }),
__metadata("design:type", Number)
], QuizResult.prototype, "totalTimeSpent", void 0);
__decorate([
(0, typeorm_1.Column)({ type: 'boolean', default: false }),
__metadata("design:type", Boolean)
], QuizResult.prototype, "isCompleted", void 0);
__decorate([
(0, typeorm_1.Column)({ type: 'varchar', length: 50, default: 'in_progress' }),
__metadata("design:type", String)
], QuizResult.prototype, "status", void 0);
__decorate([
(0, typeorm_1.Column)({ type: 'json', nullable: true }),
__metadata("design:type", Object)
], QuizResult.prototype, "metadata", void 0);
__decorate([
(0, typeorm_1.CreateDateColumn)(),
__metadata("design:type", Date)
], QuizResult.prototype, "startedAt", void 0);
__decorate([
(0, typeorm_1.UpdateDateColumn)(),
__metadata("design:type", Date)
], QuizResult.prototype, "completedAt", void 0);
__decorate([
(0, typeorm_1.ManyToOne)(() => Quiz_1.Quiz, quiz => quiz.results, {
eager: true,
}),
(0, typeorm_1.JoinColumn)({ name: 'quizId' }),
__metadata("design:type", Quiz_1.Quiz)
], QuizResult.prototype, "quiz", void 0);
__decorate([
(0, typeorm_1.OneToMany)(() => Result_1.Result, result => result.quizResult, {
cascade: true,
eager: false,
}),
__metadata("design:type", Array)
], QuizResult.prototype, "results", void 0);
exports.QuizResult = QuizResult = QuizResult_1 = __decorate([
(0, typeorm_1.Entity)('quiz_results')
], QuizResult);