/** * 数据统计和分析工具 */ const { Storage } = require('./storage.js') const { logger } = require('./logger.js') class Analytics { /** * 获取学习统计数据 */ static getStudyStats() { const gpaCourses = Storage.get('gpaCourses', []) const countdowns = Storage.get('countdowns', []) const favoriteCourses = Storage.get('favoriteCourses', []) const stats = { // GPA统计 gpa: { total: gpaCourses.length, average: this._calculateAverageGPA(gpaCourses), highest: this._getHighestScore(gpaCourses), lowest: this._getLowestScore(gpaCourses), trend: this._calculateGPATrend(gpaCourses) }, // 课程统计 courses: { total: favoriteCourses.length, byCategory: this._groupByCategory(gpaCourses), completionRate: this._calculateCompletionRate(gpaCourses) }, // 考试倒计时 exams: { total: countdowns.length, upcoming: countdowns.filter(c => c.days > 0).length, thisWeek: countdowns.filter(c => c.days <= 7 && c.days > 0).length }, // 学习时长统计(模拟数据) studyTime: { today: 0, week: 0, month: 0 } } return stats } /** * 计算平均GPA */ static _calculateAverageGPA(courses) { if (courses.length === 0) return 0 let totalPoints = 0 let totalCredits = 0 courses.forEach(course => { const gradePoint = this._scoreToGradePoint(course.score) totalPoints += gradePoint * course.credit totalCredits += course.credit }) return totalCredits > 0 ? (totalPoints / totalCredits).toFixed(2) : 0 } /** * 分数转绩点 */ static _scoreToGradePoint(score) { if (score >= 60) { return parseFloat((score / 10 - 5).toFixed(2)) } return 0 } /** * 获取最高分 */ static _getHighestScore(courses) { if (courses.length === 0) return 0 return Math.max(...courses.map(c => c.score)) } /** * 获取最低分 */ static _getLowestScore(courses) { if (courses.length === 0) return 0 return Math.min(...courses.map(c => c.score)) } /** * 计算GPA趋势 */ static _calculateGPATrend(courses) { if (courses.length < 2) return [] // 按时间排序(假设ID越大时间越新) const sorted = [...courses].sort((a, b) => a.id - b.id) const trend = [] let runningTotal = 0 let runningCredits = 0 sorted.forEach(course => { const gradePoint = this._scoreToGradePoint(course.score) runningTotal += gradePoint * course.credit runningCredits += course.credit const gpa = runningCredits > 0 ? (runningTotal / runningCredits).toFixed(2) : 0 trend.push({ name: course.name, gpa: parseFloat(gpa), score: course.score }) }) return trend } /** * 按分类分组 */ static _groupByCategory(courses) { const grouped = {} courses.forEach(course => { const category = course.category || '其他' if (!grouped[category]) { grouped[category] = { count: 0, totalScore: 0, avgScore: 0 } } grouped[category].count++ grouped[category].totalScore += course.score }) // 计算平均分 Object.keys(grouped).forEach(key => { grouped[key].avgScore = (grouped[key].totalScore / grouped[key].count).toFixed(1) }) return grouped } /** * 计算完成率 */ static _calculateCompletionRate(courses) { if (courses.length === 0) return 0 const passed = courses.filter(c => c.score >= 60).length return ((passed / courses.length) * 100).toFixed(1) } /** * 生成学习报告 */ static generateReport() { const stats = this.getStudyStats() const report = { summary: { gpa: stats.gpa.average, totalCourses: stats.courses.total, passRate: stats.courses.completionRate }, highlights: [], suggestions: [] } // 添加亮点 if (parseFloat(stats.gpa.average) >= 3.5) { report.highlights.push('GPA优秀,继续保持!') } if (parseFloat(stats.courses.completionRate) === 100) { report.highlights.push('所有课程全部通过,非常棒!') } // 添加建议 if (parseFloat(stats.gpa.average) < 2.5) { report.suggestions.push('建议加强学习,提高GPA') } if (stats.exams.thisWeek > 0) { report.suggestions.push(`本周有${stats.exams.thisWeek}场考试,请做好准备`) } logger.info('生成学习报告', report) return report } /** * 导出数据 */ static exportData() { const data = { gpaCourses: Storage.get('gpaCourses', []), favoriteCourses: Storage.get('favoriteCourses', []), schedule: Storage.get('schedule', {}), countdowns: Storage.get('countdowns', []), exportTime: new Date().toISOString() } logger.info('导出数据', { recordCount: data.gpaCourses.length }) return data } /** * 导入数据 */ static importData(data) { try { if (data.gpaCourses) { Storage.set('gpaCourses', data.gpaCourses) } if (data.favoriteCourses) { Storage.set('favoriteCourses', data.favoriteCourses) } if (data.schedule) { Storage.set('schedule', data.schedule) } if (data.countdowns) { Storage.set('countdowns', data.countdowns) } logger.info('导入数据成功', { recordCount: data.gpaCourses?.length || 0 }) return { success: true } } catch (error) { logger.error('导入数据失败', error) return { success: false, error } } } } /** * 智能推荐系统 */ class RecommendationEngine { /** * 推荐课程 */ static recommendCourses(allCourses, userCourses) { const recommendations = [] // 基于用户已选课程推荐相关课程 const userCategories = [...new Set(userCourses.map(c => c.category))] allCourses.forEach(course => { let score = 0 // 相同分类加分 if (userCategories.includes(course.category)) { score += 3 } // 热门课程加分 if (course.enrolled / course.capacity > 0.8) { score += 2 } // 高评分课程加分 if (course.rating && course.rating >= 4.5) { score += 2 } // 还有名额的课程加分 if (course.enrolled < course.capacity) { score += 1 } if (score > 0) { recommendations.push({ course, score, reason: this._getRecommendReason(score) }) } }) // 按分数排序 recommendations.sort((a, b) => b.score - a.score) return recommendations.slice(0, 5) } /** * 获取推荐理由 */ static _getRecommendReason(score) { if (score >= 6) return '强烈推荐' if (score >= 4) return '推荐' return '可以考虑' } /** * 学习建议 */ static getStudySuggestions(stats) { const suggestions = [] // GPA建议 if (parseFloat(stats.gpa.average) < 2.0) { suggestions.push({ type: 'gpa', level: 'warning', message: '当前GPA较低,建议加强学习', action: '查看学习计划' }) } else if (parseFloat(stats.gpa.average) >= 3.5) { suggestions.push({ type: 'gpa', level: 'success', message: 'GPA优秀,继续保持!', action: '分享经验' }) } // 考试提醒 if (stats.exams.thisWeek > 0) { suggestions.push({ type: 'exam', level: 'info', message: `本周有${stats.exams.thisWeek}场考试`, action: '查看倒计时' }) } return suggestions } } module.exports = { Analytics, RecommendationEngine }