286 lines
7.3 KiB
JavaScript
286 lines
7.3 KiB
JavaScript
/**
|
|
* 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();
|