ItsJayKee commited on
Commit
1af3855
Β·
verified Β·
1 Parent(s): dc933c1

okay make me a log in page, you need to put your name grade level and section. After logging in you will go into the 2nd page, this 2nd page is a fast typing test and instead of using real english language, we use html, css and Javascript language instead, they're 3 or more features but the important feature is, first you can select the type of language you test, like choosing html, css and javascript, second you can select the timer of this test, the timer is 1 minute 5 minutes 10 minutes and 30 minutes but the timer doesn't stop when it hits zero, it only stops when all the code snippets are all encoded, third is leaderboard where it shows the top users who used the typing test the leaderboard will get the credentials from the log in page and the most important is, after you finished the code, it will show your speed and accuracy, then there is a button and when you click the button it will display the code in another page

Browse files
Files changed (5) hide show
  1. README.md +8 -5
  2. index.html +70 -19
  3. script.js +37 -0
  4. style.css +67 -18
  5. typing-test.html +826 -0
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Codetyper Racer
3
- emoji: πŸ‘
4
- colorFrom: pink
5
- colorTo: red
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: CodeTyper Racer πŸš€
3
+ colorFrom: yellow
4
+ colorTo: gray
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://huggingface.co/deepsite).
index.html CHANGED
@@ -1,19 +1,70 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>CodeTyper Racer - Login</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ </head>
12
+ <body class="bg-gray-100 min-h-screen flex items-center justify-center">
13
+ <div class="w-full max-w-md">
14
+ <div class="bg-white rounded-xl shadow-2xl p-8">
15
+ <div class="text-center mb-8">
16
+ <h1 class="text-3xl font-bold text-gray-800">CodeTyper Racer πŸš€</h1>
17
+ <p class="text-gray-600 mt-2">Login to start your coding speed challenge</p>
18
+ </div>
19
+
20
+ <form id="loginForm" class="space-y-6">
21
+ <div>
22
+ <label for="name" class="block text-sm font-medium text-gray-700 mb-1">Full Name</label>
23
+ <input type="text" id="name" name="name" required
24
+ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition">
25
+ </div>
26
+
27
+ <div>
28
+ <label for="gradeLevel" class="block text-sm font-medium text-gray-700 mb-1">Grade Level</label>
29
+ <select id="gradeLevel" name="gradeLevel" required
30
+ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition">
31
+ <option value="" disabled selected>Select your grade</option>
32
+ <option value="Grade 7">Grade 7</option>
33
+ <option value="Grade 8">Grade 8</option>
34
+ <option value="Grade 9">Grade 9</option>
35
+ <option value="Grade 10">Grade 10</option>
36
+ <option value="Grade 11">Grade 11</option>
37
+ <option value="Grade 12">Grade 12</option>
38
+ </select>
39
+ </div>
40
+
41
+ <div>
42
+ <label for="section" class="block text-sm font-medium text-gray-700 mb-1">Section</label>
43
+ <input type="text" id="section" name="section" required
44
+ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition">
45
+ </div>
46
+
47
+ <button type="submit"
48
+ class="w-full bg-gradient-to-r from-blue-500 to-purple-600 text-white py-3 rounded-lg font-semibold shadow-lg hover:from-blue-600 hover:to-purple-700 transition transform hover:-translate-y-0.5">
49
+ Start Typing Challenge
50
+ </button>
51
+ </form>
52
+ </div>
53
+ </div>
54
+
55
+ <script src="script.js"></script>
56
+ <script>
57
+ feather.replace();
58
+ document.getElementById('loginForm').addEventListener('submit', function(e) {
59
+ e.preventDefault();
60
+ const name = document.getElementById('name').value;
61
+ const gradeLevel = document.getElementById('gradeLevel').value;
62
+ const section = document.getElementById('section').value;
63
+
64
+ localStorage.setItem('userData', JSON.stringify({ name, gradeLevel, section }));
65
+ window.location.href = 'typing-test.html';
66
+ });
67
+ </script>
68
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
69
+ </body>
70
+ </html>
script.js ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Shared utility functions
2
+
3
+ // Format time as MM:SS
4
+ function formatTime(seconds) {
5
+ const mins = Math.floor(seconds / 60);
6
+ const secs = seconds % 60;
7
+ return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
8
+ }
9
+
10
+ // Calculate typing statistics
11
+ function calculateTypingStats(startTime, endTime, correctChars, totalChars) {
12
+ const timeElapsed = (endTime - startTime) / 1000;
13
+ const wpm = Math.round((correctChars / 5) / (timeElapsed / 60));
14
+ const accuracy = totalChars > 0 ? Math.round((correctChars / totalChars) * 100) : 0;
15
+ return { wpm, accuracy, timeElapsed, totalChars };
16
+ }
17
+
18
+ // Save result to leaderboard
19
+ function saveToLeaderboard(result) {
20
+ const userData = JSON.parse(localStorage.getItem('userData'));
21
+ if (!userData) return;
22
+
23
+ let leaderboard = JSON.parse(localStorage.getItem('leaderboard')) || [];
24
+
25
+ leaderboard.push({
26
+ name: userData.name,
27
+ gradeLevel: userData.gradeLevel,
28
+ section: userData.section,
29
+ wpm: result.wpm,
30
+ accuracy: result.accuracy,
31
+ time: result.timeElapsed,
32
+ chars: result.totalChars,
33
+ timestamp: new Date().toISOString()
34
+ });
35
+
36
+ localStorage.setItem('leaderboard', JSON.stringify(leaderboard));
37
+ }
style.css CHANGED
@@ -1,28 +1,77 @@
 
