package com.gym.service; import com.gym.model.TrainingPlan; import com.gym.model.User; import com.gym.repository.TrainingPlanRepository; import com.gym.repository.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.util.List; import java.util.Optional; // 需要导入的包 import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; @Service public class TrainingPlanService { @Autowired private TrainingPlanRepository trainingPlanRepository; @Autowired private UserRepository userRepository; // 创建训练计划 public TrainingPlan createPlan(TrainingPlan plan, Long memberId, Long coachId) { // 验证会员是否存在 User member = userRepository.findById(memberId) .orElseThrow(() -> new RuntimeException("会员不存在")); // 验证教练是否存在 User coach = userRepository.findById(coachId) .orElseThrow(() -> new RuntimeException("教练不存在")); // 验证角色 if (!"MEMBER".equals(member.getRole())) { throw new RuntimeException("该用户不是会员"); } if (!"COACH".equals(coach.getRole())) { throw new RuntimeException("该用户不是教练"); } plan.setMember(member); plan.setCoach(coach); plan.setCompletedDays(0); plan.setProgress(0.0); plan.setStatus("ACTIVE"); plan.setCreateTime(LocalDateTime.now()); plan.setUpdateTime(LocalDateTime.now()); // 如果提供了开始和结束日期,计算周期 if (plan.getStartDate() != null && plan.getEndDate() != null) { long days = ChronoUnit.DAYS.between(plan.getStartDate(), plan.getEndDate()); plan.setDurationWeeks((int) (days / 7)); } return trainingPlanRepository.save(plan); } // 获取所有训练计划 public List getAllPlans() { return trainingPlanRepository.findAll(); } // 根据ID获取训练计划 public Optional getPlanById(Long id) { return trainingPlanRepository.findById(id); } // 获取会员的训练计划 public List getMemberPlans(Long memberId) { return trainingPlanRepository.findByMemberId(memberId); } // 获取教练制定的训练计划 public List getCoachPlans(Long coachId) { return trainingPlanRepository.findByCoachId(coachId); } // 获取活跃的训练计划 public List getActivePlansByMember(Long memberId) { return trainingPlanRepository.findActivePlansByMember(memberId); } // 更新训练计划 public TrainingPlan updatePlan(Long id, TrainingPlan updatedPlan) { return trainingPlanRepository.findById(id) .map(plan -> { if (updatedPlan.getGoal() != null) { plan.setGoal(updatedPlan.getGoal()); } if (updatedPlan.getDailyPlan() != null) { plan.setDailyPlan(updatedPlan.getDailyPlan()); } if (updatedPlan.getDietAdvice() != null) { plan.setDietAdvice(updatedPlan.getDietAdvice()); } if (updatedPlan.getTrainingContent() != null) { plan.setTrainingContent(updatedPlan.getTrainingContent()); } if (updatedPlan.getRestDays() != null) { plan.setRestDays(updatedPlan.getRestDays()); } if (updatedPlan.getDifficultyLevel() != null) { plan.setDifficultyLevel(updatedPlan.getDifficultyLevel()); } if (updatedPlan.getWarmupSuggestions() != null) { plan.setWarmupSuggestions(updatedPlan.getWarmupSuggestions()); } if (updatedPlan.getCooldownSuggestions() != null) { plan.setCooldownSuggestions(updatedPlan.getCooldownSuggestions()); } if (updatedPlan.getPrecautions() != null) { plan.setPrecautions(updatedPlan.getPrecautions()); } plan.setUpdateTime(LocalDateTime.now()); return trainingPlanRepository.save(plan); }) .orElseThrow(() -> new RuntimeException("训练计划不存在")); } // 更新训练进度 public TrainingPlan updateProgress(Long id, Integer completedDays) { return trainingPlanRepository.findById(id) .map(plan -> { plan.setCompletedDays(completedDays); // 计算进度 if (plan.getDurationWeeks() != null && plan.getDurationWeeks() > 0) { int totalDays = plan.getDurationWeeks() * 7; double progress = (double) completedDays / totalDays * 100; plan.setProgress(Math.min(progress, 100.0)); // 如果进度达到100%,标记为完成 if (progress >= 100) { plan.setStatus("COMPLETED"); } } plan.setUpdateTime(LocalDateTime.now()); return trainingPlanRepository.save(plan); }) .orElseThrow(() -> new RuntimeException("训练计划不存在")); } // 标记为完成 public TrainingPlan markAsCompleted(Long id) { return trainingPlanRepository.findById(id) .map(plan -> { plan.setStatus("COMPLETED"); plan.setProgress(100.0); plan.setUpdateTime(LocalDateTime.now()); return trainingPlanRepository.save(plan); }) .orElseThrow(() -> new RuntimeException("训练计划不存在")); } // 暂停训练计划 public TrainingPlan pausePlan(Long id) { return trainingPlanRepository.findById(id) .map(plan -> { plan.setStatus("PAUSED"); plan.setUpdateTime(LocalDateTime.now()); return trainingPlanRepository.save(plan); }) .orElseThrow(() -> new RuntimeException("训练计划不存在")); } // 恢复训练计划 public TrainingPlan resumePlan(Long id) { return trainingPlanRepository.findById(id) .map(plan -> { plan.setStatus("ACTIVE"); plan.setUpdateTime(LocalDateTime.now()); return trainingPlanRepository.save(plan); }) .orElseThrow(() -> new RuntimeException("训练计划不存在")); } // AI训练推荐(基于简单规则) public String recommendTraining(User member) { String goal = member.getFitnessGoal(); Double weight = member.getWeight(); Double height = member.getHeight(); Integer age = member.getAge(); if (goal == null) { goal = "保持健康"; } StringBuilder recommendation = new StringBuilder(); recommendation.append("💪 基于您的信息,推荐训练计划:\n\n"); // 计算BMI if (height != null && weight != null && height > 0) { double bmi = weight / ((height / 100) * (height / 100)); recommendation.append("📊 您的BMI: ").append(String.format("%.1f", bmi)).append("\n"); if (bmi < 18.5) { recommendation.append("⚠️ 体重偏轻,建议增加肌肉训练\n"); } else if (bmi > 24) { recommendation.append("⚠️ 体重偏重,建议增加有氧运动\n"); } } // 基于目标推荐 switch (goal.toLowerCase()) { case "减脂": recommendation.append("🎯 目标:减脂\n"); recommendation.append("🏃 训练建议:\n"); recommendation.append(" • 每周4-5次有氧运动(跑步、游泳、动感单车)\n"); recommendation.append(" • 每次45-60分钟\n"); recommendation.append(" • 心率保持在120-150次/分钟\n"); recommendation.append(" • 配合力量训练,每周2-3次\n"); recommendation.append("🍎 饮食建议:\n"); recommendation.append(" • 控制碳水化合物摄入\n"); recommendation.append(" • 增加蛋白质摄入\n"); recommendation.append(" • 多喝水,少喝含糖饮料\n"); break; case "增肌": recommendation.append("🎯 目标:增肌\n"); recommendation.append("🏋️ 训练建议:\n"); recommendation.append(" • 每周4-5次力量训练\n"); recommendation.append(" • 重点训练:卧推、深蹲、硬拉、引体向上\n"); recommendation.append(" • 每组8-12次,每个动作3-4组\n"); recommendation.append(" • 组间休息60-90秒\n"); recommendation.append("🍗 饮食建议:\n"); recommendation.append(" • 增加蛋白质摄入(体重×1.5-2克/天)\n"); recommendation.append(" • 适量碳水化合物提供能量\n"); recommendation.append(" • 训练后30分钟内补充蛋白质\n"); break; case "塑形": recommendation.append("🎯 目标:塑形\n"); recommendation.append("🤸 训练建议:\n"); recommendation.append(" • 每周3-4次全身训练\n"); recommendation.append(" • 结合力量和有氧训练\n"); recommendation.append(" • 重点:核心训练、臀部训练\n"); recommendation.append(" • 每组12-15次,中等重量\n"); recommendation.append("🥗 饮食建议:\n"); recommendation.append(" • 均衡饮食,控制总热量\n"); recommendation.append(" • 多吃蔬菜水果\n"); recommendation.append(" • 减少加工食品\n"); break; default: recommendation.append("🎯 目标:保持健康\n"); recommendation.append("🏃 训练建议:\n"); recommendation.append(" • 每周3-4次运动\n"); recommendation.append(" • 每次30-45分钟\n"); recommendation.append(" • 结合有氧和力量训练\n"); recommendation.append(" • 保持中等强度\n"); recommendation.append("🥦 饮食建议:\n"); recommendation.append(" • 均衡营养,多样化饮食\n"); recommendation.append(" • 控制盐、糖、油摄入\n"); recommendation.append(" • 每天喝足水\n"); } return recommendation.toString(); } // 获取统计数据 public Map getStats(Long memberId) { Map stats = new HashMap<>(); List allPlans = trainingPlanRepository.findByMemberId(memberId); List activePlans = trainingPlanRepository.findActivePlansByMember(memberId); Long completedCount = trainingPlanRepository.countCompletedPlansByMember(memberId); stats.put("totalPlans", allPlans.size()); stats.put("activePlans", activePlans.size()); stats.put("completedPlans", completedCount); // 计算平均进度 double avgProgress = allPlans.stream() .mapToDouble(TrainingPlan::getProgress) .average() .orElse(0.0); stats.put("averageProgress", String.format("%.1f%%", avgProgress)); // 按目标分类统计 Map goalStats = allPlans.stream() .collect(Collectors.groupingBy(TrainingPlan::getGoal, Collectors.counting())); stats.put("goalDistribution", goalStats); return stats; } }