From 93eb6b470773bc49ea6e1a9d4cbd914eb95d525b Mon Sep 17 00:00:00 2001 From: lrj <owen.stl@gmail.com> Date: 星期二, 30 九月 2025 17:38:04 +0800 Subject: [PATCH] feat: 完善比赛晋级功能并清理测试文件 --- backend/src/main/java/com/rongyichuang/activity/service/ActivityService.java | 295 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 213 insertions(+), 82 deletions(-) diff --git a/backend/src/main/java/com/rongyichuang/activity/service/ActivityService.java b/backend/src/main/java/com/rongyichuang/activity/service/ActivityService.java index 216689c..a0ad78b 100644 --- a/backend/src/main/java/com/rongyichuang/activity/service/ActivityService.java +++ b/backend/src/main/java/com/rongyichuang/activity/service/ActivityService.java @@ -2,26 +2,36 @@ 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 @@ -35,23 +45,37 @@ 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); + // 鏌ヨ鎵�鏈変富娲诲姩锛坧id = 0锛� + page = activityRepository.findByPidOrderByCreateTimeDesc(0L, pageable); } - + List<ActivityResponse> content = page.getContent().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 new PageResponse<>(content, page.getTotalElements(), page.getNumber(), page.getSize()); @@ -66,14 +90,30 @@ 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; } @@ -118,16 +158,31 @@ } } + // 濡傛灉鏄瘮璧涳紝楠岃瘉蹇呴』鑷冲皯鏈変竴涓樁娈� + 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()); } @@ -138,9 +193,9 @@ /** * 淇濆瓨姣旇禌闃舵 */ - 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); // 鏀堕泦浼犲叆鐨勯樁娈礗D List<Long> inputStageIds = stageInputs.stream() @@ -157,11 +212,11 @@ } // 鑾峰彇姣旇禌淇℃伅锛岀敤浜庣户鎵挎姤鍚嶆埅姝㈡椂闂村拰璇勫垎妯℃澘 - 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) { @@ -170,8 +225,8 @@ 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()); @@ -187,16 +242,17 @@ 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); @@ -206,36 +262,38 @@ /** * 淇濆瓨姣旇禌璇勫 */ - 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()) { // 姣旇禌娌℃湁闃舵锛岀洿鎺ュ叧鑱斿埌姣旇禌锛坰tage_id涓簄ull琛ㄧず鎵�鏈夐樁娈碉級 - 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锛岃〃绀鸿瘎濮旇礋璐f暣涓瘮璧涳紝stage_id璁句负null + Long actualStageId = stageId.equals(activityId) ? null : stageId; + ActivityJudge activityJudge = new ActivityJudge(activityId, judgeInput.getJudgeId(), actualStageId); activityJudgeRepository.save(activityJudge); } } @@ -251,7 +309,7 @@ Activity activity = activityOpt.get(); // 濡傛灉鏄瘮璧涳紝鍏堝垹闄ゅ叾鎵�鏈夐樁娈� - if (activity.isCompetition()) { + if (activity.isMainActivity()) { List<Activity> stages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(id, 1); for (Activity stage : stages) { stage.setState(0); // 杞垹闄� @@ -268,61 +326,46 @@ } /** - * 鑾峰彇鎵�鏈夋湁鏁堟瘮璧涘拰闃舵锛堢敤浜庝笅鎷夐�夋嫨锛� + * 鑾峰彇鎵�鏈夋湁鏁堜富姣旇禌锛堢敤浜庝笅鎷夐�夋嫨锛� */ public List<ActivityResponse> findAllActivitiesForSelection() { - // 鑾峰彇鎵�鏈夋椿鍔紙鍖呮嫭姣旇禌鍜岄樁娈碉級 - List<Activity> activities = activityRepository.findByStateOrderByPidAscNameAsc(1); + // 鑾峰彇鎵�鏈夌姸鎬佷负1鐨勬椿鍔� + List<Activity> allActivities = activityRepository.findByStateOrderByPidAscNameAsc(1); - // 鍒涘缓姣旇禌ID鍒版瘮璧涘璞$殑鏄犲皠锛岀敤浜庡揩閫熸煡鎵剧埗姣旇禌 - Map<Long, Activity> competitionMap = activities.stream() - .filter(activity -> activity.getPid() == 0) - .collect(Collectors.toMap(Activity::getId, activity -> activity)); - - // 杞崲涓篈ctivityResponse骞跺~鍏卲arent淇℃伅 - List<ActivityResponse> result = activities.stream() - .map(activity -> { - ActivityResponse response = new ActivityResponse(activity); - // 濡傛灉鏄樁娈碉紙pid > 0锛夛紝濉厖parent淇℃伅 - if (activity.getPid() > 0) { - Activity parentActivity = competitionMap.get(activity.getPid()); - if (parentActivity != null) { - response.setParent(new ActivityResponse(parentActivity)); - } - } - return response; - }) + // 杩囨护锛氬彧淇濈暀姣旇禌闃舵锛坧id>0锛� + List<Activity> filteredActivities = allActivities.stream() + .filter(activity -> activity.getPid() > 0) .collect(Collectors.toList()); - // 鑷畾涔夋帓搴忥細姣旇禌鍜屽叾闃舵鏀惧湪涓�璧� - result.sort((a, b) -> { - // 濡傛灉閮芥槸姣旇禌锛坧id=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; + // 杞崲涓篈ctivityResponse锛屽寘鍚埗姣旇禌淇℃伅 + 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); + + // 璁剧疆鐖舵瘮璧涗俊鎭� + Optional<Activity> parentOpt = activityRepository.findById(activity.getPid()); + if (parentOpt.isPresent()) { + Activity parent = parentOpt.get(); + response.setParent(new ActivityResponse(parent)); + } + + return response; + }) + .sorted((a, b) -> { + // 鍏堟寜鐖舵瘮璧涘悕绉版帓搴忥紝鍐嶆寜闃舵鍚嶇О鎺掑簭 + if (a.getParent() != null && b.getParent() != null) { + int parentCompare = a.getParent().getName().compareTo(b.getParent().getName()); + 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; - }); + }) + .collect(Collectors.toList()); return result; } @@ -330,27 +373,41 @@ /** * 鑾峰彇姣旇禌鐨勬墍鏈夐樁娈� */ - 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()); } /** * 缁熻姣旇禌鏁伴噺 */ - 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()); } @@ -368,4 +425,78 @@ return "/" + pid + "/"; } } + + /** + * 鍔犺浇娲诲姩鐨勮瘎濮旀暟鎹� + */ + private List<ActivityJudgeResponse> loadActivityJudges(Long activityId) { + // 鏌ヨ娲诲姩鐨勮瘎濮斿叧鑱� + List<ActivityJudge> activityJudges = activityJudgeRepository.findByActivityId(activityId); + + // 鎸夎瘎濮擨D鍒嗙粍锛屾敹闆嗘瘡涓瘎濮旇礋璐g殑闃舵 + Map<Long, List<Long>> judgeStageMap = activityJudges.stream() + .collect(Collectors.groupingBy( + ActivityJudge::getJudgeId, + Collectors.mapping( + aj -> aj.getStageId() != null ? aj.getStageId() : activityId, // 濡傛灉stage_id涓簄ull锛岃〃绀鸿礋璐f暣涓瘮璧涳紝浣跨敤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; + } + + /** + * 楠岃瘉闃舵鐨剆ort_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...锛�"); + } + } + + // 妫�鏌ユ槸鍚︽湁閲嶅鐨剆ortOrder + Set<Integer> uniqueSortOrders = new HashSet<>(sortOrders); + if (uniqueSortOrders.size() != sortOrders.size()) { + throw new RuntimeException("闃舵鎺掑簭涓嶈兘閲嶅"); + } + } } \ No newline at end of file -- Gitblit v1.8.0