package com.rongyichuang.activity.service;
|
|
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
|
@Transactional
|
public class ActivityService {
|
|
@Autowired
|
private ActivityRepository activityRepository;
|
|
@Autowired
|
private ActivityJudgeRepository activityJudgeRepository;
|
|
@Autowired
|
private JudgeRepository judgeRepository;
|
|
@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.findByPidAndNameContainingOrderByCreateTimeDesc(0L, name, pageable);
|
} else {
|
// 查询所有主活动(pid = 0)
|
page = activityRepository.findByPidOrderByCreateTimeDesc(0L, pageable);
|
}
|
|
List<ActivityResponse> content = page.getContent().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;
|
})
|
.collect(Collectors.toList());
|
|
return new PageResponse<>(content, page.getTotalElements(), page.getNumber(), page.getSize());
|
}
|
|
/**
|
* 获取比赛详情
|
*/
|
public ActivityResponse findById(Long id) {
|
Optional<Activity> activityOpt = activityRepository.findById(id);
|
if (activityOpt.isPresent()) {
|
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(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;
|
}
|
return null;
|
}
|
|
/**
|
* 保存比赛(新增或编辑)
|
*/
|
public ActivityResponse saveActivity(ActivityInput input) {
|
Activity activity;
|
|
if (input.isNew()) {
|
// 新增比赛
|
activity = new Activity();
|
activity.setPid(input.getPid());
|
activity.setPath(generatePath(input.getPid()));
|
} else {
|
// 编辑比赛
|
Optional<Activity> existingOpt = activityRepository.findById(input.getId());
|
if (!existingOpt.isPresent()) {
|
throw new RuntimeException("比赛不存在");
|
}
|
activity = existingOpt.get();
|
}
|
|
// 设置基本信息
|
activity.setName(input.getName());
|
activity.setDescription(input.getDescription());
|
activity.setSignupDeadline(input.getSignupDeadline());
|
activity.setMatchTime(input.getMatchTime());
|
activity.setAddress(input.getAddress());
|
activity.setRatingSchemeId(input.getRatingSchemeId());
|
activity.setPlayerMax(input.getPlayerMax());
|
activity.setState(input.getState());
|
|
// 验证评分模板是否存在
|
if (input.getRatingSchemeId() != null) {
|
Optional<RatingScheme> schemeOpt = ratingSchemeRepository.findById(input.getRatingSchemeId());
|
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());
|
}
|
|
// 保存比赛
|
activity = activityRepository.save(activity);
|
|
// 如果是比赛且有阶段信息,保存阶段
|
if (input.isMainActivity() && input.getStages() != null && !input.getStages().isEmpty()) {
|
saveActivityStages(activity.getId(), input.getStages());
|
}
|
|
// 如果是比赛且有评委信息,保存评委
|
if (input.isMainActivity() && input.getJudges() != null && !input.getJudges().isEmpty()) {
|
saveActivityJudges(activity.getId(), input.getJudges());
|
}
|
|
// 重新查询完整的数据(包含关联的stages)
|
return findById(activity.getId());
|
}
|
|
/**
|
* 保存比赛阶段
|
*/
|
private void saveActivityStages(Long activityId, List<ActivityStageInput> stageInputs) {
|
// 获取现有的所有阶段
|
List<Activity> existingStages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(activityId, 1);
|
|
// 收集传入的阶段ID
|
List<Long> inputStageIds = stageInputs.stream()
|
.filter(input -> !input.isNew())
|
.map(ActivityStageInput::getId)
|
.collect(Collectors.toList());
|
|
// 删除不在传入列表中的现有阶段(软删除)
|
for (Activity existingStage : existingStages) {
|
if (!inputStageIds.contains(existingStage.getId())) {
|
existingStage.setState(0); // 软删除
|
activityRepository.save(existingStage);
|
}
|
}
|
|
// 获取比赛信息,用于继承报名截止时间和评分模板
|
Optional<Activity> activityOpt = activityRepository.findById(activityId);
|
if (!activityOpt.isPresent()) {
|
throw new RuntimeException("比赛不存在");
|
}
|
Activity activity = activityOpt.get();
|
|
// 处理传入的阶段(新增或更新)
|
for (ActivityStageInput stageInput : stageInputs) {
|
Activity stage;
|
|
if (stageInput.isNew()) {
|
// 新增阶段
|
stage = new Activity();
|
stage.setPid(activityId);
|
stage.setPath(generatePath(activityId));
|
} else {
|
// 编辑阶段
|
Optional<Activity> existingOpt = activityRepository.findById(stageInput.getId());
|
if (!existingOpt.isPresent()) {
|
continue; // 跳过不存在的阶段
|
}
|
stage = existingOpt.get();
|
}
|
|
// 设置阶段信息
|
stage.setName(stageInput.getName());
|
stage.setDescription(stageInput.getDescription());
|
stage.setMatchTime(stageInput.getMatchTime());
|
stage.setAddress(stageInput.getAddress());
|
stage.setPlayerMax(stageInput.getPlayerMax());
|
stage.setSortOrder(stageInput.getSortOrder());
|
stage.setState(stageInput.getState());
|
|
// 阶段继承比赛的报名截止时间
|
stage.setSignupDeadline(activity.getSignupDeadline());
|
|
// 阶段的评分模板:如果指定了则使用指定的,否则继承比赛的评分模板
|
if (stageInput.getRatingSchemeId() != null) {
|
stage.setRatingSchemeId(stageInput.getRatingSchemeId());
|
} else {
|
stage.setRatingSchemeId(activity.getRatingSchemeId());
|
}
|
|
activityRepository.save(stage);
|
}
|
}
|
|
/**
|
* 保存比赛评委
|
*/
|
private void saveActivityJudges(Long activityId, List<ActivityJudgeInput> judgeInputs) {
|
if (judgeInputs == null || judgeInputs.isEmpty()) {
|
return;
|
}
|
|
// 获取比赛的所有阶段(如果有的话)
|
List<Activity> stages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(activityId, 1);
|
|
// 保存评委关联
|
for (ActivityJudgeInput judgeInput : judgeInputs) {
|
// 先删除该评委的现有关联
|
activityJudgeRepository.deleteByActivityIdAndJudgeId(activityId, judgeInput.getJudgeId());
|
|
if (judgeInput.getStageIds() == null || judgeInput.getStageIds().isEmpty()) {
|
// 如果没有指定阶段,创建关联到所有阶段(如果有阶段)或直接关联到比赛(如果没有阶段)
|
if (stages.isEmpty()) {
|
// 比赛没有阶段,直接关联到比赛(stage_id为null表示所有阶段)
|
ActivityJudge activityJudge = new ActivityJudge(activityId, judgeInput.getJudgeId(), null);
|
activityJudgeRepository.save(activityJudge);
|
} else {
|
// 为每个阶段创建关联
|
for (Activity stage : stages) {
|
ActivityJudge activityJudge = new ActivityJudge(activityId, judgeInput.getJudgeId(), stage.getId());
|
activityJudgeRepository.save(activityJudge);
|
}
|
}
|
} else {
|
// 为每个指定的阶段创建关联
|
for (Long stageId : judgeInput.getStageIds()) {
|
// 如果stageId等于当前比赛ID,表示评委负责整个比赛,stage_id设为null
|
Long actualStageId = stageId.equals(activityId) ? null : stageId;
|
ActivityJudge activityJudge = new ActivityJudge(activityId, judgeInput.getJudgeId(), actualStageId);
|
activityJudgeRepository.save(activityJudge);
|
}
|
}
|
}
|
}
|
|
/**
|
* 删除比赛
|
*/
|
public boolean deleteActivity(Long id) {
|
Optional<Activity> activityOpt = activityRepository.findById(id);
|
if (activityOpt.isPresent()) {
|
Activity activity = activityOpt.get();
|
|
// 如果是比赛,先删除其所有阶段
|
if (activity.isMainActivity()) {
|
List<Activity> stages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(id, 1);
|
for (Activity stage : stages) {
|
stage.setState(0); // 软删除
|
activityRepository.save(stage);
|
}
|
}
|
|
// 软删除比赛
|
activity.setState(0);
|
activityRepository.save(activity);
|
return true;
|
}
|
return false;
|
}
|
|
/**
|
* 获取所有有效主比赛(用于下拉选择)
|
*/
|
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);
|
|
// 设置父比赛信息
|
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());
|
})
|
.collect(Collectors.toList());
|
|
return result;
|
}
|
|
/**
|
* 获取比赛的所有阶段
|
*/
|
public List<ActivityResponse> findStagesByActivityId(Long activityId) {
|
List<Activity> stages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(activityId, 1);
|
return stages.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;
|
})
|
.collect(Collectors.toList());
|
}
|
|
/**
|
* 统计比赛数量
|
*/
|
public long countActiveActivities() {
|
return activityRepository.countActiveActivities();
|
}
|
|
/**
|
* 获取进行中的比赛
|
*/
|
public List<ActivityResponse> findOngoingActivities() {
|
List<Activity> activities = activityRepository.findOngoingActivities();
|
return activities.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;
|
})
|
.collect(Collectors.toList());
|
}
|
|
/**
|
* 生成路径
|
*/
|
private String generatePath(Long pid) {
|
if (pid == 0) {
|
return "/";
|
} else {
|
Optional<Activity> parentOpt = activityRepository.findById(pid);
|
if (parentOpt.isPresent()) {
|
return parentOpt.get().getPath() + pid + "/";
|
}
|
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("阶段排序不能重复");
|
}
|
}
|
}
|