| | |
| | | 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.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 |
| | |
| | | @Autowired |
| | | private RatingSchemeRepository ratingSchemeRepository; |
| | | |
| | | @Autowired |
| | | private ActivityPlayerRepository activityPlayerRepository; |
| | | |
| | | /** |
| | | * 分页查询比赛列表 |
| | | */ |
| | | 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.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); |
| | | } |
| | |
| | | if (!schemeOpt.isPresent()) { |
| | | throw new RuntimeException("评分模板不存在"); |
| | | } |
| | | } |
| | | |
| | | // 如果是比赛,验证必须至少有一个阶段 |
| | | 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()); |
| | | } |
| | | |
| | | // 保存比赛 |
| | |
| | | stage.setMatchTime(stageInput.getMatchTime()); |
| | | stage.setAddress(stageInput.getAddress()); |
| | | stage.setPlayerMax(stageInput.getPlayerMax()); |
| | | stage.setSortOrder(stageInput.getSortOrder()); |
| | | stage.setState(stageInput.getState()); |
| | | |
| | | // 阶段继承比赛的报名截止时间 |
| | |
| | | } else { |
| | | // 为每个指定的阶段创建关联 |
| | | for (Long stageId : judgeInput.getStageIds()) { |
| | | ActivityJudge activityJudge = new ActivityJudge(activityId, 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); |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * 获取所有有效比赛和阶段(用于下拉选择) |
| | | * 获取所有有效主比赛(用于下拉选择) |
| | | */ |
| | | public List<ActivityResponse> findAllActivitiesForSelection() { |
| | | // 获取所有活动(包括比赛和阶段) |
| | | List<Activity> activities = activityRepository.findByStateOrderByPidAscNameAsc(1); |
| | | // 获取所有状态为1的活动 |
| | | List<Activity> allActivities = activityRepository.findByStateOrderByPidAscNameAsc(1); |
| | | |
| | | // 创建比赛ID到比赛对象的映射,用于快速查找父比赛 |
| | | Map<Long, Activity> mainActivityMap = activities.stream() |
| | | // 过滤:只保留主比赛(pid=0) |
| | | List<Activity> filteredActivities = allActivities.stream() |
| | | .filter(activity -> activity.getPid() == 0) |
| | | .collect(Collectors.toMap(Activity::getId, activity -> activity)); |
| | | |
| | | // 转换为ActivityResponse并填充parent信息 |
| | | List<ActivityResponse> result = activities.stream() |
| | | .map(activity -> { |
| | | ActivityResponse response = new ActivityResponse(activity); |
| | | // 如果是阶段(pid > 0),填充parent信息 |
| | | if (activity.getPid() > 0) { |
| | | Activity parentActivity = mainActivityMap.get(activity.getPid()); |
| | | if (parentActivity != null) { |
| | | response.setParent(new ActivityResponse(parentActivity)); |
| | | } |
| | | } |
| | | return response; |
| | | }) |
| | | .collect(Collectors.toList()); |
| | | |
| | | // 自定义排序:比赛和其阶段放在一起 |
| | | result.sort((a, b) -> { |
| | | // 如果都是比赛(pid=0),按名称排序 |
| | | if (a.getPid() == 0 && b.getPid() == 0) { |
| | | return a.getName().compareTo(b.getName()); |
| | | } |
| | | // 如果都是阶段,先按父比赛名称排序,再按阶段名称排序 |
| | | if (a.getPid() > 0 && b.getPid() > 0) { |
| | | String aParentName = a.getParent() != null ? a.getParent().getName() : ""; |
| | | String bParentName = b.getParent() != null ? b.getParent().getName() : ""; |
| | | int parentCompare = aParentName.compareTo(bParentName); |
| | | if (parentCompare != 0) { |
| | | return parentCompare; |
| | | } |
| | | return a.getName().compareTo(b.getName()); |
| | | } |
| | | // 如果一个是比赛,一个是阶段 |
| | | if (a.getPid() == 0 && b.getPid() > 0) { |
| | | String bParentName = b.getParent() != null ? b.getParent().getName() : ""; |
| | | int compare = a.getName().compareTo(bParentName); |
| | | return compare <= 0 ? -1 : 1; // 比赛排在其阶段前面 |
| | | } |
| | | if (a.getPid() > 0 && b.getPid() == 0) { |
| | | String aParentName = a.getParent() != null ? a.getParent().getName() : ""; |
| | | int compare = aParentName.compareTo(b.getName()); |
| | | return compare < 0 ? -1 : 1; // 阶段排在其比赛后面 |
| | | } |
| | | return 0; |
| | | }); |
| | | // 转换为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> 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 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()); |
| | | } |
| | | |
| | |
| | | Map<Long, List<Long>> judgeStageMap = activityJudges.stream() |
| | | .collect(Collectors.groupingBy( |
| | | ActivityJudge::getJudgeId, |
| | | Collectors.mapping(ActivityJudge::getStageId, Collectors.toList()) |
| | | Collectors.mapping( |
| | | aj -> aj.getStageId() != null ? aj.getStageId() : activityId, // 如果stage_id为null,表示负责整个比赛,使用activityId |
| | | Collectors.toList() |
| | | ) |
| | | )); |
| | | |
| | | // 查询评委详细信息并构建响应 |
| | |
| | | |
| | | 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("阶段排序不能重复"); |
| | | } |
| | | } |
| | | } |