class LearningLogic { constructor() { this.currentDay = 1; this.maxDays = 10; this.rewardSystem = new RewardSystem(); this.utils = Utils; this.userProgress = this.loadUserProgress(); } loadUserProgress() { const defaultProgress = { totalScore: 0, completedLessons: [], quizScores: {}, exerciseScores: {}, lessonScores: {}, currentStreak: 0, lastActivityDate: null, achievements: [], level: 1, timeSpent: 0 }; const savedProgress = this.utils.loadFromLocalStorage('userProgress'); return { ...defaultProgress, ...savedProgress }; } saveUserProgress() { return this.utils.saveToLocalStorage('userProgress', this.userProgress); } async loadLesson(day) { try { const lessonData = await this.utils.loadJSON(`data/lessons/day${day}.json`); return lessonData; } catch (error) { console.error(`Error loading lesson day ${day}:`, error); return null; } } async loadQuiz(day) { try { const quizData = await this.utils.loadJSON(`data/quizzes/day${day}.json`); return quizData; } catch (error) { console.error(`Error loading quiz day ${day}:`, error); return null; } } async loadExercise(day) { try { const exerciseData = await this.utils.loadJSON(`data/exercises/day${day}.json`); return exerciseData; } catch (error) { console.error(`Error loading exercise day ${day}:`, error); return null; } } calculateStreak(results) { // محاسبه استریک بر اساس نتایج پی در پی صحیح let currentStreak = 0; let maxStreak = 0; for (const result of results) { if (result.isCorrect) { currentStreak++; maxStreak = Math.max(maxStreak, currentStreak); } else { currentStreak = 0; } } return maxStreak; } checkQuizAnswers(day, userAnswers, timeSpent = 0) { return this.loadQuiz(day).then(quizData => { if (!quizData) { throw new Error('Quiz data not found'); } let correctCount = 0; const results = []; quizData.questions.forEach((question, index) => { const userAnswer = userAnswers[index]; const isCorrect = userAnswer === question.correct_index; if (isCorrect) { correctCount++; } results.push({ questionId: question.id, questionText: question.question, userAnswer: userAnswer, correctAnswer: question.correct_index, isCorrect: isCorrect, explanation: question.explanation || '' }); }); const totalQuestions = quizData.questions.length; const streak = this.calculateStreak(results); const reward = this.rewardSystem.calculateQuizReward( correctCount, totalQuestions, timeSpent, streak ); // به‌روزرسانی پیشرفت کاربر this.updateUserProgress({ score: reward, completedQuiz: `day_${day}`, correctAnswers: correctCount, totalQuestions: totalQuestions }); const feedback = this.rewardSystem.getRewardFeedback( reward, totalQuestions * 3, 'quiz' ); return { results: results, correctCount: correctCount, totalQuestions: totalQuestions, reward: reward, feedback: feedback, streak: streak }; }); } checkExerciseAnswer(day, userAnswer) { return this.loadExercise(day).then(exerciseData => { if (!exerciseData) { throw new Error('Exercise data not found'); } const exercise = exerciseData.exercise; const userAnswerLower = userAnswer.toLowerCase(); let matches = 0; const matchedKeywords = []; exercise.expected_keywords.forEach(keyword => { const keywordLower = keyword.toLowerCase(); // جستجوی کلمات کلیدی در پاسخ کاربر if (userAnswerLower.includes(keywordLower)) { matches++; matchedKeywords.push(keyword); } }); const matchThreshold = exercise.match_threshold || 0.6; const isCorrect = matches >= exercise.expected_keywords.length * matchThreshold; const reward = this.rewardSystem.calculateExerciseReward( isCorrect, matches, exercise.expected_keywords.length, exercise.complexity || 1 ); // به‌روزرسانی پیشرفت کاربر if (isCorrect) { this.updateUserProgress({ score: reward, completedExercise: `day_${day}`, keywordMatches: matches, totalKeywords: exercise.expected_keywords.length }); } const feedback = this.rewardSystem.getRewardFeedback( reward, 25, 'exercise' ); return { isCorrect: isCorrect, matchedKeywords: matchedKeywords, expectedKeywords: exercise.expected_keywords, reward: reward, feedback: feedback, hint: exercise.hint || '' }; }); } completeLesson(day, duration, interactions = 0) { const reward = this.rewardSystem.calculateLessonReward(duration, interactions); this.updateUserProgress({ score: reward, completedLesson: day, lessonDuration: duration, interactions: interactions }); const feedback = this.rewardSystem.getRewardFeedback(reward, 20, 'lesson'); return { reward: reward, feedback: feedback, completed: true }; } updateUserProgress(updates) { const previousScore = this.userProgress.totalScore; const previousStreak = this.userProgress.currentStreak; // به‌روزرسانی امتیاز if (updates.score) { this.userProgress.totalScore += updates.score; } // به‌روزرسانی درس‌های تکمیل شده if (updates.completedLesson && !this.userProgress.completedLessons.includes(updates.completedLesson)) { this.userProgress.completedLessons.push(updates.completedLesson); } // به‌روزرسانی نتایج کوییز if (updates.completedQuiz) { this.userProgress.quizScores[updates.completedQuiz] = { score: updates.score, correctAnswers: updates.correctAnswers, totalQuestions: updates.totalQuestions, completedAt: new Date().toISOString() }; } // به‌روزرسانی نتایج تمرین if (updates.completedExercise) { this.userProgress.exerciseScores[updates.completedExercise] = { score: updates.score, keywordMatches: updates.keywordMatches, totalKeywords: updates.totalKeywords, completedAt: new Date().toISOString() }; } // به‌روزرسانی استریک this.updateStreak(); // بررسی دستاوردها this.checkAchievements(); // محاسبه سطح const levelInfo = this.rewardSystem.calculateLevel(this.userProgress.totalScore); this.userProgress.level = levelInfo.level; // ذخیره پیشرفت this.saveUserProgress(); // بازگشت اطلاعات تغییرات return { scoreIncrease: this.userProgress.totalScore - previousScore, streakIncrease: this.userProgress.currentStreak - previousStreak, newLevel: levelInfo.level !== Math.floor(this.rewardSystem.calculateLevel(previousScore).level), levelInfo: levelInfo }; } updateStreak() { const today = this.utils.getCurrentDate(); const lastActivity = this.userProgress.lastActivityDate; if (lastActivity === today) { return; // امروز قبلاً فعالیت داشته } if (!lastActivity) { // اولین فعالیت this.userProgress.currentStreak = 1; } else { const lastDate = new Date(lastActivity); const currentDate = new Date(today); const diffTime = currentDate - lastDate; const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24)); if (diffDays === 1) { // فعالیت متوالی this.userProgress.currentStreak++; } else if (diffDays > 1) { // شکستن استریک this.userProgress.currentStreak = 1; } } this.userProgress.lastActivityDate = today; } checkAchievements() { const achievements = []; const currentAchievements = this.userProgress.achievements || []; // دستاورد اولین درس if (this.userProgress.completedLessons.length >= 1 && !currentAchievements.includes('first_lesson')) { achievements.push('first_lesson'); } // دستاورد استاد کوییز const perfectQuizzes = Object.values(this.userProgress.quizScores) .filter(quiz => quiz.correctAnswers === quiz.totalQuestions).length; if (perfectQuizzes >= 5 && !currentAchievements.includes('quiz_master')) { achievements.push('quiz_master'); } // دستاورد تمرین کامل const completedExercises = Object.keys(this.userProgress.exerciseScores).length; if (completedExercises >= 3 && !currentAchievements.includes('exercise_pro')) { achievements.push('exercise_pro'); } // دستاورد استریک if (this.userProgress.currentStreak >= 7 && !currentAchievements.includes('week_streak')) { achievements.push('week_streak'); } // اضافه کردن دستاوردهای جدید achievements.forEach(achievement => { if (!currentAchievements.includes(achievement)) { this.userProgress.achievements.push(achievement); // اعطای پاداش دستاورد const reward = this.rewardSystem.getAchievementReward(achievement); this.userProgress.totalScore += reward; } }); return achievements; } getUserStats() { const completedLessons = this.userProgress.completedLessons.length; const completedQuizzes = Object.keys(this.userProgress.quizScores).length; const completedExercises = Object.keys(this.userProgress.exerciseScores).length; const totalQuizzes = Object.values(this.userProgress.quizScores).reduce( (sum, quiz) => sum + quiz.totalQuestions, 0 ); const correctQuizzes = Object.values(this.userProgress.quizScores).reduce( (sum, quiz) => sum + quiz.correctAnswers, 0 ); const accuracy = totalQuizzes > 0 ? (correctQuizzes / totalQuizzes) * 100 : 0; return { totalScore: this.userProgress.totalScore, level: this.userProgress.level, streak: this.userProgress.currentStreak, completedLessons: completedLessons, completedQuizzes: completedQuizzes, completedExercises: completedExercises, accuracy: Math.round(accuracy), achievements: this.userProgress.achievements.length, rank: this.rewardSystem.getRankTitle(this.userProgress.level) }; } resetProgress() { this.userProgress = { totalScore: 0, completedLessons: [], quizScores: {}, exerciseScores: {}, lessonScores: {}, currentStreak: 0, lastActivityDate: null, achievements: [], level: 1, timeSpent: 0 }; this.saveUserProgress(); return this.userProgress; } getLeaderboard(limit = 10) { // در این نسخه ساده، فقط کاربر فعلی نمایش داده می‌شود // در نسخه‌های آینده می‌توان از سرور استفاده کرد const stats = this.getUserStats(); return [{ username: 'شما', score: stats.totalScore, level: stats.level, rank: stats.rank, streak: stats.streak }]; } } // ایجاد نمونه اصلی const learningLogic = new LearningLogic();