'use strict'; /** @type {import('sequelize-cli').Migration} */ module.exports = { async up(queryInterface, Sequelize) { await queryInterface.createTable('quiz_sessions', { id: { type: Sequelize.CHAR(36), primaryKey: true, allowNull: false, comment: 'UUID primary key' }, user_id: { type: Sequelize.CHAR(36), allowNull: true, references: { model: 'users', key: 'id' }, onUpdate: 'CASCADE', onDelete: 'SET NULL', comment: 'Foreign key to users table (null for guest quizzes)' }, guest_session_id: { type: Sequelize.CHAR(36), allowNull: true, references: { model: 'guest_sessions', key: 'id' }, onUpdate: 'CASCADE', onDelete: 'SET NULL', comment: 'Foreign key to guest_sessions table (null for user quizzes)' }, category_id: { type: Sequelize.CHAR(36), allowNull: false, references: { model: 'categories', key: 'id' }, onUpdate: 'CASCADE', onDelete: 'RESTRICT', comment: 'Foreign key to categories table' }, quiz_type: { type: Sequelize.ENUM('practice', 'timed', 'exam'), allowNull: false, defaultValue: 'practice', comment: 'Type of quiz: practice (untimed), timed, or exam mode' }, difficulty: { type: Sequelize.ENUM('easy', 'medium', 'hard', 'mixed'), allowNull: false, defaultValue: 'mixed', comment: 'Difficulty level of questions in the quiz' }, total_questions: { type: Sequelize.INTEGER.UNSIGNED, allowNull: false, defaultValue: 10, comment: 'Total number of questions in this quiz session' }, questions_answered: { type: Sequelize.INTEGER.UNSIGNED, allowNull: false, defaultValue: 0, comment: 'Number of questions answered so far' }, correct_answers: { type: Sequelize.INTEGER.UNSIGNED, allowNull: false, defaultValue: 0, comment: 'Number of correct answers' }, score: { type: Sequelize.DECIMAL(5, 2), allowNull: false, defaultValue: 0.00, comment: 'Quiz score as percentage (0-100)' }, total_points: { type: Sequelize.INTEGER.UNSIGNED, allowNull: false, defaultValue: 0, comment: 'Total points earned in this quiz' }, max_points: { type: Sequelize.INTEGER.UNSIGNED, allowNull: false, defaultValue: 0, comment: 'Maximum possible points for this quiz' }, time_limit: { type: Sequelize.INTEGER.UNSIGNED, allowNull: true, comment: 'Time limit in seconds (null for untimed practice)' }, time_spent: { type: Sequelize.INTEGER.UNSIGNED, allowNull: false, defaultValue: 0, comment: 'Total time spent in seconds' }, started_at: { type: Sequelize.DATE, allowNull: true, comment: 'When the quiz was started' }, completed_at: { type: Sequelize.DATE, allowNull: true, comment: 'When the quiz was completed' }, status: { type: Sequelize.ENUM('not_started', 'in_progress', 'completed', 'abandoned', 'timed_out'), allowNull: false, defaultValue: 'not_started', comment: 'Current status of the quiz session' }, is_passed: { type: Sequelize.BOOLEAN, allowNull: true, comment: 'Whether the quiz was passed (null if not completed)' }, pass_percentage: { type: Sequelize.DECIMAL(5, 2), allowNull: false, defaultValue: 70.00, comment: 'Required percentage to pass (default 70%)' }, created_at: { type: Sequelize.DATE, allowNull: false, defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'), comment: 'Record creation timestamp' }, updated_at: { type: Sequelize.DATE, allowNull: false, defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'), comment: 'Record last update timestamp' } }, { charset: 'utf8mb4', collate: 'utf8mb4_unicode_ci', comment: 'Tracks individual quiz sessions for users and guests' }); // Add indexes for better query performance await queryInterface.addIndex('quiz_sessions', ['user_id'], { name: 'idx_quiz_sessions_user_id' }); await queryInterface.addIndex('quiz_sessions', ['guest_session_id'], { name: 'idx_quiz_sessions_guest_session_id' }); await queryInterface.addIndex('quiz_sessions', ['category_id'], { name: 'idx_quiz_sessions_category_id' }); await queryInterface.addIndex('quiz_sessions', ['status'], { name: 'idx_quiz_sessions_status' }); await queryInterface.addIndex('quiz_sessions', ['quiz_type'], { name: 'idx_quiz_sessions_quiz_type' }); await queryInterface.addIndex('quiz_sessions', ['started_at'], { name: 'idx_quiz_sessions_started_at' }); await queryInterface.addIndex('quiz_sessions', ['completed_at'], { name: 'idx_quiz_sessions_completed_at' }); await queryInterface.addIndex('quiz_sessions', ['created_at'], { name: 'idx_quiz_sessions_created_at' }); await queryInterface.addIndex('quiz_sessions', ['is_passed'], { name: 'idx_quiz_sessions_is_passed' }); // Composite index for common queries await queryInterface.addIndex('quiz_sessions', ['user_id', 'status'], { name: 'idx_quiz_sessions_user_status' }); await queryInterface.addIndex('quiz_sessions', ['guest_session_id', 'status'], { name: 'idx_quiz_sessions_guest_status' }); console.log('✅ Quiz sessions table created successfully with 21 fields and 11 indexes'); }, async down(queryInterface, Sequelize) { await queryInterface.dropTable('quiz_sessions'); console.log('✅ Quiz sessions table dropped'); } };