1
  body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
4
  }
5
 
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
 
 
 
 
 
9
  }
10
 
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
  }
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
  }
25
 
26
- .card p:last-child {
27
- margin-bottom: 0;
 
 
28
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Base styles */
2
  body {
3
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
4
+ line-height: 1.6;
5
  }
6
 
7
+ /* Code display styling */
8
+ #codeDisplay {
9
+ white-space: pre-wrap;
10
+ color: #c9d1d9;
11
+ background-color: #1e1e1e;
12
+ font-family: 'Fira Code', 'Courier New', monospace;
13
+ line-height: 1.5;
14
+ tab-size: 2;
15
  }
16
 
17
+ /* Typing area styling */
18
+ #typingArea {
19
+ font-family: 'Fira Code', 'Courier New', monospace;
20
+ line-height: 1.5;
21
+ tab-size: 2;
22
  }
23
 
24
+ /* Progress bar animation */
25
+ #progressFill {
26
+ transition: width 0.3s ease;
 
 
 
27
  }
28
 
29
+ /* Modal animations */
30
+ .modal-enter {
31
+ opacity: 0;
32
+ transform: scale(0.95);
33
  }
34
+
35
+ .modal-enter-active {
36
+ opacity: 1;
37
+ transform: scale(1);
38
+ transition: opacity 200ms, transform 200ms;
39
+ }
40
+
41
+ .modal-exit {
42
+ opacity: 1;
43
+ }
44
+
45
+ .modal-exit-active {
46
+ opacity: 0;
47
+ transform: scale(0.95);
48
+ transition: opacity 200ms, transform 200ms;
49
+ }
50
+
51
+ /* Custom scrollbar */
52
+ ::-webkit-scrollbar {
53
+ width: 8px;
54
+ height: 8px;
55
+ }
56
+
57
+ ::-webkit-scrollbar-track {
58
+ background: #2d3748;
59
+ }
60
+
61
+ ::-webkit-scrollbar-thumb {
62
+ background: #4a5568;
63
+ border-radius: 4px;
64
+ }
65
+
66
+ ::-webkit-scrollbar-thumb:hover {
67
+ background: #718096;
68
+ }
69
+
70
+ /* Leaderboard table styling */
71
+ #leaderboardBody tr:nth-child(even) {
72
+ background-color: rgba(74, 85, 104, 0.2);
73
+ }
74
+
75
+ #leaderboardBody tr:hover {
76
+ background-color: rgba(74, 85, 104, 0.4);
77
+ }
typing-test.html ADDED
@@ -0,0 +1,826 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>CodeTyper Racer - Challenge</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ </head>
12
+ <body class="bg-gray-900 text-gray-100 min-h-screen">
13
+ <header class="bg-gray-800 py-4 shadow-lg">
14
+ <div class="container mx-auto px-4 flex justify-between items-center">
15
+ <h1 class="text-xl font-bold">CodeTyper Racer πŸš€</h1>
16
+ <div class="flex items-center space-x-4">
17
+ <div id="timerDisplay" class="bg-gray-700 px-4 py-2 rounded-lg font-mono">
18
+ 00:00
19
+ </div>
20
+ <button id="leaderboardBtn" class="flex items-center space-x-1 bg-gray-700 px-3 py-2 rounded-lg hover:bg-gray-600 transition">
21
+ <i data-feather="bar-chart-2"></i>
22
+ <span>Leaderboard</span>
23
+ </button>
24
+ </div>
25
+ </div>
26
+ </header>
27
+
28
+ <main class="container mx-auto px-4 py-8">
29
+ <div class="flex flex-col lg:flex-row gap-8">
30
+ <!-- Settings Panel -->
31
+ <div class="lg:w-1/4 bg-gray-800 p-6 rounded-xl shadow-lg">
32
+ <div class="mb-6">
33
+ <h2 class="text-lg font-semibold mb-3">Language</h2>
34
+ <div class="space-y-2">
35
+ <button data-language="html" class="language-btn w-full bg-blue-600 text-white py-2 rounded-lg transition hover:bg-blue-700">
36
+ HTML
37
+ </button>
38
+ <button data-language="css" class="language-btn w-full bg-blue-600 text-white py-2 rounded-lg transition hover:bg-blue-700">
39
+ CSS
40
+ </button>
41
+ <button data-language="javascript" class="language-btn w-full bg-blue-600 text-white py-2 rounded-lg transition hover:bg-blue-700">
42
+ JavaScript
43
+ </button>
44
+ </div>
45
+ </div>
46
+
47
+ <div class="mb-6">
48
+ <h2 class="text-lg font-semibold mb-3">Timer</h2>
49
+ <div class="grid grid-cols-2 gap-2">
50
+ <button data-time="1" class="time-btn bg-gray-700 py-2 rounded-lg hover:bg-gray-600 transition">
51
+ 1 min
52
+ </button>
53
+ <button data-time="5" class="time-btn bg-gray-700 py-2 rounded-lg hover:bg-gray-600 transition">
54
+ 5 min
55
+ </button>
56
+ <button data-time="10" class="time-btn bg-gray-700 py-2 rounded-lg hover:bg-gray-600 transition">
57
+ 10 min
58
+ </button>
59
+ <button data-time="30" class="time-btn bg-gray-700 py-2 rounded-lg hover:bg-gray-600 transition">
60
+ 30 min
61
+ </button>
62
+ </div>
63
+ </div>
64
+
65
+ <div class="mb-6">
66
+ <h2 class="text-lg font-semibold mb-3">Difficulty</h2>
67
+ <div class="grid grid-cols-3 gap-2">
68
+ <button data-difficulty="easy" class="difficulty-btn bg-green-600 py-2 rounded-lg hover:bg-green-700 transition">
69
+ Easy
70
+ </button>
71
+ <button data-difficulty="medium" class="difficulty-btn bg-yellow-600 py-2 rounded-lg hover:bg-yellow-700 transition">
72
+ Medium
73
+ </button>
74
+ <button data-difficulty="hard" class="difficulty-btn bg-red-600 py-2 rounded-lg hover:bg-red-700 transition">
75
+ Hard
76
+ </button>
77
+ </div>
78
+ </div>
79
+
80
+ <button id="startTestBtn" class="w-full bg-gradient-to-r from-purple-600 to-blue-500 text-white py-3 rounded-lg font-semibold shadow-lg hover:from-purple-700 hover:to-blue-600 transition">
81
+ Start Test
82
+ </button>
83
+ </div>
84
+
85
+ <!-- Typing Area -->
86
+ <div class="lg:w-3/4">
87
+ <div id="codeDisplay" class="bg-gray-800 p-6 rounded-xl shadow-lg font-mono text-gray-300 mb-6 h-64 overflow-y-auto">
88
+ <p class="text-gray-500 italic">Select a language and click "Start Test" to begin</p>
89
+ </div>
90
+
91
+ <div class="relative">
92
+ <textarea id="typingArea" disabled class="w-full bg-gray-800 border border-gray-700 rounded-lg p-4 font-mono text-gray-300 h-48 focus:outline-none focus:ring-2 focus:ring-blue-500 resize-none" placeholder="Start typing here when the test begins..."></textarea>
93
+ <div id="progressBar" class="h-1 bg-gray-700 rounded-full mt-2">
94
+ <div id="progressFill" class="h-full bg-blue-500 rounded-full" style="width: 0%"></div>
95
+ </div>
96
+ </div>
97
+
98
+ <div class="flex justify-between items-center mt-4">
99
+ <div id="wpmDisplay" class="text-gray-400">WPM: 0</div>
100
+ <div id="accuracyDisplay" class="text-gray-400">Accuracy: 0%</div>
101
+ <button id="submitTestBtn" disabled class="bg-green-600 px-4 py-2 rounded-lg hover:bg-green-700 transition">
102
+ Submit Code
103
+ </button>
104
+ </div>
105
+ </div>
106
+ </div>
107
+ </main>
108
+
109
+ <!-- Leaderboard Modal -->
110
+ <div id="leaderboardModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden">
111
+ <div class="bg-gray-800 rounded-xl p-6 w-full max-w-2xl max-h-[80vh] overflow-y-auto">
112
+ <div class="flex justify-between items-center mb-4">
113
+ <h2 class="text-xl font-bold">Leaderboard πŸ†</h2>
114
+ <button id="closeLeaderboardBtn" class="text-gray-400 hover:text-white">
115
+ <i data-feather="x"></i>
116
+ </button>
117
+ </div>
118
+ <table class="w-full">
119
+ <thead>
120
+ <tr class="border-b border-gray-700">
121
+ <th class="text-left py-2">Rank</th>
122
+ <th class="text-left py-2">Name</th>
123
+ <th class="text-left py-2">Grade</th>
124
+ <th class="text-left py-2">Section</th>
125
+ <th class="text-right py-2">WPM</th>
126
+ <th class="text-right py-2">Accuracy</th>
127
+ </tr>
128
+ </thead>
129
+ <tbody id="leaderboardBody">
130
+ <!-- Leaderboard data will be inserted here -->
131
+ </tbody>
132
+ </table>
133
+ </div>
134
+ </div>
135
+
136
+ <!-- Results Modal -->
137
+ <div id="resultsModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden">
138
+ <div class="bg-gray-800 rounded-xl p-6 w-full max-w-2xl">
139
+ <div class="flex justify-between items-center mb-4">
140
+ <h2 class="text-xl font-bold">Your Results πŸŽ‰</h2>
141
+ <button id="closeResultsBtn" class="text-gray-400 hover:text-white">
142
+ <i data-feather="x"></i>
143
+ </button>
144
+ </div>
145
+ <div class="grid grid-cols-2 gap-4 mb-6">
146
+ <div class="bg-gray-700 p-4 rounded-lg">
147
+ <div class="text-gray-400">Words Per Minute</div>
148
+ <div id="resultWPM" class="text-3xl font-bold">0</div>
149
+ </div>
150
+ <div class="bg-gray-700 p-4 rounded-lg">
151
+ <div class="text-gray-400">Accuracy</div>
152
+ <div id="resultAccuracy" class="text-3xl font-bold">0%</div>
153
+ </div>
154
+ <div class="bg-gray-700 p-4 rounded-lg">
155
+ <div class="text-gray-400">Time</div>
156
+ <div id="resultTime" class="text-3xl font-bold">00:00</div>
157
+ </div>
158
+ <div class="bg-gray-700 p-4 rounded-lg">
159
+ <div class="text-gray-400">Characters</div>
160
+ <div id="resultChars" class="text-3xl font-bold">0</div>
161
+ </div>
162
+ </div>
163
+ <button id="viewCodeBtn" class="w-full bg-blue-600 py-3 rounded-lg hover:bg-blue-700 transition">
164
+ View Your Code
165
+ </button>
166
+ </div>
167
+ </div>
168
+
169
+ <!-- Code Display Modal -->
170
+ <div id="codeModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden">
171
+ <div class="bg-gray-800 rounded-xl p-6 w-full max-w-4xl max-h-[80vh] overflow-y-auto">
172
+ <div class="flex justify-between items-center mb-4">
173
+ <h2 class="text-xl font-bold">Your Code πŸ’»</h2>
174
+ <button id="closeCodeBtn" class="text-gray-400 hover:text-white">
175
+ <i data-feather="x"></i>
176
+ </button>
177
+ </div>
178
+ <pre id="displayedCode" class="bg-gray-900 p-4 rounded-lg overflow-x-auto"></pre>
179
+ </div>
180
+ </div>
181
+
182
+ <script src="script.js"></script>
183
+ <script>
184
+ feather.replace();
185
+
186
+ // Sample code snippets for each language
187
+ const codeSnippets = {
188
+ html: {
189
+ easy: `<div class="container">
190
+ <h1>Welcome to my website</h1>
191
+ <p>This is a paragraph of text</p>
192
+ <button class="btn">Click me</button>
193
+ </div>`,
194
+ medium: `<!DOCTYPE html>
195
+ <html lang="en">
196
+ <head>
197
+ <meta charset="UTF-8">
198
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
199
+ <title>Document</title>
200
+ <link rel="stylesheet" href="styles.css">
201
+ </head>
202
+ <body>
203
+ <header>
204
+ <nav class="navbar">
205
+ <ul class="nav-links">
206
+ <li><a href="#">Home</a></li>
207
+ <li><a href="#">About</a></li>
208
+ <li><a href="#">Contact</a></li>
209
+ </ul>
210
+ </nav>
211
+ </header>
212
+ </body>
213
+ </html>`,
214
+ hard: `<!DOCTYPE html>
215
+ <html lang="en">
216
+ <head>
217
+ <meta charset="UTF-8">
218
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
219
+ <title>Interactive Form</title>
220
+ <style>
221
+ .form-container {
222
+ max-width: 600px;
223
+ margin: 0 auto;
224
+ padding: 20px;
225
+ background: #f9f9f9;
226
+ border-radius: 8px;
227
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
228
+ }
229
+ .form-group {
230
+ margin-bottom: 15px;
231
+ }
232
+ label {
233
+ display: block;
234
+ margin-bottom: 5px;
235
+ font-weight: bold;
236
+ }
237
+ input, select, textarea {
238
+ width: 100%;
239
+ padding: 8px;
240
+ border: 1px solid #ddd;
241
+ border-radius: 4px;
242
+ }
243
+ button {
244
+ background: #4CAF50;
245
+ color: white;
246
+ padding: 10px 15px;
247
+ border: none;
248
+ border-radius: 4px;
249
+ cursor: pointer;
250
+ }
251
+ </style>
252
+ </head>
253
+ <body>
254
+ <div class="form-container">
255
+ <h1>Contact Us</h1>
256
+ <form id="contactForm">
257
+ <div class="form-group">
258
+ <label for="name">Full Name:</label>
259
+ <input type="text" id="name" name="name" required>
260
+ </div>
261
+ <div class="form-group">
262
+ <label for="email">Email:</label>
263
+ <input type="email" id="email" name="email" required>
264
+ </div>
265
+ <div class="form-group">
266
+ <label for="message">Message:</label>
267
+ <textarea id="message" name="message" rows="5" required></textarea>
268
+ </div>
269
+ <button type="submit">Submit</button>
270
+ </form>
271
+ </div>
272
+ <script>
273
+ document.getElementById('contactForm').addEventListener('submit', function(e) {
274
+ e.preventDefault();
275
+ alert('Form submitted successfully!');
276
+ this.reset();
277
+ });
278
+ </script>
279
+ </body>
280
+ </html>`
281
+ },
282
+ css: {
283
+ easy: `body {
284
+ font-family: Arial, sans-serif;
285
+ background-color: #f4f4f4;
286
+ margin: 0;
287
+ padding: 20px;
288
+ }
289
+
290
+ .container {
291
+ max-width: 800px;
292
+ margin: 0 auto;
293
+ background: white;
294
+ padding: 20px;
295
+ border-radius: 5px;
296
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
297
+ }`,
298
+ medium: `/* Button Styles */
299
+ .btn {
300
+ display: inline-block;
301
+ padding: 10px 20px;
302
+ font-size: 16px;
303
+ text-align: center;
304
+ text-decoration: none;
305
+ border-radius: 5px;
306
+ transition: all 0.3s ease;
307
+ cursor: pointer;
308
+ }
309
+
310
+ .btn-primary {
311
+ background-color: #3498db;
312
+ color: white;
313
+ border: 2px solid #3498db;
314
+ }
315
+
316
+ .btn-primary:hover {
317
+ background-color: #2980b9;
318
+ border-color: #2980b9;
319
+ }
320
+
321
+ .btn-outline {
322
+ background-color: transparent;
323
+ border: 2px solid #3498db;
324
+ color: #3498db;
325
+ }
326
+
327
+ .btn-outline:hover {
328
+ background-color: #3498db;
329
+ color: white;
330
+ }`,
331
+ hard: `/* Responsive Grid Layout */
332
+ .grid-container {
333
+ display: grid;
334
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
335
+ gap: 20px;
336
+ padding: 20px;
337
+ }
338
+
339
+ .card {
340
+ background: white;
341
+ border-radius: 8px;
342
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
343
+ overflow: hidden;
344
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
345
+ }
346
+
347
+ .card:hover {
348
+ transform: translateY(-5px);
349
+ box-shadow: 0 10px 20px rgba(0,0,0,0.1);
350
+ }
351
+
352
+ .card-header {
353
+ padding: 15px;
354
+ background: #3498db;
355
+ color: white;
356
+ font-weight: bold;
357
+ }
358
+
359
+ .card-body {
360
+ padding: 15px;
361
+ }
362
+
363
+ @media (max-width: 768px) {
364
+ .grid-container {
365
+ grid-template-columns: 1fr;
366
+ }
367
+ }
368
+
369
+ /* Animation */
370
+ @keyframes fadeIn {
371
+ from {
372
+ opacity: 0;
373
+ transform: translateY(20px);
374
+ }
375
+ to {
376
+ opacity: 1;
377
+ transform: translateY(0);
378
+ }
379
+ }
380
+
381
+ .card {
382
+ animation: fadeIn 0.5s ease forwards;
383
+ }
384
+
385
+ /* CSS Variables */
386
+ :root {
387
+ --primary-color: #3498db;
388
+ --secondary-color: #2ecc71;
389
+ --text-color: #333;
390
+ --light-gray: #f5f5f5;
391
+ }
392
+
393
+ body {
394
+ color: var(--text-color);
395
+ background: var(--light-gray);
396
+ }
397
+
398
+ .btn-primary {
399
+ background-color: var(--primary-color);
400
+ }`
401
+ },
402
+ javascript: {
403
+ easy: `// Function to greet user
404
+ function greet(name) {
405
+ return 'Hello, ' + name + '!';
406
+ }
407
+
408
+ // Calculate area of a rectangle
409
+ function calculateArea(width, height) {
410
+ return width * height;
411
+ }
412
+
413
+ // Call functions
414
+ console.log(greet('Alice'));
415
+ console.log('Area:', calculateArea(5, 3));`,
416
+ medium: `// DOM Manipulation
417
+ document.addEventListener('DOMContentLoaded', function() {
418
+ const button = document.getElementById('myButton');
419
+ const output = document.getElementById('output');
420
+
421
+ button.addEventListener('click', function() {
422
+ const name = prompt('What is your name?');
423
+ if (name) {
424
+ output.textContent = 'Hello, ' + name + '!';
425
+ }
426
+ });
427
+ });
428
+
429
+ // Fetch API example
430
+ async function fetchData(url) {
431
+ try {
432
+ const response = await fetch(url);
433
+ if (!response.ok) {
434
+ throw new Error('Network response was not ok');
435
+ }
436
+ const data = await response.json();
437
+ console.log(data);
438
+ return data;
439
+ } catch (error) {
440
+ console.error('Error:', error);
441
+ }
442
+ }
443
+
444
+ // Example usage
445
+ fetchData('https://api.example.com/data');`,
446
+ hard: `// Todo List Application
447
+ class TodoApp {
448
+ constructor() {
449
+ this.todos = [];
450
+ this.initElements();
451
+ this.bindEvents();
452
+ this.loadFromLocalStorage();
453
+ this.render();
454
+ }
455
+
456
+ initElements() {
457
+ this.todoForm = document.getElementById('todoForm');
458
+ this.todoInput = document.getElementById('todoInput');
459
+ this.todoList = document.getElementById('todoList');
460
+ }
461
+
462
+ bindEvents() {
463
+ this.todoForm.addEventListener('submit', (e) => this.handleSubmit(e));
464
+ this.todoList.addEventListener('click', (e) => this.handleListClick(e));
465
+ }
466
+
467
+ handleSubmit(e) {
468
+ e.preventDefault();
469
+ const todoText = this.todoInput.value.trim();
470
+ if (todoText) {
471
+ this.addTodo(todoText);
472
+ this.todoInput.value = '';
473
+ }
474
+ }
475
+
476
+ handleListClick(e) {
477
+ if (e.target.classList.contains('delete-btn')) {
478
+ const id = parseInt(e.target.parentElement.dataset.id);
479
+ this.removeTodo(id);
480
+ } else if (e.target.tagName === 'LI') {
481
+ const id = parseInt(e.target.dataset.id);
482
+ this.toggleTodo(id);
483
+ }
484
+ }
485
+
486
+ addTodo(text) {
487
+ const newTodo = {
488
+ id: Date.now(),
489
+ text,
490
+ completed: false
491
+ };
492
+ this.todos.push(newTodo);
493
+ this.saveToLocalStorage();
494
+ this.render();
495
+ }
496
+
497
+ removeTodo(id) {
498
+ this.todos = this.todos.filter(todo => todo.id !== id);
499
+ this.saveToLocalStorage();
500
+ this.render();
501
+ }
502
+
503
+ toggleTodo(id) {
504
+ this.todos = this.todos.map(todo =>
505
+ todo.id === id ? {...todo, completed: !todo.completed} : todo
506
+ );
507
+ this.saveToLocalStorage();
508
+ this.render();
509
+ }
510
+
511
+ saveToLocalStorage() {
512
+ localStorage.setItem('todos', JSON.stringify(this.todos));
513
+ }
514
+
515
+ loadFromLocalStorage() {
516
+ const savedTodos = localStorage.getItem('todos');
517
+ if (savedTodos) {
518
+ this.todos = JSON.parse(savedTodos);
519
+ }
520
+ }
521
+
522
+ render() {
523
+ this.todoList.innerHTML = this.todos.map(todo => \`
524
+ <li data-id="\${todo.id}" class="\${todo.completed ? 'completed' : ''}">
525
+ \${todo.text}
526
+ <button class="delete-btn">Γ—</button>
527
+ </li>
528
+ \`).join('');
529
+ }
530
+ }
531
+
532
+ // Initialize the app
533
+ document.addEventListener('DOMContentLoaded', () => {
534
+ new TodoApp();
535
+ });`
536
+ }
537
+ };
538
+
539
+ // DOM elements
540
+ const codeDisplay = document.getElementById('codeDisplay');
541
+ const typingArea = document.getElementById('typingArea');
542
+ const timerDisplay = document.getElementById('timerDisplay');
543
+ const startTestBtn = document.getElementById('startTestBtn');
544
+ const submitTestBtn = document.getElementById('submitTestBtn');
545
+ const progressFill = document.getElementById('progressFill');
546
+ const wpmDisplay = document.getElementById('wpmDisplay');
547
+ const accuracyDisplay = document.getElementById('accuracyDisplay');
548
+ const leaderboardBtn = document.getElementById('leaderboardBtn');
549
+ const leaderboardModal = document.getElementById('leaderboardModal');
550
+ const closeLeaderboardBtn = document.getElementById('closeLeaderboardBtn');
551
+ const leaderboardBody = document.getElementById('leaderboardBody');
552
+ const resultsModal = document.getElementById('resultsModal');
553
+ const closeResultsBtn = document.getElementById('closeResultsBtn');
554
+ const resultWPM = document.getElementById('resultWPM');
555
+ const resultAccuracy = document.getElementById('resultAccuracy');
556
+ const resultTime = document.getElementById('resultTime');
557
+ const resultChars = document.getElementById('resultChars');
558
+ const viewCodeBtn = document.getElementById('viewCodeBtn');
559
+ const codeModal = document.getElementById('codeModal');
560
+ const displayedCode = document.getElementById('displayedCode');
561
+ const closeCodeBtn = document.getElementById('closeCodeBtn');
562
+
563
+ // Test state variables
564
+ let selectedLanguage = 'html';
565
+ let selectedTime = 1;
566
+ let selectedDifficulty = 'easy';
567
+ let timerInterval;
568
+ let startTime;
569
+ let endTime;
570
+ let correctChars = 0;
571
+ let totalChars = 0;
572
+ let testActive = false;
573
+ let currentCode = '';
574
+ let userTypedCode = '';
575
+
576
+ // Set up language buttons
577
+ document.querySelectorAll('.language-btn').forEach(btn => {
578
+ btn.addEventListener('click', () => {
579
+ document.querySelectorAll('.language-btn').forEach(b => {
580
+ b.classList.remove('bg-blue-700');
581
+ b.classList.add('bg-blue-600');
582
+ });
583
+ btn.classList.remove('bg-blue-600');
584
+ btn.classList.add('bg-blue-700');
585
+ selectedLanguage = btn.dataset.language;
586
+ });
587
+ });
588
+
589
+ // Set up time buttons
590
+ document.querySelectorAll('.time-btn').forEach(btn => {
591
+ btn.addEventListener('click', () => {
592
+ document.querySelectorAll('.time-btn').forEach(b => {
593
+ b.classList.remove('bg-gray-600');
594
+ b.classList.add('bg-gray-700');
595
+ });
596
+ btn.classList.remove('bg-gray-700');
597
+ btn.classList.add('bg-gray-600');
598
+ selectedTime = parseInt(btn.dataset.time);
599
+ });
600
+ });
601
+
602
+ // Set up difficulty buttons
603
+ document.querySelectorAll('.difficulty-btn').forEach(btn => {
604
+ btn.addEventListener('click', () => {
605
+ document.querySelectorAll('.difficulty-btn').forEach(b => {
606
+ if (b.dataset.difficulty === 'easy') {
607
+ b.classList.remove('bg-green-700');
608
+ b.classList.add('bg-green-600');
609
+ } else if (b.dataset.difficulty === 'medium') {
610
+ b.classList.remove('bg-yellow-700');
611
+ b.classList.add('bg-yellow-600');
612
+ } else {
613
+ b.classList.remove('bg-red-700');
614
+ b.classList.add('bg-red-600');
615
+ }
616
+ });
617
+
618
+ if (btn.dataset.difficulty === 'easy') {
619
+ btn.classList.remove('bg-green-600');
620
+ btn.classList.add('bg-green-700');
621
+ } else if (btn.dataset.difficulty === 'medium') {
622
+ btn.classList.remove('bg-yellow-600');
623
+ btn.classList.add('bg-yellow-700');
624
+ } else {
625
+ btn.classList.remove('bg-red-600');
626
+ btn.classList.add('bg-red-700');
627
+ }
628
+
629
+ selectedDifficulty = btn.dataset.difficulty;
630
+ });
631
+ });
632
+
633
+ // Start test button
634
+ startTestBtn.addEventListener('click', startTest);
635
+
636
+ // Submit test button
637
+ submitTestBtn.addEventListener('click', endTest);
638
+
639
+ // Typing area events
640
+ typingArea.addEventListener('input', updateTypingStats);
641
+
642
+ // Leaderboard modal
643
+ leaderboardBtn.addEventListener('click', showLeaderboard);
644
+ closeLeaderboardBtn.addEventListener('click', () => {
645
+ leaderboardModal.classList.add('hidden');
646
+ });
647
+
648
+ // Results modal
649
+ closeResultsBtn.addEventListener('click', () => {
650
+ resultsModal.classList.add('hidden');
651
+ });
652
+
653
+ // View code button
654
+ viewCodeBtn.addEventListener('click', () => {
655
+ resultsModal.classList.add('hidden');
656
+ displayedCode.textContent = userTypedCode;
657
+ codeModal.classList.remove('hidden');
658
+ });
659
+
660
+ // Close code modal
661
+ closeCodeBtn.addEventListener('click', () => {
662
+ codeModal.classList.add('hidden');
663
+ });
664
+
665
+ // Format time as MM:SS
666
+ function formatTime(seconds) {
667
+ const mins = Math.floor(seconds / 60);
668
+ const secs = seconds % 60;
669
+ return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
670
+ }
671
+
672
+ // Start the typing test
673
+ function startTest() {
674
+ // Get the code to type
675
+ currentCode = codeSnippets[selectedLanguage][selectedDifficulty];
676
+ codeDisplay.innerHTML = currentCode
677
+ .replace(/</g, '&lt;')
678
+ .replace(/>/g, '&gt;')
679
+ .replace(/\n/g, '<br>')
680
+ .replace(/ /g, '&nbsp;');
681
+
682
+ // Reset stats
683
+ correctChars = 0;
684
+ totalChars = 0;
685
+ testActive = true;
686
+ typingArea.disabled = false;
687
+ typingArea.value = '';
688
+ typingArea.focus();
689
+ progressFill.style.width = '0%';
690
+ wpmDisplay.textContent = 'WPM: 0';
691
+ accuracyDisplay.textContent = 'Accuracy: 0%';
692
+
693
+ // Start timer
694
+ const totalSeconds = selectedTime * 60;
695
+ let secondsLeft = totalSeconds;
696
+ timerDisplay.textContent = formatTime(secondsLeft);
697
+
698
+ startTime = new Date();
699
+ timerInterval = setInterval(() => {
700
+ secondsLeft--;
701
+ timerDisplay.textContent = formatTime(secondsLeft);
702
+
703
+ if (secondsLeft <= 0) {
704
+ clearInterval(timerInterval);
705
+ timerDisplay.textContent = "00:00";
706
+ // Timer ends but test continues until all code is typed
707
+ }
708
+ }, 1000);
709
+
710
+ // Update UI
711
+ startTestBtn.disabled = true;
712
+ submitTestBtn.disabled = false;
713
+ }
714
+
715
+ // Update typing statistics
716
+ function updateTypingStats() {
717
+ if (!testActive) return;
718
+
719
+ userTypedCode = typingArea.value;
720
+ totalChars = userTypedCode.length;
721
+
722
+ // Calculate correct characters
723
+ let correct = 0;
724
+ for (let i = 0; i < totalChars; i++) {
725
+ if (i < currentCode.length && userTypedCode[i] === currentCode[i]) {
726
+ correct++;
727
+ }
728
+ }
729
+ correctChars = correct;
730
+
731
+ // Calculate progress
732
+ const progress = Math.min((totalChars / currentCode.length) * 100, 100);
733
+ progressFill.style.width = `${progress}%`;
734
+
735
+ // Calculate accuracy
736
+ const accuracy = totalChars > 0 ? Math.round((correctChars / totalChars) * 100) : 0;
737
+ accuracyDisplay.textContent = `Accuracy: ${accuracy}%`;
738
+
739
+ // Calculate WPM (assuming 5 chars = 1 word)
740
+ const timeElapsed = (new Date() - startTime) / 1000 / 60; // in minutes
741
+ const wpm = timeElapsed > 0 ? Math.round((correctChars / 5) / timeElapsed) : 0;
742
+ wpmDisplay.textContent = `WPM: ${wpm}`;
743
+
744
+ // Check if all code is typed
745
+ if (totalChars >= currentCode.length) {
746
+ endTest();
747
+ }
748
+ }
749
+
750
+ // End the typing test
751
+ function endTest() {
752
+ if (!testActive) return;
753
+
754
+ testActive = false;
755
+ clearInterval(timerInterval);
756
+ endTime = new Date();
757
+ typingArea.disabled = true;
758
+ submitTestBtn.disabled = true;
759
+ startTestBtn.disabled = false;
760
+
761
+ // Calculate final stats
762
+ const timeElapsed = (endTime - startTime) / 1000;
763
+ const wpm = Math.round((correctChars / 5) / (timeElapsed / 60));
764
+ const accuracy = totalChars > 0 ? Math.round((correctChars / totalChars) * 100) : 0;
765
+
766
+ // Show results
767
+ resultWPM.textContent = wpm;
768
+ resultAccuracy.textContent = `${accuracy}%`;
769
+ resultTime.textContent = formatTime(Math.round(timeElapsed));
770
+ resultChars.textContent = totalChars;
771
+ resultsModal.classList.remove('hidden');
772
+
773
+ // Save to leaderboard
774
+ saveToLeaderboard(wpm, accuracy);
775
+ }
776
+
777
+ // Show leaderboard
778
+ function showLeaderboard() {
779
+ leaderboardBody.innerHTML = '';
780
+
781
+ // Get leaderboard from local storage
782
+ let leaderboard = JSON.parse(localStorage.getItem('leaderboard')) || [];
783
+
784
+ // Sort by WPM descending
785
+ leaderboard.sort((a, b) => b.wpm - a.wpm);
786
+
787
+ // Display top 10
788
+ const top10 = leaderboard.slice(0, 10);
789
+ top10.forEach((entry, index) => {
790
+ const row = document.createElement('tr');
791
+ row.className = 'border-b border-gray-700';
792
+ row.innerHTML = `
793
+ <td class="py-2">${index + 1}</td>
794
+ <td class="py-2">${entry.name}</td>
795
+ <td class="py-2">${entry.gradeLevel}</td>
796
+ <td class="py-2">${entry.section}</td>
797
+ <td class="py-2 text-right">${entry.wpm}</td>
798
+ <td class="py-2 text-right">${entry.accuracy}%</td>
799
+ `;
800
+ leaderboardBody.appendChild(row);
801
+ });
802
+
803
+ leaderboardModal.classList.remove('hidden');
804
+ }
805
+
806
+ // Save result to leaderboard
807
+ function saveToLeaderboard(wpm, accuracy) {
808
+ const userData = JSON.parse(localStorage.getItem('userData'));
809
+ if (!userData) return;
810
+
811
+ let leaderboard = JSON.parse(localStorage.getItem('leaderboard')) || [];
812
+
813
+ leaderboard.push({
814
+ name: userData.name,
815
+ gradeLevel: userData.gradeLevel,
816
+ section: userData.section,
817
+ wpm,
818
+ accuracy,
819
+ timestamp: new Date().toISOString()
820
+ });
821
+
822
+ localStorage.setItem('leaderboard', JSON.stringify(leaderboard));
823
+ }
824
+ </script>
825
+ </body>
826
+ </html>