|
|
@@ -3,10 +3,14 @@ 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.app.AvtScoreItem;
|
|
|
+import org.dromara.system.domain.vo.SysDictDataVo;
|
|
|
+import org.dromara.system.domain.vo.app.AvtScoreUploadVo;
|
|
|
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.ISysDictTypeService;
|
|
|
import org.dromara.system.service.app.IElectrometerService;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
@@ -32,6 +36,7 @@ public class ElectrometerServiceImpl implements IElectrometerService {
|
|
|
private final GameAthleteCompetitionGroupMapper gameAthleteCompetitionGroupMapper;
|
|
|
private final GameEventGroupMapper gameEventGroupMapper;
|
|
|
private final GameScoreMapper gameScoreMapper;
|
|
|
+ private final ISysDictTypeService dictTypeService;
|
|
|
|
|
|
/**
|
|
|
* 获取比赛道路信息
|
|
|
@@ -56,7 +61,7 @@ public class ElectrometerServiceImpl implements IElectrometerService {
|
|
|
// 2. 查询项目信息
|
|
|
LambdaQueryWrapper<GameEventProject> projectWrapper = Wrappers.lambdaQuery(GameEventProject.class)
|
|
|
.eq(GameEventProject::getEventId, eventId)
|
|
|
- .eq(GameEventProject::getScoreRule,tjsdm);
|
|
|
+ .eq(GameEventProject::getProjectType,tjsdm);
|
|
|
|
|
|
List<GameEventProject> projects = gameEventProjectMapper.selectList(projectWrapper);
|
|
|
Map<Long, GameEventProject> projectMap = projects.stream()
|
|
|
@@ -65,10 +70,12 @@ public class ElectrometerServiceImpl implements IElectrometerService {
|
|
|
// 3. 查询运动员比赛分组信息
|
|
|
List<Long> athleteIds = athletes.stream().map(GameAthlete::getAthleteId).collect(Collectors.toList());
|
|
|
LambdaQueryWrapper<GameAthleteCompetitionGroup> groupWrapper = Wrappers.lambdaQuery(GameAthleteCompetitionGroup.class)
|
|
|
- .in(GameAthleteCompetitionGroup::getAthleteId, athleteIds);
|
|
|
+ .in(GameAthleteCompetitionGroup::getAthleteId, athleteIds)
|
|
|
+ .in(GameAthleteCompetitionGroup::getProjectId, projects.stream().map(GameEventProject::getProjectId).collect(Collectors.toList()));
|
|
|
List<GameAthleteCompetitionGroup> competitionGroups = gameAthleteCompetitionGroupMapper.selectList(groupWrapper);
|
|
|
- Map<Long, GameAthleteCompetitionGroup> groupMap = competitionGroups.stream()
|
|
|
- .collect(Collectors.toMap(GameAthleteCompetitionGroup::getAthleteId, g -> g));
|
|
|
+ // 支持一个运动员对应多个分组
|
|
|
+ Map<Long, List<GameAthleteCompetitionGroup>> groupMap = competitionGroups.stream()
|
|
|
+ .collect(Collectors.groupingBy(GameAthleteCompetitionGroup::getAthleteId));
|
|
|
|
|
|
// 4. 查询分组信息
|
|
|
List<Long> groupIds = competitionGroups.stream().map(GameAthleteCompetitionGroup::getGroupId).collect(Collectors.toList());
|
|
|
@@ -85,47 +92,61 @@ public class ElectrometerServiceImpl implements IElectrometerService {
|
|
|
|
|
|
// 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());
|
|
|
+ List<SysDictDataVo> gameStage = dictTypeService.selectDictDataByType("game_stage");
|
|
|
+ List<ElectrometerDataItemVo> result = new ArrayList<>();
|
|
|
+
|
|
|
+ for (GameAthlete athlete : athletes) {
|
|
|
+ // 获取该运动员的所有分组
|
|
|
+ List<GameAthleteCompetitionGroup> athleteGroups = groupMap.get(athlete.getAthleteId());
|
|
|
+ if (athleteGroups != null && !athleteGroups.isEmpty()) {
|
|
|
+ // 为每个分组创建一条记录
|
|
|
+ for (GameAthleteCompetitionGroup competitionGroup : athleteGroups) {
|
|
|
+ ElectrometerDataItemVo item = new ElectrometerDataItemVo();
|
|
|
+
|
|
|
+ // 基本信息
|
|
|
+ item.setHm(athlete.getAthleteCode());
|
|
|
+ item.setXm(athlete.getName());
|
|
|
+ item.setXb(athlete.getGender());
|
|
|
+ item.setDw(athlete.getUnit());
|
|
|
+
|
|
|
+ // 比赛分组信息
|
|
|
+ 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());
|
|
|
+ // 项目信息 - 根据比赛分组中的项目ID查找对应项目
|
|
|
+ GameEventProject project = projectMap.get(competitionGroup.getProjectId());
|
|
|
+ if (project != null) {
|
|
|
+ item.setXmMc(project.getProjectName());
|
|
|
+ item.setTjsDm(project.getProjectType());
|
|
|
+ item.setSx(project.getScoreRule()); // 计算规则-项目属性
|
|
|
+ Optional<String> label = gameStage.stream()
|
|
|
+ .filter(d -> d.getDictValue().equals(project.getGameStage()))
|
|
|
+ .map(SysDictDataVo::getDictLabel)
|
|
|
+ .findFirst();
|
|
|
+ item.setScMc(label.orElse("")); //比赛阶段
|
|
|
+ if (project.getStartTime() != null) {
|
|
|
+ item.setTm(project.getStartTime());
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ result.add(item);
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- return item;
|
|
|
- }).collect(Collectors.toList());
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -142,24 +163,59 @@ 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;
|
|
|
}
|
|
|
- if (saveScoreRecord(eventId, project, scoreItem)) {
|
|
|
- successCount++;
|
|
|
+ // 判断是否为计时类项目,如果是则应用时间格式转换
|
|
|
+ if (isTimingProject(project)) {
|
|
|
+ // 将成绩从字符串转换为时间格式再转换为小数
|
|
|
+ String scoreStr = scoreItem.getScore() != null ? scoreItem.getScore().toString() : null;
|
|
|
+ if (scoreStr != null && !scoreStr.isEmpty()) {
|
|
|
+ BigDecimal convertedScore = convertTimeScoreToDecimal(scoreStr);
|
|
|
+ if (convertedScore != null) {
|
|
|
+ ElectrometerScoreUploadVo convertedItem = new ElectrometerScoreUploadVo();
|
|
|
+ convertedItem.setAthleteCode(scoreItem.getAthleteCode());
|
|
|
+ convertedItem.setTrackIndex(scoreItem.getTrackIndex());
|
|
|
+ convertedItem.setGroupIndex(scoreItem.getGroupIndex());
|
|
|
+ convertedItem.setRank(scoreItem.getRank());
|
|
|
+ convertedItem.setScore(convertedScore);
|
|
|
+ if (saveScoreRecord(eventId, project, convertedItem)) {
|
|
|
+ successCount++;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Log.warn("成绩格式转换失败,跳过记录: {}", scoreStr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (saveScoreRecord(eventId, project, scoreItem)) {
|
|
|
+ successCount++;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
// Log.info("成绩上传完成,成功保存 {} 条记录", successCount);
|
|
|
@@ -176,26 +232,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) {
|
|
|
@@ -313,8 +372,13 @@ public class ElectrometerServiceImpl implements IElectrometerService {
|
|
|
|
|
|
if (existingScore != null) {
|
|
|
// 更新现有记录
|
|
|
- existingScore.setIndividualPerformance(scoreItem.getScore());
|
|
|
- existingScore.setScoreRank(scoreItem.getRank());
|
|
|
+ // scoreItem.getScore() 已经是 BigDecimal 类型,可以直接使用
|
|
|
+ if (scoreItem.getScore() != null) {
|
|
|
+ existingScore.setIndividualPerformance(scoreItem.getScore());
|
|
|
+ }
|
|
|
+ if (scoreItem.getRank() != null) {
|
|
|
+ existingScore.setScoreRank(scoreItem.getRank());
|
|
|
+ }
|
|
|
existingScore.setRemark("电计设备上传");
|
|
|
|
|
|
return gameScoreMapper.updateById(existingScore) > 0;
|
|
|
@@ -325,8 +389,12 @@ public class ElectrometerServiceImpl implements IElectrometerService {
|
|
|
newScore.setProjectId(project.getProjectId());
|
|
|
newScore.setAthleteId(athlete.getAthleteId());
|
|
|
newScore.setTeamId(athlete.getTeamId());
|
|
|
- newScore.setIndividualPerformance(scoreItem.getScore());
|
|
|
- newScore.setScoreRank(scoreItem.getRank());
|
|
|
+ if (scoreItem.getScore() != null) {
|
|
|
+ newScore.setIndividualPerformance(scoreItem.getScore());
|
|
|
+ }
|
|
|
+ if (scoreItem.getRank() != null) {
|
|
|
+ newScore.setScoreRank(scoreItem.getRank());
|
|
|
+ }
|
|
|
newScore.setScoreType("individual");
|
|
|
newScore.setStatus("0"); // 正常
|
|
|
newScore.setRemark("电计设备上传");
|
|
|
@@ -351,10 +419,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;
|
|
|
}
|
|
|
|
|
|
@@ -406,4 +475,305 @@ public class ElectrometerServiceImpl implements IElectrometerService {
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 上传径赛成绩(电计设备)- 新格式
|
|
|
+ *
|
|
|
+ * @param eventId 赛事ID
|
|
|
+ * @param scoreUpload 成绩上传数据,包含cc_dm、zc、cj字段
|
|
|
+ * @return 上传结果
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public String uploadAvtScore(String eventId, AvtScoreUploadVo scoreUpload) {
|
|
|
+ try {
|
|
|
+ Log.info("开始上传径赛成绩,赛事ID: {}", eventId);
|
|
|
+
|
|
|
+ // 解析cj字段中的数据
|
|
|
+ List<AvtScoreItem> scoreItems = parseAvtScoreData(scoreUpload.getCj());
|
|
|
+ if (scoreItems.isEmpty()) {
|
|
|
+ return "没有有效的成绩数据";
|
|
|
+ }
|
|
|
+
|
|
|
+ // 根据场次代码获取分组信息
|
|
|
+ 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.get(0).getProjectId());
|
|
|
+ if (project == null) {
|
|
|
+ return "未找到对应的项目信息";
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存成绩数据
|
|
|
+ int successCount = 0;
|
|
|
+ for (AvtScoreItem scoreItem : scoreItems) {
|
|
|
+ if (saveAvtScoreRecord(Long.valueOf(eventId), project, scoreItem)) {
|
|
|
+ successCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Log.info("径赛成绩上传完成,成功保存"+successCount+"条记录");
|
|
|
+ return String.format("成绩上传成功,共保存 %d 条记录。", successCount);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ Log.error("径赛成绩上传失败", e);
|
|
|
+ throw new RuntimeException("径赛成绩上传失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析AVT成绩数据字符串
|
|
|
+ * 格式:场次代码,编号,名次,成绩,风速,反应时,状态,组次,道次|场次代码,编号,名次,成绩,风速,反应时,状态,组次,道次......
|
|
|
+ */
|
|
|
+ private List<AvtScoreItem> parseAvtScoreData(String scoreData) {
|
|
|
+ List<AvtScoreItem> 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 >= 9) {
|
|
|
+ try {
|
|
|
+ AvtScoreItem scoreItem = new AvtScoreItem();
|
|
|
+ scoreItem.setCcdm(Long.valueOf(fields[0])); // 场次代码
|
|
|
+ scoreItem.setAthleteCode(fields[1]); // 编号
|
|
|
+ scoreItem.setRank(fields[2].isEmpty() ? null : Integer.valueOf(fields[2])); // 名次
|
|
|
+ scoreItem.setScore(fields[3].isEmpty() ? null : fields[3]); // 成绩
|
|
|
+ scoreItem.setWindSpeed(fields[4].isEmpty() ? null : fields[4]); // 风速
|
|
|
+ scoreItem.setReactionTime(fields[5].isEmpty() ? null : fields[5]); // 反应时
|
|
|
+ scoreItem.setStatus(fields[6].isEmpty() ? null : fields[6]); // 状态
|
|
|
+ scoreItem.setGroupIndex(fields[7].isEmpty() ? null : Long.valueOf(fields[7])); // 组次
|
|
|
+ scoreItem.setTrackIndex(fields[8].isEmpty() ? null : Long.valueOf(fields[8])); // 道次
|
|
|
+
|
|
|
+ scoreList.add(scoreItem);
|
|
|
+ } catch (Exception e) {
|
|
|
+ Log.warn("解析AVT成绩数据失败: {}", item, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return scoreList;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存AVT成绩记录
|
|
|
+ */
|
|
|
+ private boolean saveAvtScoreRecord(Long eventId, GameEventProject project, AvtScoreItem 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);
|
|
|
+
|
|
|
+ // 处理成绩数据 - 如果是计时类项目,应用时间格式转换
|
|
|
+ BigDecimal scoreValue = null;
|
|
|
+ if (scoreItem.getScore() != null && !scoreItem.getScore().isEmpty()) {
|
|
|
+ // 判断是否为计时类项目
|
|
|
+ if (isTimingProject(project)) {
|
|
|
+ // 使用统一的时间格式转换方法
|
|
|
+ scoreValue = convertTimeScoreToDecimal(scoreItem.getScore());
|
|
|
+ } else {
|
|
|
+ // 非计时类项目直接转换
|
|
|
+ try {
|
|
|
+ scoreValue = BigDecimal.valueOf(Double.parseDouble(scoreItem.getScore()));
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ Log.warn("解析成绩失败: {}", scoreItem.getScore(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (existingScore != null) {
|
|
|
+ // 更新现有记录
|
|
|
+ if (scoreValue != null) {
|
|
|
+ existingScore.setIndividualPerformance(scoreValue);
|
|
|
+ }
|
|
|
+ if (scoreItem.getRank() != null) {
|
|
|
+ existingScore.setScoreRank(scoreItem.getRank());
|
|
|
+ }
|
|
|
+ existingScore.setRemark("AVT电计设备上传");
|
|
|
+
|
|
|
+ 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());
|
|
|
+ if (scoreValue != null) {
|
|
|
+ newScore.setIndividualPerformance(scoreValue);
|
|
|
+ }
|
|
|
+ if (scoreItem.getRank() != null) {
|
|
|
+ newScore.setScoreRank(scoreItem.getRank());
|
|
|
+ }
|
|
|
+ newScore.setScoreType("individual");
|
|
|
+ newScore.setStatus("0");
|
|
|
+ newScore.setRemark("AVT电计设备上传");
|
|
|
+
|
|
|
+ return gameScoreMapper.insert(newScore) > 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ Log.error("保存AVT成绩记录失败: {}", e.getMessage(), e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断项目是否为计时类项目
|
|
|
+ * 根据项目的计算规则(scoreRule)判断,常见值如:"timing"、"计时"、"time"等
|
|
|
+ *
|
|
|
+ * @param project 项目信息
|
|
|
+ * @return true表示是计时类项目,false表示不是
|
|
|
+ */
|
|
|
+ private boolean isTimingProject(GameEventProject project) {
|
|
|
+ if (project == null || project.getScoreRule() == null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ List<SysDictDataVo> gameScoreType = dictTypeService.selectDictDataByType("game_score_type");
|
|
|
+ String scoreRule = project.getScoreRule().toLowerCase();
|
|
|
+ Optional<String> rule = gameScoreType.stream()
|
|
|
+ .filter(data -> data.getDictLabel().contains("计时"))
|
|
|
+ .map(SysDictDataVo::getDictValue)
|
|
|
+ .findFirst();
|
|
|
+ // 判断计算规则是否为计时类(可以根据实际字典值调整)
|
|
|
+ return rule.isPresent() && scoreRule.equals(rule.get().toLowerCase());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将各种时间格式成绩转换成小数格式存储(以秒为单位)
|
|
|
+ * 支持格式:
|
|
|
+ * - 0.111 (已经是小数格式)
|
|
|
+ * - 11.000 (已经是小数格式)
|
|
|
+ * - 11:00.000 (分:秒.毫秒格式)
|
|
|
+ * - 11:00:00.000 (时:分:秒.毫秒格式)
|
|
|
+ *
|
|
|
+ * @param timeScore 时间格式的成绩字符串
|
|
|
+ * @return 转换为秒为单位的小数值,如果解析失败返回null
|
|
|
+ */
|
|
|
+ public BigDecimal convertTimeScoreToDecimal(String timeScore) {
|
|
|
+ if (timeScore == null || timeScore.trim().isEmpty()) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ String trimmed = timeScore.trim();
|
|
|
+
|
|
|
+ // 如果包含冒号,说明是时间格式(时:分:秒.毫秒 或 分:秒.毫秒)
|
|
|
+ if (trimmed.contains(":")) {
|
|
|
+ String[] parts = trimmed.split(":");
|
|
|
+ double totalSeconds = 0.0;
|
|
|
+
|
|
|
+ if (parts.length == 2) {
|
|
|
+ // 格式:分:秒.毫秒 (如 11:00.000)
|
|
|
+ double minutes = Double.parseDouble(parts[0]);
|
|
|
+ double seconds = Double.parseDouble(parts[1]);
|
|
|
+ totalSeconds = minutes * 60 + seconds;
|
|
|
+ } else if (parts.length == 3) {
|
|
|
+ // 格式:时:分:秒.毫秒 (如 11:00:00.000)
|
|
|
+ double hours = Double.parseDouble(parts[0]);
|
|
|
+ double minutes = Double.parseDouble(parts[1]);
|
|
|
+ double seconds = Double.parseDouble(parts[2]);
|
|
|
+ totalSeconds = hours * 3600 + minutes * 60 + seconds;
|
|
|
+ } else {
|
|
|
+ Log.warn("不支持的时间格式: {}", timeScore);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return BigDecimal.valueOf(totalSeconds);
|
|
|
+ } else {
|
|
|
+ // 已经是小数格式,直接转换
|
|
|
+ return BigDecimal.valueOf(Double.parseDouble(trimmed));
|
|
|
+ }
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ Log.warn("解析时间成绩失败: {}", timeScore, e);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将小数格式的成绩转换成时间格式显示(时:分:秒.毫秒)
|
|
|
+ * 格式:xx:xx:xx.nn (时:分:秒.毫秒)
|
|
|
+ *
|
|
|
+ * @param decimalScore 以秒为单位的小数值
|
|
|
+ * @return 时间格式字符串,如 "01:23:45.678"
|
|
|
+ */
|
|
|
+ public String convertDecimalToTimeScore(BigDecimal decimalScore) {
|
|
|
+ if (decimalScore == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 计算小时
|
|
|
+ BigDecimal hoursBigDecimal = decimalScore.divide(BigDecimal.valueOf(3600), 0, java.math.RoundingMode.DOWN);
|
|
|
+ int hours = hoursBigDecimal.intValue();
|
|
|
+ BigDecimal remaining = decimalScore.remainder(BigDecimal.valueOf(3600));
|
|
|
+
|
|
|
+ // 计算分钟
|
|
|
+ BigDecimal minutesBigDecimal = remaining.divide(BigDecimal.valueOf(60), 0, java.math.RoundingMode.DOWN);
|
|
|
+ int minutes = minutesBigDecimal.intValue();
|
|
|
+ remaining = remaining.remainder(BigDecimal.valueOf(60));
|
|
|
+
|
|
|
+ // 秒和毫秒
|
|
|
+ int seconds = remaining.intValue();
|
|
|
+ // 计算毫秒:取小数部分乘以1000并四舍五入
|
|
|
+ BigDecimal millisecondsBigDecimal = remaining.subtract(BigDecimal.valueOf(seconds))
|
|
|
+ .multiply(BigDecimal.valueOf(1000))
|
|
|
+ .setScale(0, java.math.RoundingMode.HALF_UP);
|
|
|
+ int milliseconds = millisecondsBigDecimal.intValue();
|
|
|
+
|
|
|
+ // 处理毫秒溢出(理论上不应该发生,但保险起见)
|
|
|
+ if (milliseconds >= 1000) {
|
|
|
+ seconds += milliseconds / 1000;
|
|
|
+ milliseconds = milliseconds % 1000;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理秒溢出(理论上不应该发生,但保险起见)
|
|
|
+ if (seconds >= 60) {
|
|
|
+ minutes += seconds / 60;
|
|
|
+ seconds = seconds % 60;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理分钟溢出(理论上不应该发生,但保险起见)
|
|
|
+ if (minutes >= 60) {
|
|
|
+ hours += minutes / 60;
|
|
|
+ minutes = minutes % 60;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 格式化输出:时:分:秒.毫秒
|
|
|
+ return String.format("%02d:%02d:%02d.%03d", hours, minutes, seconds, milliseconds);
|
|
|
+ } catch (Exception e) {
|
|
|
+ Log.warn("转换小数为时间格式失败: {}", String.valueOf(decimalScore), e);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|