package com.rongyichuang.player.service; import com.rongyichuang.activity.entity.ActivityPlayerRating; import com.rongyichuang.activity.entity.ActivityPlayerRatingItem; import com.rongyichuang.activity.repository.ActivityPlayerRatingRepository; import com.rongyichuang.activity.repository.ActivityPlayerRatingItemRepository; import com.rongyichuang.common.util.UserContextUtil; import com.rongyichuang.judge.entity.Judge; import com.rongyichuang.judge.repository.JudgeRepository; import com.rongyichuang.activity.repository.ActivityJudgeRepository; import com.rongyichuang.player.dto.input.ActivityPlayerRatingInput; import com.rongyichuang.player.dto.input.ActivityPlayerRatingItemInput; import com.rongyichuang.player.dto.response.JudgeRatingStatusResponse; import com.rongyichuang.player.dto.response.CurrentJudgeRatingResponse; import com.rongyichuang.player.dto.response.CurrentJudgeInfoResponse; import com.rongyichuang.rating.entity.RatingItem; import com.rongyichuang.rating.repository.RatingItemRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; import java.util.Map; import java.util.Optional; @Service public class ActivityPlayerRatingService { private static final Logger log = LoggerFactory.getLogger(ActivityPlayerRatingService.class); @Autowired private JdbcTemplate jdbcTemplate; @Autowired private ActivityPlayerRatingRepository activityPlayerRatingRepository; @Autowired private ActivityPlayerRatingItemRepository activityPlayerRatingItemRepository; @Autowired private RatingItemRepository ratingItemRepository; @Autowired private JudgeRepository judgeRepository; @Autowired private UserContextUtil userContextUtil; @Autowired private ActivityJudgeRepository activityJudgeRepository; @Transactional public boolean saveRating(ActivityPlayerRatingInput input) { try { log.info("开始保存多评委评分,activityPlayerId: {}", input.getActivityPlayerId()); // 获取当前评委信息 Long currentJudgeId = userContextUtil.getCurrentJudgeId(); if (currentJudgeId == null) { throw new RuntimeException("当前用户不是评委,无法进行评分"); } Long activityPlayerId = input.getActivityPlayerId(); Long stageId = input.getStageId(); // 验证前端传递的stageId if (stageId == null) { throw new RuntimeException("stageId不能为空"); } // 查询 activity_id, player_id String queryPlayerSql = "SELECT activity_id, player_id FROM t_activity_player WHERE id = ?"; Map playerData = jdbcTemplate.queryForMap(queryPlayerSql, activityPlayerId); Long activityId = ((Number) playerData.get("activity_id")).longValue(); Long playerId = ((Number) playerData.get("player_id")).longValue(); log.info("查询到的数据 - activityId: {}, playerId: {}, judgeId: {}, stageId: {}", activityId, playerId, currentJudgeId, stageId); // 验证评委是否有权限评分此活动和阶段 if (!userContextUtil.isCurrentUserJudgeForActivity(activityId)) { throw new RuntimeException("当前评委无权限评分此活动"); } // 验证评委是否有权限评分此阶段 String verifyJudgeStageIdSql = "SELECT COUNT(*) FROM t_activity_judge WHERE activity_id = ? AND judge_id = ? AND stage_id = ?"; Number judgeStageCountNumber = jdbcTemplate.queryForObject(verifyJudgeStageIdSql, Number.class, activityId, currentJudgeId, stageId); Integer judgeStageCount = judgeStageCountNumber != null ? judgeStageCountNumber.intValue() : 0; if (judgeStageCount == null || judgeStageCount == 0) { throw new RuntimeException("当前评委无权限评分此阶段,stageId: " + stageId); } // 查询活动的评分模板ID String queryActivitySql = "SELECT rating_scheme_id FROM t_activity WHERE id = ?"; Number ratingSchemeIdNumber = jdbcTemplate.queryForObject(queryActivitySql, Number.class, activityId); Long ratingSchemeId = ratingSchemeIdNumber != null ? ratingSchemeIdNumber.longValue() : null; log.info("查询到的ratingSchemeId: {}", ratingSchemeId); if (ratingSchemeId == null) { throw new RuntimeException("活动未配置评分模板,activityId: " + activityId); } // 查找或创建ActivityPlayerRating记录 Optional existingRating = activityPlayerRatingRepository .findByActivityPlayerIdAndJudgeId(activityPlayerId, currentJudgeId); ActivityPlayerRating rating; if (existingRating.isPresent()) { rating = existingRating.get(); log.info("找到已有评分记录,ID: {}", rating.getId()); // 删除已有的评分项 activityPlayerRatingItemRepository.deleteByActivityPlayerRatingId(rating.getId()); } else { // 创建新的评分记录,使用前端传递的stageId rating = new ActivityPlayerRating(activityId, activityPlayerId, stageId, playerId, currentJudgeId, ratingSchemeId); rating = activityPlayerRatingRepository.save(rating); log.info("创建新的评分记录,ID: {}, stageId: {}", rating.getId(), stageId); } // 保存评分项 BigDecimal totalScore = BigDecimal.ZERO; for (ActivityPlayerRatingItemInput ratingItemInput : input.getRatings()) { Long itemId = ratingItemInput.getItemId(); BigDecimal score = BigDecimal.valueOf(ratingItemInput.getScore()); // 查询评分项信息 Optional ratingItemOpt = ratingItemRepository.findById(itemId); if (ratingItemOpt.isEmpty()) { log.warn("评分项不存在,itemId: {}", itemId); continue; } RatingItem ratingItem = ratingItemOpt.get(); // 创建评分项记录 ActivityPlayerRatingItem ratingItemEntity = new ActivityPlayerRatingItem( activityId, activityPlayerId, rating.getId(), stageId, // 使用前端传递的stageId playerId, currentJudgeId, ratingSchemeId, itemId, score ); activityPlayerRatingItemRepository.save(ratingItemEntity); // 累加得分 if (score != null) { totalScore = totalScore.add(score); } log.info("保存评分项目: itemId={}, score={}", itemId, score); } // 更新总分和状态 rating.setTotalScore(totalScore); rating.setState(1); // 已评分 rating.setFeedback(input.getComment()); activityPlayerRatingRepository.save(rating); log.info("评分保存完成,总分: {}", totalScore); return true; } catch (Exception e) { log.error("保存评分失败,异常类型: {}, 异常信息: {}", e.getClass().getSimpleName(), e.getMessage(), e); e.printStackTrace(); throw new RuntimeException("保存评分失败: " + e.getClass().getSimpleName() + " - " + e.getMessage(), e); } } /** * 获取指定活动选手的所有评委评分 */ public List getAllRatingsForPlayer(Long activityPlayerId) { return activityPlayerRatingRepository.findByActivityPlayerId(activityPlayerId); } /** * 获取指定活动选手的平均分 */ public BigDecimal getAverageScoreForPlayer(Long activityPlayerId) { List ratings = activityPlayerRatingRepository .findCompletedRatingsByActivityPlayerId(activityPlayerId); if (ratings.isEmpty()) { return BigDecimal.ZERO; } BigDecimal totalScore = ratings.stream() .map(ActivityPlayerRating::getTotalScore) .filter(score -> score != null) .reduce(BigDecimal.ZERO, BigDecimal::add); return totalScore.divide(BigDecimal.valueOf(ratings.size()), 2, BigDecimal.ROUND_HALF_UP); } /** * 获取当前评委对指定选手的评分 */ public CurrentJudgeRatingResponse getCurrentJudgeRating(Long activityPlayerId) { Long currentJudgeId = userContextUtil.getCurrentJudgeId(); if (currentJudgeId == null) { return null; } Optional ratingOpt = activityPlayerRatingRepository .findByActivityPlayerIdAndJudgeId(activityPlayerId, currentJudgeId); if (!ratingOpt.isPresent()) { return null; } ActivityPlayerRating rating = ratingOpt.get(); CurrentJudgeRatingResponse response = new CurrentJudgeRatingResponse(); response.setId(rating.getId()); response.setTotalScore(rating.getTotalScore()); response.setStatus(rating.getState()); response.setRemark(rating.getFeedback()); // 获取评分项 List items = activityPlayerRatingItemRepository .findByActivityPlayerRatingId(rating.getId()); List itemResponses = items.stream() .map(item -> new CurrentJudgeRatingResponse.CurrentJudgeRatingItemResponse( item.getRatingItemId(), "", // 评分项名称暂时为空 item.getScore(), item.getScore() // 使用得分作为加权得分 )) .collect(java.util.stream.Collectors.toList()); response.setItems(itemResponses); return response; } /** * 检查当前评委是否已对指定选手评分 */ public boolean hasCurrentJudgeRated(Long activityPlayerId) { Long currentJudgeId = userContextUtil.getCurrentJudgeId(); if (currentJudgeId == null) { return false; } return activityPlayerRatingRepository.existsByActivityPlayerIdAndJudgeId(activityPlayerId, currentJudgeId); } /** * 获取指定选手的所有评委评分状态 */ public List getAllJudgeRatingsForPlayer(Long activityPlayerId) { log.info("开始获取选手评委评分状态,activityPlayerId: {}", activityPlayerId); // 首先获取活动ID和阶段ID String activityPlayerSql = "SELECT activity_id, stage_id FROM t_activity_player WHERE id = ?"; Map activityPlayerData = jdbcTemplate.queryForMap(activityPlayerSql, activityPlayerId); if (activityPlayerData == null) { throw new RuntimeException("未找到活动选手记录,activityPlayerId: " + activityPlayerId); } Long activityId = ((Number) activityPlayerData.get("activity_id")).longValue(); Long stageId = ((Number) activityPlayerData.get("stage_id")).longValue(); log.info("找到活动ID: {}, 阶段ID: {}", activityId, stageId); // 获取指定阶段的评委(通过stageId过滤,确保唯一性) String judgesSql = "SELECT j.id, j.name FROM t_judge j " + "JOIN t_activity_judge aj ON j.id = aj.judge_id " + "WHERE aj.activity_id = ? AND aj.stage_id = ? ORDER BY j.name"; List> judgeRows = jdbcTemplate.queryForList(judgesSql, activityId, stageId); log.info("找到评委数量: {}", judgeRows.size()); Long currentJudgeId = userContextUtil.getCurrentJudgeId(); List result = judgeRows.stream().map(row -> { Long judgeId = ((Number) row.get("id")).longValue(); String judgeName = (String) row.get("name"); // 只查找有效的评分记录(state=1),避免重复计算 String ratingCountSql = "SELECT COUNT(*) FROM t_activity_player_rating WHERE activity_player_id = ? AND judge_id = ? AND state = 1"; Integer ratingCount = jdbcTemplate.queryForObject(ratingCountSql, Integer.class, activityPlayerId, judgeId); Boolean hasRated = ratingCount != null && ratingCount > 0; // 评审次数>0表示已评审 String ratingTime = null; BigDecimal totalScore = null; // 如果已评分,获取最新的有效评分记录 if (hasRated) { // 获取最新的有效评分记录(按更新时间倒序,取第一条) String latestRatingSql = "SELECT * FROM t_activity_player_rating " + "WHERE activity_player_id = ? AND judge_id = ? AND state = 1 " + "ORDER BY update_time DESC LIMIT 1"; try { Map ratingRow = jdbcTemplate.queryForMap(latestRatingSql, activityPlayerId, judgeId); if (ratingRow != null) { totalScore = (BigDecimal) ratingRow.get("total_score"); Object updateTimeObj = ratingRow.get("update_time"); if (updateTimeObj != null) { ratingTime = updateTimeObj.toString(); } } } catch (Exception e) { // 如果查询失败,使用repository方法作为备选 Optional ratingOpt = activityPlayerRatingRepository .findByActivityPlayerIdAndJudgeId(activityPlayerId, judgeId); if (ratingOpt.isPresent()) { ActivityPlayerRating rating = ratingOpt.get(); // 只有当记录状态为1时才使用 if (rating.getState() != null && rating.getState() == 1) { totalScore = rating.getTotalScore(); if (rating.getUpdateTime() != null) { ratingTime = rating.getUpdateTime().toString(); } } } } } JudgeRatingStatusResponse response = new JudgeRatingStatusResponse(judgeId, judgeName, hasRated, ratingTime, totalScore); log.info("评委 {} (ID: {}) 评分状态: hasRated={}, totalScore={}, ratingTime={}", judgeName, judgeId, hasRated, totalScore, ratingTime); return response; }).collect(java.util.stream.Collectors.toList()); log.info("返回评委评分状态列表,总数: {}", result.size()); return result; } /** * 获取当前评委信息 */ public CurrentJudgeInfoResponse getCurrentJudgeInfo() { Optional currentJudgeOpt = userContextUtil.getCurrentJudge(); if (!currentJudgeOpt.isPresent()) { return null; } Judge currentJudge = currentJudgeOpt.get(); return new CurrentJudgeInfoResponse( currentJudge.getId(), currentJudge.getName(), currentJudge.getTitle(), currentJudge.getCompany() ); } /** * 检查评委是否在指定比赛阶段的评委列表中 */ public boolean isJudgeInActivity(Long stageId, Long judgeId) { try { return activityJudgeRepository.existsByStageIdAndJudgeId(stageId, judgeId); } catch (Exception e) { log.error("检查评委权限时发生异常: stageId={}, judgeId={}, error={}", stageId, judgeId, e.getMessage(), e); return false; } } /** * 获取指定评委对指定选手的评分明细 */ public CurrentJudgeRatingResponse getJudgeRatingDetail(Long activityPlayerId, Long judgeId) { try { Optional ratingOpt = activityPlayerRatingRepository .findByActivityPlayerIdAndJudgeId(activityPlayerId, judgeId); if (!ratingOpt.isPresent()) { return null; } ActivityPlayerRating rating = ratingOpt.get(); // 查询评分明细项 String itemsSql = "SELECT ri.id as rating_item_id, ri.name as rating_item_name, " + "apri.score, ri.max_score " + "FROM t_activity_player_rating_item apri " + "JOIN t_rating_item ri ON apri.rating_item_id = ri.id " + "WHERE apri.activity_player_rating_id = ? " + "ORDER BY ri.order_no"; List> itemRows = jdbcTemplate.queryForList(itemsSql, rating.getId()); List items = itemRows.stream() .map(row -> new CurrentJudgeRatingResponse.CurrentJudgeRatingItemResponse( ((Number) row.get("rating_item_id")).longValue(), (String) row.get("rating_item_name"), (BigDecimal) row.get("score"), (BigDecimal) row.get("score") // weightedScore 暂时使用相同值 )) .collect(java.util.stream.Collectors.toList()); CurrentJudgeRatingResponse response = new CurrentJudgeRatingResponse(); response.setId(rating.getId()); response.setTotalScore(rating.getTotalScore()); response.setStatus(rating.getState()); response.setRemark(rating.getFeedback()); response.setItems(items); return response; } catch (Exception e) { log.error("获取评委评分明细失败: activityPlayerId={}, judgeId={}, error={}", activityPlayerId, judgeId, e.getMessage(), e); return null; } } }