Spaces:
Running
Running
File size: 4,701 Bytes
449f607 1af3855 449f607 1af3855 0a23511 1af3855 0a23511 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
// Shared utility functions and state
const appState = {
currentTest: null,
activeButton: null
};
// Format time as MM:SS
function formatTime(seconds) {
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
}
// Calculate typing statistics
function calculateTypingStats(startTime, endTime, correctChars, totalChars) {
const timeElapsed = (endTime - startTime) / 1000;
const wpm = Math.round((correctChars / 5) / (timeElapsed / 60));
const accuracy = totalChars > 0 ? Math.round((correctChars / totalChars) * 100) : 0;
return { wpm, accuracy, timeElapsed, totalChars };
}
// Highlight active button
function setActiveButton(button, category) {
if (appState.activeButton) {
appState.activeButton.classList.remove('active-button');
}
button.classList.add('active-button');
appState.activeButton = button;
appState.currentTest = { ...appState.currentTest, [category]: button.dataset[category] };
}
// Show modal with results
function showResultsModal(stats) {
const modal = document.createElement('div');
modal.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50';
modal.innerHTML = `
<div class="bg-gray-800 rounded-xl p-8 max-w-md w-full">
<h2 class="text-2xl font-bold mb-4">Test Results</h2>
<div class="space-y-4">
<div class="flex justify-between">
<span class="text-gray-400">WPM:</span>
<span class="font-bold">${stats.wpm}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-400">Accuracy:</span>
<span class="font-bold">${stats.accuracy}%</span>
</div>
<div class="flex justify-between">
<span class="text-gray-400">Time:</span>
<span class="font-bold">${formatTime(stats.timeElapsed)}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-400">Characters:</span>
<span class="font-bold">${stats.totalChars}</span>
</div>
</div>
<div class="mt-6 flex justify-end space-x-3">
<button id="closeModal" class="px-4 py-2 bg-gray-700 rounded-lg hover:bg-gray-600">Close</button>
<button id="tryAgain" class="px-4 py-2 bg-blue-600 rounded-lg hover:bg-blue-700">Try Again</button>
</div>
</div>
`;
document.body.appendChild(modal);
modal.querySelector('#closeModal').addEventListener('click', () => {
modal.remove();
window.location.href = 'leaderboard.html';
});
modal.querySelector('#tryAgain').addEventListener('click', () => {
modal.remove();
window.location.href = 'typing-test.html';
});
}
// Save result to leaderboard
function saveToLeaderboard(result) {
const userData = JSON.parse(localStorage.getItem('userData'));
if (!userData) return;
let leaderboard = JSON.parse(localStorage.getItem('leaderboard')) || [];
// Check if user already has an entry and update if new score is higher
const existingEntryIndex = leaderboard.findIndex(
entry => entry.name === userData.name &&
entry.gradeLevel === userData.gradeLevel &&
entry.section === userData.section
);
if (existingEntryIndex >= 0) {
// Update only if new score is better
if (result.wpm > leaderboard[existingEntryIndex].wpm) {
leaderboard[existingEntryIndex] = {
...leaderboard[existingEntryIndex],
wpm: result.wpm,
accuracy: result.accuracy,
time: result.timeElapsed,
chars: result.totalChars,
timestamp: new Date().toISOString()
};
}
} else {
// Add new entry
leaderboard.push({
name: userData.name,
gradeLevel: userData.gradeLevel,
section: userData.section,
wpm: result.wpm,
accuracy: result.accuracy,
time: result.timeElapsed,
chars: result.totalChars,
timestamp: new Date().toISOString()
});
}
// Sort by WPM descending
leaderboard.sort((a, b) => b.wpm - a.wpm);
// Keep only top 100 entries
if (leaderboard.length > 100) {
leaderboard = leaderboard.slice(0, 100);
}
localStorage.setItem('leaderboard', JSON.stringify(leaderboard));
}
|