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<String, Object> 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<ActivityPlayerRating> 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<RatingItem> 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<ActivityPlayerRating> getAllRatingsForPlayer(Long activityPlayerId) {
|
return activityPlayerRatingRepository.findByActivityPlayerId(activityPlayerId);
|
}
|
|
/**
|
* 获取指定活动选手的平均分
|
*/
|
public BigDecimal getAverageScoreForPlayer(Long activityPlayerId) {
|
List<ActivityPlayerRating> 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<ActivityPlayerRating> 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<ActivityPlayerRatingItem> items = activityPlayerRatingItemRepository
|
.findByActivityPlayerRatingId(rating.getId());
|
|
List<CurrentJudgeRatingResponse.CurrentJudgeRatingItemResponse> 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<JudgeRatingStatusResponse> getAllJudgeRatingsForPlayer(Long activityPlayerId) {
|
log.info("开始获取选手评委评分状态,activityPlayerId: {}", activityPlayerId);
|
|
// 首先获取活动ID和阶段ID
|
String activityPlayerSql = "SELECT activity_id, stage_id FROM t_activity_player WHERE id = ?";
|
Map<String, Object> 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<Map<String, Object>> judgeRows = jdbcTemplate.queryForList(judgesSql, activityId, stageId);
|
log.info("找到评委数量: {}", judgeRows.size());
|
|
Long currentJudgeId = userContextUtil.getCurrentJudgeId();
|
|
List<JudgeRatingStatusResponse> 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<String, Object> 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<ActivityPlayerRating> 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<Judge> 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<ActivityPlayerRating> 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<Map<String, Object>> itemRows = jdbcTemplate.queryForList(itemsSql, rating.getId());
|
|
List<CurrentJudgeRatingResponse.CurrentJudgeRatingItemResponse> 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;
|
}
|
}
|
}
|