Refactor CapitalsQuiz and FlagQuiz to utilize shared logic for achievements and settings management, enhancing code consistency and maintainability.

This commit is contained in:
sHa
2025-08-15 00:37:47 +03:00
parent eb139840ba
commit 63d6c99ff1
2 changed files with 72 additions and 212 deletions

View File

@@ -1,4 +1,9 @@
<script> <script>
import { updateAchievementCount as sharedUpdateAchievementCount } from '../quizLogic/quizAchievements.js';
import { saveSettings as sharedSaveSettings, loadSettings as sharedLoadSettings } from '../quizLogic/quizSettings.js';
import { loadGlobalStats as sharedLoadGlobalStats, updateGlobalStats as sharedUpdateGlobalStats } from '../quizLogic/quizGlobalStats.js';
import { saveSessionState as sharedSaveSessionState, loadSessionState as sharedLoadSessionState, clearSessionState as sharedClearSessionState } from '../quizLogic/quizSession.js';
import { playCorrectSound as sharedPlayCorrectSound, playWrongSound as sharedPlayWrongSound } from '../quizLogic/quizSound.js';
import { quizInfo } from '../quizInfo/CapitalsQuizInfo.js'; import { quizInfo } from '../quizInfo/CapitalsQuizInfo.js';
import { onMount } from "svelte"; import { onMount } from "svelte";
import Header from "../components/Header.svelte"; import Header from "../components/Header.svelte";
@@ -87,21 +92,18 @@
// Update achievement count when achievements component is available // Update achievement count when achievements component is available
$: if (achievementsComponent) { $: if (achievementsComponent) {
updateAchievementCount(); achievementCount = sharedUpdateAchievementCount(achievementsComponent);
} }
// Save settings when they change (after initial load) // Save settings when they change (after initial load)
$: if (settingsLoaded && typeof reduceCorrectAnswers !== "undefined") { $: if (settingsLoaded && typeof reduceCorrectAnswers !== "undefined") {
localStorage.setItem( sharedSaveSettings("capitalsQuizSettings", {
"capitalsQuizSettings", autoAdvance,
JSON.stringify({ focusWrongAnswers,
autoAdvance, reduceCorrectAnswers,
focusWrongAnswers, soundEnabled,
reduceCorrectAnswers, sessionLength,
soundEnabled, });
sessionLength,
}),
);
} }
// Load game stats from localStorage // Load game stats from localStorage
@@ -162,31 +164,23 @@
} }
// Load settings // Load settings
const savedSettings = localStorage.getItem("capitalsQuizSettings"); const loadedSettings = sharedLoadSettings("capitalsQuizSettings", {
if (savedSettings) { autoAdvance,
try { focusWrongAnswers,
const settings = JSON.parse(savedSettings); reduceCorrectAnswers,
autoAdvance = soundEnabled,
settings.autoAdvance !== undefined ? settings.autoAdvance : true; sessionLength,
focusWrongAnswers = });
settings.focusWrongAnswers !== undefined if (loadedSettings) {
? settings.focusWrongAnswers autoAdvance = loadedSettings.autoAdvance;
: false; focusWrongAnswers = loadedSettings.focusWrongAnswers;
reduceCorrectAnswers = reduceCorrectAnswers = loadedSettings.reduceCorrectAnswers;
settings.reduceCorrectAnswers !== undefined soundEnabled = loadedSettings.soundEnabled;
? settings.reduceCorrectAnswers sessionLength = loadedSettings.sessionLength;
: false;
soundEnabled =
settings.soundEnabled !== undefined ? settings.soundEnabled : true;
sessionLength =
settings.sessionLength !== undefined ? settings.sessionLength : 10;
} catch (e) {
console.error("Error loading settings:", e);
}
} }
// Load global stats and update them // Load global stats and update them
loadGlobalStats(); sharedLoadGlobalStats("globalQuizStats");
} }
await loadFlags(); await loadFlags();
@@ -255,50 +249,37 @@
sessionStartTime, sessionStartTime,
questionKey, questionKey,
}; };
localStorage.setItem("capitalsQuizSessionState", JSON.stringify(sessionState)); sharedSaveSessionState("capitalsQuizSessionState", sessionState);
} }
function loadSessionState() { function loadSessionState() {
const savedState = localStorage.getItem("capitalsQuizSessionState"); const loadedSession = sharedLoadSessionState("capitalsQuizSessionState", null);
if (savedState) { if (loadedSession) {
try { // Restore session
const state = JSON.parse(savedState); sessionInProgress = loadedSession.sessionInProgress;
if (state.sessionInProgress) { currentSessionQuestions = loadedSession.currentSessionQuestions || 0;
// Restore session sessionStats = loadedSession.sessionStats || {
sessionInProgress = state.sessionInProgress; correct: 0,
currentSessionQuestions = state.currentSessionQuestions || 0; wrong: 0,
sessionStats = state.sessionStats || { skipped: 0,
correct: 0, total: 0,
wrong: 0, sessionLength,
skipped: 0, };
total: 0, score = loadedSession.score || { correct: 0, total: 0, skipped: 0 };
sessionLength, currentQuestion = loadedSession.currentQuestion;
}; selectedAnswer = loadedSession.selectedAnswer;
score = state.score || { correct: 0, total: 0, skipped: 0 }; showResult = loadedSession.showResult || false;
currentQuestion = state.currentQuestion; gameState = loadedSession.gameState || "question";
selectedAnswer = state.selectedAnswer; quizSubpage = "quiz";
showResult = state.showResult || false; sessionStartTime = loadedSession.sessionStartTime;
gameState = state.gameState || "question"; questionKey = loadedSession.questionKey || 0;
quizSubpage = "quiz";
sessionStartTime = state.sessionStartTime;
questionKey = state.questionKey || 0;
// Mark that session was restored from reload // Mark that session was restored from reload
sessionRestoredFromReload = true; sessionRestoredFromReload = true;
// If we don't have a current question, generate one // If we don't have a current question, generate one
if (!currentQuestion) { if (!currentQuestion) {
generateQuestion(); generateQuestion();
}
} else {
// No active session, show welcome page
quizSubpage = "welcome";
gameState = "welcome";
}
} catch (e) {
console.error("Error loading session state:", e);
quizSubpage = "welcome";
gameState = "welcome";
} }
} else { } else {
// No saved state, show welcome page // No saved state, show welcome page
@@ -308,7 +289,7 @@
} }
function clearSessionState() { function clearSessionState() {
localStorage.removeItem("capitalsQuizSessionState"); sharedClearSessionState("capitalsQuizSessionState");
} }
function generateQuestion() { function generateQuestion() {
@@ -676,10 +657,6 @@
localStorage.setItem("capitalsQuizStats", JSON.stringify(gameStats)); localStorage.setItem("capitalsQuizStats", JSON.stringify(gameStats));
} }
function saveSettings() {
const settings = { autoAdvance };
localStorage.setItem("capitalsQuizSettings", JSON.stringify(settings));
}
function toggleSettings() { function toggleSettings() {
showSettings = !showSettings; showSettings = !showSettings;
@@ -736,7 +713,7 @@
// Reset achievements if component is available // Reset achievements if component is available
if (achievementsComponent) { if (achievementsComponent) {
achievementsComponent.resetAllAchievements(); achievementsComponent.resetConsecutiveSkips();
} }
showResetConfirmation = false; showResetConfirmation = false;
@@ -799,134 +776,27 @@
return `/images/flags/${flag.path}`; return `/images/flags/${flag.path}`;
} }
function updateAchievementCount() {
if (achievementsComponent) {
achievementCount = achievementsComponent.getAchievementCount();
}
}
function handleAchievementsUnlocked() { function handleAchievementsUnlocked() {
updateAchievementCount(); achievementCount = sharedUpdateAchievementCount(achievementsComponent);
} }
// Global statistics functions // Global statistics functions
function loadGlobalStats() { function loadGlobalStats() {
const savedGlobalStats = localStorage.getItem("globalQuizStats"); sharedLoadGlobalStats("globalQuizStats");
if (savedGlobalStats) {
try {
const globalStats = JSON.parse(savedGlobalStats);
console.log("Loaded global stats:", globalStats);
} catch (e) {
console.error("Error loading global stats:", e);
}
}
} }
function updateGlobalStats(isCorrect, isSkipped = false) { function updateGlobalStats(isCorrect, isSkipped = false) {
let globalStats = {}; sharedUpdateGlobalStats("globalQuizStats", "capitalsQuiz", isCorrect, isSkipped);
// Load existing global stats
const savedGlobalStats = localStorage.getItem("globalQuizStats");
if (savedGlobalStats) {
try {
globalStats = JSON.parse(savedGlobalStats);
} catch (e) {
console.error("Error parsing global stats:", e);
}
}
// Initialize stats structure if it doesn't exist
if (!globalStats.capitalsQuiz) {
globalStats.capitalsQuiz = { correct: 0, wrong: 0, total: 0, skipped: 0 };
}
if (!globalStats.overall) {
globalStats.overall = { correct: 0, wrong: 0, total: 0, skipped: 0 };
}
// Update capitals quiz stats
globalStats.capitalsQuiz.total++;
globalStats.overall.total++;
if (isSkipped) {
globalStats.capitalsQuiz.skipped++;
globalStats.overall.skipped++;
} else if (isCorrect) {
globalStats.capitalsQuiz.correct++;
globalStats.overall.correct++;
} else {
globalStats.capitalsQuiz.wrong++;
globalStats.overall.wrong++;
}
// Save updated global stats
localStorage.setItem("globalQuizStats", JSON.stringify(globalStats));
console.log("Updated global stats:", globalStats);
} }
// Sound functions // Sound functions
function playCorrectSound() { function playCorrectSound() {
if (!soundEnabled) return; sharedPlayCorrectSound(soundEnabled);
try {
const audioContext = new (window.AudioContext ||
window.webkitAudioContext)();
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
// Pleasant ascending tone for correct answer
oscillator.frequency.setValueAtTime(523.25, audioContext.currentTime); // C5
oscillator.frequency.setValueAtTime(
659.25,
audioContext.currentTime + 0.1,
); // E5
oscillator.frequency.setValueAtTime(
783.99,
audioContext.currentTime + 0.2,
); // G5
gainNode.gain.setValueAtTime(0.3, audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(
0.001,
audioContext.currentTime + 0.4,
);
oscillator.start(audioContext.currentTime);
oscillator.stop(audioContext.currentTime + 0.4);
} catch (e) {
console.log("Audio not supported:", e);
}
} }
function playWrongSound() { function playWrongSound() {
if (!soundEnabled) return; sharedPlayWrongSound(soundEnabled);
try {
const audioContext = new (window.AudioContext ||
window.webkitAudioContext)();
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
// Descending tone for wrong answer
oscillator.frequency.setValueAtTime(400, audioContext.currentTime); // Lower frequency
oscillator.frequency.setValueAtTime(300, audioContext.currentTime + 0.15);
gainNode.gain.setValueAtTime(0.3, audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(
0.001,
audioContext.currentTime + 0.3,
);
oscillator.start(audioContext.currentTime);
oscillator.stop(audioContext.currentTime + 0.3);
} catch (e) {
console.log("Audio not supported:", e);
}
} }
</script> </script>

View File

@@ -1,4 +1,6 @@
<script> <script>
import { updateAchievementCount as sharedUpdateAchievementCount } from '../quizLogic/quizAchievements.js';
import { saveSettings as sharedSaveSettings } from '../quizLogic/quizSettings.js';
import { quizInfo } from '../quizInfo/FlagQuizInfo.js'; import { quizInfo } from '../quizInfo/FlagQuizInfo.js';
import { onMount } from "svelte"; import { onMount } from "svelte";
import Header from "../components/Header.svelte"; import Header from "../components/Header.svelte";
@@ -87,21 +89,18 @@ import { quizInfo } from '../quizInfo/FlagQuizInfo.js';
// Update achievement count when achievements component is available // Update achievement count when achievements component is available
$: if (achievementsComponent) { $: if (achievementsComponent) {
updateAchievementCount(); achievementCount = sharedUpdateAchievementCount(achievementsComponent);
} }
// Save settings when they change (after initial load) // Save settings when they change (after initial load)
$: if (settingsLoaded && typeof reduceCorrectAnswers !== "undefined") { $: if (settingsLoaded && typeof reduceCorrectAnswers !== "undefined") {
localStorage.setItem( sharedSaveSettings("flagQuizSettings", {
"flagQuizSettings", autoAdvance,
JSON.stringify({ focusWrongAnswers,
autoAdvance, reduceCorrectAnswers,
focusWrongAnswers, soundEnabled,
reduceCorrectAnswers, sessionLength,
soundEnabled, });
sessionLength,
}),
);
} }
// Load game stats from localStorage // Load game stats from localStorage
@@ -670,10 +669,6 @@ import { quizInfo } from '../quizInfo/FlagQuizInfo.js';
localStorage.setItem("flagQuizStats", JSON.stringify(gameStats)); localStorage.setItem("flagQuizStats", JSON.stringify(gameStats));
} }
function saveSettings() {
const settings = { autoAdvance };
localStorage.setItem("flagQuizSettings", JSON.stringify(settings));
}
function toggleSettings() { function toggleSettings() {
showSettings = !showSettings; showSettings = !showSettings;
@@ -730,7 +725,7 @@ import { quizInfo } from '../quizInfo/FlagQuizInfo.js';
// Reset achievements if component is available // Reset achievements if component is available
if (achievementsComponent) { if (achievementsComponent) {
achievementsComponent.resetAllAchievements(); achievementsComponent.resetConsecutiveSkips();
} }
showResetConfirmation = false; showResetConfirmation = false;
@@ -789,14 +784,9 @@ import { quizInfo } from '../quizInfo/FlagQuizInfo.js';
return `/images/flags/${flag.path}`; return `/images/flags/${flag.path}`;
} }
function updateAchievementCount() {
if (achievementsComponent) {
achievementCount = achievementsComponent.getAchievementCount();
}
}
function handleAchievementsUnlocked() { function handleAchievementsUnlocked() {
updateAchievementCount(); achievementCount = sharedUpdateAchievementCount(achievementsComponent);
} }
// Global statistics functions // Global statistics functions