diff --git a/AITrainingPlanGenerator.swift b/AITrainingPlanGenerator.swift deleted file mode 100644 index b76b0e0a9..000000000 --- a/AITrainingPlanGenerator.swift +++ /dev/null @@ -1,356 +0,0 @@ -// AITrainingPlanGenerator.swift -// AI-powered personalized training plan generation for Nessa - -import Foundation -import Combine - -/// AI Training Plan Generator -/// Generates personalized workout plans based on user profile, fitness level, -/// workout history, and goals -@MainActor -class AITrainingPlanGenerator { - - // MARK: - Properties - - private let userService: UserServiceProtocol - private let workoutService: WorkoutServiceProtocol - private let analyticsService: AnalyticsServiceProtocol - private let rateLimiter = RateLimiter(maxRequests: 3, interval: 300) // 3 requests per 5 minutes - - private var cancellables = Set() - - // MARK: - Initialization - - init(userService: UserServiceProtocol = UserService.shared, - workoutService: WorkoutServiceProtocol = WorkoutService.shared, - analyticsService: AnalyticsServiceProtocol = AnalyticsService.shared) { - self.userService = userService - self.workoutService = workoutService - self.analyticsService = analyticsService - } - - // MARK: - Public Methods - - /// Generate a personalized training plan for the user - /// - Parameter goals: User's fitness goals (strength, endurance, weight loss, etc.) - /// - Parameter duration: Preferred weekly training duration in hours - /// - Parameter difficulty: Preferred difficulty level - /// - Returns: Generated training plan - func generatePlan(goals: [GoalType] = [], - duration: Double = 5.0, - difficulty: DifficultyLevel = .moderate) async throws -> TrainingPlan { - - guard rateLimiter.isAllowed() else { - throw RateLimitError.rateLimited - } - - let userProfile = await analyzeUserProfile() - let progressData = await analyzeProgress() - let recommendations = await generateRecommendations( - profile: userProfile, - goals: goals, - currentLevel: userProfile.fitnessLevel, - progress: progressData - ) - - return TrainingPlan( - id: UUID().uuidString, - userProfile: userProfile, - recommendations: recommendations, - duration: duration, - difficulty: difficulty, - generatedAt: Date(), - version: 1 - ) - } - - /// Analyze user profile and determine fitness level - func analyzeUserProfile() async throws -> UserProfile { - guard let user = await userService.currentUser else { - throw ProfileAnalysisError.noUserProfile - } - - let workoutHistory = await workoutService.getUserWorkoutHistory(limit: 50) - let performanceMetrics = await analyticsService.calculatePerformanceMetrics() - - // Determine fitness level based on workout frequency, intensity, and consistency - let workoutFrequency = Double(workoutHistory.count) / 30.0 // workouts per month - let avgIntensity = workoutHistory.map { $0.intensity }.average ?? 0.5 - let consistencyScore = calculateConsistency(workoutHistory) - - let fitnessLevel: FitnessLevel - if workoutFrequency >= 4 && avgIntensity >= 0.7 && consistencyScore >= 0.8 { - fitnessLevel = .advanced - } else if workoutFrequency >= 2 && avgIntensity >= 0.5 && consistencyScore >= 0.6 { - fitnessLevel = .intermediate - } else if workoutFrequency >= 1 && avgIntensity >= 0.3 && consistencyScore >= 0.4 { - fitnessLevel = .beginner - } else { - fitnessLevel = .absoluteBeginner - } - - return UserProfile( - userId: user.id, - name: user.name, - fitnessLevel: fitnessLevel, - workoutFrequency: workoutFrequency, - avgIntensity: avgIntensity, - consistencyScore: consistencyScore, - preferences: user.preferences ?? [], - injuries: user.injuries ?? [] - ) - } - - /// Analyze user's progress and trends - func analyzeProgress() async throws -> ProgressAnalysis { - let recentWorkouts = await workoutService.getRecentWorkouts(limit: 20) - let performanceTrends = await analyticsService.calculateTrends(recentWorkouts: recentWorkouts) - - return ProgressAnalysis( - totalWorkouts: recentWorkouts.count, - avgDuration: recentWorkouts.map { $0.duration }.average ?? 0, - avgCalories: recentWorkouts.map { $0.caloriesBurned }.average ?? 0, - improvementRate: performanceTrends.improvementRate, - consistencyStreak: performanceTrends.streak, - plateauDetected: performanceTrends.plateauDetected, - injuryRisk: performanceTrends.injuryRisk - ) - } - - /// Generate personalized recommendations - func generateRecommendations(profile: UserProfile, - goals: [GoalType], - currentLevel: FitnessLevel, - progress: ProgressAnalysis) async throws -> [Recommendation] { - - var recommendations: [Recommendation] = [] - - // Goal-based recommendations - for goal in goals { - switch goal { - case .strength: - recommendations.append(Recommendation( - type: .workout, - title: "Strength Training Focus", - description: "Incorporate 2-3 strength sessions per week with progressive overload", - priority: .high, - estimatedDuration: 60.0, - frequency: 2 - )) - case .endurance: - recommendations.append(Recommendation( - type: .workout, - title: "Endurance Building, - description: "Longer duration cardio with progressive distance increases", - priority: .high, - estimatedDuration: 90.0, - frequency: 3 - )) - case .weightLoss: - recommendations.append(Recommendation( - type: .workout, - title: "HIIT and Cardio Mix", - description: "High-intensity intervals mixed with moderate cardio", - priority: .high, - estimatedDuration: 45.0, - frequency: 4 - )) - case .flexibility: - recommendations.append(Recommendation( - type: .workout, - title: "Flexibility and Mobility", - description: "Daily stretching and mobility sessions", - priority: .medium, - estimatedDuration: 20.0, - frequency: 1 - )) - } - } - - // Level-appropriate recommendations - switch currentLevel { - case .absoluteBeginner: - recommendations.append(Recommendation( - type: .tutorial, - title: "Beginner Foundation Course", - description: "Complete the 4-week foundation program to build basic fitness", - priority: .high, - estimatedDuration: 30.0, - frequency: 3 - )) - - case .beginner: - recommendations.append(Recommendation( - type: .workout, - title: "Progressive Challenge Program", - description: "Gradually increase intensity each week", - priority: .medium, - estimatedDuration: 45.0, - frequency: 3 - )) - - case .intermediate: - recommendations.append(Recommendation( - type: .workout, - title: "Advanced Challenge Series", - description: "Introduce varied workout types and increased intensity", - priority: .medium, - estimatedDuration: 60.0, - frequency: 3 - )) - - case .advanced: - recommendations.append(Recommendation( - type: .workout, - title: "Elite Performance Program", - description: "Specialized training based on specific goals", - priority: .high, - estimatedDuration: 90.0, - frequency: 4 - )) - } - - // Progress-based adjustments - if progress.plateauDetected { - recommendations.append(Recommendation( - type: .adjustment, - title: "Break Through Plateau", - description: "Change workout variety and intensity to break through plateau", - priority: .high, - estimatedDuration: 0.0, - frequency: 0 - )) - } - - if progress.injuryRisk > 0.7 { - recommendations.append(Recommendation( - type: .caution, - title: "Injury Prevention Focus", - description: "Reduce intensity and focus on form; consult a professional", - priority: .critical, - estimatedDuration: 0.0, - frequency: 0 - )) - } - - // Filter by user preferences and injuries - recommendations = recommendations.filter { rec in - !rec.title.contains("Injury Prevention") || - (profile.injuries?.contains($0.title.lowercased()) ?? false) - } - - // Sort by priority - return recommendations.sorted { $0.priority > $1.priority } - } - - // MARK: - Helper Methods - - private func calculateConsistency(_ workouts: [Workout]) -> Double { - guard workouts.count > 0 else { return 0 } - - let workoutDates = workouts.map { $0.date } - let uniqueWeeks = Set(workoutDates.map { Calendar.current.component(.weekOfYear, from: $0) }) - let weeksActive = Calendar.current.dateComponents([.calendar], from: workoutDates.first!, to: workoutDates.last!).weekOfYear ?? 0 - - guard weeksActive > 0 else { return 0 } - - return Double(uniqueWeeks.count) / Double(weeksActive) - } - - private extension Double { - var average: Double { - guard count > 0 else { return 0 } - return sum / count - } - } - - // MARK: - Private Types - - private struct UserProfile { - let userId: String - let name: String - let fitnessLevel: FitnessLevel - let workoutFrequency: Double - let avgIntensity: Double - let consistencyScore: Double - let preferences: [String] - let injuries: [String] - } - - private struct ProgressAnalysis { - let totalWorkouts: Int - let avgDuration: Double - let avgCalories: Double - let improvementRate: Double - let consistencyStreak: Int - let plateauDetected: Bool - let injuryRisk: Double - } - - private struct Recommendation { - let type: RecommendationType - let title: String - let description: String - let priority: Priority - let estimatedDuration: Double - let frequency: Int - } - - private struct TrainingPlan { - let id: String - let userProfile: UserProfile - let recommendations: [Recommendation] - let duration: Double - let difficulty: DifficultyLevel - let generatedAt: Date - let version: Int - } - - // MARK: - Enums - - private enum GoalType { - case strength - case endurance - case weightLoss - case flexibility - } - - private enum DifficultyLevel { - case easy - case moderate - case hard - case elite - } - - private enum FitnessLevel { - case absoluteBeginner - case beginner - case intermediate - case advanced - } - - private enum Priority { - case critical > - case high > - case medium > - case low - } - - private enum RecommendationType { - case workout - case tutorial - case adjustment - case caution - } - - // MARK: - Errors - - private enum RateLimitError: Error { - case rateLimited - } - - private enum ProfileAnalysisError: Error { - case noUserProfile - case insufficientData - } -} \ No newline at end of file