From 7d8470df84c38496bc8dd11424705401381fb7e3 Mon Sep 17 00:00:00 2001 From: "nate@necloud.us" Date: Wed, 13 Aug 2025 12:43:18 -0400 Subject: [PATCH] Implement version 3.0.0 with Analytics Dashboard, Gamification Expansion, and Spaced Repetition System --- data/challenges.json | 89 + data/leaderboards.json | 511 + data/progress.json | 551 + data/results.json | 17807 ++++++++++++++++++++++++++- data/spacedRepetition.json | 300 + gamification-endpoints.js | 470 + generate-analytics-data.js | 373 + generate-gamification-data.js | 285 + generate-leaderboard-data.js | 242 + generate-spaced-repetition-data.js | 222 + package.json | 4 +- public/gamification.css | 346 + public/index.html | 50 + public/js/game.js | 74 +- public/js/gamification.js | 501 + public/js/spaced-repetition.js | 391 + public/spaced-repetition.css | 233 + seed/spacedRepetition.json | 152 + server.js | 264 +- spaced-repetition-endpoints.js | 157 + 20 files changed, 22999 insertions(+), 23 deletions(-) create mode 100644 data/challenges.json create mode 100644 data/leaderboards.json create mode 100644 data/progress.json create mode 100644 data/spacedRepetition.json create mode 100644 gamification-endpoints.js create mode 100644 generate-analytics-data.js create mode 100644 generate-gamification-data.js create mode 100644 generate-leaderboard-data.js create mode 100644 generate-spaced-repetition-data.js create mode 100644 public/gamification.css create mode 100644 public/js/gamification.js create mode 100644 public/js/spaced-repetition.js create mode 100644 public/spaced-repetition.css create mode 100644 seed/spacedRepetition.json create mode 100644 spaced-repetition-endpoints.js diff --git a/data/challenges.json b/data/challenges.json new file mode 100644 index 0000000..759ca5f --- /dev/null +++ b/data/challenges.json @@ -0,0 +1,89 @@ +{ + "daily": [ + { + "id": "daily-practice-10", + "name": "Practice Makes Perfect", + "description": "Complete 10 practice words in a day", + "type": "daily", + "target": 10, + "points": 50, + "icon": "🎯" + }, + { + "id": "daily-accuracy-90", + "name": "Sharp Shooter", + "description": "Achieve 90% accuracy in daily practice", + "type": "daily", + "target": 0.9, + "points": 75, + "icon": "🎯" + }, + { + "id": "daily-streak-3", + "name": "On Fire", + "description": "Get 3 words correct in a row", + "type": "daily", + "target": 3, + "points": 30, + "icon": "🔥" + } + ], + "weekly": [ + { + "id": "weekly-words-50", + "name": "Word Warrior", + "description": "Practice 50 words in a week", + "type": "weekly", + "target": 50, + "points": 200, + "icon": "⚔️" + }, + { + "id": "weekly-days-5", + "name": "Dedicated Scholar", + "description": "Practice on 5 different days this week", + "type": "weekly", + "target": 5, + "points": 250, + "icon": "📚" + } + ], + "achievements": [ + { + "id": "achievement-words-100", + "name": "Century Club", + "description": "Practice 100 total words", + "type": "achievement", + "target": 100, + "points": 100, + "icon": "🏆" + }, + { + "id": "achievement-words-500", + "name": "Word Master", + "description": "Practice 500 total words", + "type": "achievement", + "target": 500, + "points": 500, + "icon": "👑" + }, + { + "id": "achievement-streak-7", + "name": "Weekly Warrior", + "description": "Maintain a 7-day practice streak", + "type": "achievement", + "target": 7, + "points": 300, + "icon": "📅" + }, + { + "id": "achievement-accuracy-95", + "name": "Spelling Bee Champion", + "description": "Maintain 95% accuracy across 100 words", + "type": "achievement", + "target": 0.95, + "points": 400, + "icon": "🐝" + } + ] +} \ No newline at end of file diff --git a/data/leaderboards.json b/data/leaderboards.json new file mode 100644 index 0000000..fd8d3e6 --- /dev/null +++ b/data/leaderboards.json @@ -0,0 +1,511 @@ +{ + "allTime": { + "accuracy": [ + { + "username": "benjamina31", + "value": 94.4, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "loganm87", + "value": 93.4, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "williamh77", + "value": 90, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "logant84", + "value": 88.8, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "sophiaa25", + "value": 87.5, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "emmaa72", + "value": 86.7, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "jacobg47", + "value": 84.6, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "oliverb12", + "value": 81.7, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "student1", + "value": 79, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "admin1", + "value": 77.1, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "testuser", + "value": 77.1, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "nate", + "value": 76.3, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "ameliab34", + "value": 74.5, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "masonl4", + "value": 73.1, + "timestamp": "2025-08-13T16:18:54.828Z" + } + ], + "totalWords": [ + { + "username": "nate", + "value": 1352, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "logant84", + "value": 966, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "williamh77", + "value": 846, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "oliverb12", + "value": 835, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "student1", + "value": 819, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "testuser", + "value": 761, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "ameliab34", + "value": 743, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "admin1", + "value": 724, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "masonl4", + "value": 530, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "sophiaa25", + "value": 419, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "benjamina31", + "value": 344, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "emmaa72", + "value": 304, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "loganm87", + "value": 252, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "jacobg47", + "value": 110, + "timestamp": "2025-08-13T16:18:54.828Z" + } + ], + "sessionsCompleted": [ + { + "username": "nate", + "value": 129, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "student1", + "value": 80, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "admin1", + "value": 73, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "testuser", + "value": 71, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "logant84", + "value": 45, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "benjamina31", + "value": 41, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "jacobg47", + "value": 37, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "loganm87", + "value": 33, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "sophiaa25", + "value": 31, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "emmaa72", + "value": 28, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "masonl4", + "value": 22, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "williamh77", + "value": 21, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "ameliab34", + "value": 9, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "oliverb12", + "value": 7, + "timestamp": "2025-08-13T16:18:54.828Z" + } + ], + "streakDays": [ + { + "username": "nate", + "value": 18, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "loganm87", + "value": 14, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "logant84", + "value": 12, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "benjamina31", + "value": 12, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "student1", + "value": 10, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "sophiaa25", + "value": 10, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "williamh77", + "value": 9, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "oliverb12", + "value": 8, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "testuser", + "value": 7, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "ameliab34", + "value": 7, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "admin1", + "value": 6, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "jacobg47", + "value": 2, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "emmaa72", + "value": 1, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "masonl4", + "value": 1, + "timestamp": "2025-08-13T16:18:54.828Z" + } + ] + }, + "weekly": { + "accuracy": [ + { + "username": "benjamina31", + "value": 98.2, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "loganm87", + "value": 95.80000000000001, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "logant84", + "value": 89.8, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "emmaa72", + "value": 89.3, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "williamh77", + "value": 88.8, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "sophiaa25", + "value": 87.5, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "student1", + "value": 83.7, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "jacobg47", + "value": 81.19999999999999, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "oliverb12", + "value": 80.10000000000001, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "nate", + "value": 77.2, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "ameliab34", + "value": 76.9, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "masonl4", + "value": 75.39999999999999, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "testuser", + "value": 74.1, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "admin1", + "value": 73.19999999999999, + "timestamp": "2025-08-13T16:18:54.828Z" + } + ], + "totalWords": [ + { + "username": "logant84", + "value": 53, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "masonl4", + "value": 52, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "oliverb12", + "value": 50, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "ameliab34", + "value": 40, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "admin1", + "value": 35, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "sophiaa25", + "value": 34, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "student1", + "value": 33, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "testuser", + "value": 32, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "benjamina31", + "value": 31, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "nate", + "value": 21, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "emmaa72", + "value": 19, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "loganm87", + "value": 17, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "williamh77", + "value": 15, + "timestamp": "2025-08-13T16:18:54.828Z" + }, + { + "username": "jacobg47", + "value": 11, + "timestamp": "2025-08-13T16:18:54.828Z" + } + ], + "sessionsCompleted": [ + { + "username": "logant84", + "value": 7, + "timestamp": "2025-08-13T16:18:54.829Z" + }, + { + "username": "admin1", + "value": 6, + "timestamp": "2025-08-13T16:18:54.829Z" + }, + { + "username": "loganm87", + "value": 5, + "timestamp": "2025-08-13T16:18:54.829Z" + }, + { + "username": "emmaa72", + "value": 5, + "timestamp": "2025-08-13T16:18:54.829Z" + }, + { + "username": "jacobg47", + "value": 5, + "timestamp": "2025-08-13T16:18:54.829Z" + }, + { + "username": "benjamina31", + "value": 5, + "timestamp": "2025-08-13T16:18:54.829Z" + }, + { + "username": "masonl4", + "value": 4, + "timestamp": "2025-08-13T16:18:54.829Z" + }, + { + "username": "williamh77", + "value": 3, + "timestamp": "2025-08-13T16:18:54.829Z" + }, + { + "username": "nate", + "value": 2, + "timestamp": "2025-08-13T16:18:54.829Z" + }, + { + "username": "student1", + "value": 2, + "timestamp": "2025-08-13T16:18:54.829Z" + }, + { + "username": "sophiaa25", + "value": 2, + "timestamp": "2025-08-13T16:18:54.829Z" + }, + { + "username": "testuser", + "value": 1, + "timestamp": "2025-08-13T16:18:54.829Z" + }, + { + "username": "ameliab34", + "value": 1, + "timestamp": "2025-08-13T16:18:54.829Z" + }, + { + "username": "oliverb12", + "value": 1, + "timestamp": "2025-08-13T16:18:54.829Z" + } + ] + }, + "currentWeek": "2025-3" +} \ No newline at end of file diff --git a/data/progress.json b/data/progress.json new file mode 100644 index 0000000..ed53f9f --- /dev/null +++ b/data/progress.json @@ -0,0 +1,551 @@ +{ + "admin1": { + "streak": { + "current": 5, + "longest": 11, + "lastPractice": "2025-08-12" + }, + "points": 1017, + "level": 3, + "dailyChallenges": [ + { + "id": "daily-practice-10", + "date": "2025-08-13", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-12", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-12", + "progress": 1 + }, + { + "id": "daily-streak-3", + "date": "2025-08-12", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-10", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-09", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-09", + "progress": 1 + }, + { + "id": "daily-streak-3", + "date": "2025-08-09", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-08", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-08", + "progress": 1 + }, + { + "id": "daily-streak-3", + "date": "2025-08-08", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-07", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-07", + "progress": 1 + }, + { + "id": "daily-streak-3", + "date": "2025-08-07", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-06", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-06", + "progress": 1 + }, + { + "id": "daily-streak-3", + "date": "2025-08-06", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-05", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-05", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-04", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-04", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-02", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-07-31", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-07-31", + "progress": 1 + }, + { + "id": "daily-streak-3", + "date": "2025-07-31", + "progress": 1 + } + ], + "weeklyChallenges": [ + { + "id": "weekly-days-5", + "weekStart": "2025-07-30", + "progress": 1 + }, + { + "id": "weekly-words-50", + "weekStart": "2025-07-23", + "progress": 1 + }, + { + "id": "weekly-days-5", + "weekStart": "2025-07-16", + "progress": 1 + } + ], + "achievements": [ + { + "id": "achievement-words-100", + "date": "2025-07-22", + "progress": 1 + }, + { + "id": "achievement-words-500", + "date": "2025-08-01", + "progress": 1 + } + ], + "stats": { + "wordsAttempted": 574, + "wordsCorrect": 415.86, + "sessionsCompleted": 69, + "averageAccuracy": 0.9 + } + }, + "nate": { + "streak": { + "current": 2, + "longest": 12, + "lastPractice": "2025-08-12" + }, + "points": 543, + "level": 2, + "dailyChallenges": [ + { + "id": "daily-practice-10", + "date": "2025-08-13", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-13", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-11", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-11", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-09", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-09", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-07", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-07", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-06", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-05", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-05", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-04", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-04", + "progress": 1 + }, + { + "id": "daily-streak-3", + "date": "2025-08-04", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-03", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-03", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-02", + "progress": 1 + } + ], + "weeklyChallenges": [ + { + "id": "weekly-words-50", + "weekStart": "2025-07-23", + "progress": 1 + } + ], + "achievements": [ + { + "id": "achievement-words-100", + "date": "2025-08-01", + "progress": 1 + } + ], + "stats": { + "wordsAttempted": 817, + "wordsCorrect": 317.68, + "sessionsCompleted": 79, + "averageAccuracy": 0.95 + } + }, + "student1": { + "streak": { + "current": 6, + "longest": 9, + "lastPractice": "2025-08-12" + }, + "points": 574, + "level": 2, + "dailyChallenges": [ + { + "id": "daily-practice-10", + "date": "2025-08-13", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-12", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-12", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-11", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-11", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-10", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-06", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-06", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-05", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-05", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-04", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-04", + "progress": 1 + }, + { + "id": "daily-streak-3", + "date": "2025-08-04", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-03", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-02", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-01", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-01", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-07-31", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-07-31", + "progress": 1 + }, + { + "id": "daily-streak-3", + "date": "2025-07-31", + "progress": 1 + } + ], + "weeklyChallenges": [ + { + "id": "weekly-words-50", + "weekStart": "2025-08-06", + "progress": 1 + } + ], + "achievements": [ + { + "id": "achievement-words-100", + "date": "2025-07-23", + "progress": 1 + } + ], + "stats": { + "wordsAttempted": 102, + "wordsCorrect": 648.1800000000001, + "sessionsCompleted": 65, + "averageAccuracy": 0.78 + } + }, + "testuser": { + "streak": { + "current": 13, + "longest": 20, + "lastPractice": "2025-08-12" + }, + "points": 843, + "level": 2, + "dailyChallenges": [ + { + "id": "daily-practice-10", + "date": "2025-08-13", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-13", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-12", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-11", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-11", + "progress": 1 + }, + { + "id": "daily-streak-3", + "date": "2025-08-11", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-09", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-09", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-08", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-07", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-06", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-06", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-05", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-04", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-02", + "progress": 1 + }, + { + "id": "daily-practice-10", + "date": "2025-08-01", + "progress": 1 + }, + { + "id": "daily-accuracy-90", + "date": "2025-08-01", + "progress": 1 + }, + { + "id": "daily-streak-3", + "date": "2025-08-01", + "progress": 1 + } + ], + "weeklyChallenges": [ + { + "id": "weekly-words-50", + "weekStart": "2025-08-06", + "progress": 1 + }, + { + "id": "weekly-words-50", + "weekStart": "2025-07-30", + "progress": 1 + } + ], + "achievements": [ + { + "id": "achievement-words-100", + "date": "2025-08-03", + "progress": 1 + }, + { + "id": "achievement-words-500", + "date": "2025-07-18", + "progress": 1 + } + ], + "stats": { + "wordsAttempted": 353, + "wordsCorrect": 789.4499999999999, + "sessionsCompleted": 87, + "averageAccuracy": 0.88 + } + } +} \ No newline at end of file diff --git a/data/results.json b/data/results.json index 9d68fe3..0ff921c 100644 --- a/data/results.json +++ b/data/results.json @@ -18,6 +18,4002 @@ } ], "timestamp": "2025-07-07T12:14:21.057Z" + }, + { + "date": "2025-05-19T18:41:35Z", + "sessionId": "student1-2025-05-19-0", + "total": 11, + "correct": 7, + "score": 64, + "words": [ + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-65", + "correct": false + }, + { + "word": "sample-word-50", + "correct": false + }, + { + "word": "sample-word-53", + "correct": false + }, + { + "word": "sample-word-74", + "correct": false + } + ] + }, + { + "date": "2025-05-19T18:41:04Z", + "sessionId": "student1-2025-05-19-1", + "total": 15, + "correct": 10, + "score": 66, + "words": [ + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-87", + "correct": false + }, + { + "word": "sample-word-97", + "correct": false + }, + { + "word": "sample-word-47", + "correct": false + }, + { + "word": "sample-word-51", + "correct": false + }, + { + "word": "sample-word-96", + "correct": false + } + ] + }, + { + "date": "2025-05-23T17:41:48Z", + "sessionId": "student1-2025-05-23-0", + "total": 9, + "correct": 7, + "score": 77, + "words": [ + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-66", + "correct": false + }, + { + "word": "sample-word-78", + "correct": false + } + ] + }, + { + "date": "2025-05-27T13:53:22Z", + "sessionId": "student1-2025-05-27-0", + "total": 7, + "correct": 5, + "score": 65, + "words": [ + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-57", + "correct": false + }, + { + "word": "sample-word-22", + "correct": false + } + ] + }, + { + "date": "2025-05-27T13:28:23Z", + "sessionId": "student1-2025-05-27-1", + "total": 11, + "correct": 8, + "score": 74, + "words": [ + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-38", + "correct": false + }, + { + "word": "sample-word-6", + "correct": false + }, + { + "word": "sample-word-22", + "correct": false + } + ] + }, + { + "date": "2025-06-02T17:57:03Z", + "sessionId": "student1-2025-06-02-0", + "total": 9, + "correct": 7, + "score": 76, + "words": [ + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-24", + "correct": false + }, + { + "word": "sample-word-38", + "correct": false + } + ] + }, + { + "date": "2025-06-04T17:53:46Z", + "sessionId": "student1-2025-06-04-0", + "total": 5, + "correct": 4, + "score": 77, + "words": [ + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-89", + "correct": false + } + ] + }, + { + "date": "2025-06-04T18:46:24Z", + "sessionId": "student1-2025-06-04-1", + "total": 12, + "correct": 8, + "score": 65, + "words": [ + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-75", + "correct": false + }, + { + "word": "sample-word-51", + "correct": false + }, + { + "word": "sample-word-54", + "correct": false + }, + { + "word": "sample-word-25", + "correct": false + } + ] + }, + { + "date": "2025-06-05T17:37:05Z", + "sessionId": "student1-2025-06-05-0", + "total": 10, + "correct": 7, + "score": 71, + "words": [ + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-20", + "correct": false + }, + { + "word": "sample-word-34", + "correct": false + }, + { + "word": "sample-word-82", + "correct": false + } + ] + }, + { + "date": "2025-06-12T16:12:52Z", + "sessionId": "student1-2025-06-12-0", + "total": 13, + "correct": 8, + "score": 65, + "words": [ + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-6", + "correct": false + }, + { + "word": "sample-word-94", + "correct": false + }, + { + "word": "sample-word-30", + "correct": false + }, + { + "word": "sample-word-3", + "correct": false + }, + { + "word": "sample-word-100", + "correct": false + } + ] + }, + { + "date": "2025-06-12T15:39:35Z", + "sessionId": "student1-2025-06-12-1", + "total": 10, + "correct": 7, + "score": 65, + "words": [ + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-92", + "correct": false + }, + { + "word": "sample-word-18", + "correct": false + }, + { + "word": "sample-word-42", + "correct": false + } + ] + }, + { + "date": "2025-06-14T08:45:51Z", + "sessionId": "student1-2025-06-14-0", + "total": 14, + "correct": 9, + "score": 65, + "words": [ + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-19", + "correct": false + }, + { + "word": "sample-word-8", + "correct": false + }, + { + "word": "sample-word-74", + "correct": false + }, + { + "word": "sample-word-8", + "correct": false + }, + { + "word": "sample-word-54", + "correct": false + } + ] + }, + { + "date": "2025-06-14T14:19:22Z", + "sessionId": "student1-2025-06-14-1", + "total": 8, + "correct": 6, + "score": 72, + "words": [ + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-86", + "correct": false + }, + { + "word": "sample-word-55", + "correct": false + } + ] + }, + { + "date": "2025-06-18T17:42:18Z", + "sessionId": "student1-2025-06-18-0", + "total": 9, + "correct": 6, + "score": 70, + "words": [ + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-85", + "correct": false + }, + { + "word": "sample-word-12", + "correct": false + }, + { + "word": "sample-word-14", + "correct": false + } + ] + }, + { + "date": "2025-06-18T14:53:16Z", + "sessionId": "student1-2025-06-18-1", + "total": 13, + "correct": 11, + "score": 82, + "words": [ + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-55", + "correct": false + }, + { + "word": "sample-word-61", + "correct": false + } + ] + }, + { + "date": "2025-06-19T12:49:49Z", + "sessionId": "student1-2025-06-19-0", + "total": 13, + "correct": 11, + "score": 83, + "words": [ + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-94", + "correct": false + }, + { + "word": "sample-word-39", + "correct": false + } + ] + }, + { + "date": "2025-06-19T19:48:51Z", + "sessionId": "student1-2025-06-19-1", + "total": 13, + "correct": 9, + "score": 71, + "words": [ + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-7", + "correct": false + }, + { + "word": "sample-word-85", + "correct": false + }, + { + "word": "sample-word-63", + "correct": false + }, + { + "word": "sample-word-100", + "correct": false + } + ] + }, + { + "date": "2025-06-22T19:27:32Z", + "sessionId": "student1-2025-06-22-0", + "total": 11, + "correct": 8, + "score": 74, + "words": [ + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-66", + "correct": false + }, + { + "word": "sample-word-36", + "correct": false + }, + { + "word": "sample-word-38", + "correct": false + } + ] + }, + { + "date": "2025-06-22T18:08:07Z", + "sessionId": "student1-2025-06-22-1", + "total": 14, + "correct": 10, + "score": 70, + "words": [ + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-76", + "correct": false + }, + { + "word": "sample-word-71", + "correct": false + }, + { + "word": "sample-word-73", + "correct": false + }, + { + "word": "sample-word-53", + "correct": false + } + ] + }, + { + "date": "2025-06-23T08:49:00Z", + "sessionId": "student1-2025-06-23-0", + "total": 13, + "correct": 8, + "score": 65, + "words": [ + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-16", + "correct": false + }, + { + "word": "sample-word-82", + "correct": false + }, + { + "word": "sample-word-87", + "correct": false + }, + { + "word": "sample-word-73", + "correct": false + }, + { + "word": "sample-word-31", + "correct": false + } + ] + }, + { + "date": "2025-06-25T09:50:23Z", + "sessionId": "student1-2025-06-25-0", + "total": 10, + "correct": 7, + "score": 74, + "words": [ + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-55", + "correct": false + }, + { + "word": "sample-word-31", + "correct": false + }, + { + "word": "sample-word-25", + "correct": false + } + ] + }, + { + "date": "2025-06-27T09:23:15Z", + "sessionId": "student1-2025-06-27-0", + "total": 13, + "correct": 10, + "score": 77, + "words": [ + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-100", + "correct": false + }, + { + "word": "sample-word-17", + "correct": false + }, + { + "word": "sample-word-45", + "correct": false + } + ] + }, + { + "date": "2025-06-27T08:28:11Z", + "sessionId": "student1-2025-06-27-1", + "total": 9, + "correct": 7, + "score": 75, + "words": [ + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-96", + "correct": false + }, + { + "word": "sample-word-1", + "correct": false + } + ] + }, + { + "date": "2025-06-30T09:18:47Z", + "sessionId": "student1-2025-06-30-0", + "total": 15, + "correct": 11, + "score": 72, + "words": [ + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-8", + "correct": false + }, + { + "word": "sample-word-85", + "correct": false + }, + { + "word": "sample-word-17", + "correct": false + }, + { + "word": "sample-word-25", + "correct": false + } + ] + }, + { + "date": "2025-06-30T09:18:35Z", + "sessionId": "student1-2025-06-30-1", + "total": 15, + "correct": 11, + "score": 70, + "words": [ + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-27", + "correct": false + }, + { + "word": "sample-word-82", + "correct": false + }, + { + "word": "sample-word-69", + "correct": false + }, + { + "word": "sample-word-43", + "correct": false + } + ] + }, + { + "date": "2025-07-01T15:01:40Z", + "sessionId": "student1-2025-07-01-0", + "total": 13, + "correct": 10, + "score": 78, + "words": [ + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-17", + "correct": false + }, + { + "word": "sample-word-95", + "correct": false + }, + { + "word": "sample-word-87", + "correct": false + } + ] + }, + { + "date": "2025-07-01T11:56:41Z", + "sessionId": "student1-2025-07-01-1", + "total": 15, + "correct": 12, + "score": 77, + "words": [ + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-82", + "correct": false + }, + { + "word": "sample-word-98", + "correct": false + }, + { + "word": "sample-word-96", + "correct": false + } + ] + }, + { + "date": "2025-07-02T12:26:33Z", + "sessionId": "student1-2025-07-02-0", + "total": 9, + "correct": 7, + "score": 78, + "words": [ + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-57", + "correct": false + }, + { + "word": "sample-word-58", + "correct": false + } + ] + }, + { + "date": "2025-07-03T09:06:32Z", + "sessionId": "student1-2025-07-03-0", + "total": 11, + "correct": 9, + "score": 83, + "words": [ + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-10", + "correct": false + }, + { + "word": "sample-word-14", + "correct": false + } + ] + }, + { + "date": "2025-07-05T17:10:01Z", + "sessionId": "student1-2025-07-05-0", + "total": 10, + "correct": 8, + "score": 84, + "words": [ + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-28", + "correct": false + }, + { + "word": "sample-word-15", + "correct": false + } + ] + }, + { + "date": "2025-07-05T16:17:45Z", + "sessionId": "student1-2025-07-05-1", + "total": 13, + "correct": 11, + "score": 83, + "words": [ + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-6", + "correct": false + }, + { + "word": "sample-word-91", + "correct": false + } + ] + }, + { + "date": "2025-07-07T14:49:23Z", + "sessionId": "student1-2025-07-07-0", + "total": 8, + "correct": 7, + "score": 86, + "words": [ + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-28", + "correct": false + } + ] + }, + { + "date": "2025-07-09T20:06:02Z", + "sessionId": "student1-2025-07-09-0", + "total": 5, + "correct": 4, + "score": 83, + "words": [ + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-49", + "correct": false + } + ] + }, + { + "date": "2025-07-09T16:11:33Z", + "sessionId": "student1-2025-07-09-1", + "total": 14, + "correct": 12, + "score": 86, + "words": [ + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-10", + "correct": false + }, + { + "word": "sample-word-51", + "correct": false + } + ] + }, + { + "date": "2025-07-10T15:30:27Z", + "sessionId": "student1-2025-07-10-0", + "total": 7, + "correct": 5, + "score": 70, + "words": [ + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-34", + "correct": false + }, + { + "word": "sample-word-14", + "correct": false + } + ] + }, + { + "date": "2025-07-10T18:46:38Z", + "sessionId": "student1-2025-07-10-1", + "total": 6, + "correct": 4, + "score": 69, + "words": [ + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-91", + "correct": false + }, + { + "word": "sample-word-88", + "correct": false + } + ] + }, + { + "date": "2025-07-11T08:35:01Z", + "sessionId": "student1-2025-07-11-0", + "total": 15, + "correct": 12, + "score": 83, + "words": [ + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-38", + "correct": false + }, + { + "word": "sample-word-10", + "correct": false + }, + { + "word": "sample-word-72", + "correct": false + } + ] + }, + { + "date": "2025-07-11T17:46:30Z", + "sessionId": "student1-2025-07-11-1", + "total": 5, + "correct": 4, + "score": 84, + "words": [ + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-52", + "correct": false + } + ] + }, + { + "date": "2025-07-12T16:59:47Z", + "sessionId": "student1-2025-07-12-0", + "total": 5, + "correct": 3, + "score": 69, + "words": [ + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-66", + "correct": false + }, + { + "word": "sample-word-8", + "correct": false + } + ] + }, + { + "date": "2025-07-12T13:52:07Z", + "sessionId": "student1-2025-07-12-1", + "total": 10, + "correct": 9, + "score": 87, + "words": [ + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-80", + "correct": false + } + ] + }, + { + "date": "2025-07-13T12:10:53Z", + "sessionId": "student1-2025-07-13-0", + "total": 10, + "correct": 9, + "score": 85, + "words": [ + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-96", + "correct": false + } + ] + }, + { + "date": "2025-07-13T10:08:00Z", + "sessionId": "student1-2025-07-13-1", + "total": 11, + "correct": 9, + "score": 78, + "words": [ + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-3", + "correct": false + }, + { + "word": "sample-word-79", + "correct": false + } + ] + }, + { + "date": "2025-07-15T12:53:06Z", + "sessionId": "student1-2025-07-15-0", + "total": 11, + "correct": 8, + "score": 77, + "words": [ + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-28", + "correct": false + }, + { + "word": "sample-word-100", + "correct": false + }, + { + "word": "sample-word-9", + "correct": false + } + ] + }, + { + "date": "2025-07-16T08:01:26Z", + "sessionId": "student1-2025-07-16-0", + "total": 5, + "correct": 4, + "score": 72, + "words": [ + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-19", + "correct": false + } + ] + }, + { + "date": "2025-07-17T14:11:01Z", + "sessionId": "student1-2025-07-17-0", + "total": 15, + "correct": 13, + "score": 84, + "words": [ + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-81", + "correct": false + }, + { + "word": "sample-word-95", + "correct": false + } + ] + }, + { + "date": "2025-07-18T13:53:17Z", + "sessionId": "student1-2025-07-18-0", + "total": 14, + "correct": 11, + "score": 77, + "words": [ + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-11", + "correct": false + }, + { + "word": "sample-word-33", + "correct": false + }, + { + "word": "sample-word-94", + "correct": false + } + ] + }, + { + "date": "2025-07-18T20:53:08Z", + "sessionId": "student1-2025-07-18-1", + "total": 5, + "correct": 4, + "score": 81, + "words": [ + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-86", + "correct": false + } + ] + }, + { + "date": "2025-07-20T08:55:43Z", + "sessionId": "student1-2025-07-20-0", + "total": 15, + "correct": 13, + "score": 87, + "words": [ + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-54", + "correct": false + }, + { + "word": "sample-word-9", + "correct": false + } + ] + }, + { + "date": "2025-07-20T16:11:51Z", + "sessionId": "student1-2025-07-20-1", + "total": 6, + "correct": 4, + "score": 74, + "words": [ + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-59", + "correct": false + }, + { + "word": "sample-word-71", + "correct": false + } + ] + }, + { + "date": "2025-07-21T16:42:21Z", + "sessionId": "student1-2025-07-21-0", + "total": 7, + "correct": 5, + "score": 78, + "words": [ + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-92", + "correct": false + }, + { + "word": "sample-word-88", + "correct": false + } + ] + }, + { + "date": "2025-07-21T11:36:45Z", + "sessionId": "student1-2025-07-21-1", + "total": 11, + "correct": 10, + "score": 90, + "words": [ + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-91", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-41", + "correct": false + } + ] + }, + { + "date": "2025-07-22T09:00:12Z", + "sessionId": "student1-2025-07-22-0", + "total": 5, + "correct": 4, + "score": 74, + "words": [ + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-90", + "correct": false + } + ] + }, + { + "date": "2025-07-22T18:31:35Z", + "sessionId": "student1-2025-07-22-1", + "total": 8, + "correct": 7, + "score": 82, + "words": [ + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-75", + "correct": false + } + ] + }, + { + "date": "2025-07-23T08:16:44Z", + "sessionId": "student1-2025-07-23-0", + "total": 6, + "correct": 5, + "score": 78, + "words": [ + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-63", + "correct": false + } + ] + }, + { + "date": "2025-07-25T13:23:49Z", + "sessionId": "student1-2025-07-25-0", + "total": 11, + "correct": 10, + "score": 89, + "words": [ + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-55", + "correct": false + } + ] + }, + { + "date": "2025-07-25T15:01:38Z", + "sessionId": "student1-2025-07-25-1", + "total": 9, + "correct": 8, + "score": 90, + "words": [ + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-5", + "correct": false + } + ] + }, + { + "date": "2025-07-26T15:10:25Z", + "sessionId": "student1-2025-07-26-0", + "total": 10, + "correct": 8, + "score": 79, + "words": [ + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-84", + "correct": false + }, + { + "word": "sample-word-57", + "correct": false + } + ] + }, + { + "date": "2025-07-27T15:24:22Z", + "sessionId": "student1-2025-07-27-0", + "total": 9, + "correct": 8, + "score": 91, + "words": [ + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-91", + "correct": false + } + ] + }, + { + "date": "2025-07-28T20:20:53Z", + "sessionId": "student1-2025-07-28-0", + "total": 7, + "correct": 5, + "score": 78, + "words": [ + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-17", + "correct": false + }, + { + "word": "sample-word-88", + "correct": false + } + ] + }, + { + "date": "2025-07-28T20:47:05Z", + "sessionId": "student1-2025-07-28-1", + "total": 5, + "correct": 4, + "score": 87, + "words": [ + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-73", + "correct": false + } + ] + }, + { + "date": "2025-07-29T15:41:22Z", + "sessionId": "student1-2025-07-29-0", + "total": 15, + "correct": 14, + "score": 92, + "words": [ + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-91", + "correct": false + } + ] + }, + { + "date": "2025-07-30T20:40:27Z", + "sessionId": "student1-2025-07-30-0", + "total": 9, + "correct": 8, + "score": 87, + "words": [ + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-80", + "correct": false + } + ] + }, + { + "date": "2025-08-04T20:43:11Z", + "sessionId": "student1-2025-08-04-0", + "total": 8, + "correct": 7, + "score": 86, + "words": [ + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-53", + "correct": false + } + ] + }, + { + "date": "2025-08-04T18:09:15Z", + "sessionId": "student1-2025-08-04-1", + "total": 5, + "correct": 4, + "score": 80, + "words": [ + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-77", + "correct": false + } + ] + }, + { + "date": "2025-08-05T17:35:58Z", + "sessionId": "student1-2025-08-05-0", + "total": 13, + "correct": 12, + "score": 91, + "words": [ + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-22", + "correct": false + } + ] + }, + { + "date": "2025-08-05T12:22:39Z", + "sessionId": "student1-2025-08-05-1", + "total": 13, + "correct": 11, + "score": 82, + "words": [ + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-91", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-50", + "correct": false + }, + { + "word": "sample-word-59", + "correct": false + } + ] + }, + { + "date": "2025-08-06T14:04:28Z", + "sessionId": "student1-2025-08-06-0", + "total": 8, + "correct": 7, + "score": 82, + "words": [ + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-75", + "correct": false + } + ] + }, + { + "date": "2025-08-06T11:45:11Z", + "sessionId": "student1-2025-08-06-1", + "total": 12, + "correct": 9, + "score": 78, + "words": [ + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-77", + "correct": false + }, + { + "word": "sample-word-47", + "correct": false + }, + { + "word": "sample-word-83", + "correct": false + } + ] + }, + { + "date": "2025-08-07T13:48:14Z", + "sessionId": "student1-2025-08-07-0", + "total": 9, + "correct": 8, + "score": 87, + "words": [ + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-20", + "correct": false + } + ] + }, + { + "date": "2025-08-07T20:17:08Z", + "sessionId": "student1-2025-08-07-1", + "total": 15, + "correct": 12, + "score": 81, + "words": [ + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-97", + "correct": false + }, + { + "word": "sample-word-68", + "correct": false + }, + { + "word": "sample-word-9", + "correct": false + } + ] + }, + { + "date": "2025-08-08T20:02:58Z", + "sessionId": "student1-2025-08-08-0", + "total": 15, + "correct": 12, + "score": 77, + "words": [ + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-3", + "correct": false + }, + { + "word": "sample-word-64", + "correct": false + }, + { + "word": "sample-word-98", + "correct": false + } + ] + }, + { + "date": "2025-08-08T15:54:23Z", + "sessionId": "student1-2025-08-08-1", + "total": 13, + "correct": 11, + "score": 84, + "words": [ + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-10", + "correct": false + }, + { + "word": "sample-word-38", + "correct": false + } + ] + }, + { + "date": "2025-08-09T09:04:28Z", + "sessionId": "student1-2025-08-09-0", + "total": 11, + "correct": 8, + "score": 77, + "words": [ + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-88", + "correct": false + }, + { + "word": "sample-word-59", + "correct": false + }, + { + "word": "sample-word-19", + "correct": false + } + ] + }, + { + "date": "2025-08-09T10:07:30Z", + "sessionId": "student1-2025-08-09-1", + "total": 6, + "correct": 5, + "score": 85, + "words": [ + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-14", + "correct": false + } + ] + }, + { + "date": "2025-08-10T17:32:18Z", + "sessionId": "student1-2025-08-10-0", + "total": 7, + "correct": 6, + "score": 85, + "words": [ + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-16", + "correct": false + } + ] + }, + { + "date": "2025-08-11T14:12:10Z", + "sessionId": "student1-2025-08-11-0", + "total": 7, + "correct": 7, + "score": 94, + "words": [ + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + } + ] + }, + { + "date": "2025-08-11T17:20:27Z", + "sessionId": "student1-2025-08-11-1", + "total": 7, + "correct": 5, + "score": 78, + "words": [ + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-19", + "correct": false + }, + { + "word": "sample-word-93", + "correct": false + } + ] + }, + { + "date": "2025-08-12T14:53:45Z", + "sessionId": "student1-2025-08-12-0", + "total": 11, + "correct": 10, + "score": 88, + "words": [ + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-24", + "correct": false + } + ] + }, + { + "date": "2025-08-12T18:48:44Z", + "sessionId": "student1-2025-08-12-1", + "total": 13, + "correct": 12, + "score": 91, + "words": [ + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-44", + "correct": false + } + ] + }, + { + "date": "2025-08-13T13:39:31Z", + "sessionId": "student1-2025-08-13-0", + "total": 14, + "correct": 11, + "score": 77, + "words": [ + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-77", + "correct": false + }, + { + "word": "sample-word-31", + "correct": false + }, + { + "word": "sample-word-50", + "correct": false + } + ] } ], "nate": [ @@ -66,8 +4062,13815 @@ } ], "timestamp": "2025-07-15T14:36:13.273Z" + }, + { + "date": "2025-05-15T09:50:12Z", + "sessionId": "nate-2025-05-15-0", + "total": 12, + "correct": 8, + "score": 66, + "words": [ + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-80", + "correct": false + }, + { + "word": "sample-word-9", + "correct": false + }, + { + "word": "sample-word-55", + "correct": false + }, + { + "word": "sample-word-70", + "correct": false + } + ] + }, + { + "date": "2025-05-15T17:50:29Z", + "sessionId": "nate-2025-05-15-1", + "total": 15, + "correct": 10, + "score": 64, + "words": [ + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-32", + "correct": false + }, + { + "word": "sample-word-47", + "correct": false + }, + { + "word": "sample-word-51", + "correct": false + }, + { + "word": "sample-word-82", + "correct": false + }, + { + "word": "sample-word-45", + "correct": false + } + ] + }, + { + "date": "2025-05-18T14:10:54Z", + "sessionId": "nate-2025-05-18-0", + "total": 11, + "correct": 8, + "score": 72, + "words": [ + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-66", + "correct": false + }, + { + "word": "sample-word-9", + "correct": false + }, + { + "word": "sample-word-71", + "correct": false + } + ] + }, + { + "date": "2025-05-21T18:52:59Z", + "sessionId": "nate-2025-05-21-0", + "total": 13, + "correct": 9, + "score": 70, + "words": [ + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-88", + "correct": false + }, + { + "word": "sample-word-29", + "correct": false + }, + { + "word": "sample-word-85", + "correct": false + }, + { + "word": "sample-word-21", + "correct": false + } + ] + }, + { + "date": "2025-05-21T15:34:30Z", + "sessionId": "nate-2025-05-21-1", + "total": 12, + "correct": 7, + "score": 57, + "words": [ + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-74", + "correct": false + }, + { + "word": "sample-word-39", + "correct": false + }, + { + "word": "sample-word-80", + "correct": false + }, + { + "word": "sample-word-55", + "correct": false + }, + { + "word": "sample-word-26", + "correct": false + } + ] + }, + { + "date": "2025-05-21T18:30:10Z", + "sessionId": "nate-2025-05-21-2", + "total": 11, + "correct": 7, + "score": 59, + "words": [ + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-78", + "correct": false + }, + { + "word": "sample-word-46", + "correct": false + }, + { + "word": "sample-word-26", + "correct": false + }, + { + "word": "sample-word-100", + "correct": false + } + ] + }, + { + "date": "2025-05-22T09:29:28Z", + "sessionId": "nate-2025-05-22-0", + "total": 15, + "correct": 9, + "score": 62, + "words": [ + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-4", + "correct": false + }, + { + "word": "sample-word-50", + "correct": false + }, + { + "word": "sample-word-64", + "correct": false + }, + { + "word": "sample-word-21", + "correct": false + }, + { + "word": "sample-word-37", + "correct": false + }, + { + "word": "sample-word-1", + "correct": false + } + ] + }, + { + "date": "2025-05-22T14:26:25Z", + "sessionId": "nate-2025-05-22-1", + "total": 5, + "correct": 4, + "score": 76, + "words": [ + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-84", + "correct": false + } + ] + }, + { + "date": "2025-05-22T12:47:19Z", + "sessionId": "nate-2025-05-22-2", + "total": 9, + "correct": 6, + "score": 66, + "words": [ + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-54", + "correct": false + }, + { + "word": "sample-word-93", + "correct": false + }, + { + "word": "sample-word-60", + "correct": false + } + ] + }, + { + "date": "2025-05-23T14:30:19Z", + "sessionId": "nate-2025-05-23-0", + "total": 8, + "correct": 5, + "score": 64, + "words": [ + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-29", + "correct": false + }, + { + "word": "sample-word-43", + "correct": false + }, + { + "word": "sample-word-6", + "correct": false + } + ] + }, + { + "date": "2025-05-25T19:58:41Z", + "sessionId": "nate-2025-05-25-0", + "total": 5, + "correct": 3, + "score": 67, + "words": [ + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-48", + "correct": false + }, + { + "word": "sample-word-11", + "correct": false + } + ] + }, + { + "date": "2025-05-25T09:47:26Z", + "sessionId": "nate-2025-05-25-1", + "total": 9, + "correct": 7, + "score": 74, + "words": [ + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-46", + "correct": false + }, + { + "word": "sample-word-61", + "correct": false + } + ] + }, + { + "date": "2025-05-25T19:49:31Z", + "sessionId": "nate-2025-05-25-2", + "total": 12, + "correct": 8, + "score": 70, + "words": [ + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-89", + "correct": false + }, + { + "word": "sample-word-29", + "correct": false + }, + { + "word": "sample-word-29", + "correct": false + }, + { + "word": "sample-word-65", + "correct": false + } + ] + }, + { + "date": "2025-05-27T14:17:49Z", + "sessionId": "nate-2025-05-27-0", + "total": 10, + "correct": 6, + "score": 59, + "words": [ + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-5", + "correct": false + }, + { + "word": "sample-word-68", + "correct": false + }, + { + "word": "sample-word-46", + "correct": false + }, + { + "word": "sample-word-82", + "correct": false + } + ] + }, + { + "date": "2025-05-27T12:16:18Z", + "sessionId": "nate-2025-05-27-1", + "total": 13, + "correct": 8, + "score": 64, + "words": [ + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-95", + "correct": false + }, + { + "word": "sample-word-29", + "correct": false + }, + { + "word": "sample-word-80", + "correct": false + }, + { + "word": "sample-word-47", + "correct": false + }, + { + "word": "sample-word-65", + "correct": false + } + ] + }, + { + "date": "2025-05-27T13:17:04Z", + "sessionId": "nate-2025-05-27-2", + "total": 11, + "correct": 6, + "score": 59, + "words": [ + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-30", + "correct": false + }, + { + "word": "sample-word-50", + "correct": false + }, + { + "word": "sample-word-83", + "correct": false + }, + { + "word": "sample-word-78", + "correct": false + }, + { + "word": "sample-word-59", + "correct": false + } + ] + }, + { + "date": "2025-05-29T14:10:53Z", + "sessionId": "nate-2025-05-29-0", + "total": 7, + "correct": 4, + "score": 61, + "words": [ + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-15", + "correct": false + }, + { + "word": "sample-word-79", + "correct": false + }, + { + "word": "sample-word-86", + "correct": false + } + ] + }, + { + "date": "2025-05-29T11:14:27Z", + "sessionId": "nate-2025-05-29-1", + "total": 14, + "correct": 10, + "score": 69, + "words": [ + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-56", + "correct": false + }, + { + "word": "sample-word-77", + "correct": false + }, + { + "word": "sample-word-21", + "correct": false + }, + { + "word": "sample-word-44", + "correct": false + } + ] + }, + { + "date": "2025-05-30T11:52:28Z", + "sessionId": "nate-2025-05-30-0", + "total": 13, + "correct": 8, + "score": 63, + "words": [ + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-14", + "correct": false + }, + { + "word": "sample-word-50", + "correct": false + }, + { + "word": "sample-word-33", + "correct": false + }, + { + "word": "sample-word-18", + "correct": false + }, + { + "word": "sample-word-58", + "correct": false + } + ] + }, + { + "date": "2025-05-30T14:10:15Z", + "sessionId": "nate-2025-05-30-1", + "total": 15, + "correct": 11, + "score": 71, + "words": [ + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-47", + "correct": false + }, + { + "word": "sample-word-69", + "correct": false + }, + { + "word": "sample-word-1", + "correct": false + }, + { + "word": "sample-word-47", + "correct": false + } + ] + }, + { + "date": "2025-06-02T08:54:47Z", + "sessionId": "nate-2025-06-02-0", + "total": 15, + "correct": 11, + "score": 72, + "words": [ + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-11", + "correct": false + }, + { + "word": "sample-word-26", + "correct": false + }, + { + "word": "sample-word-4", + "correct": false + }, + { + "word": "sample-word-79", + "correct": false + } + ] + }, + { + "date": "2025-06-02T17:53:58Z", + "sessionId": "nate-2025-06-02-1", + "total": 5, + "correct": 4, + "score": 70, + "words": [ + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-21", + "correct": false + } + ] + }, + { + "date": "2025-06-03T13:21:52Z", + "sessionId": "nate-2025-06-03-0", + "total": 14, + "correct": 10, + "score": 70, + "words": [ + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-62", + "correct": false + }, + { + "word": "sample-word-75", + "correct": false + }, + { + "word": "sample-word-40", + "correct": false + }, + { + "word": "sample-word-50", + "correct": false + } + ] + }, + { + "date": "2025-06-03T08:31:48Z", + "sessionId": "nate-2025-06-03-1", + "total": 10, + "correct": 7, + "score": 66, + "words": [ + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-18", + "correct": false + }, + { + "word": "sample-word-24", + "correct": false + }, + { + "word": "sample-word-4", + "correct": false + } + ] + }, + { + "date": "2025-06-03T17:14:12Z", + "sessionId": "nate-2025-06-03-2", + "total": 11, + "correct": 8, + "score": 77, + "words": [ + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-70", + "correct": false + }, + { + "word": "sample-word-43", + "correct": false + }, + { + "word": "sample-word-92", + "correct": false + } + ] + }, + { + "date": "2025-06-04T17:21:25Z", + "sessionId": "nate-2025-06-04-0", + "total": 5, + "correct": 3, + "score": 65, + "words": [ + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-5", + "correct": false + }, + { + "word": "sample-word-40", + "correct": false + } + ] + }, + { + "date": "2025-06-08T20:44:07Z", + "sessionId": "nate-2025-06-08-0", + "total": 10, + "correct": 6, + "score": 61, + "words": [ + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-60", + "correct": false + }, + { + "word": "sample-word-68", + "correct": false + }, + { + "word": "sample-word-38", + "correct": false + }, + { + "word": "sample-word-98", + "correct": false + } + ] + }, + { + "date": "2025-06-10T08:15:18Z", + "sessionId": "nate-2025-06-10-0", + "total": 13, + "correct": 10, + "score": 77, + "words": [ + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-25", + "correct": false + }, + { + "word": "sample-word-93", + "correct": false + }, + { + "word": "sample-word-16", + "correct": false + } + ] + }, + { + "date": "2025-06-10T15:59:56Z", + "sessionId": "nate-2025-06-10-1", + "total": 9, + "correct": 6, + "score": 70, + "words": [ + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-46", + "correct": false + }, + { + "word": "sample-word-47", + "correct": false + }, + { + "word": "sample-word-48", + "correct": false + } + ] + }, + { + "date": "2025-06-17T09:28:10Z", + "sessionId": "nate-2025-06-17-0", + "total": 15, + "correct": 12, + "score": 81, + "words": [ + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-76", + "correct": false + }, + { + "word": "sample-word-57", + "correct": false + }, + { + "word": "sample-word-87", + "correct": false + } + ] + }, + { + "date": "2025-06-18T20:01:12Z", + "sessionId": "nate-2025-06-18-0", + "total": 13, + "correct": 10, + "score": 76, + "words": [ + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-91", + "correct": false + }, + { + "word": "sample-word-53", + "correct": false + }, + { + "word": "sample-word-75", + "correct": false + } + ] + }, + { + "date": "2025-06-19T16:20:33Z", + "sessionId": "nate-2025-06-19-0", + "total": 14, + "correct": 10, + "score": 71, + "words": [ + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-31", + "correct": false + }, + { + "word": "sample-word-79", + "correct": false + }, + { + "word": "sample-word-45", + "correct": false + }, + { + "word": "sample-word-18", + "correct": false + } + ] + }, + { + "date": "2025-06-19T13:38:18Z", + "sessionId": "nate-2025-06-19-1", + "total": 10, + "correct": 6, + "score": 63, + "words": [ + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-82", + "correct": false + }, + { + "word": "sample-word-25", + "correct": false + }, + { + "word": "sample-word-74", + "correct": false + }, + { + "word": "sample-word-96", + "correct": false + } + ] + }, + { + "date": "2025-06-20T19:25:55Z", + "sessionId": "nate-2025-06-20-0", + "total": 11, + "correct": 7, + "score": 67, + "words": [ + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-34", + "correct": false + }, + { + "word": "sample-word-14", + "correct": false + }, + { + "word": "sample-word-36", + "correct": false + }, + { + "word": "sample-word-59", + "correct": false + } + ] + }, + { + "date": "2025-06-20T09:39:43Z", + "sessionId": "nate-2025-06-20-1", + "total": 15, + "correct": 11, + "score": 72, + "words": [ + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-58", + "correct": false + }, + { + "word": "sample-word-64", + "correct": false + }, + { + "word": "sample-word-97", + "correct": false + }, + { + "word": "sample-word-60", + "correct": false + } + ] + }, + { + "date": "2025-06-20T20:46:58Z", + "sessionId": "nate-2025-06-20-2", + "total": 7, + "correct": 5, + "score": 66, + "words": [ + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-35", + "correct": false + }, + { + "word": "sample-word-14", + "correct": false + } + ] + }, + { + "date": "2025-06-21T18:56:41Z", + "sessionId": "nate-2025-06-21-0", + "total": 15, + "correct": 11, + "score": 70, + "words": [ + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-78", + "correct": false + }, + { + "word": "sample-word-14", + "correct": false + }, + { + "word": "sample-word-79", + "correct": false + }, + { + "word": "sample-word-92", + "correct": false + } + ] + }, + { + "date": "2025-06-22T14:44:26Z", + "sessionId": "nate-2025-06-22-0", + "total": 15, + "correct": 12, + "score": 77, + "words": [ + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-30", + "correct": false + }, + { + "word": "sample-word-73", + "correct": false + }, + { + "word": "sample-word-3", + "correct": false + } + ] + }, + { + "date": "2025-06-22T19:20:16Z", + "sessionId": "nate-2025-06-22-1", + "total": 7, + "correct": 5, + "score": 65, + "words": [ + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-47", + "correct": false + }, + { + "word": "sample-word-89", + "correct": false + } + ] + }, + { + "date": "2025-06-22T09:46:26Z", + "sessionId": "nate-2025-06-22-2", + "total": 6, + "correct": 5, + "score": 80, + "words": [ + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-42", + "correct": false + } + ] + }, + { + "date": "2025-06-23T16:11:45Z", + "sessionId": "nate-2025-06-23-0", + "total": 11, + "correct": 7, + "score": 66, + "words": [ + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-29", + "correct": false + }, + { + "word": "sample-word-100", + "correct": false + }, + { + "word": "sample-word-2", + "correct": false + }, + { + "word": "sample-word-34", + "correct": false + } + ] + }, + { + "date": "2025-06-23T08:27:53Z", + "sessionId": "nate-2025-06-23-1", + "total": 13, + "correct": 10, + "score": 74, + "words": [ + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-26", + "correct": false + }, + { + "word": "sample-word-71", + "correct": false + }, + { + "word": "sample-word-21", + "correct": false + } + ] + }, + { + "date": "2025-06-23T16:07:24Z", + "sessionId": "nate-2025-06-23-2", + "total": 6, + "correct": 4, + "score": 75, + "words": [ + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-27", + "correct": false + }, + { + "word": "sample-word-33", + "correct": false + } + ] + }, + { + "date": "2025-06-24T11:14:22Z", + "sessionId": "nate-2025-06-24-0", + "total": 8, + "correct": 7, + "score": 82, + "words": [ + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-37", + "correct": false + } + ] + }, + { + "date": "2025-06-25T14:04:12Z", + "sessionId": "nate-2025-06-25-0", + "total": 15, + "correct": 11, + "score": 71, + "words": [ + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-47", + "correct": false + }, + { + "word": "sample-word-76", + "correct": false + }, + { + "word": "sample-word-5", + "correct": false + }, + { + "word": "sample-word-59", + "correct": false + } + ] + }, + { + "date": "2025-06-25T16:47:46Z", + "sessionId": "nate-2025-06-25-1", + "total": 9, + "correct": 6, + "score": 68, + "words": [ + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-40", + "correct": false + }, + { + "word": "sample-word-88", + "correct": false + }, + { + "word": "sample-word-35", + "correct": false + } + ] + }, + { + "date": "2025-06-25T10:55:39Z", + "sessionId": "nate-2025-06-25-2", + "total": 6, + "correct": 5, + "score": 77, + "words": [ + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-66", + "correct": false + } + ] + }, + { + "date": "2025-06-26T15:08:47Z", + "sessionId": "nate-2025-06-26-0", + "total": 10, + "correct": 8, + "score": 81, + "words": [ + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-82", + "correct": false + }, + { + "word": "sample-word-78", + "correct": false + } + ] + }, + { + "date": "2025-06-26T08:47:20Z", + "sessionId": "nate-2025-06-26-1", + "total": 7, + "correct": 5, + "score": 71, + "words": [ + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-81", + "correct": false + }, + { + "word": "sample-word-6", + "correct": false + } + ] + }, + { + "date": "2025-06-26T15:46:25Z", + "sessionId": "nate-2025-06-26-2", + "total": 12, + "correct": 9, + "score": 78, + "words": [ + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-38", + "correct": false + }, + { + "word": "sample-word-48", + "correct": false + }, + { + "word": "sample-word-93", + "correct": false + } + ] + }, + { + "date": "2025-06-27T19:59:49Z", + "sessionId": "nate-2025-06-27-0", + "total": 12, + "correct": 9, + "score": 74, + "words": [ + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-1", + "correct": false + }, + { + "word": "sample-word-35", + "correct": false + }, + { + "word": "sample-word-16", + "correct": false + } + ] + }, + { + "date": "2025-06-28T11:47:13Z", + "sessionId": "nate-2025-06-28-0", + "total": 7, + "correct": 5, + "score": 68, + "words": [ + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-77", + "correct": false + }, + { + "word": "sample-word-80", + "correct": false + } + ] + }, + { + "date": "2025-06-28T17:44:44Z", + "sessionId": "nate-2025-06-28-1", + "total": 7, + "correct": 6, + "score": 85, + "words": [ + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-97", + "correct": false + } + ] + }, + { + "date": "2025-06-28T17:17:47Z", + "sessionId": "nate-2025-06-28-2", + "total": 14, + "correct": 12, + "score": 84, + "words": [ + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-64", + "correct": false + }, + { + "word": "sample-word-81", + "correct": false + } + ] + }, + { + "date": "2025-06-29T18:11:22Z", + "sessionId": "nate-2025-06-29-0", + "total": 12, + "correct": 10, + "score": 83, + "words": [ + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-85", + "correct": false + }, + { + "word": "sample-word-56", + "correct": false + } + ] + }, + { + "date": "2025-06-30T20:53:54Z", + "sessionId": "nate-2025-06-30-0", + "total": 5, + "correct": 4, + "score": 70, + "words": [ + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-97", + "correct": false + } + ] + }, + { + "date": "2025-06-30T08:15:29Z", + "sessionId": "nate-2025-06-30-1", + "total": 14, + "correct": 10, + "score": 68, + "words": [ + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-65", + "correct": false + }, + { + "word": "sample-word-70", + "correct": false + }, + { + "word": "sample-word-24", + "correct": false + }, + { + "word": "sample-word-66", + "correct": false + } + ] + }, + { + "date": "2025-06-30T14:57:21Z", + "sessionId": "nate-2025-06-30-2", + "total": 9, + "correct": 6, + "score": 68, + "words": [ + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-85", + "correct": false + }, + { + "word": "sample-word-100", + "correct": false + }, + { + "word": "sample-word-76", + "correct": false + } + ] + }, + { + "date": "2025-07-01T20:28:53Z", + "sessionId": "nate-2025-07-01-0", + "total": 14, + "correct": 11, + "score": 75, + "words": [ + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-26", + "correct": false + }, + { + "word": "sample-word-43", + "correct": false + }, + { + "word": "sample-word-26", + "correct": false + } + ] + }, + { + "date": "2025-07-01T09:12:32Z", + "sessionId": "nate-2025-07-01-1", + "total": 11, + "correct": 8, + "score": 70, + "words": [ + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-71", + "correct": false + }, + { + "word": "sample-word-26", + "correct": false + }, + { + "word": "sample-word-21", + "correct": false + } + ] + }, + { + "date": "2025-07-01T08:31:01Z", + "sessionId": "nate-2025-07-01-2", + "total": 14, + "correct": 10, + "score": 74, + "words": [ + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-98", + "correct": false + }, + { + "word": "sample-word-51", + "correct": false + }, + { + "word": "sample-word-19", + "correct": false + }, + { + "word": "sample-word-35", + "correct": false + } + ] + }, + { + "date": "2025-07-02T15:46:48Z", + "sessionId": "nate-2025-07-02-0", + "total": 13, + "correct": 9, + "score": 69, + "words": [ + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-74", + "correct": false + }, + { + "word": "sample-word-77", + "correct": false + }, + { + "word": "sample-word-67", + "correct": false + }, + { + "word": "sample-word-6", + "correct": false + } + ] + }, + { + "date": "2025-07-02T20:25:25Z", + "sessionId": "nate-2025-07-02-1", + "total": 6, + "correct": 4, + "score": 69, + "words": [ + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-37", + "correct": false + }, + { + "word": "sample-word-74", + "correct": false + } + ] + }, + { + "date": "2025-07-02T16:29:55Z", + "sessionId": "nate-2025-07-02-2", + "total": 13, + "correct": 10, + "score": 75, + "words": [ + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-79", + "correct": false + }, + { + "word": "sample-word-53", + "correct": false + }, + { + "word": "sample-word-33", + "correct": false + } + ] + }, + { + "date": "2025-07-03T17:08:54Z", + "sessionId": "nate-2025-07-03-0", + "total": 15, + "correct": 12, + "score": 77, + "words": [ + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-17", + "correct": false + }, + { + "word": "sample-word-39", + "correct": false + }, + { + "word": "sample-word-83", + "correct": false + } + ] + }, + { + "date": "2025-07-04T11:02:35Z", + "sessionId": "nate-2025-07-04-0", + "total": 8, + "correct": 7, + "score": 83, + "words": [ + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-62", + "correct": false + } + ] + }, + { + "date": "2025-07-04T20:40:55Z", + "sessionId": "nate-2025-07-04-1", + "total": 13, + "correct": 9, + "score": 71, + "words": [ + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-94", + "correct": false + }, + { + "word": "sample-word-79", + "correct": false + }, + { + "word": "sample-word-81", + "correct": false + }, + { + "word": "sample-word-69", + "correct": false + } + ] + }, + { + "date": "2025-07-07T16:49:37Z", + "sessionId": "nate-2025-07-07-0", + "total": 8, + "correct": 6, + "score": 76, + "words": [ + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-10", + "correct": false + }, + { + "word": "sample-word-39", + "correct": false + } + ] + }, + { + "date": "2025-07-07T18:40:08Z", + "sessionId": "nate-2025-07-07-1", + "total": 13, + "correct": 11, + "score": 85, + "words": [ + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-72", + "correct": false + }, + { + "word": "sample-word-37", + "correct": false + } + ] + }, + { + "date": "2025-07-08T13:05:41Z", + "sessionId": "nate-2025-07-08-0", + "total": 9, + "correct": 8, + "score": 84, + "words": [ + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-69", + "correct": false + } + ] + }, + { + "date": "2025-07-08T19:32:57Z", + "sessionId": "nate-2025-07-08-1", + "total": 11, + "correct": 9, + "score": 85, + "words": [ + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-68", + "correct": false + }, + { + "word": "sample-word-95", + "correct": false + } + ] + }, + { + "date": "2025-07-09T09:22:54Z", + "sessionId": "nate-2025-07-09-0", + "total": 15, + "correct": 12, + "score": 82, + "words": [ + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-19", + "correct": false + }, + { + "word": "sample-word-65", + "correct": false + }, + { + "word": "sample-word-80", + "correct": false + } + ] + }, + { + "date": "2025-07-11T10:46:37Z", + "sessionId": "nate-2025-07-11-0", + "total": 8, + "correct": 7, + "score": 84, + "words": [ + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-87", + "correct": false + } + ] + }, + { + "date": "2025-07-11T15:46:08Z", + "sessionId": "nate-2025-07-11-1", + "total": 7, + "correct": 5, + "score": 76, + "words": [ + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-4", + "correct": false + }, + { + "word": "sample-word-95", + "correct": false + } + ] + }, + { + "date": "2025-07-12T08:02:20Z", + "sessionId": "nate-2025-07-12-0", + "total": 14, + "correct": 12, + "score": 87, + "words": [ + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-81", + "correct": false + }, + { + "word": "sample-word-84", + "correct": false + } + ] + }, + { + "date": "2025-07-16T20:23:25Z", + "sessionId": "nate-2025-07-16-0", + "total": 9, + "correct": 8, + "score": 84, + "words": [ + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-98", + "correct": false + } + ] + }, + { + "date": "2025-07-17T14:36:18Z", + "sessionId": "nate-2025-07-17-0", + "total": 15, + "correct": 12, + "score": 82, + "words": [ + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-43", + "correct": false + }, + { + "word": "sample-word-84", + "correct": false + }, + { + "word": "sample-word-100", + "correct": false + } + ] + }, + { + "date": "2025-07-18T18:43:54Z", + "sessionId": "nate-2025-07-18-0", + "total": 7, + "correct": 6, + "score": 79, + "words": [ + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-7", + "correct": false + } + ] + }, + { + "date": "2025-07-19T17:54:51Z", + "sessionId": "nate-2025-07-19-0", + "total": 14, + "correct": 10, + "score": 74, + "words": [ + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-35", + "correct": false + }, + { + "word": "sample-word-54", + "correct": false + }, + { + "word": "sample-word-34", + "correct": false + }, + { + "word": "sample-word-6", + "correct": false + } + ] + }, + { + "date": "2025-07-19T13:47:16Z", + "sessionId": "nate-2025-07-19-1", + "total": 6, + "correct": 4, + "score": 70, + "words": [ + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-67", + "correct": false + }, + { + "word": "sample-word-50", + "correct": false + } + ] + }, + { + "date": "2025-07-20T09:53:58Z", + "sessionId": "nate-2025-07-20-0", + "total": 15, + "correct": 12, + "score": 80, + "words": [ + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-75", + "correct": false + }, + { + "word": "sample-word-93", + "correct": false + }, + { + "word": "sample-word-75", + "correct": false + } + ] + }, + { + "date": "2025-07-21T20:35:49Z", + "sessionId": "nate-2025-07-21-0", + "total": 8, + "correct": 6, + "score": 70, + "words": [ + { + "word": "sample-word-91", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-93", + "correct": false + }, + { + "word": "sample-word-16", + "correct": false + } + ] + }, + { + "date": "2025-07-21T09:31:35Z", + "sessionId": "nate-2025-07-21-1", + "total": 10, + "correct": 8, + "score": 83, + "words": [ + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-46", + "correct": false + }, + { + "word": "sample-word-88", + "correct": false + } + ] + }, + { + "date": "2025-07-21T14:29:56Z", + "sessionId": "nate-2025-07-21-2", + "total": 11, + "correct": 10, + "score": 87, + "words": [ + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-51", + "correct": false + } + ] + }, + { + "date": "2025-07-22T16:09:14Z", + "sessionId": "nate-2025-07-22-0", + "total": 8, + "correct": 7, + "score": 89, + "words": [ + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-59", + "correct": false + } + ] + }, + { + "date": "2025-07-23T15:19:23Z", + "sessionId": "nate-2025-07-23-0", + "total": 7, + "correct": 6, + "score": 88, + "words": [ + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-30", + "correct": false + } + ] + }, + { + "date": "2025-07-24T11:46:51Z", + "sessionId": "nate-2025-07-24-0", + "total": 7, + "correct": 5, + "score": 75, + "words": [ + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-46", + "correct": false + }, + { + "word": "sample-word-67", + "correct": false + } + ] + }, + { + "date": "2025-07-25T14:13:52Z", + "sessionId": "nate-2025-07-25-0", + "total": 8, + "correct": 7, + "score": 83, + "words": [ + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-18", + "correct": false + } + ] + }, + { + "date": "2025-07-25T13:23:59Z", + "sessionId": "nate-2025-07-25-1", + "total": 13, + "correct": 10, + "score": 76, + "words": [ + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-84", + "correct": false + }, + { + "word": "sample-word-51", + "correct": false + }, + { + "word": "sample-word-84", + "correct": false + } + ] + }, + { + "date": "2025-07-27T17:08:41Z", + "sessionId": "nate-2025-07-27-0", + "total": 11, + "correct": 8, + "score": 76, + "words": [ + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-60", + "correct": false + }, + { + "word": "sample-word-33", + "correct": false + }, + { + "word": "sample-word-70", + "correct": false + } + ] + }, + { + "date": "2025-07-27T14:10:30Z", + "sessionId": "nate-2025-07-27-1", + "total": 10, + "correct": 8, + "score": 83, + "words": [ + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-41", + "correct": false + }, + { + "word": "sample-word-83", + "correct": false + } + ] + }, + { + "date": "2025-07-27T09:04:35Z", + "sessionId": "nate-2025-07-27-2", + "total": 13, + "correct": 11, + "score": 83, + "words": [ + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-70", + "correct": false + }, + { + "word": "sample-word-12", + "correct": false + } + ] + }, + { + "date": "2025-07-28T17:38:42Z", + "sessionId": "nate-2025-07-28-0", + "total": 8, + "correct": 6, + "score": 76, + "words": [ + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-24", + "correct": false + }, + { + "word": "sample-word-27", + "correct": false + } + ] + }, + { + "date": "2025-07-28T16:24:53Z", + "sessionId": "nate-2025-07-28-1", + "total": 10, + "correct": 8, + "score": 83, + "words": [ + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-66", + "correct": false + }, + { + "word": "sample-word-88", + "correct": false + } + ] + }, + { + "date": "2025-07-29T08:40:46Z", + "sessionId": "nate-2025-07-29-0", + "total": 5, + "correct": 4, + "score": 77, + "words": [ + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-91", + "correct": true + }, + { + "word": "sample-word-67", + "correct": false + } + ] + }, + { + "date": "2025-07-30T14:08:14Z", + "sessionId": "nate-2025-07-30-0", + "total": 12, + "correct": 9, + "score": 74, + "words": [ + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-20", + "correct": false + }, + { + "word": "sample-word-32", + "correct": false + }, + { + "word": "sample-word-4", + "correct": false + } + ] + }, + { + "date": "2025-07-31T20:24:43Z", + "sessionId": "nate-2025-07-31-0", + "total": 8, + "correct": 6, + "score": 78, + "words": [ + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-19", + "correct": false + }, + { + "word": "sample-word-25", + "correct": false + } + ] + }, + { + "date": "2025-07-31T16:00:39Z", + "sessionId": "nate-2025-07-31-1", + "total": 13, + "correct": 11, + "score": 87, + "words": [ + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-25", + "correct": false + }, + { + "word": "sample-word-35", + "correct": false + } + ] + }, + { + "date": "2025-07-31T17:00:35Z", + "sessionId": "nate-2025-07-31-2", + "total": 12, + "correct": 9, + "score": 75, + "words": [ + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-91", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-64", + "correct": false + }, + { + "word": "sample-word-72", + "correct": false + }, + { + "word": "sample-word-99", + "correct": false + } + ] + }, + { + "date": "2025-08-01T08:37:59Z", + "sessionId": "nate-2025-08-01-0", + "total": 8, + "correct": 7, + "score": 90, + "words": [ + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-25", + "correct": false + } + ] + }, + { + "date": "2025-08-01T13:56:34Z", + "sessionId": "nate-2025-08-01-1", + "total": 10, + "correct": 9, + "score": 85, + "words": [ + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-91", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-76", + "correct": false + } + ] + }, + { + "date": "2025-08-01T15:52:28Z", + "sessionId": "nate-2025-08-01-2", + "total": 14, + "correct": 12, + "score": 84, + "words": [ + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-87", + "correct": false + }, + { + "word": "sample-word-34", + "correct": false + } + ] + }, + { + "date": "2025-08-02T20:54:30Z", + "sessionId": "nate-2025-08-02-0", + "total": 12, + "correct": 9, + "score": 77, + "words": [ + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-21", + "correct": false + }, + { + "word": "sample-word-81", + "correct": false + }, + { + "word": "sample-word-50", + "correct": false + } + ] + }, + { + "date": "2025-08-02T15:31:03Z", + "sessionId": "nate-2025-08-02-1", + "total": 9, + "correct": 8, + "score": 85, + "words": [ + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-50", + "correct": false + } + ] + }, + { + "date": "2025-08-02T15:10:53Z", + "sessionId": "nate-2025-08-02-2", + "total": 11, + "correct": 9, + "score": 79, + "words": [ + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-29", + "correct": false + }, + { + "word": "sample-word-68", + "correct": false + } + ] + }, + { + "date": "2025-08-03T12:59:01Z", + "sessionId": "nate-2025-08-03-0", + "total": 9, + "correct": 8, + "score": 89, + "words": [ + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-66", + "correct": false + } + ] + }, + { + "date": "2025-08-03T19:32:08Z", + "sessionId": "nate-2025-08-03-1", + "total": 5, + "correct": 4, + "score": 83, + "words": [ + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-60", + "correct": false + } + ] + }, + { + "date": "2025-08-04T15:00:15Z", + "sessionId": "nate-2025-08-04-0", + "total": 14, + "correct": 13, + "score": 91, + "words": [ + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-91", + "correct": false + } + ] + }, + { + "date": "2025-08-04T14:22:05Z", + "sessionId": "nate-2025-08-04-1", + "total": 13, + "correct": 12, + "score": 90, + "words": [ + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-67", + "correct": false + } + ] + }, + { + "date": "2025-08-04T11:52:47Z", + "sessionId": "nate-2025-08-04-2", + "total": 7, + "correct": 6, + "score": 90, + "words": [ + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-91", + "correct": false + } + ] + }, + { + "date": "2025-08-05T17:52:50Z", + "sessionId": "nate-2025-08-05-0", + "total": 5, + "correct": 4, + "score": 84, + "words": [ + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-41", + "correct": false + } + ] + }, + { + "date": "2025-08-05T14:35:09Z", + "sessionId": "nate-2025-08-05-1", + "total": 5, + "correct": 4, + "score": 78, + "words": [ + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-16", + "correct": false + } + ] + }, + { + "date": "2025-08-05T16:29:19Z", + "sessionId": "nate-2025-08-05-2", + "total": 14, + "correct": 11, + "score": 79, + "words": [ + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-50", + "correct": false + }, + { + "word": "sample-word-57", + "correct": false + }, + { + "word": "sample-word-91", + "correct": false + } + ] + }, + { + "date": "2025-08-06T13:24:50Z", + "sessionId": "nate-2025-08-06-0", + "total": 10, + "correct": 8, + "score": 81, + "words": [ + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-91", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-4", + "correct": false + }, + { + "word": "sample-word-49", + "correct": false + } + ] + }, + { + "date": "2025-08-06T15:16:53Z", + "sessionId": "nate-2025-08-06-1", + "total": 13, + "correct": 11, + "score": 87, + "words": [ + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-99", + "correct": false + }, + { + "word": "sample-word-49", + "correct": false + } + ] + }, + { + "date": "2025-08-07T15:05:10Z", + "sessionId": "nate-2025-08-07-0", + "total": 12, + "correct": 9, + "score": 78, + "words": [ + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-75", + "correct": false + }, + { + "word": "sample-word-92", + "correct": false + }, + { + "word": "sample-word-7", + "correct": false + } + ] + }, + { + "date": "2025-08-07T14:07:45Z", + "sessionId": "nate-2025-08-07-1", + "total": 5, + "correct": 5, + "score": 91, + "words": [ + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + } + ] + }, + { + "date": "2025-08-08T15:34:32Z", + "sessionId": "nate-2025-08-08-0", + "total": 8, + "correct": 6, + "score": 77, + "words": [ + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-31", + "correct": false + }, + { + "word": "sample-word-13", + "correct": false + } + ] + }, + { + "date": "2025-08-08T09:20:15Z", + "sessionId": "nate-2025-08-08-1", + "total": 13, + "correct": 10, + "score": 78, + "words": [ + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-18", + "correct": false + }, + { + "word": "sample-word-95", + "correct": false + }, + { + "word": "sample-word-8", + "correct": false + } + ] + }, + { + "date": "2025-08-09T13:42:00Z", + "sessionId": "nate-2025-08-09-0", + "total": 11, + "correct": 9, + "score": 85, + "words": [ + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-67", + "correct": false + }, + { + "word": "sample-word-16", + "correct": false + } + ] + }, + { + "date": "2025-08-10T19:46:20Z", + "sessionId": "nate-2025-08-10-0", + "total": 14, + "correct": 12, + "score": 85, + "words": [ + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-75", + "correct": false + }, + { + "word": "sample-word-2", + "correct": false + } + ] + }, + { + "date": "2025-08-10T20:21:03Z", + "sessionId": "nate-2025-08-10-1", + "total": 7, + "correct": 6, + "score": 89, + "words": [ + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-3", + "correct": false + } + ] + }, + { + "date": "2025-08-10T11:06:21Z", + "sessionId": "nate-2025-08-10-2", + "total": 11, + "correct": 9, + "score": 80, + "words": [ + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-67", + "correct": false + }, + { + "word": "sample-word-59", + "correct": false + } + ] + }, + { + "date": "2025-08-11T15:52:19Z", + "sessionId": "nate-2025-08-11-0", + "total": 9, + "correct": 7, + "score": 81, + "words": [ + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-92", + "correct": false + }, + { + "word": "sample-word-45", + "correct": false + } + ] + }, + { + "date": "2025-08-12T13:18:09Z", + "sessionId": "nate-2025-08-12-0", + "total": 10, + "correct": 8, + "score": 85, + "words": [ + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-13", + "correct": false + }, + { + "word": "sample-word-47", + "correct": false + } + ] + }, + { + "date": "2025-08-12T09:38:46Z", + "sessionId": "nate-2025-08-12-1", + "total": 10, + "correct": 8, + "score": 80, + "words": [ + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-71", + "correct": false + }, + { + "word": "sample-word-93", + "correct": false + } + ] + }, + { + "date": "2025-08-13T14:54:07Z", + "sessionId": "nate-2025-08-13-0", + "total": 13, + "correct": 11, + "score": 86, + "words": [ + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-22", + "correct": false + }, + { + "word": "sample-word-36", + "correct": false + } + ] + }, + { + "date": "2025-08-13T09:16:29Z", + "sessionId": "nate-2025-08-13-1", + "total": 12, + "correct": 10, + "score": 87, + "words": [ + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-81", + "correct": false + }, + { + "word": "sample-word-12", + "correct": false + } + ] + }, + { + "date": "2025-08-13T16:22:08Z", + "sessionId": "nate-2025-08-13-2", + "total": 9, + "correct": 8, + "score": 86, + "words": [ + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-21", + "correct": false + } + ] } ], - "admin1": [], - "testuser": [] + "admin1": [ + { + "date": "2025-05-22T11:09:17Z", + "sessionId": "admin1-2025-05-22-0", + "total": 11, + "correct": 7, + "score": 66, + "words": [ + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-91", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-19", + "correct": false + }, + { + "word": "sample-word-93", + "correct": false + }, + { + "word": "sample-word-97", + "correct": false + }, + { + "word": "sample-word-99", + "correct": false + } + ] + }, + { + "date": "2025-05-22T14:28:40Z", + "sessionId": "admin1-2025-05-22-1", + "total": 13, + "correct": 8, + "score": 65, + "words": [ + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-70", + "correct": false + }, + { + "word": "sample-word-30", + "correct": false + }, + { + "word": "sample-word-76", + "correct": false + }, + { + "word": "sample-word-84", + "correct": false + }, + { + "word": "sample-word-95", + "correct": false + } + ] + }, + { + "date": "2025-05-23T14:53:34Z", + "sessionId": "admin1-2025-05-23-0", + "total": 12, + "correct": 7, + "score": 60, + "words": [ + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-25", + "correct": false + }, + { + "word": "sample-word-56", + "correct": false + }, + { + "word": "sample-word-60", + "correct": false + }, + { + "word": "sample-word-39", + "correct": false + }, + { + "word": "sample-word-60", + "correct": false + } + ] + }, + { + "date": "2025-05-26T18:31:31Z", + "sessionId": "admin1-2025-05-26-0", + "total": 8, + "correct": 5, + "score": 61, + "words": [ + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-87", + "correct": false + }, + { + "word": "sample-word-11", + "correct": false + }, + { + "word": "sample-word-29", + "correct": false + } + ] + }, + { + "date": "2025-05-26T19:52:43Z", + "sessionId": "admin1-2025-05-26-1", + "total": 7, + "correct": 5, + "score": 68, + "words": [ + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-44", + "correct": false + }, + { + "word": "sample-word-61", + "correct": false + } + ] + }, + { + "date": "2025-05-27T10:04:14Z", + "sessionId": "admin1-2025-05-27-0", + "total": 14, + "correct": 10, + "score": 74, + "words": [ + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-59", + "correct": false + }, + { + "word": "sample-word-66", + "correct": false + }, + { + "word": "sample-word-5", + "correct": false + }, + { + "word": "sample-word-65", + "correct": false + } + ] + }, + { + "date": "2025-05-27T11:14:14Z", + "sessionId": "admin1-2025-05-27-1", + "total": 8, + "correct": 6, + "score": 70, + "words": [ + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-7", + "correct": false + }, + { + "word": "sample-word-50", + "correct": false + } + ] + }, + { + "date": "2025-05-31T17:12:27Z", + "sessionId": "admin1-2025-05-31-0", + "total": 11, + "correct": 7, + "score": 63, + "words": [ + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-91", + "correct": false + }, + { + "word": "sample-word-40", + "correct": false + }, + { + "word": "sample-word-100", + "correct": false + }, + { + "word": "sample-word-32", + "correct": false + } + ] + }, + { + "date": "2025-05-31T08:48:13Z", + "sessionId": "admin1-2025-05-31-1", + "total": 8, + "correct": 6, + "score": 70, + "words": [ + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-36", + "correct": false + }, + { + "word": "sample-word-88", + "correct": false + } + ] + }, + { + "date": "2025-06-01T20:59:57Z", + "sessionId": "admin1-2025-06-01-0", + "total": 15, + "correct": 10, + "score": 64, + "words": [ + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-72", + "correct": false + }, + { + "word": "sample-word-65", + "correct": false + }, + { + "word": "sample-word-61", + "correct": false + }, + { + "word": "sample-word-72", + "correct": false + }, + { + "word": "sample-word-39", + "correct": false + } + ] + }, + { + "date": "2025-06-03T14:38:09Z", + "sessionId": "admin1-2025-06-03-0", + "total": 8, + "correct": 5, + "score": 63, + "words": [ + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-5", + "correct": false + }, + { + "word": "sample-word-8", + "correct": false + }, + { + "word": "sample-word-23", + "correct": false + } + ] + }, + { + "date": "2025-06-05T08:20:15Z", + "sessionId": "admin1-2025-06-05-0", + "total": 6, + "correct": 5, + "score": 78, + "words": [ + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-4", + "correct": false + } + ] + }, + { + "date": "2025-06-07T12:58:34Z", + "sessionId": "admin1-2025-06-07-0", + "total": 6, + "correct": 4, + "score": 61, + "words": [ + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-85", + "correct": false + }, + { + "word": "sample-word-5", + "correct": false + } + ] + }, + { + "date": "2025-06-16T10:29:40Z", + "sessionId": "admin1-2025-06-16-0", + "total": 5, + "correct": 4, + "score": 80, + "words": [ + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-97", + "correct": false + } + ] + }, + { + "date": "2025-06-16T12:40:35Z", + "sessionId": "admin1-2025-06-16-1", + "total": 5, + "correct": 4, + "score": 72, + "words": [ + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-89", + "correct": false + } + ] + }, + { + "date": "2025-06-17T11:17:39Z", + "sessionId": "admin1-2025-06-17-0", + "total": 14, + "correct": 11, + "score": 79, + "words": [ + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-35", + "correct": false + }, + { + "word": "sample-word-62", + "correct": false + }, + { + "word": "sample-word-24", + "correct": false + } + ] + }, + { + "date": "2025-06-17T09:26:53Z", + "sessionId": "admin1-2025-06-17-1", + "total": 8, + "correct": 5, + "score": 67, + "words": [ + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-29", + "correct": false + }, + { + "word": "sample-word-40", + "correct": false + }, + { + "word": "sample-word-12", + "correct": false + } + ] + }, + { + "date": "2025-06-19T19:21:46Z", + "sessionId": "admin1-2025-06-19-0", + "total": 7, + "correct": 5, + "score": 75, + "words": [ + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-54", + "correct": false + }, + { + "word": "sample-word-44", + "correct": false + } + ] + }, + { + "date": "2025-06-19T09:41:43Z", + "sessionId": "admin1-2025-06-19-1", + "total": 6, + "correct": 4, + "score": 74, + "words": [ + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-91", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-26", + "correct": false + }, + { + "word": "sample-word-48", + "correct": false + } + ] + }, + { + "date": "2025-06-20T10:25:08Z", + "sessionId": "admin1-2025-06-20-0", + "total": 12, + "correct": 10, + "score": 82, + "words": [ + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-99", + "correct": false + }, + { + "word": "sample-word-20", + "correct": false + } + ] + }, + { + "date": "2025-06-21T20:03:55Z", + "sessionId": "admin1-2025-06-21-0", + "total": 13, + "correct": 11, + "score": 81, + "words": [ + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-57", + "correct": false + }, + { + "word": "sample-word-88", + "correct": false + } + ] + }, + { + "date": "2025-06-23T19:24:59Z", + "sessionId": "admin1-2025-06-23-0", + "total": 10, + "correct": 8, + "score": 76, + "words": [ + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-17", + "correct": false + }, + { + "word": "sample-word-77", + "correct": false + } + ] + }, + { + "date": "2025-06-24T09:48:09Z", + "sessionId": "admin1-2025-06-24-0", + "total": 14, + "correct": 9, + "score": 64, + "words": [ + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-69", + "correct": false + }, + { + "word": "sample-word-68", + "correct": false + }, + { + "word": "sample-word-10", + "correct": false + }, + { + "word": "sample-word-2", + "correct": false + }, + { + "word": "sample-word-95", + "correct": false + } + ] + }, + { + "date": "2025-06-24T09:54:33Z", + "sessionId": "admin1-2025-06-24-1", + "total": 10, + "correct": 8, + "score": 80, + "words": [ + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-81", + "correct": false + }, + { + "word": "sample-word-93", + "correct": false + } + ] + }, + { + "date": "2025-06-25T08:45:08Z", + "sessionId": "admin1-2025-06-25-0", + "total": 12, + "correct": 9, + "score": 75, + "words": [ + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-54", + "correct": false + }, + { + "word": "sample-word-92", + "correct": false + }, + { + "word": "sample-word-100", + "correct": false + } + ] + }, + { + "date": "2025-06-26T11:25:06Z", + "sessionId": "admin1-2025-06-26-0", + "total": 8, + "correct": 5, + "score": 68, + "words": [ + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-88", + "correct": false + }, + { + "word": "sample-word-79", + "correct": false + }, + { + "word": "sample-word-83", + "correct": false + } + ] + }, + { + "date": "2025-06-27T16:14:54Z", + "sessionId": "admin1-2025-06-27-0", + "total": 12, + "correct": 9, + "score": 72, + "words": [ + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-3", + "correct": false + }, + { + "word": "sample-word-91", + "correct": false + }, + { + "word": "sample-word-4", + "correct": false + } + ] + }, + { + "date": "2025-06-27T15:38:00Z", + "sessionId": "admin1-2025-06-27-1", + "total": 11, + "correct": 8, + "score": 70, + "words": [ + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-13", + "correct": false + }, + { + "word": "sample-word-42", + "correct": false + }, + { + "word": "sample-word-2", + "correct": false + } + ] + }, + { + "date": "2025-06-28T17:16:01Z", + "sessionId": "admin1-2025-06-28-0", + "total": 14, + "correct": 10, + "score": 73, + "words": [ + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-18", + "correct": false + }, + { + "word": "sample-word-20", + "correct": false + }, + { + "word": "sample-word-32", + "correct": false + }, + { + "word": "sample-word-52", + "correct": false + } + ] + }, + { + "date": "2025-06-28T15:41:29Z", + "sessionId": "admin1-2025-06-28-1", + "total": 7, + "correct": 5, + "score": 70, + "words": [ + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-80", + "correct": false + }, + { + "word": "sample-word-22", + "correct": false + } + ] + }, + { + "date": "2025-07-03T11:55:36Z", + "sessionId": "admin1-2025-07-03-0", + "total": 15, + "correct": 10, + "score": 70, + "words": [ + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-5", + "correct": false + }, + { + "word": "sample-word-72", + "correct": false + }, + { + "word": "sample-word-24", + "correct": false + }, + { + "word": "sample-word-76", + "correct": false + }, + { + "word": "sample-word-19", + "correct": false + } + ] + }, + { + "date": "2025-07-03T19:32:50Z", + "sessionId": "admin1-2025-07-03-1", + "total": 11, + "correct": 8, + "score": 74, + "words": [ + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-78", + "correct": false + }, + { + "word": "sample-word-58", + "correct": false + }, + { + "word": "sample-word-42", + "correct": false + } + ] + }, + { + "date": "2025-07-04T10:47:23Z", + "sessionId": "admin1-2025-07-04-0", + "total": 13, + "correct": 9, + "score": 72, + "words": [ + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-88", + "correct": false + }, + { + "word": "sample-word-91", + "correct": false + }, + { + "word": "sample-word-57", + "correct": false + }, + { + "word": "sample-word-1", + "correct": false + } + ] + }, + { + "date": "2025-07-04T13:41:48Z", + "sessionId": "admin1-2025-07-04-1", + "total": 9, + "correct": 8, + "score": 84, + "words": [ + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-28", + "correct": false + } + ] + }, + { + "date": "2025-07-05T15:16:05Z", + "sessionId": "admin1-2025-07-05-0", + "total": 13, + "correct": 10, + "score": 80, + "words": [ + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-15", + "correct": false + }, + { + "word": "sample-word-80", + "correct": false + }, + { + "word": "sample-word-20", + "correct": false + } + ] + }, + { + "date": "2025-07-07T12:02:29Z", + "sessionId": "admin1-2025-07-07-0", + "total": 6, + "correct": 4, + "score": 74, + "words": [ + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-91", + "correct": true + }, + { + "word": "sample-word-26", + "correct": false + }, + { + "word": "sample-word-24", + "correct": false + } + ] + }, + { + "date": "2025-07-13T13:38:50Z", + "sessionId": "admin1-2025-07-13-0", + "total": 10, + "correct": 9, + "score": 86, + "words": [ + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-58", + "correct": false + } + ] + }, + { + "date": "2025-07-15T09:49:57Z", + "sessionId": "admin1-2025-07-15-0", + "total": 10, + "correct": 9, + "score": 88, + "words": [ + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-91", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-63", + "correct": false + } + ] + }, + { + "date": "2025-07-15T19:12:22Z", + "sessionId": "admin1-2025-07-15-1", + "total": 8, + "correct": 6, + "score": 81, + "words": [ + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-13", + "correct": false + }, + { + "word": "sample-word-100", + "correct": false + } + ] + }, + { + "date": "2025-07-16T11:02:28Z", + "sessionId": "admin1-2025-07-16-0", + "total": 10, + "correct": 8, + "score": 80, + "words": [ + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-86", + "correct": false + }, + { + "word": "sample-word-26", + "correct": false + } + ] + }, + { + "date": "2025-07-17T08:57:53Z", + "sessionId": "admin1-2025-07-17-0", + "total": 6, + "correct": 5, + "score": 79, + "words": [ + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-23", + "correct": false + } + ] + }, + { + "date": "2025-07-18T20:54:57Z", + "sessionId": "admin1-2025-07-18-0", + "total": 9, + "correct": 7, + "score": 82, + "words": [ + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-16", + "correct": false + }, + { + "word": "sample-word-40", + "correct": false + } + ] + }, + { + "date": "2025-07-20T13:06:12Z", + "sessionId": "admin1-2025-07-20-0", + "total": 15, + "correct": 11, + "score": 75, + "words": [ + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-77", + "correct": false + }, + { + "word": "sample-word-76", + "correct": false + }, + { + "word": "sample-word-84", + "correct": false + }, + { + "word": "sample-word-18", + "correct": false + } + ] + }, + { + "date": "2025-07-21T08:24:01Z", + "sessionId": "admin1-2025-07-21-0", + "total": 7, + "correct": 6, + "score": 83, + "words": [ + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-34", + "correct": false + } + ] + }, + { + "date": "2025-07-21T08:02:27Z", + "sessionId": "admin1-2025-07-21-1", + "total": 9, + "correct": 7, + "score": 77, + "words": [ + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-36", + "correct": false + }, + { + "word": "sample-word-78", + "correct": false + } + ] + }, + { + "date": "2025-07-23T15:01:38Z", + "sessionId": "admin1-2025-07-23-0", + "total": 9, + "correct": 8, + "score": 87, + "words": [ + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-14", + "correct": false + } + ] + }, + { + "date": "2025-07-24T15:50:04Z", + "sessionId": "admin1-2025-07-24-0", + "total": 11, + "correct": 8, + "score": 75, + "words": [ + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-61", + "correct": false + }, + { + "word": "sample-word-77", + "correct": false + }, + { + "word": "sample-word-24", + "correct": false + } + ] + }, + { + "date": "2025-07-25T14:36:35Z", + "sessionId": "admin1-2025-07-25-0", + "total": 7, + "correct": 6, + "score": 89, + "words": [ + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-52", + "correct": false + } + ] + }, + { + "date": "2025-07-28T16:20:55Z", + "sessionId": "admin1-2025-07-28-0", + "total": 12, + "correct": 10, + "score": 81, + "words": [ + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-30", + "correct": false + }, + { + "word": "sample-word-46", + "correct": false + } + ] + }, + { + "date": "2025-07-29T12:51:05Z", + "sessionId": "admin1-2025-07-29-0", + "total": 10, + "correct": 8, + "score": 83, + "words": [ + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-82", + "correct": false + }, + { + "word": "sample-word-89", + "correct": false + } + ] + }, + { + "date": "2025-07-29T20:48:23Z", + "sessionId": "admin1-2025-07-29-1", + "total": 9, + "correct": 7, + "score": 75, + "words": [ + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-97", + "correct": false + }, + { + "word": "sample-word-95", + "correct": false + } + ] + }, + { + "date": "2025-07-30T11:42:11Z", + "sessionId": "admin1-2025-07-30-0", + "total": 5, + "correct": 4, + "score": 74, + "words": [ + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-78", + "correct": false + } + ] + }, + { + "date": "2025-07-30T19:43:24Z", + "sessionId": "admin1-2025-07-30-1", + "total": 14, + "correct": 11, + "score": 78, + "words": [ + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-80", + "correct": false + }, + { + "word": "sample-word-42", + "correct": false + }, + { + "word": "sample-word-63", + "correct": false + } + ] + }, + { + "date": "2025-07-31T13:10:40Z", + "sessionId": "admin1-2025-07-31-0", + "total": 8, + "correct": 6, + "score": 81, + "words": [ + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-75", + "correct": false + }, + { + "word": "sample-word-72", + "correct": false + } + ] + }, + { + "date": "2025-07-31T18:36:48Z", + "sessionId": "admin1-2025-07-31-1", + "total": 12, + "correct": 11, + "score": 91, + "words": [ + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-14", + "correct": false + } + ] + }, + { + "date": "2025-08-01T17:17:26Z", + "sessionId": "admin1-2025-08-01-0", + "total": 13, + "correct": 10, + "score": 76, + "words": [ + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-74", + "correct": false + }, + { + "word": "sample-word-27", + "correct": false + }, + { + "word": "sample-word-99", + "correct": false + } + ] + }, + { + "date": "2025-08-02T18:46:07Z", + "sessionId": "admin1-2025-08-02-0", + "total": 8, + "correct": 6, + "score": 78, + "words": [ + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-30", + "correct": false + }, + { + "word": "sample-word-15", + "correct": false + } + ] + }, + { + "date": "2025-08-02T13:11:43Z", + "sessionId": "admin1-2025-08-02-1", + "total": 5, + "correct": 4, + "score": 80, + "words": [ + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-40", + "correct": false + } + ] + }, + { + "date": "2025-08-04T13:11:43Z", + "sessionId": "admin1-2025-08-04-0", + "total": 10, + "correct": 8, + "score": 75, + "words": [ + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-6", + "correct": false + }, + { + "word": "sample-word-8", + "correct": false + } + ] + }, + { + "date": "2025-08-05T18:18:44Z", + "sessionId": "admin1-2025-08-05-0", + "total": 15, + "correct": 14, + "score": 90, + "words": [ + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-56", + "correct": false + } + ] + }, + { + "date": "2025-08-05T20:39:19Z", + "sessionId": "admin1-2025-08-05-1", + "total": 10, + "correct": 9, + "score": 91, + "words": [ + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-52", + "correct": false + } + ] + }, + { + "date": "2025-08-06T09:34:30Z", + "sessionId": "admin1-2025-08-06-0", + "total": 12, + "correct": 9, + "score": 74, + "words": [ + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-1", + "correct": false + }, + { + "word": "sample-word-54", + "correct": false + }, + { + "word": "sample-word-89", + "correct": false + } + ] + }, + { + "date": "2025-08-07T18:02:20Z", + "sessionId": "admin1-2025-08-07-0", + "total": 12, + "correct": 11, + "score": 89, + "words": [ + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-46", + "correct": false + } + ] + }, + { + "date": "2025-08-07T13:03:16Z", + "sessionId": "admin1-2025-08-07-1", + "total": 7, + "correct": 6, + "score": 79, + "words": [ + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-99", + "correct": false + } + ] + }, + { + "date": "2025-08-08T19:21:47Z", + "sessionId": "admin1-2025-08-08-0", + "total": 6, + "correct": 5, + "score": 91, + "words": [ + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-22", + "correct": false + } + ] + }, + { + "date": "2025-08-10T13:43:37Z", + "sessionId": "admin1-2025-08-10-0", + "total": 9, + "correct": 7, + "score": 79, + "words": [ + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-9", + "correct": false + }, + { + "word": "sample-word-92", + "correct": false + } + ] + }, + { + "date": "2025-08-10T16:41:44Z", + "sessionId": "admin1-2025-08-10-1", + "total": 6, + "correct": 6, + "score": 93, + "words": [ + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + } + ] + }, + { + "date": "2025-08-11T16:38:03Z", + "sessionId": "admin1-2025-08-11-0", + "total": 9, + "correct": 7, + "score": 82, + "words": [ + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-91", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-16", + "correct": false + }, + { + "word": "sample-word-47", + "correct": false + } + ] + }, + { + "date": "2025-08-11T11:25:28Z", + "sessionId": "admin1-2025-08-11-1", + "total": 8, + "correct": 6, + "score": 76, + "words": [ + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-45", + "correct": false + }, + { + "word": "sample-word-28", + "correct": false + } + ] + }, + { + "date": "2025-08-12T12:49:28Z", + "sessionId": "admin1-2025-08-12-0", + "total": 8, + "correct": 6, + "score": 76, + "words": [ + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-23", + "correct": false + }, + { + "word": "sample-word-20", + "correct": false + } + ] + }, + { + "date": "2025-08-12T12:54:17Z", + "sessionId": "admin1-2025-08-12-1", + "total": 14, + "correct": 12, + "score": 86, + "words": [ + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-23", + "correct": false + }, + { + "word": "sample-word-12", + "correct": false + } + ] + }, + { + "date": "2025-08-13T08:57:18Z", + "sessionId": "admin1-2025-08-13-0", + "total": 14, + "correct": 13, + "score": 91, + "words": [ + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-46", + "correct": false + } + ] + }, + { + "date": "2025-08-13T14:18:43Z", + "sessionId": "admin1-2025-08-13-1", + "total": 15, + "correct": 13, + "score": 85, + "words": [ + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-93", + "correct": false + }, + { + "word": "sample-word-91", + "correct": false + } + ] + } + ], + "testuser": [ + { + "date": "2025-05-16T09:06:41Z", + "sessionId": "testuser-2025-05-16-0", + "total": 12, + "correct": 9, + "score": 73, + "words": [ + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-16", + "correct": false + }, + { + "word": "sample-word-10", + "correct": false + }, + { + "word": "sample-word-66", + "correct": false + } + ] + }, + { + "date": "2025-05-16T13:25:33Z", + "sessionId": "testuser-2025-05-16-1", + "total": 15, + "correct": 10, + "score": 66, + "words": [ + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-9", + "correct": false + }, + { + "word": "sample-word-8", + "correct": false + }, + { + "word": "sample-word-1", + "correct": false + }, + { + "word": "sample-word-12", + "correct": false + }, + { + "word": "sample-word-46", + "correct": false + } + ] + }, + { + "date": "2025-05-25T16:54:56Z", + "sessionId": "testuser-2025-05-25-0", + "total": 11, + "correct": 8, + "score": 70, + "words": [ + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-25", + "correct": false + }, + { + "word": "sample-word-29", + "correct": false + }, + { + "word": "sample-word-64", + "correct": false + } + ] + }, + { + "date": "2025-05-25T12:34:18Z", + "sessionId": "testuser-2025-05-25-1", + "total": 15, + "correct": 10, + "score": 69, + "words": [ + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-22", + "correct": false + }, + { + "word": "sample-word-85", + "correct": false + }, + { + "word": "sample-word-92", + "correct": false + }, + { + "word": "sample-word-78", + "correct": false + }, + { + "word": "sample-word-53", + "correct": false + } + ] + }, + { + "date": "2025-05-29T12:29:40Z", + "sessionId": "testuser-2025-05-29-0", + "total": 13, + "correct": 10, + "score": 73, + "words": [ + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-29", + "correct": false + }, + { + "word": "sample-word-4", + "correct": false + }, + { + "word": "sample-word-59", + "correct": false + } + ] + }, + { + "date": "2025-05-30T18:50:34Z", + "sessionId": "testuser-2025-05-30-0", + "total": 9, + "correct": 7, + "score": 74, + "words": [ + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-6", + "correct": false + }, + { + "word": "sample-word-61", + "correct": false + } + ] + }, + { + "date": "2025-05-30T19:33:52Z", + "sessionId": "testuser-2025-05-30-1", + "total": 11, + "correct": 7, + "score": 64, + "words": [ + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-22", + "correct": false + }, + { + "word": "sample-word-65", + "correct": false + }, + { + "word": "sample-word-8", + "correct": false + }, + { + "word": "sample-word-65", + "correct": false + } + ] + }, + { + "date": "2025-06-06T20:54:32Z", + "sessionId": "testuser-2025-06-06-0", + "total": 11, + "correct": 7, + "score": 67, + "words": [ + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-94", + "correct": false + }, + { + "word": "sample-word-24", + "correct": false + }, + { + "word": "sample-word-87", + "correct": false + }, + { + "word": "sample-word-47", + "correct": false + } + ] + }, + { + "date": "2025-06-06T16:43:24Z", + "sessionId": "testuser-2025-06-06-1", + "total": 6, + "correct": 4, + "score": 66, + "words": [ + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-4", + "correct": false + }, + { + "word": "sample-word-55", + "correct": false + } + ] + }, + { + "date": "2025-06-08T16:39:48Z", + "sessionId": "testuser-2025-06-08-0", + "total": 7, + "correct": 5, + "score": 74, + "words": [ + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-13", + "correct": false + }, + { + "word": "sample-word-55", + "correct": false + } + ] + }, + { + "date": "2025-06-12T19:15:56Z", + "sessionId": "testuser-2025-06-12-0", + "total": 5, + "correct": 3, + "score": 65, + "words": [ + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-91", + "correct": false + }, + { + "word": "sample-word-16", + "correct": false + } + ] + }, + { + "date": "2025-06-12T12:11:45Z", + "sessionId": "testuser-2025-06-12-1", + "total": 14, + "correct": 9, + "score": 65, + "words": [ + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-79", + "correct": false + }, + { + "word": "sample-word-21", + "correct": false + }, + { + "word": "sample-word-86", + "correct": false + }, + { + "word": "sample-word-78", + "correct": false + }, + { + "word": "sample-word-90", + "correct": false + } + ] + }, + { + "date": "2025-06-13T09:44:41Z", + "sessionId": "testuser-2025-06-13-0", + "total": 11, + "correct": 8, + "score": 70, + "words": [ + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-74", + "correct": false + }, + { + "word": "sample-word-8", + "correct": false + }, + { + "word": "sample-word-73", + "correct": false + } + ] + }, + { + "date": "2025-06-14T12:00:13Z", + "sessionId": "testuser-2025-06-14-0", + "total": 10, + "correct": 8, + "score": 81, + "words": [ + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-38", + "correct": false + }, + { + "word": "sample-word-74", + "correct": false + } + ] + }, + { + "date": "2025-06-21T08:11:54Z", + "sessionId": "testuser-2025-06-21-0", + "total": 9, + "correct": 7, + "score": 78, + "words": [ + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-47", + "correct": false + }, + { + "word": "sample-word-98", + "correct": false + } + ] + }, + { + "date": "2025-06-23T11:35:57Z", + "sessionId": "testuser-2025-06-23-0", + "total": 11, + "correct": 8, + "score": 71, + "words": [ + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-59", + "correct": false + }, + { + "word": "sample-word-96", + "correct": false + }, + { + "word": "sample-word-20", + "correct": false + } + ] + }, + { + "date": "2025-06-24T14:46:46Z", + "sessionId": "testuser-2025-06-24-0", + "total": 12, + "correct": 8, + "score": 70, + "words": [ + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-31", + "correct": false + }, + { + "word": "sample-word-37", + "correct": false + }, + { + "word": "sample-word-48", + "correct": false + }, + { + "word": "sample-word-30", + "correct": false + } + ] + }, + { + "date": "2025-06-24T20:44:09Z", + "sessionId": "testuser-2025-06-24-1", + "total": 13, + "correct": 9, + "score": 72, + "words": [ + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-13", + "correct": false + }, + { + "word": "sample-word-15", + "correct": false + }, + { + "word": "sample-word-64", + "correct": false + }, + { + "word": "sample-word-51", + "correct": false + } + ] + }, + { + "date": "2025-06-27T12:54:56Z", + "sessionId": "testuser-2025-06-27-0", + "total": 13, + "correct": 9, + "score": 70, + "words": [ + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-61", + "correct": false + }, + { + "word": "sample-word-32", + "correct": false + }, + { + "word": "sample-word-28", + "correct": false + }, + { + "word": "sample-word-98", + "correct": false + } + ] + }, + { + "date": "2025-06-27T13:15:01Z", + "sessionId": "testuser-2025-06-27-1", + "total": 7, + "correct": 5, + "score": 73, + "words": [ + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-65", + "correct": false + }, + { + "word": "sample-word-18", + "correct": false + } + ] + }, + { + "date": "2025-06-28T19:39:44Z", + "sessionId": "testuser-2025-06-28-0", + "total": 10, + "correct": 7, + "score": 67, + "words": [ + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-39", + "correct": false + }, + { + "word": "sample-word-72", + "correct": false + }, + { + "word": "sample-word-80", + "correct": false + } + ] + }, + { + "date": "2025-07-01T09:13:00Z", + "sessionId": "testuser-2025-07-01-0", + "total": 15, + "correct": 11, + "score": 70, + "words": [ + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-15", + "correct": false + }, + { + "word": "sample-word-80", + "correct": false + }, + { + "word": "sample-word-57", + "correct": false + }, + { + "word": "sample-word-77", + "correct": false + } + ] + }, + { + "date": "2025-07-01T20:03:26Z", + "sessionId": "testuser-2025-07-01-1", + "total": 12, + "correct": 9, + "score": 74, + "words": [ + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-88", + "correct": false + }, + { + "word": "sample-word-8", + "correct": false + }, + { + "word": "sample-word-56", + "correct": false + } + ] + }, + { + "date": "2025-07-02T18:55:41Z", + "sessionId": "testuser-2025-07-02-0", + "total": 7, + "correct": 5, + "score": 77, + "words": [ + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-54", + "correct": true + }, + { + "word": "sample-word-31", + "correct": false + }, + { + "word": "sample-word-69", + "correct": false + } + ] + }, + { + "date": "2025-07-02T18:58:17Z", + "sessionId": "testuser-2025-07-02-1", + "total": 5, + "correct": 4, + "score": 74, + "words": [ + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-21", + "correct": false + } + ] + }, + { + "date": "2025-07-03T16:16:04Z", + "sessionId": "testuser-2025-07-03-0", + "total": 11, + "correct": 8, + "score": 72, + "words": [ + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-11", + "correct": false + }, + { + "word": "sample-word-73", + "correct": false + }, + { + "word": "sample-word-33", + "correct": false + } + ] + }, + { + "date": "2025-07-03T16:45:56Z", + "sessionId": "testuser-2025-07-03-1", + "total": 8, + "correct": 6, + "score": 71, + "words": [ + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-88", + "correct": false + }, + { + "word": "sample-word-64", + "correct": false + } + ] + }, + { + "date": "2025-07-04T10:33:24Z", + "sessionId": "testuser-2025-07-04-0", + "total": 8, + "correct": 6, + "score": 80, + "words": [ + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-28", + "correct": false + }, + { + "word": "sample-word-73", + "correct": false + } + ] + }, + { + "date": "2025-07-07T08:56:29Z", + "sessionId": "testuser-2025-07-07-0", + "total": 12, + "correct": 8, + "score": 67, + "words": [ + { + "word": "sample-word-27", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-50", + "correct": false + }, + { + "word": "sample-word-31", + "correct": false + }, + { + "word": "sample-word-10", + "correct": false + }, + { + "word": "sample-word-70", + "correct": false + } + ] + }, + { + "date": "2025-07-07T11:41:49Z", + "sessionId": "testuser-2025-07-07-1", + "total": 11, + "correct": 8, + "score": 75, + "words": [ + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-68", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-25", + "correct": false + }, + { + "word": "sample-word-21", + "correct": false + }, + { + "word": "sample-word-57", + "correct": false + } + ] + }, + { + "date": "2025-07-08T11:38:40Z", + "sessionId": "testuser-2025-07-08-0", + "total": 5, + "correct": 3, + "score": 69, + "words": [ + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-46", + "correct": false + }, + { + "word": "sample-word-2", + "correct": false + } + ] + }, + { + "date": "2025-07-10T14:51:30Z", + "sessionId": "testuser-2025-07-10-0", + "total": 11, + "correct": 8, + "score": 73, + "words": [ + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-51", + "correct": false + }, + { + "word": "sample-word-70", + "correct": false + }, + { + "word": "sample-word-8", + "correct": false + } + ] + }, + { + "date": "2025-07-10T15:57:22Z", + "sessionId": "testuser-2025-07-10-1", + "total": 15, + "correct": 10, + "score": 69, + "words": [ + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-94", + "correct": false + }, + { + "word": "sample-word-20", + "correct": false + }, + { + "word": "sample-word-82", + "correct": false + }, + { + "word": "sample-word-30", + "correct": false + }, + { + "word": "sample-word-61", + "correct": false + } + ] + }, + { + "date": "2025-07-11T18:09:25Z", + "sessionId": "testuser-2025-07-11-0", + "total": 13, + "correct": 11, + "score": 85, + "words": [ + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-59", + "correct": false + }, + { + "word": "sample-word-13", + "correct": false + } + ] + }, + { + "date": "2025-07-11T18:18:28Z", + "sessionId": "testuser-2025-07-11-1", + "total": 10, + "correct": 8, + "score": 76, + "words": [ + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-79", + "correct": false + }, + { + "word": "sample-word-32", + "correct": false + } + ] + }, + { + "date": "2025-07-12T17:13:39Z", + "sessionId": "testuser-2025-07-12-0", + "total": 11, + "correct": 9, + "score": 86, + "words": [ + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-62", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-25", + "correct": false + }, + { + "word": "sample-word-5", + "correct": false + } + ] + }, + { + "date": "2025-07-12T14:41:20Z", + "sessionId": "testuser-2025-07-12-1", + "total": 9, + "correct": 7, + "score": 75, + "words": [ + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-8", + "correct": false + }, + { + "word": "sample-word-32", + "correct": false + } + ] + }, + { + "date": "2025-07-14T13:01:33Z", + "sessionId": "testuser-2025-07-14-0", + "total": 8, + "correct": 7, + "score": 86, + "words": [ + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-49", + "correct": true + }, + { + "word": "sample-word-74", + "correct": false + } + ] + }, + { + "date": "2025-07-15T18:36:37Z", + "sessionId": "testuser-2025-07-15-0", + "total": 10, + "correct": 8, + "score": 83, + "words": [ + { + "word": "sample-word-45", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-36", + "correct": false + }, + { + "word": "sample-word-84", + "correct": false + } + ] + }, + { + "date": "2025-07-16T19:13:57Z", + "sessionId": "testuser-2025-07-16-0", + "total": 6, + "correct": 4, + "score": 75, + "words": [ + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-82", + "correct": false + }, + { + "word": "sample-word-100", + "correct": false + } + ] + }, + { + "date": "2025-07-16T16:43:38Z", + "sessionId": "testuser-2025-07-16-1", + "total": 12, + "correct": 10, + "score": 85, + "words": [ + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-19", + "correct": false + }, + { + "word": "sample-word-35", + "correct": false + } + ] + }, + { + "date": "2025-07-17T16:29:52Z", + "sessionId": "testuser-2025-07-17-0", + "total": 12, + "correct": 9, + "score": 76, + "words": [ + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-31", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-24", + "correct": false + }, + { + "word": "sample-word-60", + "correct": false + }, + { + "word": "sample-word-70", + "correct": false + } + ] + }, + { + "date": "2025-07-18T11:59:28Z", + "sessionId": "testuser-2025-07-18-0", + "total": 5, + "correct": 4, + "score": 76, + "words": [ + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-65", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-59", + "correct": false + } + ] + }, + { + "date": "2025-07-18T08:23:07Z", + "sessionId": "testuser-2025-07-18-1", + "total": 11, + "correct": 8, + "score": 77, + "words": [ + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-50", + "correct": false + }, + { + "word": "sample-word-23", + "correct": false + }, + { + "word": "sample-word-40", + "correct": false + } + ] + }, + { + "date": "2025-07-21T20:50:04Z", + "sessionId": "testuser-2025-07-21-0", + "total": 13, + "correct": 11, + "score": 86, + "words": [ + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-13", + "correct": false + }, + { + "word": "sample-word-5", + "correct": false + } + ] + }, + { + "date": "2025-07-21T12:32:08Z", + "sessionId": "testuser-2025-07-21-1", + "total": 15, + "correct": 13, + "score": 87, + "words": [ + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-80", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-55", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-15", + "correct": false + }, + { + "word": "sample-word-44", + "correct": false + } + ] + }, + { + "date": "2025-07-22T19:52:03Z", + "sessionId": "testuser-2025-07-22-0", + "total": 13, + "correct": 10, + "score": 78, + "words": [ + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-78", + "correct": false + }, + { + "word": "sample-word-50", + "correct": false + }, + { + "word": "sample-word-65", + "correct": false + } + ] + }, + { + "date": "2025-07-22T20:59:09Z", + "sessionId": "testuser-2025-07-22-1", + "total": 15, + "correct": 11, + "score": 74, + "words": [ + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-76", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-35", + "correct": true + }, + { + "word": "sample-word-97", + "correct": false + }, + { + "word": "sample-word-61", + "correct": false + }, + { + "word": "sample-word-10", + "correct": false + }, + { + "word": "sample-word-100", + "correct": false + } + ] + }, + { + "date": "2025-07-23T11:37:01Z", + "sessionId": "testuser-2025-07-23-0", + "total": 8, + "correct": 7, + "score": 90, + "words": [ + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-11", + "correct": false + } + ] + }, + { + "date": "2025-07-23T09:56:32Z", + "sessionId": "testuser-2025-07-23-1", + "total": 14, + "correct": 11, + "score": 76, + "words": [ + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-16", + "correct": true + }, + { + "word": "sample-word-1", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-86", + "correct": true + }, + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-80", + "correct": false + }, + { + "word": "sample-word-45", + "correct": false + }, + { + "word": "sample-word-48", + "correct": false + } + ] + }, + { + "date": "2025-07-24T13:30:04Z", + "sessionId": "testuser-2025-07-24-0", + "total": 11, + "correct": 10, + "score": 90, + "words": [ + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-93", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-37", + "correct": false + } + ] + }, + { + "date": "2025-07-24T14:38:39Z", + "sessionId": "testuser-2025-07-24-1", + "total": 11, + "correct": 10, + "score": 87, + "words": [ + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-36", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-53", + "correct": true + }, + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-59", + "correct": false + } + ] + }, + { + "date": "2025-07-25T11:11:34Z", + "sessionId": "testuser-2025-07-25-0", + "total": 13, + "correct": 12, + "score": 90, + "words": [ + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-61", + "correct": false + } + ] + }, + { + "date": "2025-07-25T18:16:46Z", + "sessionId": "testuser-2025-07-25-1", + "total": 13, + "correct": 11, + "score": 86, + "words": [ + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-79", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-38", + "correct": true + }, + { + "word": "sample-word-30", + "correct": true + }, + { + "word": "sample-word-96", + "correct": true + }, + { + "word": "sample-word-94", + "correct": false + }, + { + "word": "sample-word-40", + "correct": false + } + ] + }, + { + "date": "2025-07-26T10:55:57Z", + "sessionId": "testuser-2025-07-26-0", + "total": 15, + "correct": 12, + "score": 83, + "words": [ + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-40", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-91", + "correct": true + }, + { + "word": "sample-word-4", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-91", + "correct": true + }, + { + "word": "sample-word-73", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-32", + "correct": false + }, + { + "word": "sample-word-64", + "correct": false + }, + { + "word": "sample-word-4", + "correct": false + } + ] + }, + { + "date": "2025-07-27T09:44:00Z", + "sessionId": "testuser-2025-07-27-0", + "total": 14, + "correct": 11, + "score": 77, + "words": [ + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-59", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-83", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-87", + "correct": false + }, + { + "word": "sample-word-67", + "correct": false + }, + { + "word": "sample-word-31", + "correct": false + } + ] + }, + { + "date": "2025-07-27T12:17:52Z", + "sessionId": "testuser-2025-07-27-1", + "total": 7, + "correct": 5, + "score": 74, + "words": [ + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-89", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-30", + "correct": false + }, + { + "word": "sample-word-95", + "correct": false + } + ] + }, + { + "date": "2025-07-30T14:24:57Z", + "sessionId": "testuser-2025-07-30-0", + "total": 11, + "correct": 9, + "score": 84, + "words": [ + { + "word": "sample-word-97", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-25", + "correct": true + }, + { + "word": "sample-word-2", + "correct": true + }, + { + "word": "sample-word-47", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-85", + "correct": false + }, + { + "word": "sample-word-71", + "correct": false + } + ] + }, + { + "date": "2025-07-30T14:42:25Z", + "sessionId": "testuser-2025-07-30-1", + "total": 10, + "correct": 7, + "score": 75, + "words": [ + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-91", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-9", + "correct": true + }, + { + "word": "sample-word-52", + "correct": true + }, + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-73", + "correct": false + }, + { + "word": "sample-word-82", + "correct": false + }, + { + "word": "sample-word-44", + "correct": false + } + ] + }, + { + "date": "2025-07-31T14:32:55Z", + "sessionId": "testuser-2025-07-31-0", + "total": 12, + "correct": 11, + "score": 90, + "words": [ + { + "word": "sample-word-78", + "correct": true + }, + { + "word": "sample-word-88", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-66", + "correct": true + }, + { + "word": "sample-word-46", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-64", + "correct": false + } + ] + }, + { + "date": "2025-07-31T19:13:36Z", + "sessionId": "testuser-2025-07-31-1", + "total": 12, + "correct": 11, + "score": 89, + "words": [ + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-74", + "correct": true + }, + { + "word": "sample-word-39", + "correct": true + }, + { + "word": "sample-word-63", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-14", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-67", + "correct": false + } + ] + }, + { + "date": "2025-08-01T09:50:50Z", + "sessionId": "testuser-2025-08-01-0", + "total": 7, + "correct": 6, + "score": 84, + "words": [ + { + "word": "sample-word-42", + "correct": true + }, + { + "word": "sample-word-87", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-85", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-12", + "correct": false + } + ] + }, + { + "date": "2025-08-02T18:36:52Z", + "sessionId": "testuser-2025-08-02-0", + "total": 6, + "correct": 5, + "score": 88, + "words": [ + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-84", + "correct": true + }, + { + "word": "sample-word-82", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-27", + "correct": false + } + ] + }, + { + "date": "2025-08-04T13:28:13Z", + "sessionId": "testuser-2025-08-04-0", + "total": 5, + "correct": 4, + "score": 86, + "words": [ + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-99", + "correct": true + }, + { + "word": "sample-word-72", + "correct": true + }, + { + "word": "sample-word-2", + "correct": false + } + ] + }, + { + "date": "2025-08-05T08:04:19Z", + "sessionId": "testuser-2025-08-05-0", + "total": 12, + "correct": 9, + "score": 78, + "words": [ + { + "word": "sample-word-75", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-24", + "correct": true + }, + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-56", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-58", + "correct": false + }, + { + "word": "sample-word-70", + "correct": false + }, + { + "word": "sample-word-8", + "correct": false + } + ] + }, + { + "date": "2025-08-07T08:48:31Z", + "sessionId": "testuser-2025-08-07-0", + "total": 14, + "correct": 11, + "score": 82, + "words": [ + { + "word": "sample-word-29", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-18", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-60", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-88", + "correct": false + }, + { + "word": "sample-word-92", + "correct": false + }, + { + "word": "sample-word-76", + "correct": false + } + ] + }, + { + "date": "2025-08-07T19:51:04Z", + "sessionId": "testuser-2025-08-07-1", + "total": 12, + "correct": 10, + "score": 86, + "words": [ + { + "word": "sample-word-48", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-92", + "correct": true + }, + { + "word": "sample-word-20", + "correct": true + }, + { + "word": "sample-word-13", + "correct": true + }, + { + "word": "sample-word-6", + "correct": true + }, + { + "word": "sample-word-58", + "correct": true + }, + { + "word": "sample-word-95", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-51", + "correct": true + }, + { + "word": "sample-word-3", + "correct": false + }, + { + "word": "sample-word-29", + "correct": false + } + ] + }, + { + "date": "2025-08-08T16:33:24Z", + "sessionId": "testuser-2025-08-08-0", + "total": 15, + "correct": 14, + "score": 94, + "words": [ + { + "word": "sample-word-44", + "correct": true + }, + { + "word": "sample-word-23", + "correct": true + }, + { + "word": "sample-word-64", + "correct": true + }, + { + "word": "sample-word-15", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-19", + "correct": true + }, + { + "word": "sample-word-34", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-61", + "correct": true + }, + { + "word": "sample-word-5", + "correct": true + }, + { + "word": "sample-word-69", + "correct": true + }, + { + "word": "sample-word-3", + "correct": true + }, + { + "word": "sample-word-70", + "correct": true + }, + { + "word": "sample-word-52", + "correct": false + } + ] + }, + { + "date": "2025-08-11T08:58:52Z", + "sessionId": "testuser-2025-08-11-0", + "total": 8, + "correct": 7, + "score": 92, + "words": [ + { + "word": "sample-word-91", + "correct": true + }, + { + "word": "sample-word-33", + "correct": true + }, + { + "word": "sample-word-81", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-32", + "correct": true + }, + { + "word": "sample-word-11", + "correct": true + }, + { + "word": "sample-word-50", + "correct": true + }, + { + "word": "sample-word-57", + "correct": false + } + ] + }, + { + "date": "2025-08-11T11:53:52Z", + "sessionId": "testuser-2025-08-11-1", + "total": 11, + "correct": 10, + "score": 90, + "words": [ + { + "word": "sample-word-57", + "correct": true + }, + { + "word": "sample-word-26", + "correct": true + }, + { + "word": "sample-word-17", + "correct": true + }, + { + "word": "sample-word-41", + "correct": true + }, + { + "word": "sample-word-37", + "correct": true + }, + { + "word": "sample-word-28", + "correct": true + }, + { + "word": "sample-word-94", + "correct": true + }, + { + "word": "sample-word-43", + "correct": true + }, + { + "word": "sample-word-98", + "correct": true + }, + { + "word": "sample-word-67", + "correct": true + }, + { + "word": "sample-word-81", + "correct": false + } + ] + }, + { + "date": "2025-08-12T16:25:36Z", + "sessionId": "testuser-2025-08-12-0", + "total": 12, + "correct": 10, + "score": 85, + "words": [ + { + "word": "sample-word-12", + "correct": true + }, + { + "word": "sample-word-90", + "correct": true + }, + { + "word": "sample-word-7", + "correct": true + }, + { + "word": "sample-word-10", + "correct": true + }, + { + "word": "sample-word-77", + "correct": true + }, + { + "word": "sample-word-21", + "correct": true + }, + { + "word": "sample-word-100", + "correct": true + }, + { + "word": "sample-word-22", + "correct": true + }, + { + "word": "sample-word-71", + "correct": true + }, + { + "word": "sample-word-8", + "correct": true + }, + { + "word": "sample-word-5", + "correct": false + }, + { + "word": "sample-word-88", + "correct": false + } + ] + } + ] } \ No newline at end of file diff --git a/data/spacedRepetition.json b/data/spacedRepetition.json new file mode 100644 index 0000000..e1acb85 --- /dev/null +++ b/data/spacedRepetition.json @@ -0,0 +1,300 @@ +{ + "nate": { + "settings": { + "dailyLimit": 20, + "reviewThreshold": 3, + "newWordsPerDay": 5 + }, + "stats": { + "totalReviews": 15, + "correctReviews": 9, + "totalWords": 6, + "masteredWords": 0 + }, + "words": { + "computer": { + "easeFactor": 2.5, + "interval": 3, + "repetitions": 3, + "lastReview": "2025-08-10", + "nextReview": "2025-08-13" + }, + "keyboard": { + "easeFactor": 2.3, + "interval": 2, + "repetitions": 2, + "lastReview": "2025-08-11", + "nextReview": "2025-08-13" + }, + "mouse": { + "easeFactor": 2.8, + "interval": 4, + "repetitions": 4, + "lastReview": "2025-08-09", + "nextReview": "2025-08-13" + }, + "screen": { + "easeFactor": 3, + "interval": 6, + "repetitions": 5, + "lastReview": "2025-08-07", + "nextReview": "2025-08-13" + }, + "printer": { + "easeFactor": 2.2, + "interval": 1, + "repetitions": 1, + "lastReview": "2025-08-12", + "nextReview": "2025-08-13" + }, + "not": { + "easeFactor": 2.6, + "interval": 7, + "repetitions": 3, + "lastReview": "2025-08-12", + "nextReview": "2025-08-20" + }, + "bot": { + "easeFactor": 2.8, + "interval": 15, + "repetitions": 4, + "lastReview": "2025-08-05", + "nextReview": "2025-08-14" + }, + "snot": { + "easeFactor": 2.2, + "interval": 1, + "repetitions": 1, + "lastReview": "2025-08-12", + "nextReview": "2025-08-14" + }, + "bate": { + "easeFactor": 2.1, + "interval": 1, + "repetitions": 1, + "lastReview": "2025-08-12", + "nextReview": "2025-08-14" + }, + "hate": { + "easeFactor": 2.2, + "interval": 3, + "repetitions": 2, + "lastReview": "2025-08-10", + "nextReview": "2025-08-15" + }, + "late": { + "easeFactor": 2.5, + "interval": 15, + "repetitions": 4, + "lastReview": "2025-08-11", + "nextReview": "2025-08-11" + } + } + }, + "student1": { + "settings": { + "dailyLimit": 20, + "reviewThreshold": 3, + "newWordsPerDay": 5 + }, + "stats": { + "totalReviews": 10, + "correctReviews": 5, + "totalWords": 5, + "masteredWords": 0 + }, + "words": { + "apple": { + "easeFactor": 2.2, + "interval": 3, + "repetitions": 2, + "lastReview": "2025-08-10", + "nextReview": "2025-08-10" + }, + "banana": { + "easeFactor": 2.1, + "interval": 1, + "repetitions": 1, + "lastReview": "2025-08-12", + "nextReview": "2025-08-14" + }, + "cherry": { + "easeFactor": 2.4, + "interval": 3, + "repetitions": 2, + "lastReview": "2025-08-11", + "nextReview": "2025-08-16" + }, + "date": { + "easeFactor": 2.5, + "interval": 1, + "repetitions": 1, + "lastReview": "2025-08-12", + "nextReview": "2025-08-13" + }, + "elderberry": { + "easeFactor": 2.3, + "interval": 15, + "repetitions": 4, + "lastReview": "2025-08-11", + "nextReview": "2025-08-11" + } + } + }, + "admin1": { + "settings": { + "dailyLimit": 20, + "reviewThreshold": 3, + "newWordsPerDay": 5 + }, + "stats": { + "totalReviews": 12, + "correctReviews": 9, + "totalWords": 3, + "masteredWords": 1 + }, + "words": { + "administration": { + "easeFactor": 2.5, + "interval": 3, + "repetitions": 3, + "lastReview": "2025-08-10", + "nextReview": "2025-08-13" + }, + "education": { + "easeFactor": 2.8, + "interval": 4, + "repetitions": 4, + "lastReview": "2025-08-09", + "nextReview": "2025-08-13" + }, + "technology": { + "easeFactor": 2.3, + "interval": 2, + "repetitions": 2, + "lastReview": "2025-08-11", + "nextReview": "2025-08-13" + }, + "development": { + "easeFactor": 3, + "interval": 6, + "repetitions": 5, + "lastReview": "2025-08-07", + "nextReview": "2025-08-13" + }, + "programming": { + "easeFactor": 3, + "interval": 6, + "repetitions": 5, + "lastReview": "2025-08-07", + "nextReview": "2025-08-13" + }, + "boy": { + "easeFactor": 2.7, + "interval": 15, + "repetitions": 4, + "lastReview": "2025-08-09", + "nextReview": "2025-08-20" + }, + "bot": { + "easeFactor": 2.6, + "interval": 40, + "repetitions": 6, + "lastReview": "2025-07-23", + "nextReview": "2025-08-25" + }, + "snot": { + "easeFactor": 2.4, + "interval": 3, + "repetitions": 2, + "lastReview": "2025-08-10", + "nextReview": "2025-08-10" + } + } + }, + "testuser": { + "settings": { + "dailyLimit": 20, + "reviewThreshold": 3, + "newWordsPerDay": 5 + }, + "stats": { + "totalReviews": 32, + "correctReviews": 23, + "totalWords": 10, + "masteredWords": 3 + }, + "words": { + "hello": { + "easeFactor": 2.4, + "interval": 7, + "repetitions": 3, + "lastReview": "2025-08-07", + "nextReview": "2025-08-14" + }, + "world": { + "easeFactor": 2.2, + "interval": 3, + "repetitions": 2, + "lastReview": "2025-08-10", + "nextReview": "2025-08-14" + }, + "test": { + "easeFactor": 2.2, + "interval": 7, + "repetitions": 3, + "lastReview": "2025-08-08", + "nextReview": "2025-08-14" + }, + "sample": { + "easeFactor": 2.2, + "interval": 3, + "repetitions": 2, + "lastReview": "2025-08-11", + "nextReview": "2025-08-16" + }, + "basic": { + "easeFactor": 2.7, + "interval": 40, + "repetitions": 6, + "lastReview": "2025-08-03", + "nextReview": "2025-08-14" + }, + "learn": { + "easeFactor": 2.4, + "interval": 0, + "repetitions": 0, + "lastReview": null, + "nextReview": "2025-08-13" + }, + "spell": { + "easeFactor": 2.2, + "interval": 1, + "repetitions": 1, + "lastReview": "2025-08-12", + "nextReview": "2025-08-14" + }, + "word": { + "easeFactor": 2.9, + "interval": 20, + "repetitions": 5, + "lastReview": "2025-07-27", + "nextReview": "2025-08-27" + }, + "study": { + "easeFactor": 2.4, + "interval": 7, + "repetitions": 3, + "lastReview": "2025-08-08", + "nextReview": "2025-08-14" + }, + "practice": { + "easeFactor": 2.8, + "interval": 80, + "repetitions": 7, + "lastReview": "2025-07-06", + "nextReview": "2025-08-14" + } + } + } +} \ No newline at end of file diff --git a/gamification-endpoints.js b/gamification-endpoints.js new file mode 100644 index 0000000..633415f --- /dev/null +++ b/gamification-endpoints.js @@ -0,0 +1,470 @@ +// Gamification API endpoints for the Spelling Practice App + +// 🏆 Get leaderboards +app.get('/getLeaderboards', (req, res) => { + try { + const leaderboards = readJsonSafe(path.join(DATA_DIR, files.leaderboards), {}); + res.json(leaderboards); + } catch (error) { + console.error('Error getting leaderboards:', error); + res.status(500).send('Failed to get leaderboards'); + } +}); + +// 🎯 Get current challenges +app.get('/getChallenges', (req, res) => { + try { + const challenges = readJsonSafe(path.join(DATA_DIR, files.challenges), {}); + res.json(challenges); + } catch (error) { + console.error('Error getting challenges:', error); + res.status(500).send('Failed to get challenges'); + } +}); + +// 📈 Get user progress +app.get('/getUserProgress', (req, res) => { + try { + const { username } = req.query; + if (!username) { + return res.status(400).send('Username is required'); + } + + const progress = readJsonSafe(path.join(DATA_DIR, files.progress), {}); + + if (!progress[username]) { + return res.status(404).send('User progress not found'); + } + + res.json(progress[username]); + } catch (error) { + console.error('Error getting user progress:', error); + res.status(500).send('Failed to get user progress'); + } +}); + +// 📋 Get all users' progress +app.get('/getAllProgress', (req, res) => { + try { + const progress = readJsonSafe(path.join(DATA_DIR, files.progress), {}); + res.json(progress); + } catch (error) { + console.error('Error getting all progress data:', error); + res.status(500).send('Failed to get progress data'); + } +}); + +// 🔄 Update user streak +app.post('/updateStreak', (req, res) => { + try { + const { username } = req.body; + if (!username) { + return res.status(400).send('Username is required'); + } + + const progress = readJsonSafe(path.join(DATA_DIR, files.progress), {}); + + if (!progress[username]) { + return res.status(404).send('User progress not found'); + } + + const userProgress = progress[username]; + const now = new Date(); + const lastActivity = userProgress.streaks.lastActivity ? new Date(userProgress.streaks.lastActivity) : null; + + // If this is the first activity or it's a new day + if (!lastActivity || !isToday(lastActivity)) { + // Check if the streak continues (last activity was yesterday) + if (lastActivity) { + const yesterday = new Date(); + yesterday.setDate(yesterday.getDate() - 1); + + if (isSameDay(lastActivity, yesterday)) { + // Streak continues + userProgress.streaks.current++; + } else { + // Streak broken + userProgress.streaks.current = 1; + } + } else { + // First activity + userProgress.streaks.current = 1; + } + + // Update longest streak if needed + if (userProgress.streaks.current > userProgress.streaks.longest) { + userProgress.streaks.longest = userProgress.streaks.current; + } + + // Update last activity + userProgress.streaks.lastActivity = now.toISOString(); + + // Write updated progress + fs.writeFileSync(path.join(DATA_DIR, files.progress), JSON.stringify(progress, null, 2)); + + // Check for streak achievements + checkStreakAchievements(username, userProgress.streaks.current); + } + + res.json({ streak: userProgress.streaks }); + } catch (error) { + console.error('Error updating streak:', error); + res.status(500).send('Failed to update streak'); + } +}); + +// 📝 Complete challenge +app.post('/completeChallenge', (req, res) => { + try { + const { username, challengeId, challengeType } = req.body; + if (!username || !challengeId || !challengeType) { + return res.status(400).send('Username, challengeId, and challengeType are required'); + } + + // Valid challenge types + if (!['daily', 'weekly', 'achievements'].includes(challengeType)) { + return res.status(400).send('Invalid challenge type'); + } + + const progress = readJsonSafe(path.join(DATA_DIR, files.progress), {}); + const challenges = readJsonSafe(path.join(DATA_DIR, files.challenges), {}); + + if (!progress[username]) { + return res.status(404).send('User progress not found'); + } + + // Find the challenge + let challenge = null; + if (challengeType === 'achievements') { + challenge = challenges.achievements?.find(c => c.id === challengeId); + } else { + challenge = challenges[challengeType]?.current?.id === challengeId + ? challenges[challengeType].current + : challenges[challengeType]?.history?.find(c => c.id === challengeId); + } + + if (!challenge) { + return res.status(404).send('Challenge not found'); + } + + // Check if already completed + if (progress[username].challengesCompleted[challengeType].includes(challengeId)) { + return res.status(409).send('Challenge already completed'); + } + + // Mark as completed + progress[username].challengesCompleted[challengeType].push(challengeId); + + // Award points + if (challenge.reward && challenge.reward.points) { + progress[username].stats.points += challenge.reward.points; + } + + // Award badge if applicable + if (challenge.reward && challenge.reward.badge) { + const badges = readJsonSafe(path.join(DATA_DIR, files.badges), {}); + + if (!badges[username]) { + badges[username] = []; + } + + if (!badges[username].includes(challenge.reward.badge)) { + badges[username].push(challenge.reward.badge); + fs.writeFileSync(path.join(DATA_DIR, files.badges), JSON.stringify(badges, null, 2)); + } + } + + // Write updated progress + fs.writeFileSync(path.join(DATA_DIR, files.progress), JSON.stringify(progress, null, 2)); + + res.json({ + message: 'Challenge completed', + updatedProgress: progress[username] + }); + } catch (error) { + console.error('Error completing challenge:', error); + res.status(500).send('Failed to complete challenge'); + } +}); + +// 🔄 Update leaderboards +app.post('/updateLeaderboards', (req, res) => { + try { + // This should be an admin-only endpoint + const leaderboards = readJsonSafe(path.join(DATA_DIR, files.leaderboards), {}); + const progress = readJsonSafe(path.join(DATA_DIR, files.progress), {}); + + // Update all-time leaderboards + const accuracyLeaderboard = []; + const wordsLeaderboard = []; + const sessionsLeaderboard = []; + const streaksLeaderboard = []; + + Object.entries(progress).forEach(([username, data]) => { + if (data.stats.totalSessions > 0) { + // Accuracy leaderboard + accuracyLeaderboard.push({ + username, + value: data.stats.accuracy, + timestamp: new Date().toISOString() + }); + + // Words leaderboard + wordsLeaderboard.push({ + username, + value: data.stats.totalWords, + timestamp: new Date().toISOString() + }); + + // Sessions leaderboard + sessionsLeaderboard.push({ + username, + value: data.stats.totalSessions, + timestamp: new Date().toISOString() + }); + + // Streaks leaderboard + streaksLeaderboard.push({ + username, + value: data.streaks.current, + timestamp: new Date().toISOString() + }); + } + }); + + // Sort and limit leaderboards + leaderboards.allTime.accuracy = accuracyLeaderboard + .sort((a, b) => b.value - a.value) + .slice(0, 10); + + leaderboards.allTime.totalWords = wordsLeaderboard + .sort((a, b) => b.value - a.value) + .slice(0, 10); + + leaderboards.allTime.sessionsCompleted = sessionsLeaderboard + .sort((a, b) => b.value - a.value) + .slice(0, 10); + + leaderboards.allTime.streakDays = streaksLeaderboard + .sort((a, b) => b.value - a.value) + .slice(0, 10); + + // TODO: Implement weekly leaderboard calculations + + leaderboards.lastUpdated = new Date().toISOString(); + + // Write updated leaderboards + fs.writeFileSync(path.join(DATA_DIR, files.leaderboards), JSON.stringify(leaderboards, null, 2)); + + res.json({ message: 'Leaderboards updated successfully' }); + } catch (error) { + console.error('Error updating leaderboards:', error); + res.status(500).send('Failed to update leaderboards'); + } +}); + +// 🆕 Generate new daily challenge +app.post('/generateDailyChallenge', (req, res) => { + try { + const challenges = readJsonSafe(path.join(DATA_DIR, files.challenges), {}); + const today = new Date(); + const dayString = today.toISOString().split('T')[0]; + + // Check if today's challenge already exists + if (challenges.daily.current && challenges.daily.current.date === dayString) { + return res.status(409).send('Today\'s challenge already exists'); + } + + // Move current challenge to history + if (challenges.daily.current) { + if (!challenges.daily.history) { + challenges.daily.history = []; + } + challenges.daily.history.unshift(challenges.daily.current); + + // Limit history size + if (challenges.daily.history.length > 30) { + challenges.daily.history = challenges.daily.history.slice(0, 30); + } + } + + // Challenge types + const challengeTypes = [ + { + type: 'accuracy', + description: 'Complete a spelling session with at least {target}% accuracy', + target: Math.floor(Math.random() * 11) + 85, // 85-95% accuracy + points: 50 + }, + { + type: 'words', + description: 'Spell {target} words correctly in one day', + target: Math.floor(Math.random() * 16) + 10, // 10-25 words + points: 40 + }, + { + type: 'sessions', + description: 'Complete {target} spelling sessions in one day', + target: Math.floor(Math.random() * 3) + 2, // 2-4 sessions + points: 60 + } + ]; + + // Choose random challenge type + const challenge = challengeTypes[Math.floor(Math.random() * challengeTypes.length)]; + + // Create new challenge + challenges.daily.current = { + id: `daily-${dayString}`, + title: `${today.toLocaleDateString('en-US', { month: 'long', day: 'numeric' })} Challenge`, + description: challenge.description.replace('{target}', challenge.target), + type: challenge.type, + target: challenge.target, + reward: { + points: challenge.points, + badge: null + }, + date: dayString + }; + + challenges.lastUpdated = today.toISOString(); + + // Write updated challenges + fs.writeFileSync(path.join(DATA_DIR, files.challenges), JSON.stringify(challenges, null, 2)); + + res.json({ message: 'Daily challenge generated', challenge: challenges.daily.current }); + } catch (error) { + console.error('Error generating daily challenge:', error); + res.status(500).send('Failed to generate daily challenge'); + } +}); + +// 🆕 Generate new weekly challenge +app.post('/generateWeeklyChallenge', (req, res) => { + try { + const challenges = readJsonSafe(path.join(DATA_DIR, files.challenges), {}); + const today = new Date(); + const weekNum = getWeekNumber(today); + const yearNum = today.getFullYear(); + const weekId = `weekly-${yearNum}-${weekNum}`; + + // Check if this week's challenge already exists + if (challenges.weekly.current && challenges.weekly.current.id === weekId) { + return res.status(409).send('This week\'s challenge already exists'); + } + + // Move current challenge to history + if (challenges.weekly.current) { + if (!challenges.weekly.history) { + challenges.weekly.history = []; + } + challenges.weekly.history.unshift(challenges.weekly.current); + + // Limit history size + if (challenges.weekly.history.length > 12) { + challenges.weekly.history = challenges.weekly.history.slice(0, 12); + } + } + + // Challenge types + const challengeTypes = [ + { + type: 'streak', + description: 'Practice spelling for {target} consecutive days', + target: Math.floor(Math.random() * 3) + 4, // 4-6 days + points: 100, + badge: 'Weekly Warrior' + }, + { + type: 'correctWords', + description: 'Spell {target} words correctly this week', + target: Math.floor(Math.random() * 51) + 75, // 75-125 words + points: 150, + badge: 'Word Master' + }, + { + type: 'perfectSessions', + description: 'Complete {target} perfect spelling sessions this week', + target: Math.floor(Math.random() * 3) + 2, // 2-4 sessions + points: 200, + badge: 'Perfect Form' + } + ]; + + // Choose random challenge type + const challenge = challengeTypes[Math.floor(Math.random() * challengeTypes.length)]; + + // Create new challenge + challenges.weekly.current = { + id: weekId, + title: `Week ${weekNum} Challenge`, + description: challenge.description.replace('{target}', challenge.target), + type: challenge.type, + target: challenge.target, + reward: { + points: challenge.points, + badge: challenge.badge + }, + startDate: getWeekStartDate(today).toISOString().split('T')[0], + endDate: getWeekEndDate(today).toISOString().split('T')[0] + }; + + challenges.lastUpdated = today.toISOString(); + + // Write updated challenges + fs.writeFileSync(path.join(DATA_DIR, files.challenges), JSON.stringify(challenges, null, 2)); + + res.json({ message: 'Weekly challenge generated', challenge: challenges.weekly.current }); + } catch (error) { + console.error('Error generating weekly challenge:', error); + res.status(500).send('Failed to generate weekly challenge'); + } +}); + +// Helper function to check for streak achievements +function checkStreakAchievements(username, currentStreak) { + try { + const challenges = readJsonSafe(path.join(DATA_DIR, files.challenges), {}); + const progress = readJsonSafe(path.join(DATA_DIR, files.progress), {}); + + // Find streak-based achievements + const streakAchievements = challenges.achievements.filter( + a => a.type === 'streak' && a.condition === 'dailyLogin' + ); + + // Check if any achievement is unlocked by the current streak + streakAchievements.forEach(achievement => { + // If streak target met and not already completed + if (currentStreak >= achievement.target && + !progress[username].challengesCompleted.achievements.includes(achievement.id)) { + + // Mark as completed + progress[username].challengesCompleted.achievements.push(achievement.id); + + // Award points + if (achievement.reward && achievement.reward.points) { + progress[username].stats.points += achievement.reward.points; + } + + // Award badge if applicable + if (achievement.reward && achievement.reward.badge) { + const badges = readJsonSafe(path.join(DATA_DIR, files.badges), {}); + + if (!badges[username]) { + badges[username] = []; + } + + if (!badges[username].includes(achievement.reward.badge)) { + badges[username].push(achievement.reward.badge); + fs.writeFileSync(path.join(DATA_DIR, files.badges), JSON.stringify(badges, null, 2)); + } + } + } + }); + + // Write updated progress if needed + fs.writeFileSync(path.join(DATA_DIR, files.progress), JSON.stringify(progress, null, 2)); + } catch (error) { + console.error('Error checking streak achievements:', error); + } +} diff --git a/generate-analytics-data.js b/generate-analytics-data.js new file mode 100644 index 0000000..132df38 --- /dev/null +++ b/generate-analytics-data.js @@ -0,0 +1,373 @@ +/** + * Generate sample analytics data for the Spelling Practice App + * This script will add realistic user activity data to showcase the analytics features + */ + +const fs = require('fs'); +const path = require('path'); + +// Define paths +const DATA_DIR = path.join(__dirname, 'data'); +const files = { + users: path.join(DATA_DIR, 'users.json'), + results: path.join(DATA_DIR, 'results.json'), + progress: path.join(DATA_DIR, 'progress.json'), + leaderboards: path.join(DATA_DIR, 'leaderboards.json'), + challenges: path.join(DATA_DIR, 'challenges.json') +}; + +// Helper functions +function readJsonSafe(filePath, defaultValue = {}) { + try { + if (fs.existsSync(filePath)) { + const content = fs.readFileSync(filePath, 'utf8'); + return JSON.parse(content); + } + return defaultValue; + } catch (error) { + console.error(`Error reading ${filePath}:`, error); + return defaultValue; + } +} + +function writeJsonSafe(filePath, data) { + try { + fs.writeFileSync(filePath, JSON.stringify(data, null, 2)); + return true; + } catch (error) { + console.error(`Error writing to ${filePath}:`, error); + return false; + } +} + +// Random helpers +function randomInt(min, max) { + return Math.floor(Math.random() * (max - min + 1) + min); +} + +function randomFloat(min, max, decimals = 2) { + const rand = Math.random() * (max - min) + min; + return parseFloat(rand.toFixed(decimals)); +} + +// Date helpers +function addDays(date, days) { + const result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +function subtractDays(date, days) { + return addDays(date, -days); +} + +function formatDate(date) { + return date.toISOString().split('T')[0]; +} + +function generateTimeOfDay() { + const hours = randomInt(8, 20).toString().padStart(2, '0'); + const minutes = randomInt(0, 59).toString().padStart(2, '0'); + const seconds = randomInt(0, 59).toString().padStart(2, '0'); + return `${hours}:${minutes}:${seconds}`; +} + +// Main function to generate analytics data +async function generateAnalyticsData() { + console.log('Generating sample analytics data...'); + + // Load users + const users = readJsonSafe(files.users, []); + if (users.length === 0) { + console.error('No users found. Please ensure users exist before running this script.'); + return; + } + + // Generate data for each user + const usernames = users.map(user => user.username); + + // Generate 90 days of results data (covering 3 months) + const today = new Date(); + + // Load existing data + const resultsData = readJsonSafe(files.results, {}); + const progressData = readJsonSafe(files.progress, {}); + + // For each user, generate 90 days of activity + for (const username of usernames) { + console.log(`Generating data for user: ${username}`); + + // Initialize user results if not exists + if (!resultsData[username]) { + resultsData[username] = []; + } + + // Initialize user progress if not exists + if (!progressData[username]) { + progressData[username] = { + stats: { + points: 0, + totalSessions: 0, + totalWords: 0, + correctWords: 0, + accuracy: 0 + }, + streaks: { + current: 0, + longest: 0, + dates: [] + }, + challengesCompleted: { + daily: [], + weekly: [], + achievements: [] + }, + activityLog: [] + }; + } + + // Track total stats + let totalSessions = 0; + let totalWords = 0; + let totalCorrect = 0; + let streakDates = []; + let activityLog = []; + let points = randomInt(100, 500); + + // Generate 90 days of activity with increasing frequency towards present day + for (let daysAgo = 90; daysAgo >= 0; daysAgo--) { + const activityDate = subtractDays(today, daysAgo); + const dateStr = formatDate(activityDate); + + // Determine likelihood of activity on this day + // Higher chance of activity for more recent dates and on weekdays + const dayOfWeek = activityDate.getDay(); // 0 = Sunday, 6 = Saturday + const isWeekend = dayOfWeek === 0 || dayOfWeek === 6; + const recencyFactor = 1 - (daysAgo / 90); // 0 to 1 from oldest to newest + + // Combine factors to determine chance of activity + // 30% base chance + up to 50% recency bonus - 20% weekend penalty + let activityChance = 0.3 + (recencyFactor * 0.5) - (isWeekend ? 0.2 : 0); + + // For user "nate", increase activity chance to ensure good data + if (username === 'nate') { + activityChance += 0.2; + } + + // Determine if there's activity on this day + if (Math.random() < activityChance) { + // Record streak date + streakDates.push(dateStr); + + // Determine number of sessions for this day (1-3) + const sessionsToday = randomInt(1, username === 'nate' ? 3 : 2); + + for (let s = 0; s < sessionsToday; s++) { + // Generate session ID + const sessionId = `${username}-${dateStr}-${s}`; + + // Determine session details + const numWords = randomInt(5, 15); + + // Base accuracy that improves over time due to learning + let baseAccuracy = 0.65 + (recencyFactor * 0.2); + + // Add some randomness + const accuracy = Math.min(0.98, baseAccuracy + randomFloat(-0.1, 0.1)); + + // Calculate correct words + const correctWords = Math.round(numWords * accuracy); + + // Generate random words + const words = Array.from({length: numWords}, (_, i) => { + const isCorrect = i < correctWords; + return { + word: `sample-word-${randomInt(1, 100)}`, + correct: isCorrect + }; + }); + + // Create session result + const sessionResult = { + date: `${dateStr}T${generateTimeOfDay()}Z`, + sessionId, + total: numWords, + correct: correctWords, + score: Math.round(accuracy * 100), + words + }; + + // Add to results + resultsData[username].push(sessionResult); + + // Update totals + totalSessions++; + totalWords += numWords; + totalCorrect += correctWords; + + // Add to activity log + activityLog.push({ + type: 'session_completed', + timestamp: `${dateStr}T${generateTimeOfDay()}Z`, + details: { + sessionId, + score: Math.round(accuracy * 100), + words: numWords + } + }); + + // Occasionally add badge earning (1 in 10 sessions) + if (Math.random() < 0.1) { + const badges = [ + "Perfect Round", "Speed Demon", "Word Wizard", "Consistent Learner", + "Weekly Warrior", "Quick Study", "No Misses" + ]; + const badge = badges[randomInt(0, badges.length - 1)]; + + activityLog.push({ + type: 'badge_earned', + timestamp: `${dateStr}T${generateTimeOfDay()}Z`, + details: { + badge, + sessionId + } + }); + + points += randomInt(10, 50); + } + + // Occasionally add challenge completion (1 in 8 sessions) + if (Math.random() < 0.125) { + const challengeTypes = ['daily', 'weekly', 'achievements']; + const challengeType = challengeTypes[randomInt(0, challengeTypes.length - 1)]; + const challengeId = `${challengeType}-${dateStr}-${randomInt(1, 5)}`; + + // Add to completed challenges + if (!progressData[username].challengesCompleted[challengeType].includes(challengeId)) { + progressData[username].challengesCompleted[challengeType].push(challengeId); + } + + activityLog.push({ + type: 'challenge_completed', + timestamp: `${dateStr}T${generateTimeOfDay()}Z`, + details: { + challengeId, + challengeType, + reward: { + points: randomInt(10, 50) + } + } + }); + + points += randomInt(20, 100); + } + } + } + } + + // Calculate streak stats + const streakDays = streakDates.length; + const currentStreak = calculateCurrentStreak(streakDates, today); + const longestStreak = calculateLongestStreak(streakDates); + + // Update progress data with calculated stats + progressData[username].stats = { + points, + totalSessions, + totalWords, + correctWords: totalCorrect, + accuracy: totalWords > 0 ? Math.round((totalCorrect / totalWords) * 1000) / 10 : 0 + }; + + progressData[username].streaks = { + current: currentStreak, + longest: longestStreak, + dates: streakDates + }; + + progressData[username].activityLog = activityLog; + } + + // Save updated data + console.log('Saving updated results data...'); + writeJsonSafe(files.results, resultsData); + + console.log('Saving updated progress data...'); + writeJsonSafe(files.progress, progressData); + + console.log('Sample data generation complete!'); +} + +// Helper to calculate current streak +function calculateCurrentStreak(dates, today) { + if (!dates || dates.length === 0) return 0; + + // Convert dates to Date objects for easier comparison + const sortedDates = [...dates].map(d => new Date(d)).sort((a, b) => b - a); + + // Check if today is included + const todayStr = formatDate(today); + const hasTodayActivity = dates.includes(todayStr); + + if (!hasTodayActivity) { + // Check if yesterday is included + const yesterday = subtractDays(today, 1); + const yesterdayStr = formatDate(yesterday); + const hasYesterdayActivity = dates.includes(yesterdayStr); + + if (!hasYesterdayActivity) { + return 0; // Streak broken if neither today nor yesterday has activity + } + } + + // Count consecutive days + let streak = hasTodayActivity ? 1 : 0; + let currentDate = hasTodayActivity ? subtractDays(today, 1) : subtractDays(today, 2); + + while (true) { + const dateStr = formatDate(currentDate); + if (!dates.includes(dateStr)) { + break; + } + streak++; + currentDate = subtractDays(currentDate, 1); + } + + return streak; +} + +// Helper to calculate longest streak +function calculateLongestStreak(dates) { + if (!dates || dates.length === 0) return 0; + + // Convert dates to Date objects and sort + const sortedDates = [...dates].map(d => new Date(d)).sort((a, b) => a - b); + + let longestStreak = 1; + let currentStreak = 1; + + for (let i = 1; i < sortedDates.length; i++) { + const prevDate = sortedDates[i - 1]; + const currentDate = sortedDates[i]; + + // Calculate difference in days + const diffTime = currentDate.getTime() - prevDate.getTime(); + const diffDays = Math.round(diffTime / (1000 * 60 * 60 * 24)); + + if (diffDays === 1) { + // Consecutive day + currentStreak++; + if (currentStreak > longestStreak) { + longestStreak = currentStreak; + } + } else if (diffDays > 1) { + // Streak broken + currentStreak = 1; + } + } + + return longestStreak; +} + +// Execute the script +generateAnalyticsData(); diff --git a/generate-gamification-data.js b/generate-gamification-data.js new file mode 100644 index 0000000..69f2daa --- /dev/null +++ b/generate-gamification-data.js @@ -0,0 +1,285 @@ +/** + * Generate sample gamification data for the Spelling Practice App + * This script will populate challenges and user progress with realistic data + */ + +const fs = require('fs'); +const path = require('path'); + +// Define paths +const DATA_DIR = path.join(__dirname, 'data'); +const files = { + users: path.join(DATA_DIR, 'users.json'), + challenges: path.join(DATA_DIR, 'challenges.json'), + progress: path.join(DATA_DIR, 'progress.json') +}; + +// Helper functions +function readJsonSafe(filePath, defaultValue = {}) { + try { + if (fs.existsSync(filePath)) { + const content = fs.readFileSync(filePath, 'utf8'); + return JSON.parse(content); + } + return defaultValue; + } catch (error) { + console.error(`Error reading ${filePath}:`, error); + return defaultValue; + } +} + +function writeJsonSafe(filePath, data) { + try { + fs.writeFileSync(filePath, JSON.stringify(data, null, 2)); + return true; + } catch (error) { + console.error(`Error writing to ${filePath}:`, error); + return false; + } +} + +// Random helpers +function randomInt(min, max) { + return Math.floor(Math.random() * (max - min + 1) + min); +} + +// Date helpers +function formatDate(date) { + return date.toISOString().split('T')[0]; +} + +function subtractDays(date, days) { + const result = new Date(date); + result.setDate(result.getDate() - days); + return result; +} + +// Generate sample challenges +function generateChallenges() { + const challenges = { + daily: [ + { + id: "daily-practice-10", + name: "Practice Makes Perfect", + description: "Complete 10 practice words in a day", + type: "daily", + target: 10, + points: 50, + icon: "🎯" + }, + { + id: "daily-accuracy-90", + name: "Sharp Shooter", + description: "Achieve 90% accuracy in daily practice", + type: "daily", + target: 0.9, + points: 75, + icon: "🎯" + }, + { + id: "daily-streak-3", + name: "On Fire", + description: "Get 3 words correct in a row", + type: "daily", + target: 3, + points: 30, + icon: "🔥" + } + ], + weekly: [ + { + id: "weekly-words-50", + name: "Word Warrior", + description: "Practice 50 words in a week", + type: "weekly", + target: 50, + points: 200, + icon: "⚔️" + }, + { + id: "weekly-days-5", + name: "Dedicated Scholar", + description: "Practice on 5 different days this week", + type: "weekly", + target: 5, + points: 250, + icon: "📚" + } + ], + achievements: [ + { + id: "achievement-words-100", + name: "Century Club", + description: "Practice 100 total words", + type: "achievement", + target: 100, + points: 100, + icon: "🏆" + }, + { + id: "achievement-words-500", + name: "Word Master", + description: "Practice 500 total words", + type: "achievement", + target: 500, + points: 500, + icon: "👑" + }, + { + id: "achievement-streak-7", + name: "Weekly Warrior", + description: "Maintain a 7-day practice streak", + type: "achievement", + target: 7, + points: 300, + icon: "📅" + }, + { + id: "achievement-accuracy-95", + name: "Spelling Bee Champion", + description: "Maintain 95% accuracy across 100 words", + type: "achievement", + target: 0.95, + points: 400, + icon: "🐝" + } + ] + }; + + return challenges; +} + +// Generate progress data for a user +function generateUserProgress(username) { + const today = new Date(); + + // Generate streak data + const currentStreak = randomInt(1, 14); + const longestStreak = Math.max(currentStreak, randomInt(7, 21)); + + // Generate points from challenges and achievements + const totalPoints = randomInt(500, 2000); + + // Generate completed challenges + const dailyChallenges = []; + const weeklyChallenges = []; + const achievements = []; + + // Generate some daily challenges for the past 14 days + for (let i = 0; i < 14; i++) { + const date = formatDate(subtractDays(today, i)); + + // 70% chance to have completed some daily challenges + if (Math.random() < 0.7) { + // Random selection of daily challenges + const dailyIds = ["daily-practice-10", "daily-accuracy-90", "daily-streak-3"]; + const completedCount = randomInt(1, dailyIds.length); + + for (let j = 0; j < completedCount; j++) { + dailyChallenges.push({ + id: dailyIds[j], + date, + progress: 1.0 // 100% complete + }); + } + } + } + + // Generate weekly challenges for the past 4 weeks + for (let i = 0; i < 4; i++) { + const weekStart = formatDate(subtractDays(today, 7 * (i + 1))); + + // 60% chance to have completed a weekly challenge + if (Math.random() < 0.6) { + const weeklyIds = ["weekly-words-50", "weekly-days-5"]; + const completedId = weeklyIds[randomInt(0, weeklyIds.length - 1)]; + + weeklyChallenges.push({ + id: completedId, + weekStart, + progress: 1.0 + }); + } + } + + // Generate achievements (randomly completed) + const achievementIds = [ + "achievement-words-100", + "achievement-words-500", + "achievement-streak-7", + "achievement-accuracy-95" + ]; + + // 30-70% of achievements completed + const completedCount = randomInt( + Math.floor(achievementIds.length * 0.3), + Math.floor(achievementIds.length * 0.7) + ); + + for (let i = 0; i < completedCount; i++) { + const achievementId = achievementIds[i]; + const daysAgo = randomInt(1, 30); + + achievements.push({ + id: achievementId, + date: formatDate(subtractDays(today, daysAgo)), + progress: 1.0 + }); + } + + // Overall user progress data + return { + streak: { + current: currentStreak, + longest: longestStreak, + lastPractice: formatDate(subtractDays(today, 1)) // Yesterday + }, + points: totalPoints, + level: Math.floor(totalPoints / 500) + 1, // Level up every 500 points + dailyChallenges, + weeklyChallenges, + achievements, + stats: { + wordsAttempted: randomInt(100, 1000), + wordsCorrect: randomInt(70, 95) / 100 * randomInt(100, 1000), + sessionsCompleted: randomInt(20, 100), + averageAccuracy: randomInt(70, 98) / 100 + } + }; +} + +// Main function to generate gamification data +async function generateGamificationData() { + console.log('Generating sample gamification data...'); + + // Load users + const users = readJsonSafe(files.users, []); + + if (users.length === 0) { + console.error('No users found. Please ensure users exist before running this script.'); + return; + } + + // Generate challenges + console.log('Generating challenges data...'); + const challenges = generateChallenges(); + + // Generate progress for each user + const progress = {}; + + for (const user of users) { + const username = user.username; + console.log(`Generating progress data for user: ${username}`); + progress[username] = generateUserProgress(username); + } + + // Save data + console.log('Saving challenges and progress data...'); + writeJsonSafe(files.challenges, challenges); + writeJsonSafe(files.progress, progress); + + console.log('Gamification data generation complete!'); +} + +// Execute the script +generateGamificationData(); diff --git a/generate-leaderboard-data.js b/generate-leaderboard-data.js new file mode 100644 index 0000000..266ec33 --- /dev/null +++ b/generate-leaderboard-data.js @@ -0,0 +1,242 @@ +/** + * Generate sample leaderboard data for the Spelling Practice App + * This script will populate leaderboards with realistic data for the analytics dashboard + */ + +const fs = require('fs'); +const path = require('path'); + +// Define paths +const DATA_DIR = path.join(__dirname, 'data'); +const files = { + users: path.join(DATA_DIR, 'users.json'), + progress: path.join(DATA_DIR, 'progress.json'), + leaderboards: path.join(DATA_DIR, 'leaderboards.json') +}; + +// Helper functions +function readJsonSafe(filePath, defaultValue = {}) { + try { + if (fs.existsSync(filePath)) { + const content = fs.readFileSync(filePath, 'utf8'); + return JSON.parse(content); + } + return defaultValue; + } catch (error) { + console.error(`Error reading ${filePath}:`, error); + return defaultValue; + } +} + +function writeJsonSafe(filePath, data) { + try { + fs.writeFileSync(filePath, JSON.stringify(data, null, 2)); + return true; + } catch (error) { + console.error(`Error writing to ${filePath}:`, error); + return false; + } +} + +// Random helpers +function randomInt(min, max) { + return Math.floor(Math.random() * (max - min + 1) + min); +} + +function randomFloat(min, max, decimals = 2) { + const rand = Math.random() * (max - min) + min; + return parseFloat(rand.toFixed(decimals)); +} + +// Generate additional fake users for the leaderboards +function generateFakeUsers(count) { + const firstNames = ['Emma', 'Liam', 'Olivia', 'Noah', 'Ava', 'William', 'Sophia', 'James', 'Isabella', 'Logan', + 'Mia', 'Benjamin', 'Charlotte', 'Mason', 'Amelia', 'Elijah', 'Harper', 'Oliver', 'Evelyn', 'Jacob']; + + const lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis', 'Rodriguez', 'Martinez', + 'Hernandez', 'Lopez', 'Gonzalez', 'Wilson', 'Anderson', 'Thomas', 'Taylor', 'Moore', 'Jackson', 'Martin']; + + const users = []; + + for (let i = 0; i < count; i++) { + const firstName = firstNames[randomInt(0, firstNames.length - 1)]; + const lastName = lastNames[randomInt(0, lastNames.length - 1)]; + const username = `${firstName.toLowerCase()}${lastName.substring(0, 1).toLowerCase()}${randomInt(1, 99)}`; + + users.push(username); + } + + return users; +} + +// Main function to generate leaderboard data +async function generateLeaderboardData() { + console.log('Generating sample leaderboard data...'); + + // Load users and progress data + const users = readJsonSafe(files.users, []); + const progressData = readJsonSafe(files.progress, {}); + + if (users.length === 0) { + console.error('No users found. Please ensure users exist before running this script.'); + return; + } + + // Generate 10 additional fake users for leaderboards + const fakeUsers = generateFakeUsers(10); + const allUsers = [...users.map(u => u.username), ...fakeUsers]; + + // Create leaderboard data + const leaderboards = { + allTime: { + accuracy: [], + totalWords: [], + sessionsCompleted: [], + streakDays: [] + }, + weekly: { + accuracy: [], + totalWords: [], + sessionsCompleted: [] + }, + currentWeek: `${new Date().getFullYear()}-${Math.ceil((new Date().getDate() + new Date().getDay()) / 7)}` + }; + + // Generate data for each category + + // All-time accuracy leaderboard + allUsers.forEach(username => { + // For real users, use their actual progress data if available + if (progressData[username]) { + leaderboards.allTime.accuracy.push({ + username, + value: progressData[username].stats.accuracy || randomFloat(70, 98, 1), + timestamp: new Date().toISOString() + }); + } else { + // For fake users, generate random data + leaderboards.allTime.accuracy.push({ + username, + value: randomFloat(70, 98, 1), + timestamp: new Date().toISOString() + }); + } + }); + + // Sort by value (descending) + leaderboards.allTime.accuracy.sort((a, b) => b.value - a.value); + + // All-time totalWords leaderboard + allUsers.forEach(username => { + if (progressData[username]) { + leaderboards.allTime.totalWords.push({ + username, + value: progressData[username].stats.totalWords || randomInt(100, 1000), + timestamp: new Date().toISOString() + }); + } else { + leaderboards.allTime.totalWords.push({ + username, + value: randomInt(100, 1000), + timestamp: new Date().toISOString() + }); + } + }); + + leaderboards.allTime.totalWords.sort((a, b) => b.value - a.value); + + // All-time sessionsCompleted leaderboard + allUsers.forEach(username => { + if (progressData[username]) { + leaderboards.allTime.sessionsCompleted.push({ + username, + value: progressData[username].stats.totalSessions || randomInt(5, 50), + timestamp: new Date().toISOString() + }); + } else { + leaderboards.allTime.sessionsCompleted.push({ + username, + value: randomInt(5, 50), + timestamp: new Date().toISOString() + }); + } + }); + + leaderboards.allTime.sessionsCompleted.sort((a, b) => b.value - a.value); + + // All-time streakDays leaderboard + allUsers.forEach(username => { + if (progressData[username]) { + leaderboards.allTime.streakDays.push({ + username, + value: progressData[username].streaks?.longest || randomInt(1, 14), + timestamp: new Date().toISOString() + }); + } else { + leaderboards.allTime.streakDays.push({ + username, + value: randomInt(1, 14), + timestamp: new Date().toISOString() + }); + } + }); + + leaderboards.allTime.streakDays.sort((a, b) => b.value - a.value); + + // Generate weekly leaderboards + // Copy from all-time but with different values + + // Weekly accuracy + allUsers.forEach(username => { + const allTimeEntry = leaderboards.allTime.accuracy.find(entry => entry.username === username); + const baseValue = allTimeEntry ? allTimeEntry.value : randomFloat(70, 98, 1); + + // Weekly value is slightly different from all-time + leaderboards.weekly.accuracy.push({ + username, + value: Math.min(99.9, Math.max(50, baseValue + randomFloat(-5, 5, 1))), + timestamp: new Date().toISOString() + }); + }); + + leaderboards.weekly.accuracy.sort((a, b) => b.value - a.value); + + // Weekly totalWords + allUsers.forEach(username => { + const allTimeEntry = leaderboards.allTime.totalWords.find(entry => entry.username === username); + const baseValue = allTimeEntry ? allTimeEntry.value : randomInt(100, 1000); + + // Weekly value is much smaller than all-time + leaderboards.weekly.totalWords.push({ + username, + value: randomInt(10, Math.min(100, Math.floor(baseValue / 10))), + timestamp: new Date().toISOString() + }); + }); + + leaderboards.weekly.totalWords.sort((a, b) => b.value - a.value); + + // Weekly sessionsCompleted + allUsers.forEach(username => { + const allTimeEntry = leaderboards.allTime.sessionsCompleted.find(entry => entry.username === username); + const baseValue = allTimeEntry ? allTimeEntry.value : randomInt(5, 50); + + // Weekly value is much smaller than all-time + leaderboards.weekly.sessionsCompleted.push({ + username, + value: randomInt(1, Math.min(7, Math.floor(baseValue / 5))), + timestamp: new Date().toISOString() + }); + }); + + leaderboards.weekly.sessionsCompleted.sort((a, b) => b.value - a.value); + + // Save the leaderboard data + console.log('Saving leaderboard data...'); + writeJsonSafe(files.leaderboards, leaderboards); + + console.log('Leaderboard data generation complete!'); +} + +// Execute the script +generateLeaderboardData(); diff --git a/generate-spaced-repetition-data.js b/generate-spaced-repetition-data.js new file mode 100644 index 0000000..301d6cf --- /dev/null +++ b/generate-spaced-repetition-data.js @@ -0,0 +1,222 @@ +/** + * Generate sample spaced repetition data for the Spelling Practice App + * This script will populate the spaced repetition system with realistic learning data + */ + +const fs = require('fs'); +const path = require('path'); + +// Define paths +const DATA_DIR = path.join(__dirname, 'data'); +const files = { + users: path.join(DATA_DIR, 'users.json'), + wordlists: path.join(DATA_DIR, 'wordlists.json'), + spacedRepetition: path.join(DATA_DIR, 'spacedRepetition.json') +}; + +// Helper functions +function readJsonSafe(filePath, defaultValue = {}) { + try { + if (fs.existsSync(filePath)) { + const content = fs.readFileSync(filePath, 'utf8'); + return JSON.parse(content); + } + return defaultValue; + } catch (error) { + console.error(`Error reading ${filePath}:`, error); + return defaultValue; + } +} + +function writeJsonSafe(filePath, data) { + try { + fs.writeFileSync(filePath, JSON.stringify(data, null, 2)); + return true; + } catch (error) { + console.error(`Error writing to ${filePath}:`, error); + return false; + } +} + +// Random helpers +function randomInt(min, max) { + return Math.floor(Math.random() * (max - min + 1) + min); +} + +function randomFloat(min, max, decimals = 2) { + const rand = Math.random() * (max - min) + min; + return parseFloat(rand.toFixed(decimals)); +} + +// Date helpers +function addDays(date, days) { + const result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +function subtractDays(date, days) { + return addDays(date, -days); +} + +function formatDate(date) { + return date.toISOString().split('T')[0]; +} + +// Main function to generate spaced repetition data +async function generateSpacedRepetitionData() { + console.log('Generating sample spaced repetition data...'); + + // Load users and wordlists + const users = readJsonSafe(files.users, []); + const wordlists = readJsonSafe(files.wordlists, {}); + + if (users.length === 0) { + console.error('No users found. Please ensure users exist before running this script.'); + return; + } + + // Create spaced repetition data structure + const srData = readJsonSafe(files.spacedRepetition, {}); + + // Generate data for each user + const today = new Date(); + + for (const user of users) { + const username = user.username; + console.log(`Generating spaced repetition data for user: ${username}`); + + // Get user's words + let userWords = []; + + // Handle different wordlist structures + if (Array.isArray(wordlists[username])) { + userWords = wordlists[username]; + } else if (wordlists[username] && wordlists[username].weeks && Array.isArray(wordlists[username].weeks)) { + // Extract all words from all weeks + wordlists[username].weeks.forEach(week => { + if (week.words && Array.isArray(week.words)) { + userWords = [...userWords, ...week.words]; + } + }); + } + + if (userWords.length === 0) { + console.log(`No words found for user ${username}. Skipping...`); + continue; + } + + // Initialize user's spaced repetition data if not exists + if (!srData[username]) { + srData[username] = { + settings: { + dailyLimit: 20, + reviewThreshold: 3, + newWordsPerDay: 5 + }, + stats: { + totalReviews: 0, + correctReviews: 0, + totalWords: 0, + masteredWords: 0 + }, + words: {} + }; + } + + // Add words with different mastery levels + let totalReviews = 0; + let correctReviews = 0; + let masteredWords = 0; + + for (const word of userWords) { + // Determine mastery level + // 0: New - 20% + // 1-2: Learning - 30% + // 3-4: Reviewing - 30% + // 5+: Mastered - 20% + + const rand = Math.random(); + let repetitions = 0; + let interval = 0; + let easeFactor = 2.5; + + if (rand < 0.2) { + // New word + repetitions = 0; + interval = 0; + easeFactor = randomFloat(2.3, 2.7, 1); + } else if (rand < 0.5) { + // Learning + repetitions = randomInt(1, 2); + interval = repetitions === 1 ? 1 : 3; + easeFactor = randomFloat(2.0, 2.5, 1); + totalReviews += repetitions; + correctReviews += repetitions - 1; + } else if (rand < 0.8) { + // Reviewing + repetitions = randomInt(3, 4); + interval = repetitions === 3 ? 7 : 15; + easeFactor = randomFloat(2.2, 2.8, 1); + totalReviews += repetitions; + correctReviews += repetitions - 1; + } else { + // Mastered + repetitions = randomInt(5, 8); + interval = Math.pow(2, repetitions - 4) * 10; // Exponential increase + easeFactor = randomFloat(2.6, 3.0, 1); + totalReviews += repetitions; + correctReviews += repetitions - 1; + masteredWords++; + } + + // Calculate last and next review dates + let nextReview = null; + let lastReview = null; + + if (repetitions > 0) { + // If the word has been reviewed before, set lastReview + lastReview = formatDate(subtractDays(today, randomInt(1, interval))); + + // Next review might be due + const dueChance = 0.3; // 30% chance word is due + if (Math.random() < dueChance) { + // Word is due today or in the past + nextReview = formatDate(subtractDays(today, randomInt(0, 3))); + } else { + // Word is due in the future + nextReview = formatDate(addDays(today, randomInt(1, interval))); + } + } else { + // New word, not reviewed yet + nextReview = formatDate(today); + } + + // Add word to user's SR data + srData[username].words[word] = { + easeFactor, + interval, + repetitions, + lastReview, + nextReview + }; + } + + // Update user stats + srData[username].stats = { + totalReviews, + correctReviews, + totalWords: userWords.length, + masteredWords + }; + } + + // Save spaced repetition data + console.log('Saving spaced repetition data...'); + writeJsonSafe(files.spacedRepetition, srData); + + console.log('Spaced repetition data generation complete!'); +} + +// Execute the script +generateSpacedRepetitionData(); diff --git a/package.json b/package.json index b51b062..f718d07 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "modern-spelling-practice", - "version": "2.1.0", - "description": "A modern, multi-user spelling practice application with admin controls, customizable themes, and analytics", + "version": "3.0.0", + "description": "A modern, multi-user spelling practice application with admin controls, customizable themes, analytics, gamification, and spaced repetition learning", "main": "server.js", "scripts": { "start": "node server.js", diff --git a/public/gamification.css b/public/gamification.css new file mode 100644 index 0000000..da32ab0 --- /dev/null +++ b/public/gamification.css @@ -0,0 +1,346 @@ +/* Gamification CSS for Spelling Practice App */ + +/* Leaderboard styles */ +.leaderboard-container { + margin-top: 1rem; +} + +.leaderboard-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 1rem; +} + +.leaderboard-tabs { + display: flex; + gap: 1rem; + margin-bottom: 1rem; +} + +.leaderboard-tab { + padding: 0.5rem 1rem; + border-radius: var(--radius); + cursor: pointer; + background-color: var(--bg-secondary); + transition: all 0.2s ease; +} + +.leaderboard-tab.active { + background-color: var(--primary); + color: white; +} + +.leaderboard-table { + width: 100%; + border-collapse: collapse; + border-radius: var(--radius); + overflow: hidden; +} + +.leaderboard-table th { + background-color: var(--bg-secondary); + padding: 0.75rem 1rem; + text-align: left; + font-weight: 600; +} + +.leaderboard-table tr:nth-child(even) { + background-color: var(--bg-secondary); +} + +.leaderboard-table tr:hover { + background-color: var(--bg-hover); +} + +.leaderboard-table td { + padding: 0.75rem 1rem; +} + +.leaderboard-rank { + font-weight: 700; + text-align: center; + width: 3rem; +} + +.leaderboard-value { + font-weight: 600; + text-align: right; +} + +.leaderboard-date { + font-size: 0.85rem; + color: var(--text-secondary); + text-align: right; +} + +/* Top ranks */ +.leaderboard-table tr:nth-child(1) .leaderboard-rank { + color: gold; +} + +.leaderboard-table tr:nth-child(2) .leaderboard-rank { + color: silver; +} + +.leaderboard-table tr:nth-child(3) .leaderboard-rank { + color: #cd7f32; /* bronze */ +} + +/* Challenges styles */ +.challenges-container { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + +.challenge-card { + background-color: var(--bg-secondary); + border-radius: var(--radius); + padding: 1.25rem; + box-shadow: var(--shadow-sm); + position: relative; + overflow: hidden; + transition: all 0.2s ease; +} + +.challenge-card:hover { + transform: translateY(-3px); + box-shadow: var(--shadow); +} + +.challenge-card.daily { + border-left: 4px solid var(--primary); +} + +.challenge-card.weekly { + border-left: 4px solid var(--accent); +} + +.challenge-card.achievement { + border-left: 4px solid var(--success); +} + +.challenge-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 0.75rem; +} + +.challenge-title { + font-size: 1.1rem; + font-weight: 600; + margin: 0; +} + +.challenge-badge { + font-size: 0.9rem; + padding: 0.25rem 0.75rem; + border-radius: 99px; + background-color: var(--bg-primary); +} + +.challenge-badge.daily { + background-color: var(--primary-soft); + color: var(--primary); +} + +.challenge-badge.weekly { + background-color: var(--accent-soft); + color: var(--accent); +} + +.challenge-badge.achievement { + background-color: var(--success-soft); + color: var(--success); +} + +.challenge-description { + margin: 0.5rem 0; + color: var(--text-secondary); +} + +.challenge-progress { + margin-top: 1rem; +} + +.progress-bar-container { + width: 100%; + height: 0.5rem; + background-color: var(--bg-primary); + border-radius: var(--radius); + overflow: hidden; + margin: 0.5rem 0; +} + +.progress-bar-fill { + height: 100%; + background-color: var(--primary); + transition: width 0.3s ease; +} + +.progress-bar-fill.daily { + background-color: var(--primary); +} + +.progress-bar-fill.weekly { + background-color: var(--accent); +} + +.progress-bar-fill.achievement { + background-color: var(--success); +} + +.challenge-footer { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 1rem; +} + +.challenge-meta { + font-size: 0.85rem; + color: var(--text-secondary); +} + +.challenge-reward { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.challenge-points { + font-weight: 600; + color: var(--primary); +} + +.challenge-complete-btn { + padding: 0.5rem 1rem; + background-color: var(--primary); + color: white; + border: none; + border-radius: var(--radius); + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; +} + +.challenge-complete-btn:hover { + background-color: var(--primary-hover); + transform: translateY(-2px); +} + +.challenge-complete-btn:active { + transform: translateY(0); +} + +.challenge-complete-btn.completed { + background-color: var(--success); + pointer-events: none; +} + +.challenge-complete-btn.locked { + background-color: var(--bg-primary); + color: var(--text-secondary); + cursor: not-allowed; +} + +/* User profile stats */ +.user-stats { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 1rem; + margin-bottom: 1.5rem; +} + +.stat-card { + background-color: var(--bg-secondary); + border-radius: var(--radius); + padding: 1.25rem; + text-align: center; +} + +.stat-value { + font-size: 2rem; + font-weight: 700; + margin: 0.25rem 0; +} + +.stat-label { + color: var(--text-secondary); + font-size: 0.9rem; +} + +/* Streak indicator */ +.streak-container { + display: flex; + align-items: center; + gap: 1rem; + background-color: var(--bg-secondary); + border-radius: var(--radius); + padding: 0.75rem 1.25rem; + margin-bottom: 1.5rem; +} + +.streak-flame { + font-size: 1.5rem; +} + +.streak-info { + flex: 1; +} + +.streak-days { + font-weight: 600; + font-size: 1.1rem; +} + +.streak-subtitle { + font-size: 0.85rem; + color: var(--text-secondary); +} + +.streak-progress { + display: flex; + gap: 0.35rem; + margin-top: 0.5rem; +} + +.streak-day { + width: 0.75rem; + height: 0.75rem; + border-radius: 50%; + background-color: var(--bg-primary); +} + +.streak-day.active { + background-color: var(--primary); +} + +/* Achievements grid */ +.achievements-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); + gap: 1rem; + margin-top: 1rem; +} + +/* Responsive adjustments */ +@media (max-width: 768px) { + .user-stats { + grid-template-columns: repeat(2, 1fr); + } + + .challenge-header { + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; + } + + .challenge-footer { + flex-direction: column; + align-items: flex-start; + gap: 0.75rem; + } +} diff --git a/public/index.html b/public/index.html index dc82d9f..3a52a7b 100644 --- a/public/index.html +++ b/public/index.html @@ -9,6 +9,8 @@ + + @@ -22,6 +24,8 @@ + + @@ -459,6 +463,12 @@

Choose an activity to start practicing

+ +
+
+
+
+

🎨 Choose Your Theme

@@ -484,6 +494,46 @@
+ + +
+
+

🎯 Active Challenges

+
+
+
+ + +
+
+

🏆 Leaderboards

+
+
+
+ + +
+
+

📚 Spaced Repetition

+
+ +
+

How Spaced Repetition Works

+

Words you find difficult will appear more frequently, while words you know well will appear less often. This helps you learn more efficiently!

+
+ + +
+ + +
+ + +
+ + +
+
diff --git a/public/js/game.js b/public/js/game.js index 4f227aa..ffcf177 100644 --- a/public/js/game.js +++ b/public/js/game.js @@ -3,6 +3,7 @@ let words = []; let currentWord = ''; let currentIndex = 0; let results = []; +let isSpacedRepetitionMode = false; // 📝 Check user's answer and move to next window.submitAnswer = function() { const input = document.getElementById('userInput').value.trim(); @@ -73,7 +74,7 @@ function showStudent() { } // 🚀 Begin game session -window.startGame = async function() { +window.startGame = async function(customWords = null, isSpacedRepetition = false) { console.log('🎮 Starting spelling game'); const user = JSON.parse(localStorage.getItem('loggedInUser')); @@ -95,29 +96,43 @@ window.startGame = async function() { document.getElementById('summary')?.classList.add('hidden'); document.getElementById('badgeDisplay')?.classList.add('hidden'); - // Fetch words - const response = await fetch(`/getWordList?username=${user.username}`); - const data = await response.json(); - console.log('Received words:', data); - - let weekWords = []; - // If weeks format and activeWeek is set, use only that week's words - if (data.words && Array.isArray(data.words)) { - weekWords = data.words; - } else if (data.words && data.words.weeks && data.words.activeWeek) { - const active = data.words.activeWeek; - const found = data.words.weeks.find(w => w.date === active); - if (found) weekWords = found.words; + let wordList; + + // Use custom words if provided (for spaced repetition) + if (customWords && Array.isArray(customWords) && customWords.length > 0) { + wordList = customWords; + isSpacedRepetitionMode = isSpacedRepetition; + console.log('Using custom word list for spaced repetition:', wordList); + } else { + // Fetch words from user's word list + const response = await fetch(`/getWordList?username=${user.username}`); + const data = await response.json(); + console.log('Received words:', data); + + let weekWords = []; + // If weeks format and activeWeek is set, use only that week's words + if (data.words && Array.isArray(data.words)) { + weekWords = data.words; + } else if (data.words && data.words.weeks && data.words.activeWeek) { + const active = data.words.activeWeek; + const found = data.words.weeks.find(w => w.date === active); + if (found) weekWords = found.words; + } else if (Array.isArray(data)) { + // If data is already an array + weekWords = data; + } + + wordList = weekWords; } - if (!weekWords.length) { + if (!wordList.length) { alert('No words found for practice'); return; } // Start game - words = [...weekWords]; - typingWords = [...weekWords]; // Initialize typing words too + words = [...wordList]; + typingWords = [...wordList]; // Initialize typing words too currentIndex = 0; results = []; // Reset results array showWord(); @@ -176,7 +191,8 @@ function showSummary() { const summary = document.getElementById('summary'); let correct = 0; let missed = []; - + + // Process results to calculate correct answers and build a report const report = results.map(({ word, attempt }) => { const isCorrect = word.toLowerCase() === attempt.toLowerCase(); if (isCorrect) correct++; @@ -184,11 +200,33 @@ function showSummary() { return `
  • ${word} — ${attempt || '(no answer)'}
  • `; }).join(''); + // Create detailed results for spaced repetition processing + const detailedResults = results.map(({ word, attempt }) => { + return { + word, + correct: word.toLowerCase() === attempt.toLowerCase(), + attempt + }; + }); + + // Dispatch event for spaced repetition system if in SR mode + if (isSpacedRepetitionMode) { + const event = new CustomEvent('gameResultsAvailable', { + detail: { + isSpacedRepetition: true, + results: detailedResults + } + }); + document.dispatchEvent(event); + } + + // Build and display summary summary.innerHTML = `

    Results

    You got ${correct} out of ${words.length} correct (${Math.round((correct / words.length) * 100)}%)

    ${missed.length ? `` : ''} + ${isSpacedRepetitionMode ? `` : ''} `; summary.classList.remove('hidden'); diff --git a/public/js/gamification.js b/public/js/gamification.js new file mode 100644 index 0000000..7345051 --- /dev/null +++ b/public/js/gamification.js @@ -0,0 +1,501 @@ +/** + * Gamification features for Spelling Practice App + * - Leaderboards + * - Challenges & Achievements + * - Streaks + * - Points system + */ + +// Global variables for gamification +let userProgress = null; +let challenges = null; +let leaderboards = null; +let currentUser = null; + +// Initialize gamification features +document.addEventListener('DOMContentLoaded', function() { + // Event listener will be triggered when a user logs in + document.addEventListener('userLoggedIn', function(e) { + currentUser = e.detail.username; + initGamification(currentUser); + }); +}); + +// Main initialization function for gamification +async function initGamification(username) { + try { + // Fetch all required data + await Promise.all([ + fetchUserProgress(username), + fetchChallenges(), + fetchLeaderboards() + ]); + + // Update streak (marks user as active today) + await updateUserStreak(username); + + // Render all gamification components + renderStreakIndicator(); + renderUserStats(); + renderChallenges(); + renderLeaderboards(); + + console.log('🎮 Gamification features initialized'); + } catch (error) { + console.error('Error initializing gamification:', error); + } +} + +// Fetch user progress data +async function fetchUserProgress(username) { + try { + const response = await fetch(`/getUserProgress?username=${encodeURIComponent(username)}`); + if (!response.ok) { + throw new Error(`Failed to fetch user progress: ${response.status}`); + } + userProgress = await response.json(); + return userProgress; + } catch (error) { + console.error('Error fetching user progress:', error); + return null; + } +} + +// Fetch challenges data +async function fetchChallenges() { + try { + const response = await fetch('/getChallenges'); + if (!response.ok) { + throw new Error(`Failed to fetch challenges: ${response.status}`); + } + challenges = await response.json(); + return challenges; + } catch (error) { + console.error('Error fetching challenges:', error); + return null; + } +} + +// Fetch leaderboards data +async function fetchLeaderboards() { + try { + const response = await fetch('/getLeaderboards'); + if (!response.ok) { + throw new Error(`Failed to fetch leaderboards: ${response.status}`); + } + leaderboards = await response.json(); + return leaderboards; + } catch (error) { + console.error('Error fetching leaderboards:', error); + return null; + } +} + +// Update user streak +async function updateUserStreak(username) { + try { + const response = await fetch('/updateStreak', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ username }) + }); + + if (!response.ok) { + throw new Error(`Failed to update streak: ${response.status}`); + } + + const result = await response.json(); + + // Update local data + if (userProgress) { + userProgress.streaks = result.streak; + } + + return result; + } catch (error) { + console.error('Error updating streak:', error); + return null; + } +} + +// Complete a challenge +async function completeChallenge(challengeId, challengeType) { + if (!currentUser) { + console.error('No user logged in'); + return; + } + + try { + const response = await fetch('/completeChallenge', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + username: currentUser, + challengeId, + challengeType + }) + }); + + if (!response.ok) { + throw new Error(`Failed to complete challenge: ${response.status}`); + } + + const result = await response.json(); + + // Update local data + userProgress = result.updatedProgress; + + // Update UI + renderUserStats(); + renderChallenges(); + + // Show success message + showToast('Challenge completed!', 'success'); + + return result; + } catch (error) { + console.error('Error completing challenge:', error); + showToast('Failed to complete challenge', 'error'); + return null; + } +} + +// Render streak indicator in student panel +function renderStreakIndicator() { + const streakContainer = document.getElementById('streakContainer'); + if (!streakContainer || !userProgress) return; + + // Clear previous content + streakContainer.innerHTML = ''; + + const currentStreak = userProgress.streaks.current || 0; + + // Create streak element + const streakEl = document.createElement('div'); + streakEl.className = 'streak-container'; + + streakEl.innerHTML = ` +
    🔥
    +
    +
    ${currentStreak} Day${currentStreak === 1 ? '' : 's'}
    +
    ${currentStreak > 0 ? 'Current streak' : 'Start your streak today!'}
    +
    + ${Array.from({ length: 7 }, (_, i) => + `
    ` + ).join('')} +
    +
    +
    +
    Best
    +
    ${userProgress.streaks.longest || 0}
    +
    + `; + + streakContainer.appendChild(streakEl); +} + +// Render user stats in student panel +function renderUserStats() { + const statsContainer = document.getElementById('userStatsContainer'); + if (!statsContainer || !userProgress) return; + + // Clear previous content + statsContainer.innerHTML = ''; + + // Create stats container + const statsEl = document.createElement('div'); + statsEl.className = 'user-stats'; + + // Add stat cards + statsEl.innerHTML = ` +
    +
    ${userProgress.stats.points || 0}
    +
    Points
    +
    +
    +
    ${userProgress.stats.accuracy ? userProgress.stats.accuracy.toFixed(1) + '%' : '0%'}
    +
    Accuracy
    +
    +
    +
    ${userProgress.stats.totalSessions || 0}
    +
    Sessions
    +
    +
    +
    ${userProgress.stats.totalWords || 0}
    +
    Words
    +
    + `; + + statsContainer.appendChild(statsEl); +} + +// Render challenges in student panel +function renderChallenges() { + const challengesContainer = document.getElementById('challengesContainer'); + if (!challengesContainer || !challenges || !userProgress) return; + + // Clear previous content + challengesContainer.innerHTML = ''; + + // Create challenges container + const challengesEl = document.createElement('div'); + challengesEl.className = 'challenges-container'; + + // Daily challenge + if (challenges.daily && challenges.daily.current) { + const dailyChallenge = challenges.daily.current; + const isCompleted = userProgress.challengesCompleted.daily.includes(dailyChallenge.id); + + challengesEl.appendChild(createChallengeCard(dailyChallenge, 'daily', isCompleted)); + } + + // Weekly challenge + if (challenges.weekly && challenges.weekly.current) { + const weeklyChallenge = challenges.weekly.current; + const isCompleted = userProgress.challengesCompleted.weekly.includes(weeklyChallenge.id); + + challengesEl.appendChild(createChallengeCard(weeklyChallenge, 'weekly', isCompleted)); + } + + // Achievement challenges (show only 3 unearned ones) + if (challenges.achievements && challenges.achievements.length > 0) { + const uncompletedAchievements = challenges.achievements + .filter(achievement => !userProgress.challengesCompleted.achievements.includes(achievement.id)) + .slice(0, 3); + + uncompletedAchievements.forEach(achievement => { + challengesEl.appendChild(createChallengeCard(achievement, 'achievement', false)); + }); + } + + challengesContainer.appendChild(challengesEl); +} + +// Create a challenge card element +function createChallengeCard(challenge, type, isCompleted) { + const card = document.createElement('div'); + card.className = `challenge-card ${type}`; + card.dataset.id = challenge.id; + + // Calculate progress for the challenge + let progress = 0; + let progressText = ''; + + switch (challenge.type) { + case 'accuracy': + progress = userProgress.stats.accuracy ? Math.min(userProgress.stats.accuracy / challenge.target, 1) : 0; + progressText = `${userProgress.stats.accuracy ? userProgress.stats.accuracy.toFixed(1) : 0}% / ${challenge.target}%`; + break; + case 'words': + case 'correctWords': + progress = Math.min(userProgress.stats.correctWords / challenge.target, 1); + progressText = `${userProgress.stats.correctWords || 0} / ${challenge.target}`; + break; + case 'sessions': + progress = Math.min(userProgress.stats.totalSessions / challenge.target, 1); + progressText = `${userProgress.stats.totalSessions || 0} / ${challenge.target}`; + break; + case 'streak': + progress = Math.min(userProgress.streaks.current / challenge.target, 1); + progressText = `${userProgress.streaks.current || 0} / ${challenge.target}`; + break; + case 'perfectSessions': + // Would need to track this separately + progress = 0; + progressText = `0 / ${challenge.target}`; + break; + } + + // Format date for challenge time period + let timeframe = ''; + if (type === 'daily') { + timeframe = `Today (${new Date(challenge.date).toLocaleDateString()})`; + } else if (type === 'weekly') { + timeframe = `${new Date(challenge.startDate).toLocaleDateString()} - ${new Date(challenge.endDate).toLocaleDateString()}`; + } + + card.innerHTML = ` +
    +

    ${challenge.title}

    + ${ + type === 'daily' ? 'Daily' + : type === 'weekly' ? 'Weekly' + : 'Achievement' + } +
    +
    ${challenge.description}
    +
    +
    +
    +
    +
    + ${progressText} + ${Math.round(progress * 100)}% +
    +
    + + `; + + return card; +} + +// Render leaderboards in student panel +function renderLeaderboards() { + const leaderboardsContainer = document.getElementById('leaderboardsContainer'); + if (!leaderboardsContainer || !leaderboards) return; + + // Clear previous content + leaderboardsContainer.innerHTML = ''; + + // Create leaderboard container + const leaderboardEl = document.createElement('div'); + leaderboardEl.className = 'leaderboard-container'; + + // Create header with tabs + const header = document.createElement('div'); + header.className = 'leaderboard-header'; + header.innerHTML = ` +

    Leaderboards

    +
    +
    Accuracy
    +
    Words
    +
    Streaks
    +
    + `; + + leaderboardEl.appendChild(header); + + // Create leaderboard table container + const tableContainer = document.createElement('div'); + tableContainer.id = 'leaderboardTableContainer'; + + // Initially show accuracy leaderboard + tableContainer.appendChild(createLeaderboardTable('accuracy')); + + leaderboardEl.appendChild(tableContainer); + leaderboardsContainer.appendChild(leaderboardEl); + + // Add event listeners for tabs + const tabs = header.querySelectorAll('.leaderboard-tab'); + tabs.forEach(tab => { + tab.addEventListener('click', function() { + // Remove active class from all tabs + tabs.forEach(t => t.classList.remove('active')); + + // Add active class to clicked tab + this.classList.add('active'); + + // Update table + const category = this.dataset.category; + tableContainer.innerHTML = ''; + tableContainer.appendChild(createLeaderboardTable(category)); + }); + }); +} + +// Create a leaderboard table for a specific category +function createLeaderboardTable(category) { + const table = document.createElement('table'); + table.className = 'leaderboard-table'; + + // Create table header + const thead = document.createElement('thead'); + thead.innerHTML = ` + + # + User + ${ + category === 'accuracy' ? 'Accuracy' + : category === 'totalWords' ? 'Words' + : category === 'sessionsCompleted' ? 'Sessions' + : 'Streak Days' + } + + `; + table.appendChild(thead); + + // Create table body + const tbody = document.createElement('tbody'); + + // Get leaderboard data + const data = leaderboards.allTime[category] || []; + + if (data.length === 0) { + const tr = document.createElement('tr'); + tr.innerHTML = 'No data available'; + tbody.appendChild(tr); + } else { + data.forEach((entry, index) => { + const tr = document.createElement('tr'); + tr.innerHTML = ` + ${index + 1} + ${entry.username}${entry.username === currentUser ? ' (You)' : ''} + ${ + category === 'accuracy' ? entry.value.toFixed(1) + '%' + : entry.value + } + `; + + // Highlight current user + if (entry.username === currentUser) { + tr.style.backgroundColor = 'var(--primary-soft)'; + } + + tbody.appendChild(tr); + }); + } + + table.appendChild(tbody); + return table; +} + +// Helper function to show toast messages +function showToast(message, type = 'info') { + // Check if toast container exists + let toastContainer = document.querySelector('.toast-container'); + if (!toastContainer) { + toastContainer = document.createElement('div'); + toastContainer.className = 'toast-container'; + document.body.appendChild(toastContainer); + } + + // Create toast + const toast = document.createElement('div'); + toast.className = `toast toast-${type}`; + toast.textContent = message; + + // Add to container + toastContainer.appendChild(toast); + + // Show toast with animation + setTimeout(() => toast.classList.add('show'), 10); + + // Remove after delay + setTimeout(() => { + toast.classList.remove('show'); + setTimeout(() => toast.remove(), 300); + }, 3000); +} + +// Expose functions to window for use in HTML +window.completeChallenge = completeChallenge; diff --git a/public/js/spaced-repetition.js b/public/js/spaced-repetition.js new file mode 100644 index 0000000..4c526a2 --- /dev/null +++ b/public/js/spaced-repetition.js @@ -0,0 +1,391 @@ +/** + * Spaced Repetition System for Spelling Practice App + * + * Based on the SM-2 algorithm (SuperMemo) with adaptations for spelling practice + * This system schedules words for review based on user performance + * Words are assigned difficulty levels and review intervals are adjusted accordingly + */ + +// Global variables +let spacedRepetitionData = null; +let currentUser = null; +let currentWords = []; +let reviewQueue = []; + +// Initialize the spaced repetition system +document.addEventListener('DOMContentLoaded', function() { + // Event listener will be triggered when a user logs in + document.addEventListener('userLoggedIn', function(e) { + currentUser = e.detail.username; + initializeSpacedRepetition(currentUser); + }); +}); + +// Main initialization function +async function initializeSpacedRepetition(username) { + try { + await fetchSpacedRepetitionData(username); + updateSpacedRepetitionUI(); + console.log('🔄 Spaced repetition system initialized'); + } catch (error) { + console.error('Error initializing spaced repetition:', error); + } +} + +// Fetch spaced repetition data for the current user +async function fetchSpacedRepetitionData(username) { + try { + const response = await fetch(`/getSpacedRepetitionData?username=${encodeURIComponent(username)}`); + if (!response.ok) { + throw new Error(`Failed to fetch spaced repetition data: ${response.status}`); + } + spacedRepetitionData = await response.json(); + + // If there are words due for review today, add them to the review queue + buildReviewQueue(); + + return spacedRepetitionData; + } catch (error) { + console.error('Error fetching spaced repetition data:', error); + return null; + } +} + +// Build a queue of words that are due for review +function buildReviewQueue() { + if (!spacedRepetitionData || !spacedRepetitionData.words) { + reviewQueue = []; + return; + } + + const today = new Date().toISOString().split('T')[0]; + reviewQueue = Object.entries(spacedRepetitionData.words) + .filter(([_, wordData]) => { + return wordData.nextReview && wordData.nextReview <= today; + }) + .map(([word, wordData]) => ({ + word, + easeFactor: wordData.easeFactor, + interval: wordData.interval, + repetitions: wordData.repetitions, + lastReview: wordData.lastReview, + nextReview: wordData.nextReview, + priority: calculatePriority(wordData) + })) + .sort((a, b) => b.priority - a.priority); // Sort by priority (highest first) +} + +// Calculate priority for a word based on how overdue it is and its difficulty +function calculatePriority(wordData) { + if (!wordData.nextReview) return 0; + + const today = new Date(); + const nextReview = new Date(wordData.nextReview); + const daysOverdue = Math.max(0, (today - nextReview) / (1000 * 60 * 60 * 24)); + + // Priority increases with days overdue and decreases with ease factor + // This prioritizes difficult, overdue words + return daysOverdue * (5 - wordData.easeFactor); +} + +// Update the UI to show spaced repetition information +function updateSpacedRepetitionUI() { + const srStatsContainer = document.getElementById('srStatsContainer'); + if (!srStatsContainer || !spacedRepetitionData) return; + + // Clear previous content + srStatsContainer.innerHTML = ''; + + // Create stats container + const statsDiv = document.createElement('div'); + statsDiv.className = 'sr-stats'; + + const todayCount = reviewQueue.length; + const masteredCount = Object.values(spacedRepetitionData.words || {}) + .filter(word => word.easeFactor >= 2.5 && word.repetitions >= 5).length; + const totalCount = Object.keys(spacedRepetitionData.words || {}).length; + + statsDiv.innerHTML = ` +
    +
    ${todayCount}
    +
    Due Today
    +
    +
    +
    ${masteredCount}
    +
    Mastered
    +
    +
    +
    ${totalCount}
    +
    Total Words
    +
    + `; + + srStatsContainer.appendChild(statsDiv); + + // Update review button state + const reviewButton = document.getElementById('startSpacedReviewBtn'); + if (reviewButton) { + if (todayCount > 0) { + reviewButton.classList.remove('disabled'); + reviewButton.innerHTML = `🔄 Start Review (${todayCount})`; + } else { + reviewButton.classList.add('disabled'); + reviewButton.innerHTML = '✓ All Caught Up'; + } + } + + // Update progress visualization + updateProgressVisualization(); +} + +// Update the progress visualization +function updateProgressVisualization() { + const progressContainer = document.getElementById('srProgressContainer'); + if (!progressContainer || !spacedRepetitionData || !spacedRepetitionData.words) return; + + // Clear previous content + progressContainer.innerHTML = ''; + + const words = Object.entries(spacedRepetitionData.words); + if (words.length === 0) { + progressContainer.innerHTML = '

    No words in your spaced repetition system yet.

    '; + return; + } + + // Create progress visualization + const progressDiv = document.createElement('div'); + progressDiv.className = 'sr-progress-visualization'; + + // Group words by mastery level + const levels = { + 'New': words.filter(([_, w]) => w.repetitions === 0).length, + 'Learning': words.filter(([_, w]) => w.repetitions > 0 && w.repetitions < 3).length, + 'Reviewing': words.filter(([_, w]) => w.repetitions >= 3 && w.repetitions < 5).length, + 'Mastered': words.filter(([_, w]) => w.repetitions >= 5).length + }; + + const totalWords = Object.values(levels).reduce((sum, count) => sum + count, 0); + + // Create progress bar + const progressBar = document.createElement('div'); + progressBar.className = 'sr-progress-bar'; + + const colors = { + 'New': '#ff6b6b', + 'Learning': '#feca57', + 'Reviewing': '#54a0ff', + 'Mastered': '#1dd1a1' + }; + + Object.entries(levels).forEach(([level, count]) => { + if (count === 0) return; + + const percentage = (count / totalWords) * 100; + const segment = document.createElement('div'); + segment.className = 'sr-progress-segment'; + segment.style.width = `${percentage}%`; + segment.style.backgroundColor = colors[level]; + segment.title = `${level}: ${count} words (${percentage.toFixed(1)}%)`; + + progressBar.appendChild(segment); + }); + + // Create legend + const legend = document.createElement('div'); + legend.className = 'sr-legend'; + + Object.entries(levels).forEach(([level, count]) => { + const legendItem = document.createElement('div'); + legendItem.className = 'sr-legend-item'; + + legendItem.innerHTML = ` + + ${level}: ${count} + `; + + legend.appendChild(legendItem); + }); + + progressDiv.appendChild(progressBar); + progressDiv.appendChild(legend); + progressContainer.appendChild(progressDiv); +} + +// Start a spaced repetition review session +async function startSpacedReview() { + if (reviewQueue.length === 0) { + showToast('No words to review right now!', 'info'); + return; + } + + // Hide student panel and show game section + document.getElementById('studentPanel').classList.add('hidden'); + document.getElementById('gameSection').classList.remove('hidden'); + + // Update UI to indicate this is a spaced repetition session + document.querySelector('#gameSection h3').textContent = '🔄 Spaced Repetition Review'; + + // Prepare words for the session (take up to 10 words from the queue) + currentWords = reviewQueue.slice(0, 10).map(item => item.word); + + // Start the game with these words + await startGame(currentWords, true); +} + +// Process results from a spaced repetition session +function processSpacedRepetitionResults(results) { + if (!currentUser || !spacedRepetitionData || !results || results.length === 0) return; + + const now = new Date(); + const today = now.toISOString().split('T')[0]; + + // Process each word from the results + results.forEach(result => { + const word = result.word; + const correct = result.correct; + + // If word doesn't exist in the system yet, initialize it + if (!spacedRepetitionData.words[word]) { + spacedRepetitionData.words[word] = { + easeFactor: 2.5, // Initial ease factor + interval: 0, // Initial interval (0 = first time) + repetitions: 0, // Number of successful reviews + lastReview: null, + nextReview: null + }; + } + + const wordData = spacedRepetitionData.words[word]; + + // Apply SM-2 algorithm + if (correct) { + // Update based on correct answer + if (wordData.repetitions === 0) { + // First successful review + wordData.interval = 1; + } else if (wordData.repetitions === 1) { + // Second successful review + wordData.interval = 6; + } else { + // Subsequent successful reviews - increase interval + wordData.interval = Math.round(wordData.interval * wordData.easeFactor); + } + + // Increment repetitions counter + wordData.repetitions += 1; + + // Adjust ease factor (make it slightly easier if correct) + wordData.easeFactor = Math.max(1.3, wordData.easeFactor + 0.1); + } else { + // Reset on incorrect answer + wordData.repetitions = 0; + wordData.interval = 1; + + // Make it harder if incorrect + wordData.easeFactor = Math.max(1.3, wordData.easeFactor - 0.2); + } + + // Update review dates + wordData.lastReview = today; + + // Calculate next review date + const nextDate = new Date(now); + nextDate.setDate(nextDate.getDate() + wordData.interval); + wordData.nextReview = nextDate.toISOString().split('T')[0]; + }); + + // Save updated data to the server + saveSpacedRepetitionData(); + + // Update the queue and UI + buildReviewQueue(); + updateSpacedRepetitionUI(); +} + +// Save the updated spaced repetition data to the server +async function saveSpacedRepetitionData() { + if (!currentUser || !spacedRepetitionData) return; + + try { + const response = await fetch('/updateSpacedRepetitionData', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + username: currentUser, + data: spacedRepetitionData + }) + }); + + if (!response.ok) { + throw new Error(`Failed to update spaced repetition data: ${response.status}`); + } + + return true; + } catch (error) { + console.error('Error saving spaced repetition data:', error); + return false; + } +} + +// Import new words to the spaced repetition system from a word list +async function importWordsToSR() { + if (!currentUser || !spacedRepetitionData) return; + + try { + // Get user's word lists + const response = await fetch(`/getWordlistsForUser?username=${encodeURIComponent(currentUser)}`); + if (!response.ok) { + throw new Error(`Failed to fetch wordlists: ${response.status}`); + } + + const wordlists = await response.json(); + if (!wordlists || !Array.isArray(wordlists) || wordlists.length === 0) { + showToast('No word lists found', 'error'); + return; + } + + // For simplicity, let's import all words from the user's word list + const allWords = [...new Set(wordlists)]; // Remove duplicates + + // Add each word to the spaced repetition system if not already present + let newWordsCount = 0; + allWords.forEach(word => { + if (!spacedRepetitionData.words[word]) { + spacedRepetitionData.words[word] = { + easeFactor: 2.5, + interval: 0, + repetitions: 0, + lastReview: null, + nextReview: new Date().toISOString().split('T')[0] // Due immediately + }; + newWordsCount++; + } + }); + + // Save the updated data + await saveSpacedRepetitionData(); + + // Update UI + buildReviewQueue(); + updateSpacedRepetitionUI(); + + showToast(`Added ${newWordsCount} new words to your spaced repetition system`, 'success'); + } catch (error) { + console.error('Error importing words:', error); + showToast('Failed to import words', 'error'); + } +} + +// Export functions to window for use in HTML +window.startSpacedReview = startSpacedReview; +window.importWordsToSR = importWordsToSR; + +// Register a handler for when game results are available +document.addEventListener('gameResultsAvailable', function(e) { + // Only process if this was a spaced repetition session + if (e.detail.isSpacedRepetition) { + processSpacedRepetitionResults(e.detail.results); + } +}); diff --git a/public/spaced-repetition.css b/public/spaced-repetition.css new file mode 100644 index 0000000..a59a037 --- /dev/null +++ b/public/spaced-repetition.css @@ -0,0 +1,233 @@ +/* Spaced Repetition System Styles */ + +.sr-container { + margin-top: 1.5rem; +} + +.sr-stats { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1rem; + margin-bottom: 1.5rem; +} + +.sr-stat-card { + background-color: var(--card-bg); + border-radius: 8px; + padding: 1rem; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + transition: transform 0.2s ease; +} + +.sr-stat-card:hover { + transform: translateY(-3px); +} + +.sr-stat-value { + font-size: 1.8rem; + font-weight: 700; + color: var(--primary); + margin-bottom: 0.3rem; +} + +.sr-stat-label { + color: var(--text-secondary); + font-size: 0.9rem; +} + +.sr-actions { + display: flex; + gap: 1rem; + margin: 1.5rem 0; + justify-content: center; +} + +.sr-actions button { + padding: 0.75rem 1.5rem; + font-size: 1rem; + border-radius: 8px; + cursor: pointer; + transition: all 0.2s ease; + border: none; +} + +.sr-actions button.disabled { + opacity: 0.7; + cursor: not-allowed; +} + +.sr-progress-visualization { + margin-top: 1.5rem; +} + +.sr-progress-bar { + height: 24px; + border-radius: 12px; + overflow: hidden; + display: flex; + width: 100%; + background-color: var(--card-bg); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.sr-progress-segment { + height: 100%; + transition: width 0.3s ease; +} + +.sr-legend { + display: flex; + justify-content: center; + flex-wrap: wrap; + gap: 1rem; + margin-top: 0.75rem; +} + +.sr-legend-item { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.85rem; +} + +.sr-legend-color { + width: 12px; + height: 12px; + border-radius: 3px; + display: inline-block; +} + +.sr-legend-label { + color: var(--text-secondary); +} + +.sr-calendar { + margin-top: 2rem; +} + +.sr-calendar-title { + font-size: 1.2rem; + font-weight: 600; + margin-bottom: 1rem; + text-align: center; +} + +.sr-calendar-grid { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 0.5rem; +} + +.sr-calendar-header { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 0.5rem; + margin-bottom: 0.5rem; +} + +.sr-calendar-header-cell { + text-align: center; + font-weight: 600; + font-size: 0.8rem; + color: var(--text-secondary); +} + +.sr-calendar-day { + aspect-ratio: 1; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + font-size: 0.9rem; + position: relative; + background-color: var(--card-bg); + cursor: default; +} + +.sr-calendar-day.has-reviews { + background-color: var(--primary-soft); + color: var(--primary); + font-weight: 600; +} + +.sr-calendar-day.today { + border: 2px solid var(--primary); + color: var(--primary); + font-weight: 700; +} + +.sr-calendar-day .count { + position: absolute; + top: 2px; + right: 2px; + font-size: 0.7rem; + background-color: var(--primary); + color: white; + width: 16px; + height: 16px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; +} + +.sr-no-words { + text-align: center; + padding: 2rem; + color: var(--text-secondary); +} + +.sr-import-section { + margin-top: 2rem; + text-align: center; +} + +.sr-info { + background-color: var(--info-light); + border-left: 4px solid var(--info); + padding: 1rem; + border-radius: 4px; + margin: 1.5rem 0; +} + +.sr-info h4 { + color: var(--info); + margin-top: 0; + margin-bottom: 0.5rem; +} + +.sr-info p { + margin: 0; + font-size: 0.9rem; + color: var(--text-secondary); +} + +.sr-difficulty { + display: flex; + align-items: center; + gap: 0.5rem; + margin-top: 0.5rem; +} + +.sr-difficulty-label { + font-size: 0.8rem; + color: var(--text-secondary); +} + +.sr-difficulty-bar { + flex: 1; + height: 6px; + background-color: #eee; + border-radius: 3px; + overflow: hidden; +} + +.sr-difficulty-fill { + height: 100%; + background: linear-gradient(to right, #1dd1a1, #feca57, #ff6b6b); +} diff --git a/seed/spacedRepetition.json b/seed/spacedRepetition.json new file mode 100644 index 0000000..10fa426 --- /dev/null +++ b/seed/spacedRepetition.json @@ -0,0 +1,152 @@ +{ + "nate": { + "settings": { + "dailyLimit": 20, + "reviewThreshold": 3, + "newWordsPerDay": 5 + }, + "stats": { + "totalReviews": 15, + "correctReviews": 12, + "totalWords": 25, + "masteredWords": 5 + }, + "words": { + "computer": { + "easeFactor": 2.5, + "interval": 3, + "repetitions": 3, + "lastReview": "2025-08-10", + "nextReview": "2025-08-13" + }, + "keyboard": { + "easeFactor": 2.3, + "interval": 2, + "repetitions": 2, + "lastReview": "2025-08-11", + "nextReview": "2025-08-13" + }, + "mouse": { + "easeFactor": 2.8, + "interval": 4, + "repetitions": 4, + "lastReview": "2025-08-09", + "nextReview": "2025-08-13" + }, + "screen": { + "easeFactor": 3.0, + "interval": 6, + "repetitions": 5, + "lastReview": "2025-08-07", + "nextReview": "2025-08-13" + }, + "printer": { + "easeFactor": 2.2, + "interval": 1, + "repetitions": 1, + "lastReview": "2025-08-12", + "nextReview": "2025-08-13" + } + } + }, + "student1": { + "settings": { + "dailyLimit": 20, + "reviewThreshold": 3, + "newWordsPerDay": 5 + }, + "stats": { + "totalReviews": 8, + "correctReviews": 6, + "totalWords": 10, + "masteredWords": 2 + }, + "words": { + "apple": { + "easeFactor": 2.6, + "interval": 3, + "repetitions": 3, + "lastReview": "2025-08-10", + "nextReview": "2025-08-13" + }, + "banana": { + "easeFactor": 2.4, + "interval": 2, + "repetitions": 2, + "lastReview": "2025-08-11", + "nextReview": "2025-08-13" + }, + "cherry": { + "easeFactor": 2.7, + "interval": 5, + "repetitions": 4, + "lastReview": "2025-08-08", + "nextReview": "2025-08-13" + }, + "date": { + "easeFactor": 3.0, + "interval": 7, + "repetitions": 5, + "lastReview": "2025-08-06", + "nextReview": "2025-08-13" + }, + "elderberry": { + "easeFactor": 1.8, + "interval": 1, + "repetitions": 1, + "lastReview": "2025-08-12", + "nextReview": "2025-08-13" + } + } + }, + "admin1": { + "settings": { + "dailyLimit": 20, + "reviewThreshold": 3, + "newWordsPerDay": 5 + }, + "stats": { + "totalReviews": 10, + "correctReviews": 9, + "totalWords": 5, + "masteredWords": 3 + }, + "words": { + "administration": { + "easeFactor": 2.5, + "interval": 3, + "repetitions": 3, + "lastReview": "2025-08-10", + "nextReview": "2025-08-13" + }, + "education": { + "easeFactor": 2.8, + "interval": 4, + "repetitions": 4, + "lastReview": "2025-08-09", + "nextReview": "2025-08-13" + }, + "technology": { + "easeFactor": 2.3, + "interval": 2, + "repetitions": 2, + "lastReview": "2025-08-11", + "nextReview": "2025-08-13" + }, + "development": { + "easeFactor": 3.0, + "interval": 6, + "repetitions": 5, + "lastReview": "2025-08-07", + "nextReview": "2025-08-13" + }, + "programming": { + "easeFactor": 3.0, + "interval": 6, + "repetitions": 5, + "lastReview": "2025-08-07", + "nextReview": "2025-08-13" + } + } + } +} diff --git a/server.js b/server.js index bbf670f..20e8ad7 100644 --- a/server.js +++ b/server.js @@ -19,12 +19,67 @@ const DATA_DIR = path.join(__dirname, 'data'); const SEED_DIR = path.join(__dirname, 'seed'); if (!fs.existsSync(DATA_DIR)) fs.mkdirSync(DATA_DIR); +// Date utility functions for gamification features +function getWeekNumber(date) { + const firstDayOfYear = new Date(date.getFullYear(), 0, 1); + const pastDaysOfYear = (date - firstDayOfYear) / 86400000; + return Math.ceil((pastDaysOfYear + firstDayOfYear.getDay() + 1) / 7); +} + +function getWeekStartDate(date) { + const result = new Date(date); + result.setDate(result.getDate() - result.getDay()); + return result; +} + +function getWeekEndDate(date) { + const result = new Date(date); + result.setDate(result.getDate() + (6 - result.getDay())); + return result; +} + +function isToday(dateString) { + if (!dateString) return false; + const today = new Date().toISOString().split('T')[0]; + return dateString.split('T')[0] === today; +} + +function isSameDay(date1, date2) { + return date1.toISOString().split('T')[0] === date2.toISOString().split('T')[0]; +} + +function daysInARow(dateStrings) { + if (!dateStrings || !dateStrings.length) return 0; + + // Convert strings to Date objects + const dates = dateStrings.map(d => new Date(d)).sort((a, b) => a - b); + + let currentStreak = 1; + for (let i = 1; i < dates.length; i++) { + const prevDate = new Date(dates[i-1]); + prevDate.setDate(prevDate.getDate() + 1); + + // If consecutive days + if (isSameDay(prevDate, dates[i])) { + currentStreak++; + } else { + break; + } + } + + return currentStreak; +} + // 🗃 File mapping const files = { users: 'users.json', wordlists: 'wordlists.json', results: 'results.json', - badges: 'badges.json' + badges: 'badges.json', + leaderboards: 'leaderboards.json', + challenges: 'challenges.json', + progress: 'progress.json', + spacedRepetition: 'spacedRepetition.json' }; // 🌱 Initialize data from seeds if missing/empty @@ -82,6 +137,156 @@ function ensureFileWithSeed(name, fallback = '{}') { }; fs.writeFileSync(targetPath, JSON.stringify(defaultBadges, null, 2)); console.log(`🏆 Created default badge structure`); + } else if (name === 'leaderboards.json') { + const defaultLeaderboards = { + "allTime": { + "accuracy": [], + "totalWords": [], + "sessionsCompleted": [], + "streakDays": [] + }, + "weekly": { + "accuracy": [], + "totalWords": [], + "sessionsCompleted": [] + }, + "lastUpdated": new Date().toISOString() + }; + fs.writeFileSync(targetPath, JSON.stringify(defaultLeaderboards, null, 2)); + console.log(`🏅 Created default leaderboards structure`); + } else if (name === 'challenges.json') { + const today = new Date(); + const dayString = today.toISOString().split('T')[0]; + const weekNum = getWeekNumber(today); + const yearNum = today.getFullYear(); + + const defaultChallenges = { + "daily": { + "current": { + "id": `daily-${dayString}`, + "title": `${new Date().toLocaleDateString('en-US', { month: 'long', day: 'numeric' })} Challenge`, + "description": "Complete a spelling session with at least 90% accuracy", + "type": "accuracy", + "target": 90, + "reward": { + "points": 50, + "badge": null + }, + "date": dayString + }, + "history": [] + }, + "weekly": { + "current": { + "id": `weekly-${yearNum}-${weekNum}`, + "title": `Week ${weekNum} Challenge`, + "description": "Practice spelling for 5 consecutive days", + "type": "streak", + "target": 5, + "reward": { + "points": 100, + "badge": "Weekly Warrior" + }, + "startDate": getWeekStartDate(today).toISOString().split('T')[0], + "endDate": getWeekEndDate(today).toISOString().split('T')[0] + }, + "history": [] + }, + "achievements": [ + { + "id": "perfect-accuracy", + "title": "Perfect Accuracy", + "description": "Complete a session with 100% accuracy", + "type": "session", + "condition": "accuracy", + "target": 100, + "reward": { + "points": 75, + "badge": "Perfection" + } + }, + { + "id": "persistent-learner", + "title": "Persistent Learner", + "description": "Practice for 7 days in a row", + "type": "streak", + "condition": "dailyLogin", + "target": 7, + "reward": { + "points": 200, + "badge": "Persistence" + } + }, + { + "id": "spelling-veteran", + "title": "Spelling Veteran", + "description": "Complete 50 spelling sessions", + "type": "cumulative", + "condition": "sessions", + "target": 50, + "reward": { + "points": 300, + "badge": "Veteran" + } + } + ], + "lastUpdated": new Date().toISOString() + }; + fs.writeFileSync(targetPath, JSON.stringify(defaultChallenges, null, 2)); + console.log(`🎯 Created default challenges structure`); + } else if (name === 'progress.json') { + // Create empty progress structure for each user + const users = readJsonSafe(path.join(DATA_DIR, files.users), []); + const defaultProgress = {}; + + users.forEach(user => { + defaultProgress[user.username] = { + "stats": { + "points": 0, + "totalSessions": 0, + "totalWords": 0, + "correctWords": 0, + "accuracy": 0 + }, + "streaks": { + "current": 0, + "longest": 0, + "lastActivity": null + }, + "challengesCompleted": { + "daily": [], + "weekly": [], + "achievements": [] + } + }; + }); + + fs.writeFileSync(targetPath, JSON.stringify(defaultProgress, null, 2)); + console.log(`📈 Created default progress structure for ${Object.keys(defaultProgress).length} users`); + } else if (name === 'spacedRepetition.json') { + // Create empty spaced repetition structure for each user + const users = readJsonSafe(path.join(DATA_DIR, files.users), []); + const defaultSRData = {}; + + users.forEach(user => { + defaultSRData[user.username] = { + "settings": { + "dailyLimit": 20, + "reviewThreshold": 3, + "newWordsPerDay": 5 + }, + "stats": { + "totalReviews": 0, + "correctReviews": 0, + "totalWords": 0, + "masteredWords": 0 + }, + "words": {} + }; + }); + + fs.writeFileSync(targetPath, JSON.stringify(defaultSRData, null, 2)); + console.log(`📚 Created default spaced repetition structure for ${Object.keys(defaultSRData).length} users`); } else { fs.writeFileSync(targetPath, fallback); console.log(`📄 Initialized ${name} with default`); @@ -161,6 +366,55 @@ function initializeUserInAllFiles(username) { fs.writeFileSync(badgesPath, JSON.stringify(badges, null, 2)); console.log(`🏆 Added badge tracking for "${username}"`); } + + // Initialize in progress.json + const progressPath = path.join(DATA_DIR, files.progress); + const progress = readJsonSafe(progressPath, {}); + if (!progress[username]) { + progress[username] = { + stats: { + points: 0, + totalSessions: 0, + totalWords: 0, + correctWords: 0, + accuracy: 0 + }, + streaks: { + current: 0, + longest: 0, + lastActivity: null + }, + challengesCompleted: { + daily: [], + weekly: [], + achievements: [] + } + }; + fs.writeFileSync(progressPath, JSON.stringify(progress, null, 2)); + console.log(`📈 Added progress tracking for "${username}"`); + } + + // Initialize in spacedRepetition.json + const srPath = path.join(DATA_DIR, files.spacedRepetition); + const srData = readJsonSafe(srPath, {}); + if (!srData[username]) { + srData[username] = { + settings: { + dailyLimit: 20, + reviewThreshold: 3, + newWordsPerDay: 5 + }, + stats: { + totalReviews: 0, + correctReviews: 0, + totalWords: 0, + masteredWords: 0 + }, + words: {} + }; + fs.writeFileSync(srPath, JSON.stringify(srData, null, 2)); + console.log(`📚 Added spaced repetition data for "${username}"`); + } } // 🔐 Verify login @@ -384,6 +638,14 @@ app.get('/getResults', (req, res) => { res.json(results); }); +// Include gamification endpoints +const gamificationEndpoints = fs.readFileSync(path.join(__dirname, 'gamification-endpoints.js'), 'utf8'); +eval(gamificationEndpoints); + +// Include spaced repetition endpoints +const spacedRepetitionEndpoints = fs.readFileSync(path.join(__dirname, 'spaced-repetition-endpoints.js'), 'utf8'); +eval(spacedRepetitionEndpoints); + // 📈 Enhanced Analytics API endpoint app.get('/getAnalytics', (req, res) => { try { diff --git a/spaced-repetition-endpoints.js b/spaced-repetition-endpoints.js new file mode 100644 index 0000000..704e24c --- /dev/null +++ b/spaced-repetition-endpoints.js @@ -0,0 +1,157 @@ +/** + * Spaced Repetition System API endpoints for the Spelling Practice App + */ + +// Get spaced repetition data +app.get('/getSpacedRepetitionData', (req, res) => { + try { + const { username } = req.query; + if (!username) { + return res.status(400).json({ error: 'Username is required' }); + } + + // Get spaced repetition data + const srPath = path.join(DATA_DIR, files.spacedRepetition); + const srData = readJsonSafe(srPath, {}); + + // If user doesn't have data yet, initialize them + if (!srData[username]) { + srData[username] = { + settings: { + dailyLimit: 20, + reviewThreshold: 3, + newWordsPerDay: 5 + }, + stats: { + totalReviews: 0, + correctReviews: 0, + totalWords: 0, + masteredWords: 0 + }, + words: {} + }; + + // Save the new user data + fs.writeFileSync(srPath, JSON.stringify(srData, null, 2)); + console.log(`📚 Initialized spaced repetition data for "${username}"`); + } + + res.json(srData[username]); + } catch (error) { + console.error('Error getting spaced repetition data:', error); + res.status(500).json({ error: 'Failed to get spaced repetition data' }); + } +}); + +// Get word lists for a user (for importing into spaced repetition) +app.get('/getWordlistsForUser', (req, res) => { + try { + const { username } = req.query; + if (!username) { + return res.status(400).json({ error: 'Username is required' }); + } + + // Get word lists + const wordlistsPath = path.join(DATA_DIR, files.wordlists); + const wordlists = readJsonSafe(wordlistsPath, {}); + + // If user doesn't have a word list, return an empty array + if (!wordlists[username]) { + return res.json([]); + } + + res.json(wordlists[username]); + } catch (error) { + console.error('Error getting wordlists for user:', error); + res.status(500).json({ error: 'Failed to get wordlists' }); + } +}); + +// Update spaced repetition data +app.post('/updateSpacedRepetitionData', (req, res) => { + try { + const { username, data } = req.body; + if (!username || !data) { + return res.status(400).json({ error: 'Username and data are required' }); + } + + // Update data + const srPath = path.join(DATA_DIR, files.spacedRepetition); + const srData = readJsonSafe(srPath, {}); + + // Update user data + srData[username] = data; + + // Calculate stats + const words = Object.values(data.words || {}); + data.stats = { + totalReviews: words.reduce((sum, word) => sum + (word.repetitions || 0), 0), + correctReviews: words.reduce((sum, word) => sum + ((word.repetitions > 0) ? word.repetitions - 1 : 0), 0), + totalWords: words.length, + masteredWords: words.filter(word => word.repetitions >= 5).length + }; + + // Save updated data + fs.writeFileSync(srPath, JSON.stringify(srData, null, 2)); + + res.json({ success: true }); + } catch (error) { + console.error('Error updating spaced repetition data:', error); + res.status(500).json({ error: 'Failed to update spaced repetition data' }); + } +}); + +// Generate a spaced repetition review session +app.post('/generateSpacedRepetitionSession', (req, res) => { + try { + const { username, count = 10 } = req.body; + if (!username) { + return res.status(400).json({ error: 'Username is required' }); + } + + // Get spaced repetition data + const srPath = path.join(DATA_DIR, files.spacedRepetition); + const srData = readJsonSafe(srPath, {}); + + // If user doesn't exist, return an error + if (!srData[username]) { + return res.status(404).json({ error: 'User not found' }); + } + + const userData = srData[username]; + const today = new Date().toISOString().split('T')[0]; + + // Find words due for review + const dueWords = Object.entries(userData.words || {}) + .filter(([_, wordData]) => wordData.nextReview && wordData.nextReview <= today) + .map(([word, wordData]) => ({ + word, + easeFactor: wordData.easeFactor, + interval: wordData.interval, + priority: calculatePriority(wordData, today) + })) + .sort((a, b) => b.priority - a.priority) // Sort by priority (highest first) + .slice(0, count) // Take only the requested number of words + .map(item => item.word); + + res.json({ words: dueWords }); + } catch (error) { + console.error('Error generating spaced repetition session:', error); + res.status(500).json({ error: 'Failed to generate session' }); + } +}); + +// Helper function to calculate priority for a word +function calculatePriority(wordData, today) { + if (!wordData.nextReview) return 0; + + const nextReview = new Date(wordData.nextReview); + const todayDate = new Date(today); + const daysOverdue = Math.max(0, (todayDate - nextReview) / (1000 * 60 * 60 * 24)); + + // Priority increases with days overdue and decreases with ease factor + // This prioritizes difficult, overdue words + return daysOverdue * (5 - wordData.easeFactor); +} + +console.log('📚 Spaced repetition system endpoints initialized');