ReneeHWT commited on
Commit
9f6e48a
·
verified ·
1 Parent(s): d02a4aa

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +103 -392
app.py CHANGED
@@ -1,392 +1,103 @@
1
- <html><head><base href="https://example.com">
2
- <meta charset="UTF-8">
3
- <title>Personal English Vocabulary App</title>
4
- <!-- Google Fonts -->
5
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
6
- <!-- CSS for styling and animations -->
7
- <style>
8
- body {
9
- font-family: 'Inter', sans-serif;
10
- background: linear-gradient(135deg, #d6c8c0, #b3a9b8);
11
- display: flex;
12
- flex-direction: column;
13
- align-items: center;
14
- padding: 20px;
15
- min-height: 100vh;
16
- }
17
-
18
- h1 {
19
- color: #5a5a5a;
20
- margin-bottom: 20px;
21
- animation: fadeInDown 1s ease-in-out;
22
- display: flex;
23
- align-items: center;
24
- gap: 10px;
25
- }
26
-
27
- #upload-section, #quiz-section {
28
- background: #f5f5f5;
29
- padding: 20px 30px;
30
- border-radius: 10px;
31
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
32
- width: 100%;
33
- max-width: 600px;
34
- margin-bottom: 20px;
35
- animation: fadeInUp 1s ease-in-out;
36
- }
37
-
38
- label {
39
- display: block;
40
- margin-bottom: 10px;
41
- color: #6b6b6b;
42
- }
43
-
44
- input[type="file"], input[type="text"], button {
45
- width: 100%;
46
- padding: 10px;
47
- margin-bottom: 15px;
48
- border: none;
49
- border-radius: 5px;
50
- font-size: 16px;
51
- }
52
-
53
- input[type="text"] {
54
- background-color: #ffffff;
55
- border: 1px solid #ccc;
56
- }
57
-
58
- button {
59
- background-color: #a89fcb;
60
- color: #fff;
61
- cursor: pointer;
62
- transition: background-color 0.3s ease;
63
- }
64
-
65
- button:hover {
66
- background-color: #8e82b7;
67
- }
68
-
69
- #quiz-container {
70
- display: none;
71
- text-align: center;
72
- width: 100%;
73
- }
74
-
75
- #matching-game {
76
- display: flex;
77
- justify-content: space-between;
78
- gap: 20px;
79
- flex-wrap: wrap;
80
- }
81
-
82
- .column {
83
- width: 45%;
84
- }
85
-
86
- .column h3 {
87
- color: #5a5a5a;
88
- margin-bottom: 10px;
89
- animation: fadeInDown 1s ease-in-out;
90
- }
91
-
92
- .list {
93
- list-style: none;
94
- padding: 0;
95
- }
96
-
97
- .list-item {
98
- background: #cfcfcf;
99
- padding: 10px;
100
- margin: 5px 0;
101
- border-radius: 5px;
102
- cursor: pointer;
103
- transition: background 0.3s ease, transform 0.3s ease;
104
- color: #5a5a5a;
105
- user-select: none;
106
- }
107
-
108
- .list-item:hover {
109
- background: #bcbcbc;
110
- transform: scale(1.05);
111
- }
112
-
113
- .selected {
114
- background: #a89fcb;
115
- color: #fff;
116
- }
117
-
118
- #result {
119
- font-size: 1.2em;
120
- margin-top: 20px;
121
- color: #6ab04c;
122
- animation: fadeIn 0.5s ease-in-out;
123
- }
124
-
125
- /* Animations */
126
- @keyframes fadeInDown {
127
- from {
128
- opacity: 0;
129
- transform: translateY(-20px);
130
- }
131
- to {
132
- opacity: 1;
133
- transform: translateY(0);
134
- }
135
- }
136
-
137
- @keyframes fadeInUp {
138
- from {
139
- opacity: 0;
140
- transform: translateY(20px);
141
- }
142
- to {
143
- opacity: 1;
144
- transform: translateY(0);
145
- }
146
- }
147
-
148
- @keyframes fadeIn {
149
- from { opacity: 0; }
150
- to { opacity: 1; }
151
- }
152
-
153
- /* SVG Icon */
154
- .icon {
155
- width: 50px;
156
- height: 50px;
157
- margin-bottom: 10px;
158
- fill: #a89fcb;
159
- animation: rotate 4s linear infinite;
160
- }
161
-
162
- @keyframes rotate {
163
- from { transform: rotate(0deg); }
164
- to { transform: rotate(360deg); }
165
- }
166
-
167
- hr {
168
- border: none;
169
- border-top: 1px solid #ddd;
170
- margin: 20px 0;
171
- }
172
-
173
- h2 {
174
- color: #5a5a5a;
175
- margin-bottom: 15px;
176
- animation: fadeInDown 1s ease-in-out;
177
- }
178
- </style>
179
- </head>
180
- <body>
181
- <h1>
182
- 📚 Personal English Vocabulary App
183
- </h1>
184
- <div id="upload-section">
185
- <svg class="icon" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
186
- <path d="M48,4H16C10.477,4,6,8.477,6,14v36c0,5.523,4.477,10,10,10h32c5.523,0,10-4.477,10-10V14C58,8.477,53.523,4,48,4z M48,50H16c-2.209,0-4-1.791-4-4V14c0-2.209,1.791-4,4-4h32c2.209,0,4,1.791,4,4v32C52,48.209,50.209,50,48,50z"/>
187
- <path d="M22,22h20v4H22V22z M22,30h20v4H22V30z M22,38h20v4H22V38z"/>
188
- </svg>
189
- <label for="vocab-file">Upload Your Vocabulary (CSV format: word, definition)</label>
190
- <input type="file" id="vocab-file" accept=".csv">
191
- <button id="start-quiz">Start Quiz</button>
192
- <hr>
193
- <h2>Add a Vocabulary Word Manually</h2>
194
- <label for="manual-word">Word:</label>
195
- <input type="text" id="manual-word" placeholder="Enter word">
196
- <label for="manual-definition">Definition:</label>
197
- <input type="text" id="manual-definition" placeholder="Enter definition">
198
- <button id="add-word">Add Word</button>
199
- </div>
200
-
201
- <div id="quiz-section">
202
- <div id="quiz-container">
203
- <div id="matching-game">
204
- <div class="column" id="words-column">
205
- <h3>Words</h3>
206
- <ul class="list" id="words-list">
207
- <!-- Words will be generated here -->
208
- </ul>
209
- </div>
210
- <div class="column" id="definitions-column">
211
- <h3>Definitions</h3>
212
- <ul class="list" id="definitions-list">
213
- <!-- Definitions will be generated here -->
214
- </ul>
215
- </div>
216
- </div>
217
- <div id="result"></div>
218
- <button id="reset-quiz" style="margin-top: 20px; display: none;">Reset Quiz</button>
219
- </div>
220
- </div>
221
-
222
- <!-- JavaScript for functionality -->
223
- <script>
224
- const uploadSection = document.getElementById('upload-section');
225
- const quizSection = document.getElementById('quiz-section');
226
- const startQuizButton = document.getElementById('start-quiz');
227
- const vocabFileInput = document.getElementById('vocab-file');
228
- const wordsList = document.getElementById('words-list');
229
- const definitionsList = document.getElementById('definitions-list');
230
- const resultEl = document.getElementById('result');
231
- const addWordButton = document.getElementById('add-word');
232
- const manualWordInput = document.getElementById('manual-word');
233
- const manualDefInput = document.getElementById('manual-definition');
234
- const resetQuizButton = document.getElementById('reset-quiz');
235
-
236
- let vocabulary = [];
237
- let matches = {};
238
- let selectedWord = null;
239
- let selectedDefinition = null;
240
- let score = 0;
241
-
242
- startQuizButton.addEventListener('click', () => {
243
- const file = vocabFileInput.files[0];
244
- if (file) {
245
- const reader = new FileReader();
246
- reader.onload = function(e) {
247
- const text = e.target.result;
248
- parseCSV(text);
249
- if(vocabulary.length > 0){
250
- uploadSection.style.display = 'none';
251
- quizSection.style.display = 'block';
252
- startMatchingGame();
253
- } else {
254
- alert('Please upload a valid CSV file or add words manually.');
255
- }
256
- }
257
- reader.readAsText(file);
258
- } else if (vocabulary.length > 0) {
259
- uploadSection.style.display = 'none';
260
- quizSection.style.display = 'block';
261
- startMatchingGame();
262
- } else {
263
- alert('Please upload a CSV file or add words manually.');
264
- }
265
- });
266
-
267
- addWordButton.addEventListener('click', () => {
268
- const word = manualWordInput.value.trim();
269
- const definition = manualDefInput.value.trim();
270
- if (word && definition) {
271
- vocabulary.push({ word, definition });
272
- manualWordInput.value = '';
273
- manualDefInput.value = '';
274
- alert(`Added "${word}" to your vocabulary.`);
275
- } else {
276
- alert('Please enter both word and definition.');
277
- }
278
- });
279
-
280
- resetQuizButton.addEventListener('click', () => {
281
- vocabulary = [];
282
- matches = {};
283
- selectedWord = null;
284
- selectedDefinition = null;
285
- score = 0;
286
- wordsList.innerHTML = '';
287
- definitionsList.innerHTML = '';
288
- resultEl.innerText = '';
289
- resetQuizButton.style.display = 'none';
290
- uploadSection.style.display = 'block';
291
- quizSection.style.display = 'none';
292
- });
293
-
294
- function parseCSV(text) {
295
- const lines = text.split('\\n');
296
- const parsed = lines.map(line => {
297
- const [word, definition] = line.split(',');
298
- return { word: word.trim(), definition: definition.trim() };
299
- }).filter(item => item.word && item.definition);
300
- vocabulary = vocabulary.concat(parsed);
301
- }
302
-
303
- function startMatchingGame() {
304
- shuffleArray(vocabulary);
305
- displayWords();
306
- displayDefinitions();
307
- }
308
-
309
- function displayWords() {
310
- wordsList.innerHTML = '';
311
- vocabulary.forEach((item, index) => {
312
- const li = document.createElement('li');
313
- li.classList.add('list-item');
314
- li.innerText = item.word;
315
- li.dataset.word = item.word;
316
- li.addEventListener('click', () => selectWord(li));
317
- wordsList.appendChild(li);
318
- });
319
- }
320
-
321
- function displayDefinitions() {
322
- definitionsList.innerHTML = '';
323
- const shuffledDefinitions = [...vocabulary.map(item => item.definition)];
324
- shuffleArray(shuffledDefinitions);
325
- shuffledDefinitions.forEach((def, index) => {
326
- const li = document.createElement('li');
327
- li.classList.add('list-item');
328
- li.innerText = def;
329
- li.dataset.definition = def;
330
- li.addEventListener('click', () => selectDefinition(li));
331
- definitionsList.appendChild(li);
332
- });
333
- }
334
-
335
- function selectWord(element) {
336
- if (selectedWord) {
337
- selectedWord.classList.remove('selected');
338
- }
339
- selectedWord = element;
340
- selectedWord.classList.add('selected');
341
- checkMatch();
342
- }
343
-
344
- function selectDefinition(element) {
345
- if (selectedDefinition) {
346
- selectedDefinition.classList.remove('selected');
347
- }
348
- selectedDefinition = element;
349
- selectedDefinition.classList.add('selected');
350
- checkMatch();
351
- }
352
-
353
- function checkMatch() {
354
- if (selectedWord && selectedDefinition) {
355
- const word = selectedWord.dataset.word;
356
- const definition = selectedDefinition.dataset.definition;
357
- const vocabItem = vocabulary.find(item => item.word === word);
358
- if (vocabItem.definition === definition) {
359
- score++;
360
- resultEl.style.color = '#6ab04c';
361
- resultEl.innerText = 'Correct! 🎉';
362
- selectedWord.style.backgroundColor = '#6ab04c';
363
- selectedDefinition.style.backgroundColor = '#6ab04c';
364
- } else {
365
- resultEl.style.color = '#e74c3c';
366
- resultEl.innerText = `Incorrect! "${word}" does not match the selected definition.`;
367
- selectedWord.style.backgroundColor = '#e74c3c';
368
- selectedDefinition.style.backgroundColor = '#e74c3c';
369
- }
370
- // Disable further selection
371
- selectedWord.removeEventListener('click', selectWord);
372
- selectedDefinition.removeEventListener('click', selectDefinition);
373
- selectedWord = null;
374
- selectedDefinition = null;
375
-
376
- // Check if all matches are done
377
- if (score === vocabulary.length) {
378
- resultEl.innerText += ' You matched all correctly!';
379
- resetQuizButton.style.display = 'block';
380
- }
381
- }
382
- }
383
-
384
- function shuffleArray(array) {
385
- for (let i = array.length - 1; i > 0; i--) {
386
- const j = Math.floor(Math.random() * (i + 1));
387
- [array[i], array[j]] = [array[j], array[i]];
388
- }
389
- }
390
- </script>
391
- </body>
392
- </html>
 
