Browse Source

refactor(game-event):优化成绩上传与队伍号码分配逻辑

- 修改"赛次名称"注释描述,从"比赛轮次"改为"比赛阶段"- 在电表数据项中添加比赛阶段字段(sc_mc)- 重构成绩上传验证逻辑,使用LambdaQueryWrapper查询分组信息
- 添加运动员代码与分组信息映射校验,提高数据一致性检查准确性
-优化径赛成绩上传方法中的分组信息查询方式
- 完善队伍号码段分配策略,支持自定义号码段和默认分配
- 新增号码段有效性校验方法,确保号码段格式正确
- 实现队伍信息更新时同步更新号码段的功能
- 添加日志记录未找到运动员的情况,便于问题追踪
- 统一成绩上传成功后的返回提示语格式,增强用户体验
zhou 1 month ago
parent
commit
3ec56fcfc2

+ 1 - 1
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/app/ElectrometerDataItemVo.java

@@ -59,7 +59,7 @@ public class ElectrometerDataItemVo implements Serializable {
     private String xmMc;
 
     /**
-     * 赛次名称(预赛, 复赛, 半决赛, 决赛), 对应比赛轮次
+     * 赛次名称(预赛, 复赛, 半决赛, 决赛), 对应比赛阶段
      */
     @JsonProperty("sc_mc")
     private String scMc;

+ 175 - 63
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/IEnrollServiceImpl.java

@@ -513,77 +513,31 @@ public class IEnrollServiceImpl implements IEnrollService {
             AtomicInteger currentNumber;
             boolean isNewTeam = false;
             String numberRange = "";
+            boolean needUpdateNumberRange = false;
 
             // 判断队伍是否已存在
-            if (existingTeamMap.containsKey(teamName)) {
-                // 队伍已存在,使用现有队伍的号码段
-                GameTeam existingTeam = existingTeamMap.get(teamName);
+            GameTeam existingTeam = existingTeamMap.get(teamName);
+            if (existingTeam != null) {
+                // 队伍已存在
                 teamId = existingTeam.getTeamId();
                 numberRange = existingTeam.getNumberRange();
 
-                try {
-                    // 尝试查询该队伍的最大队员编号
-                    String maxNumberStr = gameAthleteService.queryMaxNumber(teamId);
-                    Integer maxNumber = Integer.valueOf(maxNumberStr);
-
-                    // 如果最大编号为0,说明队伍实际上没有队员,从号码段起始开始
-                    if (maxNumber == 0) {
-                        String[] rangeParts = numberRange.split("-");
-                        int startNumber = Integer.valueOf(rangeParts[0]);
-                        currentNumber = new AtomicInteger(startNumber);
-                    } else {
-                        // 成功获取到有效编号,续着分配
-                        currentNumber = new AtomicInteger(maxNumber + 1);
-                    }
-                } catch (NumberFormatException e) {
-                    log.warn("解析队伍{}的号码段失败: {},从号码段起始开始分配", teamName, numberRange, e);
-                    String[] rangeParts = numberRange.split("-");
-                    int startNumber = Integer.valueOf(rangeParts[0]);
-                    currentNumber = new AtomicInteger(startNumber);
-                } catch (Exception e) {
-                    log.error("查询队伍{}的最大队员编号时发生异常", teamName, e);
-                    String[] rangeParts = numberRange.split("-");
-                    int startNumber = Integer.valueOf(rangeParts[0]);
-                    currentNumber = new AtomicInteger(startNumber);
+                // 检查号码段是否为空或无效
+                if (StringUtils.isBlank(numberRange) || !isValidNumberRange(numberRange)) {
+                    log.warn("队伍{}存在但号码段为空或无效: {},将为队伍生成新的号码段", teamName, numberRange);
+                    numberRange = generateOrGetNumberRange(athletes, eventId, teamId, dataList.size(), teamIndexCounter);
+                    currentNumber = initializeCurrentNumber(numberRange, teamId, teamName);
+                    needUpdateNumberRange = true;
+                } else {
+                    // 号码段有效,使用现有号码段
+                    currentNumber = getCurrentNumberFromExistingTeam(numberRange, teamId, teamName);
                 }
             } else {
-                // 队伍不存在,创建新队伍并分配新的300号码段
+                // 队伍不存在,创建新队伍
                 isNewTeam = true;
                 teamId = snowflake.nextId();
-
-                // 检查是否有填写的号码
-                List<String> providedCodes = athletes.stream()
-                .map(EnrollProjectVo::getAthleteCode)
-                .filter(StringUtils::isNotBlank)
-                .map(code -> code.trim())
-                .filter(code -> StringUtils.isNotBlank(code))
-                .collect(Collectors.toList());
-
-                if (!providedCodes.isEmpty()) {
-                    // 有填写的号码,使用ASCII值比较来确定号码段
-                    numberRange = generateCustomNumberRangeWithChars(providedCodes, eventId, null);
-
-                    if (numberRange != null) {
-                        // 成功生成自定义号码段
-                        currentNumber = null; // 对于字符号码,不使用数字计数器
-                        log.info("队伍 {} 使用自定义字符号码段: {}", teamName, numberRange);
-                    } else {
-                        // 生成失败,使用默认方式
-                        int teamIndex = teamIndexCounter.getAndIncrement();
-                        numberRange = generateNumberRange(dataList.size(), teamIndex);
-                        String[] rangeParts = numberRange.split("-");
-                        int startNumber = Integer.valueOf(rangeParts[0]);
-                        currentNumber = new AtomicInteger(startNumber);
-                        log.warn("队伍 {} 自定义号码段生成失败,使用默认号码段: {}", teamName, numberRange);
-                    }
-                } else {
-                    // 没有填写的号码,使用默认的300号码段
-                    int teamIndex = teamIndexCounter.getAndIncrement();
-                    numberRange = generateNumberRange(dataList.size(), teamIndex);
-                    String[] rangeParts = numberRange.split("-");
-                    int startNumber = Integer.valueOf(rangeParts[0]);
-                    currentNumber = new AtomicInteger(startNumber);
-                }
+                numberRange = generateOrGetNumberRange(athletes, eventId, null, dataList.size(), teamIndexCounter);
+                currentNumber = initializeCurrentNumber(numberRange, null, teamName);
             }
 
             // 保存队员信息
@@ -609,7 +563,11 @@ public class IEnrollServiceImpl implements IEnrollService {
                 gameTeamService.insertByBo(gameTeamBo);
             } else {
                 // 更新现有队伍的队员列表和数量
-                updateExistingTeam(teamId, athletesId, athletes.size());
+                if (needUpdateNumberRange) {
+                    updateExistingTeamWithNumberRange(teamId, athletesId, athletes.size(), numberRange);
+                } else {
+                    updateExistingTeam(teamId, athletesId, athletes.size());
+                }
             }
         }
 
@@ -980,6 +938,160 @@ public class IEnrollServiceImpl implements IEnrollService {
         }
     }
 
+    /**
+     * 更新现有队伍信息(包括号码段)
+     */
+    private void updateExistingTeamWithNumberRange(Long teamId, List<Long> newAthletesId, int newAthleteCount, String numberRange) {
+        GameTeamVo existingTeam = gameTeamService.queryById(teamId);
+        if (existingTeam != null) {
+            // 合并现有队员ID和新队员ID
+            List<Long> existingAthletes = JSONUtil.toList(existingTeam.getAthleteValue(), Long.class);
+            List<Long> allAthletes = new ArrayList<>();
+            if (existingAthletes != null) {
+                allAthletes.addAll(existingAthletes);
+            }
+            allAthletes.addAll(newAthletesId);
+
+            // 更新队伍信息
+            GameTeamBo updateTeamBo = new GameTeamBo();
+            updateTeamBo.setTeamId(teamId);
+            updateTeamBo.setAthleteValue(JSONUtil.toJsonStr(allAthletes));
+            updateTeamBo.setAthleteNum(existingTeam.getAthleteNum() + newAthleteCount);
+            updateTeamBo.setNumberRange(numberRange); // 更新号码段
+            gameTeamService.updateByBo(updateTeamBo);
+        }
+    }
+
+    /**
+     * 验证号码段格式是否有效
+     * 号码段格式为:xxxx-yyyy(如:0001-0300)
+     *
+     * @param numberRange 号码段
+     * @return 是否有效
+     */
+    private boolean isValidNumberRange(String numberRange) {
+        if (StringUtils.isBlank(numberRange)) {
+            return false;
+        }
+
+        // 检查是否包含"-"分隔符
+        if (!numberRange.contains("-")) {
+            return false;
+        }
+
+        // 检查是否能够正确分割
+        String[] parts = numberRange.split("-");
+        if (parts.length != 2) {
+            return false;
+        }
+
+        // 检查起始和结束号码都不为空
+        if (StringUtils.isBlank(parts[0]) || StringUtils.isBlank(parts[1])) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * 生成或获取号码段
+     *
+     * @param athletes 运动员列表
+     * @param eventId 赛事ID
+     * @param teamId 队伍ID(可为null)
+     * @param totalSize 总人数
+     * @param teamIndexCounter 队伍索引计数器
+     * @return 号码段
+     */
+    private String generateOrGetNumberRange(List<EnrollProjectVo> athletes, Long eventId, Long teamId,
+                                           int totalSize, AtomicInteger teamIndexCounter) {
+        // 收集填写的号码
+        List<String> providedCodes = athletes.stream()
+            .map(EnrollProjectVo::getAthleteCode)
+            .filter(StringUtils::isNotBlank)
+            .map(String::trim)
+            .filter(code -> StringUtils.isNotBlank(code))
+            .collect(Collectors.toList());
+
+        if (!providedCodes.isEmpty()) {
+            // 尝试生成自定义号码段
+            String customRange = generateCustomNumberRangeWithChars(providedCodes, eventId, teamId);
+            if (customRange != null) {
+                log.info("使用自定义号码段: {}", customRange);
+                return customRange;
+            }
+        }
+
+        // 生成默认号码段
+        int teamIndex = teamIndexCounter.getAndIncrement();
+        return generateNumberRange(totalSize, teamIndex);
+    }
+
+    /**
+     * 初始化当前号码
+     *
+     * @param numberRange 号码段
+     * @param teamId 队伍ID(可为null)
+     * @param teamName 队伍名称
+     * @return 当前号码
+     */
+    private AtomicInteger initializeCurrentNumber(String numberRange, Long teamId, String teamName) {
+        // 尝试分割号码段
+        String[] rangeParts = numberRange.split("-");
+        if (rangeParts.length == 2) {
+            try {
+                int startNumber = Integer.valueOf(rangeParts[0]);
+                return new AtomicInteger(startNumber);
+            } catch (NumberFormatException e) {
+                log.warn("解析号码段起始号码失败: {}, 使用默认值", numberRange);
+            }
+        }
+
+        // 如果解析失败,尝试从队伍查询
+        if (teamId != null) {
+            try {
+                String maxNumberStr = gameAthleteService.queryMaxNumber(teamId);
+                Integer maxNumber = Integer.valueOf(maxNumberStr);
+                return new AtomicInteger(maxNumber > 0 ? maxNumber + 1 : 1);
+            } catch (Exception e) {
+                log.warn("查询队伍{}的最大号码失败", teamName, e);
+            }
+        }
+
+        return new AtomicInteger(1);
+    }
+
+    /**
+     * 从现有队伍获取当前号码
+     *
+     * @param numberRange 号码段
+     * @param teamId 队伍ID
+     * @param teamName 队伍名称
+     * @return 当前号码
+     */
+    private AtomicInteger getCurrentNumberFromExistingTeam(String numberRange, Long teamId, String teamName) {
+        try {
+            // 查询队伍的最大队员编号
+            String maxNumberStr = gameAthleteService.queryMaxNumber(teamId);
+            Integer maxNumber = Integer.valueOf(maxNumberStr);
+
+            // 如果最大编号为0,从号码段起始开始
+            if (maxNumber == 0) {
+                String[] rangeParts = numberRange.split("-");
+                int startNumber = Integer.valueOf(rangeParts[0]);
+                return new AtomicInteger(startNumber);
+            } else {
+                // 续着分配
+                return new AtomicInteger(maxNumber + 1);
+            }
+        } catch (Exception e) {
+            log.warn("查询队伍{}的号码失败: {},从号码段起始开始", teamName, numberRange, e);
+            String[] rangeParts = numberRange.split("-");
+            int startNumber = Integer.valueOf(rangeParts[0]);
+            return new AtomicInteger(startNumber);
+        }
+    }
+
     private String generateNumberRangeByMax(int maxNumber) {
         // 每个队伍固定分配300个号码
         int start = maxNumber + 1;

+ 45 - 25
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/app/ElectrometerServiceImpl.java

@@ -120,6 +120,7 @@ public class ElectrometerServiceImpl implements IElectrometerService {
                     item.setXmMc(project.getProjectName());
                     item.setTjsDm(project.getProjectType());
                     item.setSx(project.getScoreRule()); // 计算规则-项目属性
+                    item.setScMc(project.getGameStage()); // 比赛阶段
                     if (project.getStartTime() != null) {
                         item.setTm(project.getStartTime());
                     }
@@ -144,19 +145,32 @@ public class ElectrometerServiceImpl implements IElectrometerService {
 //            Log.info("开始上传成绩,赛事ID: {}, 场次代码: {}", eventId, scoreUpload.getCcDm());
             // 5. 保存成绩数据
             int successCount = 0;
+            // 2. 根据场次代码获取分组信息
+            LambdaQueryWrapper<GameAthleteCompetitionGroup> groupWrapper = Wrappers.lambdaQuery(GameAthleteCompetitionGroup.class)
+                .eq(GameAthleteCompetitionGroup::getGroupId, scoreUpload.get(0).getCcdm())
+                .eq(GameAthleteCompetitionGroup::getEventId, eventId);
+            List<GameAthleteCompetitionGroup> groupInfo = gameAthleteCompetitionGroupMapper.selectList(groupWrapper);
+            if (groupInfo == null || groupInfo.isEmpty()) {
+                return "未找到对应的比赛分组信息";
+            }
+            Map<String, GameAthleteCompetitionGroup> groupMap = groupInfo.stream()
+                    .collect(Collectors.toMap(GameAthleteCompetitionGroup::getAthleteCode, g -> g));
+
+            // 3. 获取项目信息
+            GameEventProject project = gameEventProjectMapper.selectById(groupInfo.get(0).getProjectId());
+            if (project == null) {
+                return "未找到对应的项目信息";
+            }
             for (ElectrometerScoreUploadVo scoreItem : scoreUpload) {
-                // 2. 根据场次代码获取分组信息
-                GameAthleteCompetitionGroup groupInfo = gameAthleteCompetitionGroupMapper.selectById(scoreItem.getCcdm());
-                if (groupInfo == null) {
-                    return "未找到对应的比赛分组信息";
-                }
-                // 3. 获取项目信息
-                GameEventProject project = gameEventProjectMapper.selectById(groupInfo.getProjectId());
-                if (project == null) {
-                    return "未找到对应的项目信息";
-                }
+
                 // 4. 验证成绩数据与分组信息的一致性
-                String validationResult = validateScoreData(scoreItem, groupInfo);
+                String validationResult;
+                if (groupMap.containsKey(scoreItem.getAthleteCode())){
+                    validationResult = validateScoreData(scoreItem, groupMap.get(scoreItem.getAthleteCode()));
+                }else {
+                    validationResult = String.format("该分组未找到对应的运动员信息:%s", scoreItem.getAthleteCode());
+                }
+
                 if (!"OK".equals(validationResult)) {
                     return validationResult;
                 }
@@ -178,26 +192,29 @@ public class ElectrometerServiceImpl implements IElectrometerService {
     public String uploadDistanceScore(Long eventId, DistanceScoreUploadVo scoreUpload) {
         try{
             //根据场次代码获取分组信息
-            GameAthleteCompetitionGroup groupInfo = gameAthleteCompetitionGroupMapper.selectById(scoreUpload.getCcdm());
+            LambdaQueryWrapper<GameAthleteCompetitionGroup> groupWrapper = Wrappers.lambdaQuery(GameAthleteCompetitionGroup.class)
+                .eq(GameAthleteCompetitionGroup::getGroupId, scoreUpload.getCcdm())
+                .eq(GameAthleteCompetitionGroup::getEventId, eventId);
+            List<GameAthleteCompetitionGroup> groupInfo = gameAthleteCompetitionGroupMapper.selectList(groupWrapper);
             if (groupInfo == null) {
                 return "未找到对应的比赛分组信息";
             }
             //根据分组信息获取项目信息
-            GameEventProject project = gameEventProjectMapper.selectById(groupInfo.getProjectId());
+            GameEventProject project = gameEventProjectMapper.selectById(groupInfo.get(0).getProjectId());
             if (project == null) {
                 return "未找到对应的项目";
             }
             //根据分组信息获取运动员信息
             List<DistanceScoreUploadVo.ScoreItem> scoreList = parseScoreData(scoreUpload.getCj());
-            GameAthlete athlete = gameAthleteMapper.selectById(groupInfo.getAthleteId());
-            if (athlete == null) {
-                return "未找到对应运动员";
-            }
+//            GameAthlete athlete = gameAthleteMapper.selectById(groupInfo.getAthleteId());
+//            if (athlete == null) {
+//                return "未找到对应运动员";
+//            }
             int successCount = saveScoreRecord(eventId, project, scoreList);
             if(successCount > 0){
-                return String.format("成绩上传成功,共保存 %d 条记录", successCount);
+                return String.format("成绩上传成功,共保存 %d 条记录", successCount);
             }else{
-                return "成绩上传失败";
+                return String.format("成绩上传成功,但符合数据库环境的保存记录数为:%d", successCount);
             }
 
         } catch (Exception e) {
@@ -353,10 +370,11 @@ public class ElectrometerServiceImpl implements IElectrometerService {
                     .eq(GameAthlete::getEventId, eventId)
                     .eq(GameAthlete::getAthleteCode, scoreItem.getAthleteCode())
                     .eq(GameAthlete::getStatus, "0")
-                    .eq(GameAthlete::getDelFlag, "0");
+                    .eq(GameAthlete::getDelFlag, "0"); // 0-存在
                 GameAthlete athlete = gameAthleteMapper.selectOne(athleteWrapper);
 
                 if (athlete == null) {
+                    Log.warn("数据库中未找到运动员: "+scoreItem.getAthleteCode());
                     continue;
                 }
 
@@ -429,14 +447,16 @@ public class ElectrometerServiceImpl implements IElectrometerService {
             }
 
             // 根据场次代码获取分组信息
-            Long groupId = Long.valueOf(scoreUpload.getCcDm());
-            GameAthleteCompetitionGroup groupInfo = gameAthleteCompetitionGroupMapper.selectById(groupId);
+            LambdaQueryWrapper<GameAthleteCompetitionGroup> groupWrapper = Wrappers.lambdaQuery(GameAthleteCompetitionGroup.class)
+                .eq(GameAthleteCompetitionGroup::getGroupId, scoreUpload.getCcDm())
+                .eq(GameAthleteCompetitionGroup::getEventId, eventId);
+            List<GameAthleteCompetitionGroup> groupInfo = gameAthleteCompetitionGroupMapper.selectList(groupWrapper);
             if (groupInfo == null) {
                 return "未找到对应的比赛分组信息";
             }
 
             // 获取项目信息
-            GameEventProject project = gameEventProjectMapper.selectById(groupInfo.getProjectId());
+            GameEventProject project = gameEventProjectMapper.selectById(groupInfo.get(0).getProjectId());
             if (project == null) {
                 return "未找到对应的项目信息";
             }
@@ -449,8 +469,8 @@ public class ElectrometerServiceImpl implements IElectrometerService {
                 }
             }
 
-            Log.info("径赛成绩上传完成,成功保存 {} 条记录", String.valueOf(successCount));
-            return String.format("成绩上传成功,共保存 %d 条记录", successCount);
+            Log.info("径赛成绩上传完成,成功保存"+successCount+"条记录");
+            return String.format("成绩上传成功,共保存 %d 条记录", successCount);
 
         } catch (Exception e) {
             Log.error("径赛成绩上传失败", e);