ktskhoa commited on
Commit
01470f0
·
verified ·
1 Parent(s): 80f08e4

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +939 -19
  3. prompts.txt +0 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Game Learning
3
- emoji: 📊
4
- colorFrom: purple
5
- colorTo: blue
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: game-learning
3
+ emoji: 🐳
4
+ colorFrom: gray
5
+ colorTo: yellow
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,939 @@
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>English Vocabulary Learning Game</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ .card {
11
+ perspective: 1000px;
12
+ }
13
+ .card-inner {
14
+ transition: transform 0.8s;
15
+ transform-style: preserve-3d;
16
+ }
17
+ .card.flipped .card-inner {
18
+ transform: rotateY(180deg);
19
+ }
20
+ .card-front, .card-back {
21
+ backface-visibility: hidden;
22
+ position: absolute;
23
+ width: 100%;
24
+ height: 100%;
25
+ }
26
+ .card-back {
27
+ transform: rotateY(180deg);
28
+ }
29
+ .progress-bar {
30
+ transition: width 0.5s ease-in-out;
31
+ }
32
+ .shake {
33
+ animation: shake 0.5s;
34
+ }
35
+ @keyframes shake {
36
+ 0%, 100% { transform: translateX(0); }
37
+ 20%, 60% { transform: translateX(-5px); }
38
+ 40%, 80% { transform: translateX(5px); }
39
+ }
40
+ .bounce {
41
+ animation: bounce 0.5s;
42
+ }
43
+ @keyframes bounce {
44
+ 0%, 100% { transform: translateY(0); }
45
+ 50% { transform: translateY(-10px); }
46
+ }
47
+ </style>
48
+ </head>
49
+ <body class="bg-gradient-to-br from-blue-50 to-indigo-100 min-h-screen">
50
+ <div class="container mx-auto px-4 py-8">
51
+ <header class="text-center mb-8">
52
+ <h1 class="text-4xl font-bold text-indigo-800 mb-2">Vocabulary Master</h1>
53
+ <p class="text-gray-600">Learn English words effectively</p>
54
+ </header>
55
+
56
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
57
+ <!-- Vocabulary Input Section -->
58
+ <div class="bg-white rounded-xl shadow-lg p-6">
59
+ <h2 class="text-2xl font-semibold text-indigo-700 mb-4">Add New Words</h2>
60
+ <div class="space-y-4">
61
+ <div>
62
+ <label class="block text-gray-700 mb-2">English Word</label>
63
+ <input type="text" id="englishWord" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
64
+ </div>
65
+ <div>
66
+ <label class="block text-gray-700 mb-2">Vietnamese Meaning</label>
67
+ <input type="text" id="vietnameseMeaning" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
68
+ </div>
69
+ <div>
70
+ <label class="block text-gray-700 mb-2">Example Sentence (Optional)</label>
71
+ <input type="text" id="exampleSentence" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
72
+ </div>
73
+ <button id="addWordBtn" class="w-full bg-indigo-600 text-white py-2 px-4 rounded-lg hover:bg-indigo-700 transition flex items-center justify-center">
74
+ <i class="fas fa-plus-circle mr-2"></i> Add Word
75
+ </button>
76
+ </div>
77
+
78
+ <div class="mt-6">
79
+ <h3 class="text-lg font-medium text-gray-800 mb-3">Your Vocabulary List</h3>
80
+ <div id="wordList" class="max-h-60 overflow-y-auto border border-gray-200 rounded-lg p-2">
81
+ <p class="text-gray-500 text-center py-4">No words added yet</p>
82
+ </div>
83
+ <div class="mt-3 flex space-x-2">
84
+ <button id="clearWordsBtn" class="flex-1 bg-red-100 text-red-700 py-1 px-3 rounded hover:bg-red-200 transition">
85
+ <i class="fas fa-trash-alt mr-1"></i> Clear All
86
+ </button>
87
+ <button id="exportWordsBtn" class="flex-1 bg-green-100 text-green-700 py-1 px-3 rounded hover:bg-green-200 transition">
88
+ <i class="fas fa-file-export mr-1"></i> Export
89
+ </button>
90
+ <button id="importWordsBtn" class="flex-1 bg-blue-100 text-blue-700 py-1 px-3 rounded hover:bg-blue-200 transition">
91
+ <i class="fas fa-file-import mr-1"></i> Import
92
+ </button>
93
+ </div>
94
+ <input type="file" id="importFileInput" class="hidden" accept=".json">
95
+ </div>
96
+ </div>
97
+
98
+ <!-- Learning Modes Section -->
99
+ <div class="bg-white rounded-xl shadow-lg p-6">
100
+ <h2 class="text-2xl font-semibold text-indigo-700 mb-4">Learning Modes</h2>
101
+ <div class="space-y-4">
102
+ <button id="flashcardsBtn" class="w-full bg-purple-100 text-purple-800 py-3 px-4 rounded-lg hover:bg-purple-200 transition flex items-center justify-between">
103
+ <div>
104
+ <i class="fas fa-layer-group mr-2"></i> Flashcards
105
+ </div>
106
+ <i class="fas fa-chevron-right"></i>
107
+ </button>
108
+ <button id="quizBtn" class="w-full bg-teal-100 text-teal-800 py-3 px-4 rounded-lg hover:bg-teal-200 transition flex items-center justify-between">
109
+ <div>
110
+ <i class="fas fa-question-circle mr-2"></i> Multiple Choice Quiz
111
+ </div>
112
+ <i class="fas fa-chevron-right"></i>
113
+ </button>
114
+ <button id="typingBtn" class="w-full bg-amber-100 text-amber-800 py-3 px-4 rounded-lg hover:bg-amber-200 transition flex items-center justify-between">
115
+ <div>
116
+ <i class="fas fa-keyboard mr-2"></i> Typing Practice
117
+ </div>
118
+ <i class="fas fa-chevron-right"></i>
119
+ </button>
120
+ </div>
121
+
122
+ <div class="mt-6">
123
+ <h3 class="text-lg font-medium text-gray-800 mb-3">Progress Tracking</h3>
124
+ <div class="bg-gray-100 rounded-lg p-4">
125
+ <div class="flex justify-between mb-1">
126
+ <span class="text-sm font-medium text-gray-700">Mastery</span>
127
+ <span id="masteryPercent" class="text-sm font-medium text-gray-700">0%</span>
128
+ </div>
129
+ <div class="w-full bg-gray-300 rounded-full h-2.5">
130
+ <div id="masteryBar" class="bg-indigo-600 h-2.5 rounded-full progress-bar" style="width: 0%"></div>
131
+ </div>
132
+ <div class="mt-3 grid grid-cols-3 gap-2 text-center">
133
+ <div class="bg-blue-50 p-2 rounded">
134
+ <div class="text-blue-800 font-bold" id="totalWords">0</div>
135
+ <div class="text-xs text-blue-600">Total Words</div>
136
+ </div>
137
+ <div class="bg-green-50 p-2 rounded">
138
+ <div class="text-green-800 font-bold" id="knownWords">0</div>
139
+ <div class="text-xs text-green-600">Known</div>
140
+ </div>
141
+ <div class="bg-red-50 p-2 rounded">
142
+ <div class="text-red-800 font-bold" id="learningWords">0</div>
143
+ <div class="text-xs text-red-600">Learning</div>
144
+ </div>
145
+ </div>
146
+ </div>
147
+ </div>
148
+ </div>
149
+
150
+ <!-- Game Display Area -->
151
+ <div class="bg-white rounded-xl shadow-lg p-6">
152
+ <div id="gameArea" class="h-full flex flex-col items-center justify-center">
153
+ <div class="text-center text-gray-500">
154
+ <i class="fas fa-book-open text-4xl mb-2"></i>
155
+ <p>Select a learning mode to begin</p>
156
+ </div>
157
+ </div>
158
+ </div>
159
+ </div>
160
+ </div>
161
+
162
+ <!-- Flashcards Modal -->
163
+ <div id="flashcardsModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
164
+ <div class="bg-white rounded-xl shadow-2xl w-full max-w-md mx-4">
165
+ <div class="p-4 border-b border-gray-200 flex justify-between items-center">
166
+ <h3 class="text-xl font-semibold text-indigo-700">Flashcards</h3>
167
+ <button id="closeFlashcards" class="text-gray-500 hover:text-gray-700">
168
+ <i class="fas fa-times"></i>
169
+ </button>
170
+ </div>
171
+ <div class="p-6">
172
+ <div id="flashcardContainer" class="relative h-64 mb-6">
173
+ <div id="noCardsMessage" class="text-center text-gray-500 py-10">
174
+ <i class="fas fa-exclamation-circle text-3xl mb-3"></i>
175
+ <p>No flashcards available. Please add some words first.</p>
176
+ </div>
177
+ <div id="flashcard" class="card hidden w-full h-full">
178
+ <div class="card-inner w-full h-full">
179
+ <div class="card-front bg-indigo-100 rounded-lg shadow-md flex items-center justify-center cursor-pointer p-4">
180
+ <div class="text-center">
181
+ <p class="text-2xl font-bold text-indigo-800" id="cardFrontText">Word</p>
182
+ <p class="text-sm text-indigo-600 mt-2">Click to flip</p>
183
+ </div>
184
+ </div>
185
+ <div class="card-back bg-white rounded-lg shadow-md flex items-center justify-center cursor-pointer p-4 border-2 border-indigo-200">
186
+ <div class="text-center">
187
+ <p class="text-xl font-semibold text-gray-800" id="cardBackMeaning">Meaning</p>
188
+ <p class="text-sm text-gray-600 mt-2 italic" id="cardBackExample">Example sentence</p>
189
+ <div class="mt-4 flex justify-center space-x-3">
190
+ <button class="knowBtn px-3 py-1 bg-green-100 text-green-800 rounded-full text-sm hover:bg-green-200">
191
+ <i class="fas fa-check mr-1"></i> Know
192
+ </button>
193
+ <button class="dontKnowBtn px-3 py-1 bg-red-100 text-red-800 rounded-full text-sm hover:bg-red-200">
194
+ <i class="fas fa-times mr-1"></i> Don't Know
195
+ </button>
196
+ </div>
197
+ </div>
198
+ </div>
199
+ </div>
200
+ </div>
201
+ </div>
202
+ <div class="flex justify-between items-center">
203
+ <div class="text-sm text-gray-600">
204
+ Card <span id="currentCard">0</span> of <span id="totalCards">0</span>
205
+ </div>
206
+ <div class="flex space-x-2">
207
+ <button id="prevCard" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300">
208
+ <i class="fas fa-arrow-left"></i> Previous
209
+ </button>
210
+ <button id="nextCard" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700">
211
+ Next <i class="fas fa-arrow-right"></i>
212
+ </button>
213
+ </div>
214
+ </div>
215
+ </div>
216
+ </div>
217
+ </div>
218
+
219
+ <!-- Quiz Modal -->
220
+ <div id="quizModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
221
+ <div class="bg-white rounded-xl shadow-2xl w-full max-w-md mx-4">
222
+ <div class="p-4 border-b border-gray-200 flex justify-between items-center">
223
+ <h3 class="text-xl font-semibold text-indigo-700">Multiple Choice Quiz</h3>
224
+ <button id="closeQuiz" class="text-gray-500 hover:text-gray-700">
225
+ <i class="fas fa-times"></i>
226
+ </button>
227
+ </div>
228
+ <div class="p-6">
229
+ <div id="quizContainer" class="mb-6">
230
+ <div id="noQuizMessage" class="text-center text-gray-500 py-10">
231
+ <i class="fas fa-exclamation-circle text-3xl mb-3"></i>
232
+ <p>Not enough words for a quiz. Please add at least 4 words.</p>
233
+ </div>
234
+ <div id="quizQuestion" class="hidden">
235
+ <div class="bg-indigo-50 rounded-lg p-4 mb-4">
236
+ <p class="text-lg font-medium text-center text-indigo-800" id="quizWord">Word</p>
237
+ </div>
238
+ <p class="text-sm text-gray-600 mb-4 text-center">What is the correct meaning?</p>
239
+ <div class="space-y-3" id="quizOptions">
240
+ <!-- Options will be added here by JavaScript -->
241
+ </div>
242
+ </div>
243
+ </div>
244
+ <div class="flex justify-between items-center">
245
+ <div class="text-sm text-gray-600">
246
+ Question <span id="currentQuestion">0</span> of <span id="totalQuestions">0</span>
247
+ </div>
248
+ <div class="flex space-x-2">
249
+ <button id="prevQuestion" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300">
250
+ <i class="fas fa-arrow-left"></i> Previous
251
+ </button>
252
+ <button id="nextQuestion" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700">
253
+ Next <i class="fas fa-arrow-right"></i>
254
+ </button>
255
+ </div>
256
+ </div>
257
+ </div>
258
+ </div>
259
+ </div>
260
+
261
+ <!-- Typing Practice Modal -->
262
+ <div id="typingModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
263
+ <div class="bg-white rounded-xl shadow-2xl w-full max-w-md mx-4">
264
+ <div class="p-4 border-b border-gray-200 flex justify-between items-center">
265
+ <h3 class="text-xl font-semibold text-indigo-700">Typing Practice</h3>
266
+ <button id="closeTyping" class="text-gray-500 hover:text-gray-700">
267
+ <i class="fas fa-times"></i>
268
+ </button>
269
+ </div>
270
+ <div class="p-6">
271
+ <div id="typingContainer" class="mb-6">
272
+ <div id="noTypingMessage" class="text-center text-gray-500 py-10">
273
+ <i class="fas fa-exclamation-circle text-3xl mb-3"></i>
274
+ <p>No words available for typing practice. Please add some words first.</p>
275
+ </div>
276
+ <div id="typingQuestion" class="hidden">
277
+ <div class="bg-indigo-50 rounded-lg p-4 mb-4">
278
+ <p class="text-lg font-medium text-center text-indigo-800" id="typingPrompt">Meaning</p>
279
+ </div>
280
+ <div class="mb-4">
281
+ <label class="block text-sm text-gray-600 mb-2">Type the English word:</label>
282
+ <input type="text" id="typingAnswer" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" autocomplete="off">
283
+ </div>
284
+ <div id="typingFeedback" class="hidden text-center py-2 rounded-lg"></div>
285
+ </div>
286
+ </div>
287
+ <div class="flex justify-between items-center">
288
+ <div class="text-sm text-gray-600">
289
+ Word <span id="currentTyping">0</span> of <span id="totalTyping">0</span>
290
+ </div>
291
+ <div class="flex space-x-2">
292
+ <button id="checkTyping" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700">
293
+ <i class="fas fa-check mr-1"></i> Check
294
+ </button>
295
+ <button id="nextTyping" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 hidden">
296
+ Next <i class="fas fa-arrow-right"></i>
297
+ </button>
298
+ </div>
299
+ </div>
300
+ </div>
301
+ </div>
302
+ </div>
303
+
304
+ <script>
305
+ // Vocabulary data storage
306
+ let vocabulary = JSON.parse(localStorage.getItem('vocabulary')) || [];
307
+ let knownWords = JSON.parse(localStorage.getItem('knownWords')) || [];
308
+
309
+ // Current game state
310
+ let currentFlashcardIndex = 0;
311
+ let currentQuizIndex = 0;
312
+ let currentTypingIndex = 0;
313
+ let quizAnswers = [];
314
+ let typingAnswers = [];
315
+
316
+ // DOM elements
317
+ const wordList = document.getElementById('wordList');
318
+ const englishWordInput = document.getElementById('englishWord');
319
+ const vietnameseMeaningInput = document.getElementById('vietnameseMeaning');
320
+ const exampleSentenceInput = document.getElementById('exampleSentence');
321
+ const addWordBtn = document.getElementById('addWordBtn');
322
+ const clearWordsBtn = document.getElementById('clearWordsBtn');
323
+ const exportWordsBtn = document.getElementById('exportWordsBtn');
324
+ const importWordsBtn = document.getElementById('importWordsBtn');
325
+ const importFileInput = document.getElementById('importFileInput');
326
+
327
+ // Game mode buttons
328
+ const flashcardsBtn = document.getElementById('flashcardsBtn');
329
+ const quizBtn = document.getElementById('quizBtn');
330
+ const typingBtn = document.getElementById('typingBtn');
331
+
332
+ // Progress elements
333
+ const totalWordsEl = document.getElementById('totalWords');
334
+ const knownWordsEl = document.getElementById('knownWords');
335
+ const learningWordsEl = document.getElementById('learningWords');
336
+ const masteryPercentEl = document.getElementById('masteryPercent');
337
+ const masteryBarEl = document.getElementById('masteryBar');
338
+
339
+ // Flashcards modal elements
340
+ const flashcardsModal = document.getElementById('flashcardsModal');
341
+ const flashcardContainer = document.getElementById('flashcardContainer');
342
+ const flashcard = document.getElementById('flashcard');
343
+ const noCardsMessage = document.getElementById('noCardsMessage');
344
+ const cardFrontText = document.getElementById('cardFrontText');
345
+ const cardBackMeaning = document.getElementById('cardBackMeaning');
346
+ const cardBackExample = document.getElementById('cardBackExample');
347
+ const currentCardEl = document.getElementById('currentCard');
348
+ const totalCardsEl = document.getElementById('totalCards');
349
+ const prevCardBtn = document.getElementById('prevCard');
350
+ const nextCardBtn = document.getElementById('nextCard');
351
+ const closeFlashcards = document.getElementById('closeFlashcards');
352
+
353
+ // Quiz modal elements
354
+ const quizModal = document.getElementById('quizModal');
355
+ const quizContainer = document.getElementById('quizContainer');
356
+ const noQuizMessage = document.getElementById('noQuizMessage');
357
+ const quizQuestion = document.getElementById('quizQuestion');
358
+ const quizWord = document.getElementById('quizWord');
359
+ const quizOptions = document.getElementById('quizOptions');
360
+ const currentQuestionEl = document.getElementById('currentQuestion');
361
+ const totalQuestionsEl = document.getElementById('totalQuestions');
362
+ const prevQuestionBtn = document.getElementById('prevQuestion');
363
+ const nextQuestionBtn = document.getElementById('nextQuestion');
364
+ const closeQuiz = document.getElementById('closeQuiz');
365
+
366
+ // Typing modal elements
367
+ const typingModal = document.getElementById('typingModal');
368
+ const typingContainer = document.getElementById('typingContainer');
369
+ const noTypingMessage = document.getElementById('noTypingMessage');
370
+ const typingQuestion = document.getElementById('typingQuestion');
371
+ const typingPrompt = document.getElementById('typingPrompt');
372
+ const typingAnswer = document.getElementById('typingAnswer');
373
+ const typingFeedback = document.getElementById('typingFeedback');
374
+ const currentTypingEl = document.getElementById('currentTyping');
375
+ const totalTypingEl = document.getElementById('totalTyping');
376
+ const checkTypingBtn = document.getElementById('checkTyping');
377
+ const nextTypingBtn = document.getElementById('nextTyping');
378
+ const closeTyping = document.getElementById('closeTyping');
379
+
380
+ // Initialize the app
381
+ function init() {
382
+ updateWordList();
383
+ updateProgress();
384
+ setupEventListeners();
385
+ }
386
+
387
+ // Set up event listeners
388
+ function setupEventListeners() {
389
+ // Add word button
390
+ addWordBtn.addEventListener('click', addWord);
391
+
392
+ // Enter key to add word
393
+ englishWordInput.addEventListener('keypress', (e) => {
394
+ if (e.key === 'Enter') addWord();
395
+ });
396
+ vietnameseMeaningInput.addEventListener('keypress', (e) => {
397
+ if (e.key === 'Enter') addWord();
398
+ });
399
+
400
+ // Clear, export, import buttons
401
+ clearWordsBtn.addEventListener('click', clearWords);
402
+ exportWordsBtn.addEventListener('click', exportWords);
403
+ importWordsBtn.addEventListener('click', () => importFileInput.click());
404
+ importFileInput.addEventListener('change', importWords);
405
+
406
+ // Game mode buttons
407
+ flashcardsBtn.addEventListener('click', startFlashcards);
408
+ quizBtn.addEventListener('click', startQuiz);
409
+ typingBtn.addEventListener('click', startTyping);
410
+
411
+ // Flashcards events
412
+ flashcard.addEventListener('click', flipCard);
413
+ prevCardBtn.addEventListener('click', showPreviousCard);
414
+ nextCardBtn.addEventListener('click', showNextCard);
415
+ closeFlashcards.addEventListener('click', () => flashcardsModal.classList.add('hidden'));
416
+
417
+ // Quiz events
418
+ prevQuestionBtn.addEventListener('click', showPreviousQuestion);
419
+ nextQuestionBtn.addEventListener('click', showNextQuestion);
420
+ closeQuiz.addEventListener('click', () => quizModal.classList.add('hidden'));
421
+
422
+ // Typing events
423
+ typingAnswer.addEventListener('keypress', (e) => {
424
+ if (e.key === 'Enter') checkTypingAnswer();
425
+ });
426
+ checkTypingBtn.addEventListener('click', checkTypingAnswer);
427
+ nextTypingBtn.addEventListener('click', showNextTyping);
428
+ closeTyping.addEventListener('click', () => typingModal.classList.add('hidden'));
429
+ }
430
+
431
+ // Add a new word to vocabulary
432
+ function addWord() {
433
+ const englishWord = englishWordInput.value.trim();
434
+ const vietnameseMeaning = vietnameseMeaningInput.value.trim();
435
+ const exampleSentence = exampleSentenceInput.value.trim();
436
+
437
+ if (!englishWord || !vietnameseMeaning) {
438
+ alert('Please enter both English word and Vietnamese meaning');
439
+ return;
440
+ }
441
+
442
+ // Check if word already exists
443
+ if (vocabulary.some(word => word.english.toLowerCase() === englishWord.toLowerCase())) {
444
+ alert('This word already exists in your vocabulary list');
445
+ return;
446
+ }
447
+
448
+ const newWord = {
449
+ english: englishWord,
450
+ vietnamese: vietnameseMeaning,
451
+ example: exampleSentence,
452
+ added: new Date().toISOString()
453
+ };
454
+
455
+ vocabulary.push(newWord);
456
+ saveVocabulary();
457
+
458
+ // Clear inputs
459
+ englishWordInput.value = '';
460
+ vietnameseMeaningInput.value = '';
461
+ exampleSentenceInput.value = '';
462
+
463
+ // Focus back to English input
464
+ englishWordInput.focus();
465
+
466
+ // Update UI
467
+ updateWordList();
468
+ updateProgress();
469
+ }
470
+
471
+ // Clear all words
472
+ function clearWords() {
473
+ if (confirm('Are you sure you want to clear all words?')) {
474
+ vocabulary = [];
475
+ knownWords = [];
476
+ saveVocabulary();
477
+ updateWordList();
478
+ updateProgress();
479
+ }
480
+ }
481
+
482
+ // Export words to JSON file
483
+ function exportWords() {
484
+ if (vocabulary.length === 0) {
485
+ alert('No words to export');
486
+ return;
487
+ }
488
+
489
+ const data = {
490
+ vocabulary: vocabulary,
491
+ knownWords: knownWords,
492
+ exported: new Date().toISOString()
493
+ };
494
+
495
+ const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
496
+ const url = URL.createObjectURL(blob);
497
+
498
+ const a = document.createElement('a');
499
+ a.href = url;
500
+ a.download = `vocabulary-${new Date().toISOString().slice(0, 10)}.json`;
501
+ document.body.appendChild(a);
502
+ a.click();
503
+ document.body.removeChild(a);
504
+ URL.revokeObjectURL(url);
505
+ }
506
+
507
+ // Import words from JSON file
508
+ function importWords(e) {
509
+ const file = e.target.files[0];
510
+ if (!file) return;
511
+
512
+ const reader = new FileReader();
513
+ reader.onload = (event) => {
514
+ try {
515
+ const data = JSON.parse(event.target.result);
516
+
517
+ if (data.vocabulary && Array.isArray(data.vocabulary)) {
518
+ // Merge with existing vocabulary, avoiding duplicates
519
+ data.vocabulary.forEach(word => {
520
+ if (!vocabulary.some(w => w.english.toLowerCase() === word.english.toLowerCase())) {
521
+ vocabulary.push(word);
522
+ }
523
+ });
524
+
525
+ // Update known words if they exist in import
526
+ if (data.knownWords && Array.isArray(data.knownWords)) {
527
+ data.knownWords.forEach(word => {
528
+ if (!knownWords.includes(word) && vocabulary.some(w => w.english === word)) {
529
+ knownWords.push(word);
530
+ }
531
+ });
532
+ }
533
+
534
+ saveVocabulary();
535
+ updateWordList();
536
+ updateProgress();
537
+ alert(`Successfully imported ${data.vocabulary.length} words`);
538
+ } else {
539
+ alert('Invalid file format');
540
+ }
541
+ } catch (error) {
542
+ alert('Error reading file: ' + error.message);
543
+ }
544
+
545
+ // Reset file input
546
+ e.target.value = '';
547
+ };
548
+ reader.readAsText(file);
549
+ }
550
+
551
+ // Save vocabulary to localStorage
552
+ function saveVocabulary() {
553
+ localStorage.setItem('vocabulary', JSON.stringify(vocabulary));
554
+ localStorage.setItem('knownWords', JSON.stringify(knownWords));
555
+ }
556
+
557
+ // Update the word list display
558
+ function updateWordList() {
559
+ if (vocabulary.length === 0) {
560
+ wordList.innerHTML = '<p class="text-gray-500 text-center py-4">No words added yet</p>';
561
+ return;
562
+ }
563
+
564
+ wordList.innerHTML = '';
565
+ vocabulary.forEach((word, index) => {
566
+ const isKnown = knownWords.includes(word.english);
567
+
568
+ const wordEl = document.createElement('div');
569
+ wordEl.className = `flex justify-between items-center p-2 mb-2 rounded-lg ${isKnown ? 'bg-green-50' : 'bg-white'} border ${isKnown ? 'border-green-200' : 'border-gray-200'}`;
570
+
571
+ wordEl.innerHTML = `
572
+ <div>
573
+ <div class="font-medium text-gray-800">${word.english}</div>
574
+ <div class="text-sm text-gray-600">${word.vietnamese}</div>
575
+ ${word.example ? `<div class="text-xs text-gray-500 italic mt-1">"${word.example}"</div>` : ''}
576
+ </div>
577
+ <div class="flex space-x-1">
578
+ <button class="know-toggle px-2 py-1 text-xs rounded ${isKnown ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800'}" data-word="${word.english}">
579
+ <i class="fas ${isKnown ? 'fa-check-circle' : 'fa-question-circle'} mr-1"></i> ${isKnown ? 'Known' : 'Learning'}
580
+ </button>
581
+ <button class="delete-word px-2 py-1 text-xs bg-red-100 text-red-800 rounded" data-index="${index}">
582
+ <i class="fas fa-trash-alt"></i>
583
+ </button>
584
+ </div>
585
+ `;
586
+
587
+ wordList.appendChild(wordEl);
588
+ });
589
+
590
+ // Add event listeners for dynamically created buttons
591
+ document.querySelectorAll('.know-toggle').forEach(btn => {
592
+ btn.addEventListener('click', toggleKnownWord);
593
+ });
594
+
595
+ document.querySelectorAll('.delete-word').forEach(btn => {
596
+ btn.addEventListener('click', deleteWord);
597
+ });
598
+ }
599
+
600
+ // Toggle word between known and learning
601
+ function toggleKnownWord(e) {
602
+ const word = e.target.closest('button').getAttribute('data-word');
603
+ const index = knownWords.indexOf(word);
604
+
605
+ if (index === -1) {
606
+ knownWords.push(word);
607
+ } else {
608
+ knownWords.splice(index, 1);
609
+ }
610
+
611
+ saveVocabulary();
612
+ updateWordList();
613
+ updateProgress();
614
+ }
615
+
616
+ // Delete a word from vocabulary
617
+ function deleteWord(e) {
618
+ const index = parseInt(e.target.closest('button').getAttribute('data-index'));
619
+ vocabulary.splice(index, 1);
620
+
621
+ // Remove from known words if it was there
622
+ const wordToDelete = vocabulary[index]?.english;
623
+ if (wordToDelete) {
624
+ const knownIndex = knownWords.indexOf(wordToDelete);
625
+ if (knownIndex !== -1) {
626
+ knownWords.splice(knownIndex, 1);
627
+ }
628
+ }
629
+
630
+ saveVocabulary();
631
+ updateWordList();
632
+ updateProgress();
633
+ }
634
+
635
+ // Update progress stats
636
+ function updateProgress() {
637
+ const total = vocabulary.length;
638
+ const known = knownWords.length;
639
+ const learning = total - known;
640
+ const mastery = total > 0 ? Math.round((known / total) * 100) : 0;
641
+
642
+ totalWordsEl.textContent = total;
643
+ knownWordsEl.textContent = known;
644
+ learningWordsEl.textContent = learning;
645
+ masteryPercentEl.textContent = `${mastery}%`;
646
+ masteryBarEl.style.width = `${mastery}%`;
647
+
648
+ // Change color based on mastery level
649
+ if (mastery >= 70) {
650
+ masteryBarEl.className = 'bg-green-600 h-2.5 rounded-full progress-bar';
651
+ } else if (mastery >= 40) {
652
+ masteryBarEl.className = 'bg-yellow-500 h-2.5 rounded-full progress-bar';
653
+ } else {
654
+ masteryBarEl.className = 'bg-red-500 h-2.5 rounded-full progress-bar';
655
+ }
656
+ }
657
+
658
+ // Start flashcards game
659
+ function startFlashcards() {
660
+ if (vocabulary.length === 0) {
661
+ alert('Please add some words first');
662
+ return;
663
+ }
664
+
665
+ currentFlashcardIndex = 0;
666
+ updateFlashcard();
667
+
668
+ // Show modal
669
+ flashcardsModal.classList.remove('hidden');
670
+ }
671
+
672
+ // Update flashcard display
673
+ function updateFlashcard() {
674
+ if (vocabulary.length === 0) {
675
+ noCardsMessage.classList.remove('hidden');
676
+ flashcard.classList.add('hidden');
677
+ return;
678
+ }
679
+
680
+ noCardsMessage.classList.add('hidden');
681
+ flashcard.classList.remove('hidden');
682
+
683
+ const word = vocabulary[currentFlashcardIndex];
684
+ cardFrontText.textContent = word.english;
685
+ cardBackMeaning.textContent = word.vietnamese;
686
+ cardBackExample.textContent = word.example || 'No example provided';
687
+
688
+ // Reset card to front
689
+ flashcard.classList.remove('flipped');
690
+
691
+ // Update counters
692
+ currentCardEl.textContent = currentFlashcardIndex + 1;
693
+ totalCardsEl.textContent = vocabulary.length;
694
+
695
+ // Update button states
696
+ prevCardBtn.disabled = currentFlashcardIndex === 0;
697
+ nextCardBtn.disabled = currentFlashcardIndex === vocabulary.length - 1;
698
+ }
699
+
700
+ // Flip the flashcard
701
+ function flipCard() {
702
+ flashcard.classList.toggle('flipped');
703
+ }
704
+
705
+ // Show previous flashcard
706
+ function showPreviousCard() {
707
+ if (currentFlashcardIndex > 0) {
708
+ currentFlashcardIndex--;
709
+ updateFlashcard();
710
+ }
711
+ }
712
+
713
+ // Show next flashcard
714
+ function showNextCard() {
715
+ if (currentFlashcardIndex < vocabulary.length - 1) {
716
+ currentFlashcardIndex++;
717
+ updateFlashcard();
718
+ }
719
+ }
720
+
721
+ // Start quiz game
722
+ function startQuiz() {
723
+ if (vocabulary.length < 4) {
724
+ alert('You need at least 4 words to start a quiz');
725
+ return;
726
+ }
727
+
728
+ currentQuizIndex = 0;
729
+ quizAnswers = [];
730
+ updateQuizQuestion();
731
+
732
+ // Show modal
733
+ quizModal.classList.remove('hidden');
734
+ }
735
+
736
+ // Update quiz question display
737
+ function updateQuizQuestion() {
738
+ if (vocabulary.length < 4) {
739
+ noQuizMessage.classList.remove('hidden');
740
+ quizQuestion.classList.add('hidden');
741
+ return;
742
+ }
743
+
744
+ noQuizMessage.classList.add('hidden');
745
+ quizQuestion.classList.remove('hidden');
746
+
747
+ const currentWord = vocabulary[currentQuizIndex];
748
+ quizWord.textContent = currentWord.english;
749
+
750
+ // Generate options (1 correct + 3 random incorrect)
751
+ const options = [currentWord.vietnamese];
752
+
753
+ // Get 3 random incorrect options
754
+ while (options.length < 4) {
755
+ const randomIndex = Math.floor(Math.random() * vocabulary.length);
756
+ if (randomIndex !== currentQuizIndex && !options.includes(vocabulary[randomIndex].vietnamese)) {
757
+ options.push(vocabulary[randomIndex].vietnamese);
758
+ }
759
+ }
760
+
761
+ // Shuffle options
762
+ options.sort(() => Math.random() - 0.5);
763
+
764
+ // Display options
765
+ quizOptions.innerHTML = '';
766
+ options.forEach((option, i) => {
767
+ const optionEl = document.createElement('button');
768
+ optionEl.className = 'w-full text-left p-3 bg-gray-100 hover:bg-gray-200 rounded-lg transition';
769
+ optionEl.textContent = `${i + 1}. ${option}`;
770
+ optionEl.dataset.option = option;
771
+
772
+ // Check if this option was already selected
773
+ const currentAnswer = quizAnswers[currentQuizIndex];
774
+ if (currentAnswer && currentAnswer.selected === option) {
775
+ optionEl.className = currentAnswer.correct ?
776
+ 'w-full text-left p-3 bg-green-100 text-green-800 rounded-lg' :
777
+ 'w-full text-left p-3 bg-red-100 text-red-800 rounded-lg';
778
+ }
779
+
780
+ optionEl.addEventListener('click', () => selectQuizOption(optionEl, option, currentWord.vietnamese));
781
+ quizOptions.appendChild(optionEl);
782
+ });
783
+
784
+ // Update counters
785
+ currentQuestionEl.textContent = currentQuizIndex + 1;
786
+ totalQuestionsEl.textContent = vocabulary.length;
787
+
788
+ // Update button states
789
+ prevQuestionBtn.disabled = currentQuizIndex === 0;
790
+ nextQuestionBtn.disabled = currentQuizIndex === vocabulary.length - 1;
791
+ }
792
+
793
+ // Select a quiz option
794
+ function selectQuizOption(optionEl, selectedOption, correctOption) {
795
+ // Don't allow changing answer after selection
796
+ if (quizAnswers[currentQuizIndex]) return;
797
+
798
+ const isCorrect = selectedOption === correctOption;
799
+
800
+ // Update button appearance
801
+ optionEl.className = isCorrect ?
802
+ 'w-full text-left p-3 bg-green-100 text-green-800 rounded-lg bounce' :
803
+ 'w-full text-left p-3 bg-red-100 text-red-800 rounded-lg shake';
804
+
805
+ // Store answer
806
+ quizAnswers[currentQuizIndex] = {
807
+ selected: selectedOption,
808
+ correct: isCorrect
809
+ };
810
+
811
+ // Update known words if answered correctly
812
+ const currentWord = vocabulary[currentQuizIndex].english;
813
+ if (isCorrect && !knownWords.includes(currentWord)) {
814
+ knownWords.push(currentWord);
815
+ saveVocabulary();
816
+ updateProgress();
817
+ }
818
+ }
819
+
820
+ // Show previous quiz question
821
+ function showPreviousQuestion() {
822
+ if (currentQuizIndex > 0) {
823
+ currentQuizIndex--;
824
+ updateQuizQuestion();
825
+ }
826
+ }
827
+
828
+ // Show next quiz question
829
+ function showNextQuestion() {
830
+ if (currentQuizIndex < vocabulary.length - 1) {
831
+ currentQuizIndex++;
832
+ updateQuizQuestion();
833
+ }
834
+ }
835
+
836
+ // Start typing practice
837
+ function startTyping() {
838
+ if (vocabulary.length === 0) {
839
+ alert('Please add some words first');
840
+ return;
841
+ }
842
+
843
+ currentTypingIndex = 0;
844
+ typingAnswers = [];
845
+ updateTypingQuestion();
846
+
847
+ // Show modal
848
+ typingModal.classList.remove('hidden');
849
+ }
850
+
851
+ // Update typing question display
852
+ function updateTypingQuestion() {
853
+ if (vocabulary.length === 0) {
854
+ noTypingMessage.classList.remove('hidden');
855
+ typingQuestion.classList.add('hidden');
856
+ return;
857
+ }
858
+
859
+ noTypingMessage.classList.add('hidden');
860
+ typingQuestion.classList.remove('hidden');
861
+ typingFeedback.classList.add('hidden');
862
+
863
+ const currentWord = vocabulary[currentTypingIndex];
864
+ typingPrompt.textContent = currentWord.vietnamese;
865
+ typingAnswer.value = '';
866
+
867
+ // Update counters
868
+ currentTypingEl.textContent = currentTypingIndex + 1;
869
+ totalTypingEl.textContent = vocabulary.length;
870
+
871
+ // Focus on input
872
+ typingAnswer.focus();
873
+
874
+ // Show check button, hide next button
875
+ checkTypingBtn.classList.remove('hidden');
876
+ nextTypingBtn.classList.add('hidden');
877
+ }
878
+
879
+ // Check typing answer
880
+ function checkTypingAnswer() {
881
+ const userAnswer = typingAnswer.value.trim().toLowerCase();
882
+ const correctAnswer = vocabulary[currentTypingIndex].english.toLowerCase();
883
+
884
+ const isCorrect = userAnswer === correctAnswer;
885
+
886
+ // Show feedback
887
+ typingFeedback.classList.remove('hidden');
888
+ if (isCorrect) {
889
+ typingFeedback.className = 'bg-green-100 text-green-800 text-center py-2 rounded-lg bounce';
890
+ typingFeedback.innerHTML = `<i class="fas fa-check-circle mr-2"></i> Correct!`;
891
+
892
+ // Add to known words if not already there
893
+ if (!knownWords.includes(vocabulary[currentTypingIndex].english)) {
894
+ knownWords.push(vocabulary[currentTypingIndex].english);
895
+ saveVocabulary();
896
+ updateProgress();
897
+ }
898
+ } else {
899
+ typingFeedback.className = 'bg-red-100 text-red-800 text-center py-2 rounded-lg shake';
900
+ typingFeedback.innerHTML = `<i class="fas fa-times-circle mr-2"></i> Incorrect. The correct answer is "${vocabulary[currentTypingIndex].english}"`;
901
+ }
902
+
903
+ // Store answer
904
+ typingAnswers[currentTypingIndex] = {
905
+ answer: userAnswer,
906
+ correct: isCorrect
907
+ };
908
+
909
+ // Show next button, hide check button
910
+ checkTypingBtn.classList.add('hidden');
911
+ nextTypingBtn.classList.remove('hidden');
912
+ }
913
+
914
+ // Show next typing question
915
+ function showNextTyping() {
916
+ if (currentTypingIndex < vocabulary.length - 1) {
917
+ currentTypingIndex++;
918
+ updateTypingQuestion();
919
+ } else {
920
+ // Calculate score if finished all words
921
+ const correctCount = typingAnswers.filter(a => a.correct).length;
922
+ const score = Math.round((correctCount / vocabulary.length) * 100);
923
+
924
+ typingFeedback.classList.remove('hidden');
925
+ typingFeedback.className = 'bg-blue-100 text-blue-800 text-center py-2 rounded-lg';
926
+ typingFeedback.innerHTML = `
927
+ <div class="font-medium">Practice complete!</div>
928
+ <div>Score: ${score}% (${correctCount} of ${vocabulary.length})</div>
929
+ `;
930
+
931
+ nextTypingBtn.classList.add('hidden');
932
+ }
933
+ }
934
+
935
+ // Initialize the app
936
+ init();
937
+ </script>
938
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=ktskhoa/game-learning" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
939
+ </html>
prompts.txt ADDED
File without changes