From 278dfe48f9b89dfee382b8f985fe245e093e8c1c Mon Sep 17 00:00:00 2001 From: Aditya8369 Date: Thu, 25 Jun 2026 17:59:56 +0530 Subject: [PATCH 1/2] =?UTF-8?q?Master=20=E2=80=9CAchievements=20&=20XP?= =?UTF-8?q?=E2=80=9D=20system?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- progress.js | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/progress.js b/progress.js index 53fd6a1..8918d57 100644 --- a/progress.js +++ b/progress.js @@ -40,18 +40,30 @@ const STATE_COLORS = { }; const STORAGE_KEY = "learnsphere_progress"; +// XP system constants +const XP_PER_LEVEL = 1000; // XP required per level const REVIEW_SCHEDULE_KEY = "learnsphere_review_schedule_v1"; // ── Storage Helpers ─────────────────────────────────────────────────────────── function loadProgress() { try { - return JSON.parse(localStorage.getItem(STORAGE_KEY)) || {}; + const data = JSON.parse(localStorage.getItem(STORAGE_KEY)) || {}; + // Ensure XP and level fields exist + if (typeof data.xp !== "number") data.xp = 0; + if (typeof data.level !== "number") data.level = 0; + return data; } catch { - return {}; + return { xp: 0, level: 0 }; } } +// Helper to calculate level from XP +function calculateLevel(xp) { + if (typeof xp !== "number" || xp < 0) return 0; + return Math.floor(xp / XP_PER_LEVEL); +} + function loadReviewSchedule() { try { return JSON.parse(localStorage.getItem(REVIEW_SCHEDULE_KEY)) || {}; @@ -71,6 +83,9 @@ function saveReviewSchedule(scheduleMap) { function saveProgress(progressMap) { try { + // Ensure XP and level are persisted + if (typeof progressMap.xp !== "number") progressMap.xp = 0; + if (typeof progressMap.level !== "number") progressMap.level = 0; localStorage.setItem(STORAGE_KEY, JSON.stringify(progressMap)); } catch (e) { console.warn("LearnSphere: Could not save progress to localStorage.", e); @@ -281,6 +296,17 @@ function updateProgressSummary() { window.studyProgress = { STREAK_KEY: "learnsphere_streak_state_v1", + // XP related helpers + addXP(amount) { + const progress = loadProgress(); + const inc = Number(amount) || 0; + progress.xp = (progress.xp || 0) + inc; + progress.level = calculateLevel(progress.xp); + saveProgress(progress); + }, + getXP() { return (loadProgress().xp) || 0; }, + getLevel() { return (loadProgress().level) || 0; }, + XP_PER_LEVEL, loadStreakState() { try { From 4c5b0d44ea23f14070dc1da00e8bf967e5fa3c01 Mon Sep 17 00:00:00 2001 From: Aditya8369 Date: Thu, 25 Jun 2026 18:04:56 +0530 Subject: [PATCH 2/2] Quiz question bank with categories + difficulty --- quiz/bank/physics-motion.json | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 quiz/bank/physics-motion.json diff --git a/quiz/bank/physics-motion.json b/quiz/bank/physics-motion.json new file mode 100644 index 0000000..89a0756 --- /dev/null +++ b/quiz/bank/physics-motion.json @@ -0,0 +1,37 @@ +[ + { + "category": "General", + "difficulty": "easy", + "question": "What is the SI unit of speed?", + "options": ["m/s", "km/h", "m/s²", "N"], + "answer": "m/s" + }, + { + "category": "General", + "difficulty": "easy", + "question": "What causes an object to accelerate?", + "options": ["Mass", "Force", "Friction", "Temperature"], + "answer": "Force" + }, + { + "category": "General", + "difficulty": "medium", + "question": "Which of these is a scalar quantity?", + "options": ["Velocity", "Acceleration", "Displacement", "Speed"], + "answer": "Speed" + }, + { + "category": "General", + "difficulty": "medium", + "question": "What does Newton's First Law state?", + "options": ["F = ma", "Action = Reaction", "Objects stay in motion/rest unless acted on", "Momentum is conserved"], + "answer": "Objects stay in motion/rest unless acted on" + }, + { + "category": "General", + "difficulty": "hard", + "question": "What is the formula for acceleration?", + "options": ["v/t", "d/t", "Δv/t", "F/m"], + "answer": "Δv/t" + } +]