<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebQuiz Live Stats</title>
    <style>
        :root {
            --bg-color: #f5f5f5;
            --container-bg: white;
            --text-color: #333;
            --border-color: #ddd;
            --think-color: #fff3cd;
            --ok-color: #d4edda;
            --fail-color: #f8d7da;
            --empty-color: #e9ecef;
            --header-bg: #007bff;
            --header-color: white;
        }

        html, body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            height: 100%;
            background-color: var(--bg-color);
            color: var(--text-color);
        }

        body {
            display: flex;
            flex-direction: column;
            padding: 20px;
            box-sizing: border-box;
        }

        .connection-status {
            padding: 10px;
            border-radius: 5px;
            margin-bottom: 20px;
            text-align: center;
            font-weight: bold;
            flex-shrink: 0;
        }

        .connected {
            background: var(--ok-color);
            color: #155724;
        }

        .disconnected {
            background: var(--fail-color);
            color: #721c24;
        }

        .connecting {
            background: var(--think-color);
            color: #856404;
        }

        .filter-bar {
            display: flex;
            gap: 10px;
            justify-content: center;
            margin-bottom: 20px;
            flex-wrap: wrap;
            flex-shrink: 0;
        }

        .filter-button {
            padding: 10px 20px;
            border: 2px solid var(--border-color);
            background: var(--container-bg);
            color: var(--text-color);
            border-radius: 8px;
            cursor: pointer;
            font-size: 16px;
            font-weight: bold;
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .filter-button:hover {
            background: #f0f0f0;
            transform: translateY(-2px);
            box-shadow: 0 4px 8px rgba(0,0,0,0.1);
        }

        .filter-button.active {
            background: var(--header-bg);
            color: var(--header-color);
            border-color: var(--header-bg);
        }

        .filter-badge {
            background: rgba(0, 0, 0, 0.2);
            padding: 2px 8px;
            border-radius: 10px;
            font-size: 12px;
            min-width: 20px;
            text-align: center;
        }

        .filter-button.active .filter-badge {
            background: rgba(255, 255, 255, 0.3);
        }

        .stats-container {
            background: var(--container-bg);
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            overflow: hidden;
            flex: 1;
            display: flex;
            flex-direction: column;
            min-height: 0;
        }

        .group-section {
            display: flex;
            flex-direction: column;
            min-height: 0;
            flex: 1;
        }

        .stats-table {
            width: 100%;
            border-collapse: collapse;
            min-width: 600px;
        }

        .stats-table th,
        .stats-table td {
            padding: 12px;
            text-align: center;
            border: 1px solid var(--border-color);
        }

        .stats-table th {
            background: var(--header-bg);
            color: var(--header-color);
            font-weight: bold;
            position: sticky;
            top: 0;
            z-index: 10;
        }

        .stats-table .username-header {
            background: var(--header-bg);
            color: var(--header-color);
            font-weight: bold;
            text-align: left;
            width: 150px;
            position: sticky;
            left: 0;
            z-index: 11;
        }

        .stats-table .username-cell {
            background: var(--container-bg);
            font-weight: bold;
            text-align: left;
            position: sticky;
            left: 0;
            z-index: 5;
            border-right: 2px solid var(--border-color);
        }

        .state-cell {
            width: 80px;
            height: 50px;
            font-size: 14px;
            font-weight: bold;
            position: relative;
            padding: 4px;
        }

        .cell-content {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100%;
        }

        .state-icon {
            font-size: 18px;
            line-height: 1;
        }

        .time-display {
            font-size: 10px;
            font-weight: normal;
            opacity: 0.8;
            margin-top: 2px;
            line-height: 1;
        }

        .state-think {
            background: var(--think-color);
            color: #856404;
        }

        .state-ok {
            background: var(--ok-color);
            color: #155724;
        }

        .state-fail {
            background: var(--fail-color);
            color: #721c24;
        }

        .state-empty {
            background: var(--empty-color);
            color: #6c757d;
        }

        .no-data {
            text-align: center;
            padding: 40px;
            color: #6c757d;
            font-style: italic;
        }

        /* Statistics styling */
        .question-header {
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 5px;
        }

        .question-text {
            font-weight: bold;
            text-align: center;
            margin-bottom: 4px;
        }

        .question-stats {
            font-size: 11px;
            font-weight: normal;
            color: #dddddd;
            background: rgba(0,0,0,0.1);
            padding: 2px 6px;
            border-radius: 3px;
        }

        .username-text {
            font-weight: bold;
        }

        .user-stats {
            font-size: 11px;
            font-weight: normal;
            color: #666;
            background: rgba(0,0,0,0.1);
            padding: 2px 6px;
            border-radius: 3px;
            margin-top: 4px;
            text-align: center;
        }

        .image-header .question-stats {
            margin-top: 4px;
        }

        .table-wrapper {
            overflow: auto;
            flex: 1;
            height: 100%;
        }

        .image-header {
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 5px;
        }

        .header-image {
            max-width: 40px;
            max-height: 40px;
            object-fit: cover;
            border-radius: 3px;
            margin-bottom: 4px;
            box-shadow: 0 1px 3px rgba(0,0,0,0.2);
        }

        .image-filename {
            text-align: center;
            line-height: 1.1;
            max-width: 80px;
            word-break: break-all;
            overflow: hidden;
            text-overflow: ellipsis;
            display: -webkit-box;
            -webkit-line-clamp: 2;
            -webkit-box-orient: vertical;
        }

        .file-indicator {
            margin-left: 4px;
            cursor: help;
        }

        .points-indicator {
            margin-left: 4px;
            font-size: 0.85em;
            color: #ffc107;
        }

        @media (max-width: 768px) {
            body {
                padding: 10px;
            }

            .stats-table th,
            .stats-table td {
                padding: 8px 4px;
            }

            .username-header,
            .username-cell {
                width: 100px;
            }

            .state-cell {
                width: 60px;
                height: 40px;
                font-size: 12px;
            }

            .state-icon {
                font-size: 14px;
            }

            .time-display {
                font-size: 8px;
            }
        }
    </style>
</head>
<body>
    <div id="connectionStatus" class="connection-status" style="display: none;">
    </div>

    <!-- Filter Bar -->
    <div class="filter-bar">
        <button class="filter-button active" id="filterAll" onclick="window.liveStatsClient.setFilter('all')">
            <span>All</span>
            <span class="filter-badge" id="countAll">0</span>
        </button>
        <button class="filter-button" id="filterInProgress" onclick="window.liveStatsClient.setFilter('inProgress')">
            <span>🔄 In Progress</span>
            <span class="filter-badge" id="countInProgress">0</span>
        </button>
        <button class="filter-button" id="filterCompleted" onclick="window.liveStatsClient.setFilter('completed')">
            <span>✅ Completed</span>
            <span class="filter-badge" id="countCompleted">0</span>
        </button>
    </div>

    <div class="stats-container">
        <!-- Single table that shows filtered users -->
        <div id="statsSection" class="group-section" style="display: none;">
            <div class="table-wrapper">
                <table class="stats-table" id="statsTable">
                    <thead>
                        <tr id="statsHeader">
                            <th class="username-header">User</th>
                        </tr>
                    </thead>
                    <tbody id="statsBody">
                    </tbody>
                </table>
            </div>
        </div>

        <!-- No data message -->
        <div id="noDataMessage" class="no-data" style="padding: 40px; text-align: center;">
            Waiting for users to join the quiz...
        </div>
    </div>

    <script>
        class LiveStatsClient {
            constructor() {
                this.ws = null;
                this.users = {};
                this.liveStats = {};
                this.completedUsers = {};  // user_id -> boolean (completed status)
                this.completionTimes = {};  // user_id -> ISO timestamp when completed
                this.questions = [];
                this.totalQuestions = 0;
                this.currentQuiz = null;
                this.userStatistics = {};  // user_id -> {correct_count, total_answered}
                this.questionStatistics = {};  // question_id -> {correct_count, total_attempts}
                this.reconnectAttempts = 0;
                this.maxReconnectAttempts = 5;
                this.reconnectDelay = 1000;
                this.currentFilter = 'all';  // 'all', 'inProgress', 'completed'

                this.statusElement = document.getElementById('connectionStatus');

                // Single table elements
                this.statsSection = document.getElementById('statsSection');
                this.statsHeader = document.getElementById('statsHeader');
                this.statsBody = document.getElementById('statsBody');

                // Filter elements
                this.filterAll = document.getElementById('filterAll');
                this.filterInProgress = document.getElementById('filterInProgress');
                this.filterCompleted = document.getElementById('filterCompleted');
                this.countAll = document.getElementById('countAll');
                this.countInProgress = document.getElementById('countInProgress');
                this.countCompleted = document.getElementById('countCompleted');

                // No data message
                this.noDataMessage = document.getElementById('noDataMessage');

                // Make this instance globally accessible for onclick handlers
                window.liveStatsClient = this;

                this.connect();
            }

            setFilter(filter) {
                this.currentFilter = filter;

                // Update active button state
                this.filterAll.classList.remove('active');
                this.filterInProgress.classList.remove('active');
                this.filterCompleted.classList.remove('active');

                if (filter === 'all') {
                    this.filterAll.classList.add('active');
                } else if (filter === 'inProgress') {
                    this.filterInProgress.classList.add('active');
                } else if (filter === 'completed') {
                    this.filterCompleted.classList.add('active');
                }

                // Rebuild table with current filter
                this.buildTable();
            }

            connect() {
                const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
                const wsUrl = `${protocol}//${window.location.host}/ws/live-stats`;

                this.hideStatus();

                try {
                    this.ws = new WebSocket(wsUrl);

                    this.ws.onopen = () => {
                        this.hideStatus();
                        this.reconnectAttempts = 0;
                        console.log('WebSocket connected');
                    };

                    this.ws.onmessage = (event) => {
                        try {
                            const data = JSON.parse(event.data);
                            this.handleMessage(data);
                        } catch (error) {
                            console.error('Error parsing WebSocket message:', error);
                        }
                    };

                    this.ws.onclose = () => {
                        this.updateStatus('disconnected', '🔴 Disconnected from server');
                        console.log('WebSocket disconnected');
                        this.scheduleReconnect();
                    };

                    this.ws.onerror = (error) => {
                        console.error('WebSocket error:', error);
                        this.updateStatus('disconnected', '🔴 Connection error');
                    };

                } catch (error) {
                    console.error('Error creating WebSocket:', error);
                    this.updateStatus('disconnected', '🔴 Failed to connect');
                    this.scheduleReconnect();
                }
            }

            scheduleReconnect() {
                if (this.reconnectAttempts < this.maxReconnectAttempts) {
                    this.reconnectAttempts++;
                    const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);

                    this.updateStatus('connecting', `🔄 Reconnecting in ${delay/1000}s... (${this.reconnectAttempts}/${this.maxReconnectAttempts})`);

                    setTimeout(() => {
                        this.connect();
                    }, delay);
                } else {
                    this.updateStatus('disconnected', '🔴 Failed to reconnect. Refresh page to try again.');
                }
            }

            updateStatus(status, message) {
                this.statusElement.className = `connection-status ${status}`;
                this.statusElement.textContent = message;
                this.statusElement.style.display = 'block';
            }

            hideStatus() {
                this.statusElement.style.display = 'none';
            }

            handleMessage(data) {
                switch (data.type) {
                    case 'initial_state':
                        this.handleInitialState(data);
                        break;
                    case 'user_registered':
                        this.handleUserRegistered(data);
                        break;
                    case 'state_update':
                        this.handleStateUpdate(data);
                        break;
                    case 'quiz_switched':
                        this.handleQuizSwitched(data);
                        break;
                    case 'pong':
                        // Keep-alive response
                        break;
                    default:
                        console.log('Unknown message type:', data.type);
                }
            }

            handleInitialState(data) {
                this.users = data.users || {};
                this.liveStats = this.normalizeStatsData(data.live_stats || {});
                this.completedUsers = data.completed_users || {};
                this.completionTimes = data.completion_times || {};
                this.questions = data.questions || [];
                this.totalQuestions = data.total_questions || 0;
                this.totalPoints = data.total_points || this.questions.reduce((sum, q) => sum + (q.points || 1), 0);
                this.currentQuiz = data.current_quiz || 'No quiz selected';

                // Calculate statistics client-side
                this.calculateStatistics();

                this.buildTable();
            }

            normalizeStatsData(liveStats) {
                // Convert old format to new format if needed
                const normalized = {};
                for (const userId in liveStats) {
                    normalized[userId] = {};
                    for (const questionId in liveStats[userId]) {
                        const value = liveStats[userId][questionId];
                        if (typeof value === 'string') {
                            // Old format: just the state
                            normalized[userId][questionId] = {
                                state: value,
                                time_taken: null
                            };
                        } else {
                            // New format: object with state and time_taken
                            normalized[userId][questionId] = value;
                        }
                    }
                }
                return normalized;
            }

            handleUserRegistered(data) {
                this.users[data.user_id] = data.username;
                if (!this.liveStats[data.user_id]) {
                    this.liveStats[data.user_id] = {};
                }
                this.liveStats[data.user_id][data.question_id] = {
                    state: data.state,
                    time_taken: data.time_taken
                };

                // New users are not completed yet
                this.completedUsers[data.user_id] = false;

                // Calculate statistics client-side
                this.calculateStatistics();

                this.buildTable();
            }

            handleStateUpdate(data) {
                const userId = data.user_id;
                const questionId = data.question_id;
                const newState = data.state;
                const timeTaken = data.time_taken;
                const completed = data.completed || false;
                const completedAt = data.completed_at;

                // Check if user is moving from in-progress to completed
                const wasCompleted = this.completedUsers[userId] || false;
                const isNowCompleted = completed;

                // Get old state for incremental stats update
                const oldState = (this.liveStats[userId] && this.liveStats[userId][questionId])
                    ? this.liveStats[userId][questionId].state
                    : 'empty';

                // Update live stats
                if (!this.liveStats[userId]) {
                    this.liveStats[userId] = {};
                }
                this.liveStats[userId][questionId] = {
                    state: newState,
                    time_taken: timeTaken
                };

                // Update completion status and time
                this.completedUsers[userId] = isNowCompleted;
                if (isNowCompleted && completedAt) {
                    this.completionTimes[userId] = completedAt;
                }

                // Update statistics incrementally
                this.updateStatisticsIncremental(userId, questionId, oldState, newState);

                // If user moved groups, rebuild tables completely
                if (!wasCompleted && isNowCompleted) {
                    this.buildTable();
                } else {
                    // Update only the affected cell
                    this.updateCell(userId, questionId, newState, timeTaken);

                    // Update affected headers/stats
                    this.updateQuestionHeader(questionId);
                    this.updateUserStats(userId);
                }
            }

            handleQuizSwitched(data) {
                this.users = {};
                this.liveStats = {};
                this.completedUsers = {};
                this.questions = data.questions || [];
                this.totalQuestions = data.total_questions || 0;
                this.currentQuiz = data.current_quiz || 'No quiz selected';

                // Calculate statistics client-side
                this.calculateStatistics();

                this.buildTable();
            }

            calculateStatistics() {
                // Calculate user statistics (with points)
                this.userStatistics = {};
                for (const userId in this.liveStats) {
                    let correctCount = 0;
                    let totalAnswered = 0;
                    let earnedPoints = 0;
                    let attemptedPoints = 0;

                    for (const questionId in this.liveStats[userId]) {
                        const state = this.liveStats[userId][questionId].state;
                        const qId = parseInt(questionId);
                        const question = this.questions.find(q => q.id === qId);
                        const questionPoints = question ? (question.points || 1) : 1;

                        if (state === 'ok' || state === 'fail') {
                            totalAnswered++;
                            attemptedPoints += questionPoints;
                            if (state === 'ok') {
                                correctCount++;
                                earnedPoints += questionPoints;
                            }
                        }
                    }

                    this.userStatistics[userId] = {
                        correct_count: correctCount,
                        total_answered: totalAnswered,
                        earned_points: earnedPoints,
                        attempted_points: attemptedPoints
                    };
                }

                // Calculate question statistics
                this.questionStatistics = {};
                for (let i = 1; i <= this.questions.length; i++) {
                    this.questionStatistics[i] = {
                        correct_count: 0,
                        total_attempts: 0
                    };
                }

                for (const userId in this.liveStats) {
                    for (const questionId in this.liveStats[userId]) {
                        const state = this.liveStats[userId][questionId].state;
                        if (state === 'ok' || state === 'fail') {
                            const qId = parseInt(questionId);
                            this.questionStatistics[qId].total_attempts++;
                            if (state === 'ok') {
                                this.questionStatistics[qId].correct_count++;
                            }
                        }
                    }
                }
            }

            updateStatisticsIncremental(userId, questionId, oldState, newState) {
                // Get question points
                const question = this.questions.find(q => q.id === parseInt(questionId));
                const questionPoints = question ? (question.points || 1) : 1;

                // Initialize stats if needed
                if (!this.userStatistics[userId]) {
                    this.userStatistics[userId] = { correct_count: 0, total_answered: 0, earned_points: 0, attempted_points: 0 };
                }
                if (!this.questionStatistics[questionId]) {
                    this.questionStatistics[questionId] = { correct_count: 0, total_attempts: 0 };
                }

                // Remove old state contribution
                if (oldState === 'ok' || oldState === 'fail') {
                    this.userStatistics[userId].total_answered--;
                    this.userStatistics[userId].attempted_points -= questionPoints;
                    this.questionStatistics[questionId].total_attempts--;
                    if (oldState === 'ok') {
                        this.userStatistics[userId].correct_count--;
                        this.userStatistics[userId].earned_points -= questionPoints;
                        this.questionStatistics[questionId].correct_count--;
                    }
                }

                // Add new state contribution
                if (newState === 'ok' || newState === 'fail') {
                    this.userStatistics[userId].total_answered++;
                    this.userStatistics[userId].attempted_points += questionPoints;
                    this.questionStatistics[questionId].total_attempts++;
                    if (newState === 'ok') {
                        this.userStatistics[userId].correct_count++;
                        this.userStatistics[userId].earned_points += questionPoints;
                        this.questionStatistics[questionId].correct_count++;
                    }
                }
            }

            buildTable() {
                const userIds = Object.keys(this.users);

                // Separate users into two groups
                const inProgressUsers = [];
                const completedUsers = [];

                userIds.forEach(userId => {
                    if (this.completedUsers[userId]) {
                        completedUsers.push(userId);
                    } else {
                        inProgressUsers.push(userId);
                    }
                });

                // Sort completed users by completion time (most recent first)
                completedUsers.sort((a, b) => {
                    const timeA = this.completionTimes[a];
                    const timeB = this.completionTimes[b];

                    // If both have completion times, sort by time (descending - newest first)
                    if (timeA && timeB) {
                        return new Date(timeB) - new Date(timeA);
                    }
                    // If only one has completion time, prioritize it
                    if (timeA) return -1;
                    if (timeB) return 1;
                    // If neither has completion time, maintain order
                    return 0;
                });

                // Update filter counts
                this.countAll.textContent = userIds.length;
                this.countInProgress.textContent = inProgressUsers.length;
                this.countCompleted.textContent = completedUsers.length;

                // Determine which users to display based on filter
                let displayUsers = [];
                if (this.currentFilter === 'all') {
                    displayUsers = userIds;
                } else if (this.currentFilter === 'inProgress') {
                    displayUsers = inProgressUsers;
                } else if (this.currentFilter === 'completed') {
                    displayUsers = completedUsers;
                }

                // If no users or no users in filtered view, show no-data message
                if (userIds.length === 0 || displayUsers.length === 0) {
                    this.noDataMessage.style.display = 'block';
                    this.statsSection.style.display = 'none';

                    if (userIds.length === 0) {
                        this.noDataMessage.textContent = 'Waiting for users to join the quiz...';
                    } else {
                        this.noDataMessage.textContent = `No users in this category yet.`;
                    }
                    return;
                }

                this.noDataMessage.style.display = 'none';
                this.statsSection.style.display = 'flex';

                // Build table
                this.statsHeader.innerHTML = this.buildTableHeader();
                this.statsBody.innerHTML = this.buildTableRows(displayUsers);
            }

            buildTableHeader() {
                // Build header with question statistics
                let headerHtml = '<th class="username-header">User</th>';
                for (let i = 0; i < this.questions.length; i++) {
                    const question = this.questions[i];
                    const questionId = i + 1;
                    const questionPoints = question.points || 1;

                    // Get question statistics
                    const questionStats = this.questionStatistics[questionId] || { correct_count: 0, total_attempts: 0 };
                    const statsText = `${questionStats.correct_count}/${questionStats.total_attempts}`;

                    // Build file indicator if question has a file attachment
                    const fileIndicator = question.file ? `<span class="file-indicator" title="${question.file.split('/').pop()}">📎</span>` : '';

                    // Build points indicator if question has more than 1 point
                    const pointsIndicator = questionPoints > 1 ? `<span class="points-indicator" title="${questionPoints} points">🏆 ${questionPoints}</span>` : '';

                    if (question.image && !question.question) {
                        // Image-only question: show filename and small image
                        const imagePath = question.image;
                        const filename = imagePath.split('/').pop().split('.').slice(0, -1).join('.');
                        headerHtml += `<th title="${filename} - Correct: ${statsText}${questionPoints > 1 ? ` - ${questionPoints} points` : ''}">
                            <div class="image-header">
                                <img src="${imagePath}" alt="${filename}" class="header-image">
                                <div class="image-filename">${filename}${fileIndicator}${pointsIndicator}</div>
                                <div class="question-stats">${statsText}</div>
                            </div>
                        </th>`;
                    } else {
                        // Regular question with text
                        const questionText = question.question || `Q${i + 1}`;
                        headerHtml += `<th title="${questionText} - Correct: ${statsText}${questionPoints > 1 ? ` - ${questionPoints} points` : ''}">
                            <div class="question-header">
                                <div class="question-text">${questionText}${fileIndicator}${pointsIndicator}</div>
                                <div class="question-stats">${statsText}</div>
                            </div>
                        </th>`;
                    }
                }
                return headerHtml;
            }

            buildTableRows(userIds) {
                let bodyHtml = '';
                userIds.forEach(userId => {
                    const username = this.users[userId];

                    // Get user statistics - show points instead of question count
                    const userStats = this.userStatistics[userId] || { correct_count: 0, total_answered: 0, earned_points: 0, attempted_points: 0 };
                    const userStatsText = `${userStats.earned_points}/${this.totalPoints}`;

                    bodyHtml += `<tr id="user-${userId}">`;
                    bodyHtml += `<td class="username-cell">
                        <div class="username-content">
                            <div class="username-text">${username}</div>
                            <span class="user-stats">${userStatsText}</span>
                        </div>
                    </td>`;

                    for (let questionId = 1; questionId <= this.questions.length; questionId++) {
                        const cellData = this.liveStats[userId] && this.liveStats[userId][questionId]
                            ? this.liveStats[userId][questionId]
                            : { state: 'empty', time_taken: null };

                        const state = cellData.state || 'empty';
                        const timeTaken = cellData.time_taken;
                        const stateIcon = this.getStateIcon(state);
                        const timeDisplay = this.formatTime(timeTaken);

                        bodyHtml += `<td class="state-cell state-${state}" id="cell-${userId}-${questionId}">
                            <div class="cell-content">
                                <div class="state-icon">${stateIcon}</div>
                                ${timeDisplay ? `<div class="time-display">${timeDisplay}</div>` : ''}
                            </div>
                        </td>`;
                    }

                    bodyHtml += '</tr>';
                });

                return bodyHtml;
            }

            updateCell(userId, questionId, state, timeTaken) {
                const cellElement = document.getElementById(`cell-${userId}-${questionId}`);
                if (cellElement) {
                    cellElement.className = `state-cell state-${state}`;
                    const stateIcon = this.getStateIcon(state);
                    const timeDisplay = this.formatTime(timeTaken);

                    cellElement.innerHTML = `
                        <div class="cell-content">
                            <div class="state-icon">${stateIcon}</div>
                            ${timeDisplay ? `<div class="time-display">${timeDisplay}</div>` : ''}
                        </div>
                    `;
                }
            }

            updateQuestionHeader(questionId) {
                const questionStats = this.questionStatistics[questionId] || { correct_count: 0, total_attempts: 0 };
                const statsText = `${questionStats.correct_count}/${questionStats.total_attempts}`;

                // Update header in the single table
                const headerCell = this.statsHeader.children[questionId];
                if (headerCell) {
                    const statsElement = headerCell.querySelector('.question-stats');
                    if (statsElement) {
                        statsElement.textContent = statsText;
                    }
                }
            }

            updateUserStats(userId) {
                const userStats = this.userStatistics[userId] || { correct_count: 0, total_answered: 0 };
                const userStatsText = `${userStats.correct_count}/${userStats.total_answered}`;

                // Find the user stats element
                const userRow = document.getElementById(`user-${userId}`);
                if (userRow) {
                    const statsElement = userRow.querySelector('.user-stats');
                    if (statsElement) {
                        statsElement.textContent = userStatsText;
                    }
                }
            }

            formatTime(seconds) {
                if (seconds === null || seconds === undefined) {
                    return null;
                }

                if (seconds < 60) {
                    return `${Math.round(seconds)}s`;
                } else {
                    const minutes = Math.floor(seconds / 60);
                    const remainingSeconds = Math.round(seconds % 60);
                    return `${minutes}m ${remainingSeconds}s`;
                }
            }

            getStateIcon(state) {
                switch (state) {
                    case 'think': return '🟡';
                    case 'ok': return '🟢';
                    case 'fail': return '🔴';
                    default: return '⚪';
                }
            }

            // Send periodic ping to keep connection alive
            startKeepAlive() {
                setInterval(() => {
                    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
                        this.ws.send(JSON.stringify({ type: 'ping' }));
                    }
                }, 30000); // Ping every 30 seconds
            }
        }

        // Initialize the live stats client when page loads
        document.addEventListener('DOMContentLoaded', () => {
            const client = new LiveStatsClient();
            client.startKeepAlive();
        });
    </script>
</body>
</html>