1
+ import gradio as gr
2
+ import random
3
+ import pandas as pd
4
+ import ssl
5
+
6
+ # Workaround for SSL issues in some environments
7
+ ssl._create_default_https_context = ssl._create_unverified_context
8
+
9
+ # Global Variables
10
+ vocabulary = []
11
+ matches = {}
12
+ score = 0
13
+
14
+ # Helper Functions
15
+ def parse_csv(file):
16
+ try:
17
+ data = pd.read_csv(file.name, header=None)
18
+ vocab = data.dropna().values.tolist()
19
+ return [{"word": row[0].strip(), "definition": row[1].strip()} for row in vocab]
20
+ except Exception as e:
21
+ return []
22
+
23
+ def add_word(word, definition):
24
+ global vocabulary
25
+ if word and definition:
26
+ vocabulary.append({"word": word.strip(), "definition": definition.strip()})
27
+ return f'Word "{word}" added successfully!', vocabulary
28
+ else:
29
+ return "Both word and definition are required.", vocabulary
30
+
31
+ def start_quiz():
32
+ global matches, score
33
+ score = 0
34
+ if len(vocabulary) < 1:
35
+ return "Please add some words first.", [], []
36
+
37
+ random.shuffle(vocabulary)
38
+ words = [item['word'] for item in vocabulary]
39
+ definitions = [item['definition'] for item in vocabulary]
40
+ random.shuffle(definitions)
41
+
42
+ matches = {item['word']: item['definition'] for item in vocabulary}
43
+ return "Match the words with their definitions.", words, definitions
44
+
45
+ def check_match(word, definition):
46
+ global matches, score
47
+ if matches.get(word) == definition:
48
+ score += 1
49
+ return f"Correct! {word} matches {definition}.", score
50
+ else:
51
+ return f"Incorrect! {word} does not match {definition}.", score
52
+
53
+ def reset_app():
54
+ global vocabulary, matches, score
55
+ vocabulary = []
56
+ matches = {}
57
+ score = 0
58
+ return "Application has been reset.", vocabulary
59
+
60
+ # Gradio Interface
61
+ def main():
62
+ with gr.Blocks() as app:
63
+ gr.Markdown("# Personal English Vocabulary App")
64
+
65
+ with gr.Tab("Upload Vocabulary"):
66
+ csv_upload = gr.File(label="Upload CSV (word, definition)")
67
+ upload_button = gr.Button("Upload")
68
+ upload_output = gr.Textbox(label="Upload Status")
69
+
70
+ with gr.Tab("Add Vocabulary"):
71
+ word_input = gr.Textbox(label="Word")
72
+ definition_input = gr.Textbox(label="Definition")
73
+ add_button = gr.Button("Add Word")
74
+ add_output = gr.Textbox(label="Add Status")
75
+
76
+ with gr.Tab("Start Quiz"):
77
+ quiz_status = gr.Textbox(label="Quiz Status")
78
+ start_button = gr.Button("Start Quiz")
79
+
80
+ with gr.Tab("Matching Game"):
81
+ word_dropdown = gr.Dropdown(label="Select Word")
82
+ definition_dropdown = gr.Dropdown(label="Select Definition")
83
+ match_button = gr.Button("Check Match")
84
+ match_output = gr.Textbox(label="Match Result")
85
+ score_output = gr.Textbox(label="Score")
86
+
87
+ with gr.Tab("Reset Application"):
88
+ reset_button = gr.Button("Reset")
89
+ reset_output = gr.Textbox(label="Reset Status")
90
+
91
+ # Actions
92
+ upload_button.click(parse_csv, inputs=[csv_upload], outputs=[upload_output])
93
+ add_button.click(add_word, inputs=[word_input, definition_input], outputs=[add_output, word_dropdown])
94
+ start_button.click(start_quiz, outputs=[quiz_status, word_dropdown, definition_dropdown])
95
+ match_button.click(check_match, inputs=[word_dropdown, definition_dropdown], outputs=[match_output, score_output])
96
+ reset_button.click(reset_app, outputs=[reset_output])
97
+
98
+ return app
99
+
100
+ # Run Application
101
+ if __name__ == "__main__":
102
+ app = main()
103
+ app.launch()