|
@@ -0,0 +1,414 @@
|
|
|
+package org.dromara.system.service.impl.app;
|
|
|
+
|
|
|
+import com.esotericsoftware.minlog.Log;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import org.dromara.system.domain.*;
|
|
|
+import org.dromara.system.domain.vo.GameAthleteVo;
|
|
|
+import org.dromara.system.domain.vo.app.DistanceScoreUploadVo;
|
|
|
+import org.dromara.system.domain.vo.app.ElectrometerDataItemVo;
|
|
|
+import org.dromara.system.domain.vo.app.ElectrometerScoreUploadVo;
|
|
|
+import org.dromara.system.mapper.*;
|
|
|
+import org.dromara.system.service.app.IElectrometerService;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 澳亚特设备服务实现
|
|
|
+ *
|
|
|
+ * @author zlt
|
|
|
+ * @date 2025-01-20
|
|
|
+ */
|
|
|
+@RequiredArgsConstructor
|
|
|
+@Service
|
|
|
+public class ElectrometerServiceImpl implements IElectrometerService {
|
|
|
+
|
|
|
+ private final GameAthleteMapper gameAthleteMapper;
|
|
|
+ private final GameEventProjectMapper gameEventProjectMapper;
|
|
|
+ private final GameAthleteCompetitionGroupMapper gameAthleteCompetitionGroupMapper;
|
|
|
+ private final GameEventGroupMapper gameEventGroupMapper;
|
|
|
+ private final GameScoreMapper gameScoreMapper;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取比赛道路信息
|
|
|
+ *
|
|
|
+ * @param eventId 赛事ID
|
|
|
+ * @param tjsdm 项目类型(1-径赛, 2-田赛)
|
|
|
+ * @return 比赛道路信息列表
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public List<ElectrometerDataItemVo> getMatchRoadInfo(Long eventId, String tjsdm) {
|
|
|
+ // 1. 查询运动员信息
|
|
|
+ LambdaQueryWrapper<GameAthlete> athleteWrapper = Wrappers.lambdaQuery(GameAthlete.class)
|
|
|
+ .eq(GameAthlete::getEventId, eventId)
|
|
|
+ .eq(GameAthlete::getStatus, "0")
|
|
|
+ .eq(GameAthlete::getDelFlag, "0");
|
|
|
+ List<GameAthlete> athletes = gameAthleteMapper.selectList(athleteWrapper);
|
|
|
+
|
|
|
+ if (athletes.isEmpty()) {
|
|
|
+ return List.of();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 查询项目信息
|
|
|
+ LambdaQueryWrapper<GameEventProject> projectWrapper = Wrappers.lambdaQuery(GameEventProject.class)
|
|
|
+ .eq(GameEventProject::getEventId, eventId)
|
|
|
+ .eq(GameEventProject::getScoreRule,tjsdm);
|
|
|
+
|
|
|
+ List<GameEventProject> projects = gameEventProjectMapper.selectList(projectWrapper);
|
|
|
+ Map<Long, GameEventProject> projectMap = projects.stream()
|
|
|
+ .collect(Collectors.toMap(GameEventProject::getProjectId, p -> p));
|
|
|
+
|
|
|
+ // 3. 查询运动员比赛分组信息
|
|
|
+ List<Long> athleteIds = athletes.stream().map(GameAthlete::getAthleteId).collect(Collectors.toList());
|
|
|
+ LambdaQueryWrapper<GameAthleteCompetitionGroup> groupWrapper = Wrappers.lambdaQuery(GameAthleteCompetitionGroup.class)
|
|
|
+ .in(GameAthleteCompetitionGroup::getAthleteId, athleteIds);
|
|
|
+ List<GameAthleteCompetitionGroup> competitionGroups = gameAthleteCompetitionGroupMapper.selectList(groupWrapper);
|
|
|
+ Map<Long, GameAthleteCompetitionGroup> groupMap = competitionGroups.stream()
|
|
|
+ .collect(Collectors.toMap(GameAthleteCompetitionGroup::getAthleteId, g -> g));
|
|
|
+
|
|
|
+ // 4. 查询分组信息
|
|
|
+ List<Long> groupIds = competitionGroups.stream().map(GameAthleteCompetitionGroup::getGroupId).collect(Collectors.toList());
|
|
|
+ Map<Long, GameEventGroup> eventGroupMap;
|
|
|
+ if (!groupIds.isEmpty()) {
|
|
|
+ LambdaQueryWrapper<GameEventGroup> eventGroupWrapper = Wrappers.lambdaQuery(GameEventGroup.class)
|
|
|
+ .in(GameEventGroup::getGroupId, groupIds);
|
|
|
+ List<GameEventGroup> eventGroups = gameEventGroupMapper.selectList(eventGroupWrapper);
|
|
|
+ eventGroupMap = eventGroups.stream()
|
|
|
+ .collect(Collectors.toMap(GameEventGroup::getGroupId, g -> g));
|
|
|
+ } else {
|
|
|
+ eventGroupMap = Map.of();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5. 组装数据
|
|
|
+// SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
|
|
|
+ return athletes.stream().map(athlete -> {
|
|
|
+ ElectrometerDataItemVo item = new ElectrometerDataItemVo();
|
|
|
+
|
|
|
+ // 基本信息
|
|
|
+ item.setHm(athlete.getAthleteCode());
|
|
|
+ item.setXm(athlete.getName());
|
|
|
+ item.setXb(athlete.getGender());
|
|
|
+ item.setDw(athlete.getUnit());
|
|
|
+
|
|
|
+ // 获取比赛分组信息
|
|
|
+ GameAthleteCompetitionGroup competitionGroup = groupMap.get(athlete.getAthleteId());
|
|
|
+ if (competitionGroup != null) {
|
|
|
+ item.setCcDm(String.valueOf(competitionGroup.getGroupId()));
|
|
|
+ item.setZc(String.valueOf(competitionGroup.getGroupIndex()));
|
|
|
+ item.setDc(String.valueOf(competitionGroup.getTrackIndex()));
|
|
|
+
|
|
|
+ // 组别信息
|
|
|
+ if (!eventGroupMap.isEmpty()) {
|
|
|
+ GameEventGroup eventGroup = eventGroupMap.get(competitionGroup.getGroupId());
|
|
|
+ if (eventGroup != null) {
|
|
|
+ item.setZbMc(eventGroup.getGroupName());
|
|
|
+ if (eventGroup.getBeginTime() != null) {
|
|
|
+ item.setTm(eventGroup.getBeginTime());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 项目信息 - 根据比赛分组中的项目ID查找对应项目
|
|
|
+ GameEventProject project = projectMap.get(competitionGroup.getProjectId());
|
|
|
+ if (project != null) {
|
|
|
+ item.setXmMc(project.getProjectName());
|
|
|
+ item.setTjsDm(project.getProjectType());
|
|
|
+ item.setSx(project.getScoreRule()); // 计算规则-项目属性
|
|
|
+ if (project.getStartTime() != null) {
|
|
|
+ item.setTm(project.getStartTime());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return item;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 上传计时类项目成绩
|
|
|
+ *
|
|
|
+ * @param eventId 赛事ID
|
|
|
+ * @param scoreUpload 成绩上传数据
|
|
|
+ * @return 上传结果
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public String uploadScore(Long eventId, List<ElectrometerScoreUploadVo> scoreUpload) {
|
|
|
+ try {
|
|
|
+// Log.info("开始上传成绩,赛事ID: {}, 场次代码: {}", eventId, scoreUpload.getCcDm());
|
|
|
+ // 5. 保存成绩数据
|
|
|
+ int successCount = 0;
|
|
|
+ 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);
|
|
|
+ if (!"OK".equals(validationResult)) {
|
|
|
+ return validationResult;
|
|
|
+ }
|
|
|
+ if (saveScoreRecord(eventId, project, scoreItem)) {
|
|
|
+ successCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+// Log.info("成绩上传完成,成功保存 {} 条记录", successCount);
|
|
|
+ return String.format("成绩上传成功,共保存 %d 条记录", successCount);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ Log.error("成绩上传失败", e);
|
|
|
+ throw new RuntimeException("成绩上传失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public String uploadDistanceScore(Long eventId, DistanceScoreUploadVo scoreUpload) {
|
|
|
+ try{
|
|
|
+ //根据场次代码获取分组信息
|
|
|
+ GameAthleteCompetitionGroup groupInfo = gameAthleteCompetitionGroupMapper.selectById(scoreUpload.getCcdm());
|
|
|
+ if (groupInfo == null) {
|
|
|
+ return "未找到对应的比赛分组信息";
|
|
|
+ }
|
|
|
+ //根据分组信息获取项目信息
|
|
|
+ GameEventProject project = gameEventProjectMapper.selectById(groupInfo.getProjectId());
|
|
|
+ if (project == null) {
|
|
|
+ return "未找到对应的项目";
|
|
|
+ }
|
|
|
+ //根据分组信息获取运动员信息
|
|
|
+ List<DistanceScoreUploadVo.ScoreItem> scoreList = parseScoreData(scoreUpload.getCj());
|
|
|
+ GameAthlete athlete = gameAthleteMapper.selectById(groupInfo.getAthleteId());
|
|
|
+ if (athlete == null) {
|
|
|
+ return "未找到对应运动员";
|
|
|
+ }
|
|
|
+ int successCount = saveScoreRecord(eventId, project, scoreList);
|
|
|
+ if(successCount > 0){
|
|
|
+ return String.format("成绩上传成功,共保存 %d 条记录", successCount);
|
|
|
+ }else{
|
|
|
+ return "成绩上传失败";
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("成绩上传失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析成绩数据字符串
|
|
|
+ */
|
|
|
+ private List<DistanceScoreUploadVo.ScoreItem> parseScoreData(String scoreData) {
|
|
|
+ List<DistanceScoreUploadVo.ScoreItem> scoreList = new ArrayList<>();
|
|
|
+
|
|
|
+ if (scoreData == null || scoreData.trim().isEmpty()) {
|
|
|
+ return scoreList;
|
|
|
+ }
|
|
|
+
|
|
|
+ String[] items = scoreData.split("\\|");
|
|
|
+ for (String item : items) {
|
|
|
+ if (item.trim().isEmpty()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ String[] fields = item.split(",");
|
|
|
+ // 添加更严格的数据验证
|
|
|
+ if (fields.length >= 15 && !fields[2].trim().isEmpty() && !fields[3].trim().isEmpty()) {
|
|
|
+ try {
|
|
|
+ DistanceScoreUploadVo.ScoreItem scoreItem = new DistanceScoreUploadVo.ScoreItem();
|
|
|
+ List<String> indexList = new ArrayList<>();
|
|
|
+ indexList.add(fields[0]); // 组次
|
|
|
+ indexList.add(fields[1]); // 道次
|
|
|
+ scoreItem.setIndexList(indexList);
|
|
|
+ scoreItem.setAthleteCode(fields[2]); // 运动员编号
|
|
|
+ scoreItem.setAthleteName(fields[3]); // 姓名
|
|
|
+
|
|
|
+ // 安全地解析成绩数据
|
|
|
+ List<BigDecimal> scores = new ArrayList<>();
|
|
|
+ for (int i = 4; i < fields.length - 1; i += 2) {
|
|
|
+ if (i < fields.length && !fields[i].trim().isEmpty()) {
|
|
|
+ try {
|
|
|
+ scores.add(BigDecimal.valueOf(Double.parseDouble(fields[i])));
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ // 忽略无效的成绩数据
|
|
|
+ Log.warn("解析成绩数据失败: {}", fields[i], e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ scoreItem.setScoreList(scores);
|
|
|
+
|
|
|
+ // 安全地解析排名
|
|
|
+ try {
|
|
|
+ scoreItem.setRank(Integer.valueOf(fields[fields.length-1]));
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ Log.warn("解析排名失败: {}", fields[fields.length-1], e);
|
|
|
+ scoreItem.setRank(0); // 默认排名
|
|
|
+ }
|
|
|
+
|
|
|
+ scoreList.add(scoreItem);
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 记录错误但继续处理其他数据
|
|
|
+ Log.warn("解析成绩数据失败: {}", item, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return scoreList;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证成绩数据与分组信息的一致性
|
|
|
+ */
|
|
|
+ private String validateScoreData(ElectrometerScoreUploadVo scoreItem, GameAthleteCompetitionGroup groupInfo) {
|
|
|
+ // 验证场次代码是否一致
|
|
|
+ if (!scoreItem.getTrackIndex().equals(groupInfo.getTrackIndex())) {
|
|
|
+ return "场次代码不一致";
|
|
|
+ }
|
|
|
+ // 验证组次是否一致
|
|
|
+ if (!scoreItem.getGroupIndex().equals(groupInfo.getGroupIndex())) {
|
|
|
+ return "组次不一致";
|
|
|
+ }
|
|
|
+ // 验证运动员编号是否一致
|
|
|
+ if (!scoreItem.getAthleteCode().equals(groupInfo.getAthleteCode())) {
|
|
|
+ return "运动员编号不一致";
|
|
|
+ }
|
|
|
+ return "OK";
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存计时类项目成绩记录
|
|
|
+ */
|
|
|
+ private boolean saveScoreRecord(Long eventId, GameEventProject project, ElectrometerScoreUploadVo scoreItem) {
|
|
|
+ try {
|
|
|
+ // 根据运动员编号查找运动员ID
|
|
|
+ LambdaQueryWrapper<GameAthlete> athleteWrapper = Wrappers.lambdaQuery(GameAthlete.class)
|
|
|
+ .eq(GameAthlete::getEventId, eventId)
|
|
|
+ .eq(GameAthlete::getAthleteCode, scoreItem.getAthleteCode())
|
|
|
+ .eq(GameAthlete::getStatus, "0")
|
|
|
+ .eq(GameAthlete::getDelFlag, "0");
|
|
|
+ GameAthlete athlete = gameAthleteMapper.selectOne(athleteWrapper);
|
|
|
+
|
|
|
+ if (athlete == null) {
|
|
|
+ Log.warn("未找到运动员: {}", scoreItem.getAthleteCode());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否已存在成绩记录
|
|
|
+ LambdaQueryWrapper<GameScore> scoreWrapper = Wrappers.lambdaQuery(GameScore.class)
|
|
|
+ .eq(GameScore::getEventId, eventId)
|
|
|
+ .eq(GameScore::getProjectId, project.getProjectId())
|
|
|
+ .eq(GameScore::getAthleteId, athlete.getAthleteId());
|
|
|
+
|
|
|
+ GameScore existingScore = gameScoreMapper.selectOne(scoreWrapper);
|
|
|
+
|
|
|
+ if (existingScore != null) {
|
|
|
+ // 更新现有记录
|
|
|
+ existingScore.setIndividualPerformance(scoreItem.getScore());
|
|
|
+ existingScore.setScoreRank(scoreItem.getRank());
|
|
|
+ existingScore.setStatusFlag("1"); // 已处理
|
|
|
+ existingScore.setRemark("电计设备上传");
|
|
|
+
|
|
|
+ return gameScoreMapper.updateById(existingScore) > 0;
|
|
|
+ } else {
|
|
|
+ // 创建新记录
|
|
|
+ GameScore newScore = new GameScore();
|
|
|
+ newScore.setEventId(eventId);
|
|
|
+ newScore.setProjectId(project.getProjectId());
|
|
|
+ newScore.setAthleteId(athlete.getAthleteId());
|
|
|
+ newScore.setTeamId(athlete.getTeamId());
|
|
|
+ newScore.setIndividualPerformance(scoreItem.getScore());
|
|
|
+ newScore.setScoreRank(scoreItem.getRank());
|
|
|
+ newScore.setScoreType("individual");
|
|
|
+ newScore.setStatusFlag("1"); // 已处理
|
|
|
+ newScore.setStatus("0"); // 正常
|
|
|
+ newScore.setRemark("电计设备上传");
|
|
|
+ return gameScoreMapper.insert(newScore) > 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+// log.error("保存成绩记录失败: {}", e.getMessage(), e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存远度距离类项目成绩记录
|
|
|
+ */
|
|
|
+ private int saveScoreRecord(Long eventId, GameEventProject project, List<DistanceScoreUploadVo.ScoreItem> scoreList) {
|
|
|
+ try {
|
|
|
+ int successCount = 0;
|
|
|
+ for (DistanceScoreUploadVo.ScoreItem scoreItem : scoreList) {
|
|
|
+ // 根据运动员编号查找运动员ID
|
|
|
+ LambdaQueryWrapper<GameAthlete> athleteWrapper = Wrappers.lambdaQuery(GameAthlete.class)
|
|
|
+ .eq(GameAthlete::getEventId, eventId)
|
|
|
+ .eq(GameAthlete::getAthleteCode, scoreItem.getAthleteCode())
|
|
|
+ .eq(GameAthlete::getStatus, "0")
|
|
|
+ .eq(GameAthlete::getDelFlag, "0");
|
|
|
+ GameAthlete athlete = gameAthleteMapper.selectOne(athleteWrapper);
|
|
|
+
|
|
|
+ if (athlete == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否已存在成绩记录
|
|
|
+ LambdaQueryWrapper<GameScore> scoreWrapper = Wrappers.lambdaQuery(GameScore.class)
|
|
|
+ .eq(GameScore::getEventId, eventId)
|
|
|
+ .eq(GameScore::getProjectId, project.getProjectId())
|
|
|
+ .eq(GameScore::getAthleteId, athlete.getAthleteId());
|
|
|
+
|
|
|
+ GameScore existingScore = gameScoreMapper.selectOne(scoreWrapper);
|
|
|
+
|
|
|
+ if (existingScore != null) {
|
|
|
+ // 更新现有记录 - 远度距离类项目可能有多次成绩,取最好成绩
|
|
|
+ BigDecimal bestScore = scoreItem.getScoreList().stream()
|
|
|
+ .max(BigDecimal::compareTo)
|
|
|
+ .orElse(BigDecimal.ZERO);
|
|
|
+ existingScore.setIndividualPerformance(bestScore);
|
|
|
+ existingScore.setScoreRank(scoreItem.getRank());
|
|
|
+ existingScore.setStatusFlag("1");
|
|
|
+ existingScore.setRemark("电计设备上传-田赛");
|
|
|
+
|
|
|
+ if (gameScoreMapper.updateById(existingScore) > 0) {
|
|
|
+ successCount++;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 创建新记录
|
|
|
+ GameScore newScore = new GameScore();
|
|
|
+ newScore.setEventId(eventId);
|
|
|
+ newScore.setProjectId(project.getProjectId());
|
|
|
+ newScore.setAthleteId(athlete.getAthleteId());
|
|
|
+ newScore.setTeamId(athlete.getTeamId());
|
|
|
+
|
|
|
+ // 远度距离类项目取最好成绩
|
|
|
+ BigDecimal bestScore = scoreItem.getScoreList().stream()
|
|
|
+ .max(BigDecimal::compareTo)
|
|
|
+ .orElse(BigDecimal.ZERO);
|
|
|
+ newScore.setIndividualPerformance(bestScore);
|
|
|
+ newScore.setScoreRank(scoreItem.getRank());
|
|
|
+ newScore.setScoreType("individual");
|
|
|
+ newScore.setStatusFlag("1");
|
|
|
+ newScore.setStatus("0");
|
|
|
+ newScore.setRemark("电计设备上传-田赛");
|
|
|
+
|
|
|
+ if (gameScoreMapper.insert(newScore) > 0) {
|
|
|
+ successCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return successCount;
|
|
|
+ } catch (Exception e) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|