| | |
| | | |
| | | import com.rongyichuang.activity.dto.ActivityInput; |
| | | import com.rongyichuang.activity.dto.ActivityJudgeInput; |
| | | import com.rongyichuang.activity.dto.ActivityJudgeResponse; |
| | | import com.rongyichuang.activity.dto.ActivityResponse; |
| | | import com.rongyichuang.activity.dto.ActivityStageInput; |
| | | import com.rongyichuang.activity.entity.Activity; |
| | | import com.rongyichuang.activity.entity.ActivityJudge; |
| | | import com.rongyichuang.activity.repository.ActivityJudgeRepository; |
| | | import com.rongyichuang.activity.repository.ActivityRepository; |
| | | import com.rongyichuang.judge.entity.Judge; |
| | | import com.rongyichuang.player.repository.ActivityPlayerRepository; |
| | | import com.rongyichuang.judge.repository.JudgeRepository; |
| | | import com.rongyichuang.common.dto.PageRequest; |
| | | import com.rongyichuang.common.dto.PageResponse; |
| | | import com.rongyichuang.rating.entity.RatingScheme; |
| | | import com.rongyichuang.rating.repository.RatingSchemeRepository; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.data.domain.Example; |
| | | import org.springframework.data.domain.ExampleMatcher; |
| | | import org.springframework.data.domain.Page; |
| | | import org.springframework.data.domain.Pageable; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | import java.util.Optional; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Service |
| | |
| | | private ActivityJudgeRepository activityJudgeRepository; |
| | | |
| | | @Autowired |
| | | private JudgeRepository judgeRepository; |
| | | |
| | | @Autowired |
| | | private RatingSchemeRepository ratingSchemeRepository; |
| | | |
| | | @Autowired |
| | | private ActivityPlayerRepository activityPlayerRepository; |
| | | |
| | | /** |
| | | * 分页查询比赛列表 |
| | | */ |
| | | public PageResponse<ActivityResponse> findCompetitions(PageRequest pageRequest, String name) { |
| | | public PageResponse<ActivityResponse> findActivities(PageRequest pageRequest, String name) { |
| | | Pageable pageable = pageRequest.toPageable(); |
| | | Page<Activity> page; |
| | | |
| | | |
| | | if (StringUtils.hasText(name)) { |
| | | page = activityRepository.findByPidAndStateAndNameContainingOrderByCreateTimeDesc(0L, 1, name, pageable); |
| | | page = activityRepository.findByPidAndNameContainingOrderByCreateTimeDesc(0L, name, pageable); |
| | | } else { |
| | | page = activityRepository.findByPidAndStateOrderByCreateTimeDesc(0L, 1, pageable); |
| | | // 查询所有主活动(pid = 0) |
| | | page = activityRepository.findByPidOrderByCreateTimeDesc(0L, pageable); |
| | | } |
| | | |
| | | |
| | | List<ActivityResponse> content = page.getContent().stream() |
| | | .map(ActivityResponse::new) |
| | | .map(activity -> { |
| | | ActivityResponse response = new ActivityResponse(activity); |
| | | // 设置参赛人数(只统计第一阶段的审核通过学员人数) |
| | | int playerCount = 0; |
| | | Activity firstStage = activityRepository.findFirstStageByActivityId(activity.getId()); |
| | | if (firstStage != null) { |
| | | // 如果有第一阶段,统计第一阶段的审核通过人数 |
| | | Long playerCountLong = activityPlayerRepository.countByStageIdAndState(firstStage.getId(), 1); |
| | | playerCount = playerCountLong != null ? playerCountLong.intValue() : 0; |
| | | } else { |
| | | // 如果没有阶段,统计活动本身的审核通过人数 |
| | | Long playerCountLong = activityPlayerRepository.countByActivityIdAndState(activity.getId(), 1); |
| | | playerCount = playerCountLong != null ? playerCountLong.intValue() : 0; |
| | | } |
| | | response.setPlayerCount(playerCount); |
| | | return response; |
| | | }) |
| | | .collect(Collectors.toList()); |
| | | |
| | | return new PageResponse<>(content, page.getTotalElements(), page.getNumber(), page.getSize()); |
| | |
| | | Activity activity = activityOpt.get(); |
| | | ActivityResponse response = new ActivityResponse(activity); |
| | | |
| | | // 设置参赛人数(审核通过的报名数量) |
| | | Long playerCountLong = activityPlayerRepository.countByActivityId(activity.getId()); |
| | | int playerCount = playerCountLong != null ? playerCountLong.intValue() : 0; |
| | | response.setPlayerCount(playerCount); |
| | | |
| | | // 如果是比赛,加载其阶段 |
| | | if (activity.isCompetition()) { |
| | | if (activity.isMainActivity()) { |
| | | List<Activity> stages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(id, 1); |
| | | List<ActivityResponse> stageResponses = stages.stream() |
| | | .map(ActivityResponse::new) |
| | | .map(stage -> { |
| | | ActivityResponse stageResponse = new ActivityResponse(stage); |
| | | // 设置阶段的参赛人数 |
| | | Long stagePlayerCountLong = activityPlayerRepository.countByActivityId(stage.getId()); |
| | | int stagePlayerCount = stagePlayerCountLong != null ? stagePlayerCountLong.intValue() : 0; |
| | | stageResponse.setPlayerCount(stagePlayerCount); |
| | | return stageResponse; |
| | | }) |
| | | .collect(Collectors.toList()); |
| | | response.setStages(stageResponses); |
| | | } |
| | | |
| | | // 加载评委数据 |
| | | List<ActivityJudgeResponse> judges = loadActivityJudges(id); |
| | | response.setJudges(judges); |
| | | |
| | | return response; |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | // 如果是比赛,验证必须至少有一个阶段 |
| | | if (input.isMainActivity()) { |
| | | if (input.getStages() == null || input.getStages().isEmpty()) { |
| | | throw new RuntimeException("比赛必须至少有一个阶段"); |
| | | } |
| | | |
| | | // 验证阶段数量不超过5个 |
| | | if (input.getStages().size() > 5) { |
| | | throw new RuntimeException("比赛阶段数量不能超过5个"); |
| | | } |
| | | |
| | | // 验证sort_order连续性 |
| | | validateSortOrderContinuity(input.getStages()); |
| | | } |
| | | |
| | | // 保存比赛 |
| | | activity = activityRepository.save(activity); |
| | | |
| | | // 如果是比赛且有阶段信息,保存阶段 |
| | | if (input.isCompetition() && input.getStages() != null && !input.getStages().isEmpty()) { |
| | | if (input.isMainActivity() && input.getStages() != null && !input.getStages().isEmpty()) { |
| | | saveActivityStages(activity.getId(), input.getStages()); |
| | | } |
| | | |
| | | // 如果是比赛且有评委信息,保存评委 |
| | | if (input.isCompetition() && input.getJudges() != null && !input.getJudges().isEmpty()) { |
| | | if (input.isMainActivity() && input.getJudges() != null && !input.getJudges().isEmpty()) { |
| | | saveActivityJudges(activity.getId(), input.getJudges()); |
| | | } |
| | | |
| | |
| | | /** |
| | | * 保存比赛阶段 |
| | | */ |
| | | private void saveActivityStages(Long competitionId, List<ActivityStageInput> stageInputs) { |
| | | private void saveActivityStages(Long activityId, List<ActivityStageInput> stageInputs) { |
| | | // 获取现有的所有阶段 |
| | | List<Activity> existingStages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(competitionId, 1); |
| | | List<Activity> existingStages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(activityId, 1); |
| | | |
| | | // 收集传入的阶段ID |
| | | List<Long> inputStageIds = stageInputs.stream() |
| | |
| | | } |
| | | |
| | | // 获取比赛信息,用于继承报名截止时间和评分模板 |
| | | Optional<Activity> competitionOpt = activityRepository.findById(competitionId); |
| | | if (!competitionOpt.isPresent()) { |
| | | Optional<Activity> activityOpt = activityRepository.findById(activityId); |
| | | if (!activityOpt.isPresent()) { |
| | | throw new RuntimeException("比赛不存在"); |
| | | } |
| | | Activity competition = competitionOpt.get(); |
| | | Activity activity = activityOpt.get(); |
| | | |
| | | // 处理传入的阶段(新增或更新) |
| | | for (ActivityStageInput stageInput : stageInputs) { |
| | |
| | | if (stageInput.isNew()) { |
| | | // 新增阶段 |
| | | stage = new Activity(); |
| | | stage.setPid(competitionId); |
| | | stage.setPath(generatePath(competitionId)); |
| | | stage.setPid(activityId); |
| | | stage.setPath(generatePath(activityId)); |
| | | } else { |
| | | // 编辑阶段 |
| | | Optional<Activity> existingOpt = activityRepository.findById(stageInput.getId()); |
| | |
| | | stage.setMatchTime(stageInput.getMatchTime()); |
| | | stage.setAddress(stageInput.getAddress()); |
| | | stage.setPlayerMax(stageInput.getPlayerMax()); |
| | | stage.setSortOrder(stageInput.getSortOrder()); |
| | | stage.setState(stageInput.getState()); |
| | | |
| | | // 阶段继承比赛的报名截止时间 |
| | | stage.setSignupDeadline(competition.getSignupDeadline()); |
| | | stage.setSignupDeadline(activity.getSignupDeadline()); |
| | | |
| | | // 阶段的评分模板:如果指定了则使用指定的,否则继承比赛的评分模板 |
| | | if (stageInput.getRatingSchemeId() != null) { |
| | | stage.setRatingSchemeId(stageInput.getRatingSchemeId()); |
| | | } else { |
| | | stage.setRatingSchemeId(competition.getRatingSchemeId()); |
| | | stage.setRatingSchemeId(activity.getRatingSchemeId()); |
| | | } |
| | | |
| | | activityRepository.save(stage); |
| | |
| | | /** |
| | | * 保存比赛评委 |
| | | */ |
| | | private void saveActivityJudges(Long competitionId, List<ActivityJudgeInput> judgeInputs) { |
| | | private void saveActivityJudges(Long activityId, List<ActivityJudgeInput> judgeInputs) { |
| | | if (judgeInputs == null || judgeInputs.isEmpty()) { |
| | | return; |
| | | } |
| | | |
| | | // 获取比赛的所有阶段(如果有的话) |
| | | List<Activity> stages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(competitionId, 1); |
| | | List<Activity> stages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(activityId, 1); |
| | | |
| | | // 保存评委关联 |
| | | for (ActivityJudgeInput judgeInput : judgeInputs) { |
| | | // 先删除该评委的现有关联 |
| | | activityJudgeRepository.deleteByActivityIdAndJudgeId(competitionId, judgeInput.getJudgeId()); |
| | | activityJudgeRepository.deleteByActivityIdAndJudgeId(activityId, judgeInput.getJudgeId()); |
| | | |
| | | if (judgeInput.getStageIds() == null || judgeInput.getStageIds().isEmpty()) { |
| | | // 如果没有指定阶段,创建关联到所有阶段(如果有阶段)或直接关联到比赛(如果没有阶段) |
| | | if (stages.isEmpty()) { |
| | | // 比赛没有阶段,直接关联到比赛(stage_id为null表示所有阶段) |
| | | ActivityJudge activityJudge = new ActivityJudge(competitionId, judgeInput.getJudgeId(), null); |
| | | ActivityJudge activityJudge = new ActivityJudge(activityId, judgeInput.getJudgeId(), null); |
| | | activityJudgeRepository.save(activityJudge); |
| | | } else { |
| | | // 为每个阶段创建关联 |
| | | for (Activity stage : stages) { |
| | | ActivityJudge activityJudge = new ActivityJudge(competitionId, judgeInput.getJudgeId(), stage.getId()); |
| | | ActivityJudge activityJudge = new ActivityJudge(activityId, judgeInput.getJudgeId(), stage.getId()); |
| | | activityJudgeRepository.save(activityJudge); |
| | | } |
| | | } |
| | | } else { |
| | | // 为每个指定的阶段创建关联 |
| | | for (Long stageId : judgeInput.getStageIds()) { |
| | | ActivityJudge activityJudge = new ActivityJudge(competitionId, judgeInput.getJudgeId(), stageId); |
| | | // 如果stageId等于当前比赛ID,表示评委负责整个比赛,stage_id设为null |
| | | Long actualStageId = stageId.equals(activityId) ? null : stageId; |
| | | ActivityJudge activityJudge = new ActivityJudge(activityId, judgeInput.getJudgeId(), actualStageId); |
| | | activityJudgeRepository.save(activityJudge); |
| | | } |
| | | } |
| | |
| | | Activity activity = activityOpt.get(); |
| | | |
| | | // 如果是比赛,先删除其所有阶段 |
| | | if (activity.isCompetition()) { |
| | | if (activity.isMainActivity()) { |
| | | List<Activity> stages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(id, 1); |
| | | for (Activity stage : stages) { |
| | | stage.setState(0); // 软删除 |
| | |
| | | } |
| | | |
| | | /** |
| | | * 获取所有有效比赛(用于下拉选择) |
| | | * 获取所有有效主比赛(用于下拉选择) |
| | | */ |
| | | public List<ActivityResponse> findAllCompetitions() { |
| | | // 临时修改:不使用state字段进行查询 |
| | | List<Activity> activities = activityRepository.findByPidOrderByNameAsc(0L); |
| | | return activities.stream() |
| | | .map(ActivityResponse::new) |
| | | public List<ActivityResponse> findAllActivitiesForSelection() { |
| | | // 获取所有状态为1的活动 |
| | | List<Activity> allActivities = activityRepository.findByStateOrderByPidAscNameAsc(1); |
| | | |
| | | // 过滤:只保留主比赛(pid=0) |
| | | List<Activity> filteredActivities = allActivities.stream() |
| | | .filter(activity -> activity.getPid() == 0) |
| | | .collect(Collectors.toList()); |
| | | |
| | | // 转换为ActivityResponse |
| | | List<ActivityResponse> result = filteredActivities.stream() |
| | | .map(activity -> { |
| | | ActivityResponse response = new ActivityResponse(activity); |
| | | // 设置参赛人数(所有阶段的报名数量总和) |
| | | Long playerCountLong = activityPlayerRepository.countByActivityId(activity.getId()); |
| | | int playerCount = playerCountLong != null ? playerCountLong.intValue() : 0; |
| | | response.setPlayerCount(playerCount); |
| | | |
| | | return response; |
| | | }) |
| | | .sorted((a, b) -> a.getName().compareTo(b.getName())) |
| | | .collect(Collectors.toList()); |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 获取比赛的所有阶段 |
| | | */ |
| | | public List<ActivityResponse> findStagesByCompetitionId(Long competitionId) { |
| | | List<Activity> stages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(competitionId, 1); |
| | | public List<ActivityResponse> findStagesByActivityId(Long activityId) { |
| | | List<Activity> stages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(activityId, 1); |
| | | return stages.stream() |
| | | .map(ActivityResponse::new) |
| | | .map(activity -> { |
| | | ActivityResponse response = new ActivityResponse(activity); |
| | | // 设置参赛人数(审核通过的报名数量) |
| | | Long playerCountLong = activityPlayerRepository.countByActivityId(activity.getId()); |
| | | int playerCount = playerCountLong != null ? playerCountLong.intValue() : 0; |
| | | response.setPlayerCount(playerCount); |
| | | return response; |
| | | }) |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | /** |
| | | * 获取所有比赛阶段(用于评审页面下拉选择) |
| | | * 返回所有状态为1且pid>0的比赛阶段 |
| | | */ |
| | | public List<ActivityResponse> findAllStagesForSelection() { |
| | | // 获取所有状态为1的活动 |
| | | List<Activity> allActivities = activityRepository.findByStateOrderByPidAscNameAsc(1); |
| | | |
| | | // 分离主比赛和阶段 |
| | | Map<Long, Activity> parentActivitiesMap = allActivities.stream() |
| | | .filter(activity -> activity.getPid() == 0) |
| | | .collect(Collectors.toMap(Activity::getId, activity -> activity)); |
| | | |
| | | // 过滤:只保留比赛阶段(pid>0) |
| | | List<Activity> filteredStages = allActivities.stream() |
| | | .filter(activity -> activity.getPid() > 0) |
| | | .collect(Collectors.toList()); |
| | | |
| | | // 转换为ActivityResponse |
| | | List<ActivityResponse> result = filteredStages.stream() |
| | | .map(activity -> { |
| | | ActivityResponse response = new ActivityResponse(activity); |
| | | // 设置参赛人数(审核通过的报名数量) |
| | | Long playerCountLong = activityPlayerRepository.countByActivityId(activity.getId()); |
| | | int playerCount = playerCountLong != null ? playerCountLong.intValue() : 0; |
| | | response.setPlayerCount(playerCount); |
| | | |
| | | // 手动设置parent信息 |
| | | Activity parentActivity = parentActivitiesMap.get(activity.getPid()); |
| | | if (parentActivity != null) { |
| | | ActivityResponse parentResponse = new ActivityResponse(parentActivity); |
| | | response.setParent(parentResponse); |
| | | } |
| | | |
| | | return response; |
| | | }) |
| | | .sorted((a, b) -> { |
| | | // 先按父比赛ID排序,再按阶段名称排序 |
| | | int pidCompare = Long.compare(a.getPid(), b.getPid()); |
| | | if (pidCompare != 0) return pidCompare; |
| | | return a.getName().compareTo(b.getName()); |
| | | }) |
| | | .collect(Collectors.toList()); |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 统计比赛数量 |
| | | */ |
| | | public long countActiveCompetitions() { |
| | | return activityRepository.countActiveCompetitions(); |
| | | public long countActiveActivities() { |
| | | return activityRepository.countActiveActivities(); |
| | | } |
| | | |
| | | /** |
| | | * 获取进行中的比赛 |
| | | */ |
| | | public List<ActivityResponse> findOngoingCompetitions() { |
| | | List<Activity> activities = activityRepository.findOngoingCompetitions(); |
| | | public List<ActivityResponse> findOngoingActivities() { |
| | | List<Activity> activities = activityRepository.findOngoingActivities(); |
| | | return activities.stream() |
| | | .map(ActivityResponse::new) |
| | | .map(activity -> { |
| | | ActivityResponse response = new ActivityResponse(activity); |
| | | // 设置参赛人数(审核通过的报名数量) |
| | | Long playerCountLong = activityPlayerRepository.countByActivityId(activity.getId()); |
| | | int playerCount = playerCountLong != null ? playerCountLong.intValue() : 0; |
| | | response.setPlayerCount(playerCount); |
| | | return response; |
| | | }) |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | |
| | | return "/" + pid + "/"; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 加载活动的评委数据 |
| | | */ |
| | | private List<ActivityJudgeResponse> loadActivityJudges(Long activityId) { |
| | | // 查询活动的评委关联 |
| | | List<ActivityJudge> activityJudges = activityJudgeRepository.findByActivityId(activityId); |
| | | |
| | | // 按评委ID分组,收集每个评委负责的阶段 |
| | | Map<Long, List<Long>> judgeStageMap = activityJudges.stream() |
| | | .collect(Collectors.groupingBy( |
| | | ActivityJudge::getJudgeId, |
| | | Collectors.mapping( |
| | | aj -> aj.getStageId() != null ? aj.getStageId() : activityId, // 如果stage_id为null,表示负责整个比赛,使用activityId |
| | | Collectors.toList() |
| | | ) |
| | | )); |
| | | |
| | | // 查询评委详细信息并构建响应 |
| | | List<ActivityJudgeResponse> result = new ArrayList<>(); |
| | | for (Map.Entry<Long, List<Long>> entry : judgeStageMap.entrySet()) { |
| | | Long judgeId = entry.getKey(); |
| | | List<Long> stageIds = entry.getValue(); |
| | | |
| | | Optional<Judge> judgeOpt = judgeRepository.findById(judgeId); |
| | | if (judgeOpt.isPresent()) { |
| | | Judge judge = judgeOpt.get(); |
| | | ActivityJudgeResponse judgeResponse = new ActivityJudgeResponse( |
| | | judge.getId(), |
| | | judge.getName(), |
| | | judge.getPhone(), |
| | | judge.getDescription(), |
| | | stageIds |
| | | ); |
| | | result.add(judgeResponse); |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 验证阶段的sort_order连续性 |
| | | */ |
| | | private void validateSortOrderContinuity(List<ActivityStageInput> stages) { |
| | | if (stages == null || stages.isEmpty()) { |
| | | return; |
| | | } |
| | | |
| | | // 收集所有的sortOrder值 |
| | | List<Integer> sortOrders = stages.stream() |
| | | .map(ActivityStageInput::getSortOrder) |
| | | .filter(Objects::nonNull) |
| | | .sorted() |
| | | .collect(Collectors.toList()); |
| | | |
| | | // 检查是否从1开始 |
| | | if (sortOrders.isEmpty() || sortOrders.get(0) != 1) { |
| | | throw new RuntimeException("阶段排序必须从1开始"); |
| | | } |
| | | |
| | | // 检查连续性 |
| | | for (int i = 0; i < sortOrders.size(); i++) { |
| | | if (sortOrders.get(i) != i + 1) { |
| | | throw new RuntimeException("阶段排序必须连续,不能跳跃(如:1,2,3...)"); |
| | | } |
| | | } |
| | | |
| | | // 检查是否有重复的sortOrder |
| | | Set<Integer> uniqueSortOrders = new HashSet<>(sortOrders); |
| | | if (uniqueSortOrders.size() != sortOrders.size()) { |
| | | throw new RuntimeException("阶段排序不能重复"); |
| | | } |
| | | } |
| | | } |