Skip to content

Commit 613fd08

Browse files
Add random question shuffling on load and shuffle button
- Questions are now randomized when app loads - Added shuffle button in header for re-randomizing questions - Questions shuffle when changing topics or difficulty - Uses Fisher-Yates algorithm for proper randomization - Added shuffle icon and disabled state handling
1 parent 1af1aec commit 613fd08

1 file changed

Lines changed: 56 additions & 12 deletions

File tree

src/App.jsx

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ import {
4444
Refresh,
4545
AutoAwesome,
4646
Terminal,
47-
MenuBook
47+
MenuBook,
48+
Shuffle
4849
} from '@mui/icons-material'
4950

5051
import { questions } from './data/questions'
@@ -233,44 +234,51 @@ function App() {
233234
await db.load()
234235
setQuestionDatabase(db)
235236

236-
// Load questions for the active topic
237+
// Load questions for the active topic and shuffle them
237238
const topicQuestions = db.getQuestionsByCategory(activeTopic, selectedDifficulty)
238-
setDatabaseQuestions(topicQuestions)
239+
setDatabaseQuestions(shuffleArray(topicQuestions))
239240

240241
console.log(`Loaded ${db.getTotalQuestions()} questions from database`)
241242
} catch (error) {
242243
console.error('Failed to load question database:', error)
243-
// Fallback to legacy questions
244-
setDatabaseQuestions(questions.filter(q => q.topic === activeTopic))
244+
// Fallback to legacy questions and shuffle them
245+
const fallbackQuestions = questions.filter(q => q.topic === activeTopic)
246+
setDatabaseQuestions(shuffleArray(fallbackQuestions))
245247
} finally {
246248
setIsLoading(false)
247249
}
248250
}
249251

250252
initDatabase()
251-
}, [])
253+
}, [activeTopic, selectedDifficulty])
252254

253255
// Update questions when topic or difficulty changes
254256
useEffect(() => {
255257
if (questionDatabase) {
256258
const topicQuestions = questionDatabase.getQuestionsByCategory(activeTopic, selectedDifficulty)
257-
setDatabaseQuestions(topicQuestions)
259+
setDatabaseQuestions(shuffleArray(topicQuestions))
258260
setCurrentQuestionIndex(0)
259261
setSelectedAnswer(null)
260262
setShowResult(false)
261263
}
262264
}, [activeTopic, selectedDifficulty, questionDatabase])
263265

264-
// Get current questions (database or fallback)
265-
const availableQuestions = databaseQuestions.length > 0 ? databaseQuestions :
266-
questions.filter(q => q.topic === activeTopic && (selectedDifficulty === 'all' || q.difficulty === selectedDifficulty))
266+
// Helper function to shuffle array using Fisher-Yates algorithm
267+
const shuffleArray = (array) => {
268+
const shuffled = [...array]
269+
for (let i = shuffled.length - 1; i > 0; i--) {
270+
const j = Math.floor(Math.random() * (i + 1))
271+
;[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]
272+
}
273+
return shuffled
274+
}
267275
const getTopicQuestions = (topicId, difficulty = 'all') => {
268276
// Use database questions if available, otherwise fallback to legacy questions
269277
if (databaseQuestions.length > 0) {
270278
return databaseQuestions
271279
}
272280

273-
// Legacy fallback
281+
// Legacy fallback with shuffling
274282
const topicMap = {
275283
'variables': 'Variables',
276284
'arrays': 'Arrays',
@@ -291,7 +299,7 @@ function App() {
291299
}
292300

293301
console.log(`Found ${filteredQuestions.length} questions for topic ${topicId} (${topicMap[topicId]}) with difficulty ${difficulty}`)
294-
return filteredQuestions
302+
return shuffleArray(filteredQuestions)
295303
}
296304

297305
const topicQuestions = getTopicQuestions(activeTopic, selectedDifficulty)
@@ -334,6 +342,21 @@ function App() {
334342
// Get normalized difficulty for UI display
335343
const currentDifficulty = currentTopicQuestion ? normalizeDifficulty(currentTopicQuestion.difficulty) : 'easy'
336344

345+
// Function to shuffle current questions
346+
const handleShuffleQuestions = () => {
347+
if (databaseQuestions.length > 0) {
348+
setDatabaseQuestions(shuffleArray(databaseQuestions))
349+
setCurrentQuestionIndex(0)
350+
setSelectedAnswer(null)
351+
setShowResult(false)
352+
setSnackbar({
353+
open: true,
354+
message: '🔀 Questions shuffled! Starting fresh...',
355+
severity: 'info'
356+
})
357+
}
358+
}
359+
337360
// Multiple choice options - updated to handle both formats
338361
const getMultipleChoiceOptions = (question) => {
339362
if (!question) return []
@@ -874,6 +897,27 @@ function App() {
874897
</Select>
875898
</FormControl>
876899

900+
{/* Shuffle Questions Button */}
901+
<IconButton
902+
onClick={handleShuffleQuestions}
903+
disabled={!databaseQuestions.length}
904+
sx={{
905+
borderRadius: '50%',
906+
p: 1,
907+
backgroundColor: darkMode ? '#3c4043' : '#f8f9fa',
908+
color: databaseQuestions.length ? (darkMode ? '#e8eaed' : '#5f6368') : '#9aa0a6',
909+
'&:hover': {
910+
backgroundColor: databaseQuestions.length ? (darkMode ? '#5f6368' : '#e8eaed') : 'transparent',
911+
},
912+
'&.Mui-disabled': {
913+
color: '#9aa0a6',
914+
},
915+
}}
916+
title="Shuffle Questions"
917+
>
918+
<Shuffle />
919+
</IconButton>
920+
877921
{/* Theme Toggle - Google Style */}
878922
<IconButton
879923
onClick={() => setDarkMode(!darkMode)}

0 commit comments

Comments
 (0)