import 'package:flutter/foundation.dart' show kIsWeb; import '../models/daily_stats.dart'; import '../models/app_usage.dart'; import '../database/app_usage_dao.dart'; import '../database/daily_stats_dao.dart'; import 'mock_data_service.dart'; class StatisticsService { final AppUsageDao _appUsageDao = AppUsageDao(); final DailyStatsDao _dailyStatsDao = DailyStatsDao(); // 获取今日统计(如果不存在则计算) Future getTodayStats() async { // Web 平台返回测试数据 if (kIsWeb) { return MockDataService.generateTodayStats(); } final today = DateTime.now(); // 先查数据库 var stats = await _dailyStatsDao.getTodayStats(); if (stats != null) { return stats; } // 如果不存在,计算并保存 stats = await _calculateDailyStats(today); if (stats != null) { await _dailyStatsDao.upsertDailyStats(stats); } else { // 如果没有数据,返回空统计 stats = DailyStats( date: today, totalTime: 0, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); } return stats; } // 计算指定日期的统计 Future _calculateDailyStats(DateTime date) async { final startOfDay = DateTime(date.year, date.month, date.day); final endOfDay = startOfDay.add(const Duration(days: 1)); // 获取该日期的所有应用使用记录 final appUsages = await _appUsageDao.getAppUsages( startTime: startOfDay, endTime: endOfDay, ); if (appUsages.isEmpty) return null; // 按分类聚合 final categoryTime = {}; int totalTime = 0; int appSwitchCount = 0; for (final usage in appUsages) { categoryTime[usage.category] = (categoryTime[usage.category] ?? 0) + usage.duration; totalTime += usage.duration; appSwitchCount += usage.deviceUnlockCount; } // 计算效率评分 final efficiencyScore = _calculateEfficiencyScore(categoryTime, totalTime); // 计算专注度评分 final focusScore = _calculateFocusScore(appSwitchCount, totalTime); return DailyStats( date: startOfDay, totalTime: totalTime, workTime: categoryTime['work'] ?? 0, studyTime: categoryTime['study'] ?? 0, entertainmentTime: categoryTime['entertainment'] ?? 0, socialTime: categoryTime['social'] ?? 0, toolTime: categoryTime['tool'] ?? 0, efficiencyScore: efficiencyScore, focusScore: focusScore, appSwitchCount: appSwitchCount, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); } // 计算效率评分 int _calculateEfficiencyScore(Map categoryTime, int totalTime) { if (totalTime == 0) return 0; // 工作时间占比(40%) final workRatio = (categoryTime['work'] ?? 0) / totalTime; final workScore = workRatio * 40; // 学习时间占比(30%) final studyRatio = (categoryTime['study'] ?? 0) / totalTime; final studyScore = studyRatio * 30; // 娱乐时间占比(越低越好,30%) final entertainmentRatio = (categoryTime['entertainment'] ?? 0) / totalTime; final entertainmentScore = (1 - entertainmentRatio) * 30; return (workScore + studyScore + entertainmentScore).round(); } // 计算专注度评分 int _calculateFocusScore(int appSwitchCount, int totalTime) { if (totalTime == 0) return 0; // 平均每小时切换次数 final switchesPerHour = (appSwitchCount / (totalTime / 3600)); // 理想情况:每小时切换 < 10 次 = 100分 // 每小时切换 > 50 次 = 0分 final score = 100 - (switchesPerHour * 2).clamp(0, 100); return score.round(); } // 获取本周统计 Future> getWeekStats() async { // Web 平台返回测试数据 if (kIsWeb) { return MockDataService.generateWeekStats(); } final stats = await _dailyStatsDao.getWeekStats(); // 如果数据不完整,计算缺失的日期 final now = DateTime.now(); final startOfWeek = now.subtract(Duration(days: now.weekday - 1)); final result = []; for (int i = 0; i < 7; i++) { final date = startOfWeek.add(Duration(days: i)); final existing = stats.firstWhere( (s) => s.date.year == date.year && s.date.month == date.month && s.date.day == date.day, orElse: () => DailyStats( date: date, totalTime: 0, createdAt: DateTime.now(), updatedAt: DateTime.now(), ), ); result.add(existing); } return result; } // 获取本月统计 Future> getMonthStats() async { return await _dailyStatsDao.getMonthStats(); } // 刷新今日统计(重新计算) Future refreshTodayStats() async { final today = DateTime.now(); final stats = await _calculateDailyStats(today); if (stats != null) { await _dailyStatsDao.upsertDailyStats(stats); return stats; } else { final emptyStats = DailyStats( date: today, totalTime: 0, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); await _dailyStatsDao.upsertDailyStats(emptyStats); return emptyStats; } } // 获取 Top 应用 Future> getTopApps({ required DateTime startTime, required DateTime endTime, int limit = 10, }) async { // Web 平台返回测试数据 if (kIsWeb) { return MockDataService.generateTopApps().take(limit).toList(); } return await _appUsageDao.getTopApps( startTime: startTime, endTime: endTime, limit: limit, ); } }