# 比赛日流程功能 - 详细任务清单

**优先级：** P1（重要）
**预计工时：** 4天
**负责人：** 待分配
**创建时间：** 2025-11-30

---

## 📋 任务概述

比赛日流程功能包括运动员签到检录、评分验证、异常处理等关键环节。

---

## ✅ 任务列表

### 任务 2.1：运动员签到/检录系统 🔴

**状态：** 未开始
**工时：** 1.5天

#### 需求描述
- 运动员签到功能
- 更新比赛状态（待出场 → 进行中 → 已完成）
- 检录员角色权限管理

#### 实现要点
```java
// MartialAthleteServiceImpl.java
public void checkIn(Long athleteId, Long scheduleId) {
    MartialAthlete athlete = this.getById(athleteId);

    // 更新运动员状态：待出场 → 进行中
    athlete.setCompetitionStatus(1);  // 进行中
    this.updateById(athlete);

    // 更新赛程运动员关联状态
    MartialScheduleAthlete scheduleAthlete = scheduleAthleteService.getOne(
        new QueryWrapper<MartialScheduleAthlete>()
            .eq("schedule_id", scheduleId)
            .eq("athlete_id", athleteId)
    );
    scheduleAthlete.setIsCompleted(0);  // 未完成
    scheduleAthleteService.updateById(scheduleAthlete);
}

public void completePerformance(Long athleteId) {
    MartialAthlete athlete = this.getById(athleteId);
    athlete.setCompetitionStatus(2);  // 已完成
    this.updateById(athlete);
}
```

#### API接口
- `POST /martial/athlete/checkin` - 签到
- `POST /martial/athlete/complete` - 完成比赛

---

### 任务 2.2：评分有效性验证 🔴

**状态：** 未开始
**工时：** 0.5天

#### 需求描述
- 分数范围检查（5.000 - 10.000）
- 评分提交前验证
- 异常分数提示

#### 实现要点
```java
// MartialScoreServiceImpl.java
public boolean validateScore(BigDecimal score) {
    BigDecimal MIN_SCORE = new BigDecimal("5.000");
    BigDecimal MAX_SCORE = new BigDecimal("10.000");

    return score.compareTo(MIN_SCORE) >= 0
        && score.compareTo(MAX_SCORE) <= 0;
}

@Override
public boolean save(MartialScore score) {
    // 验证分数范围
    if (!validateScore(score.getScore())) {
        throw new ServiceException("分数必须在5.000-10.000之间");
    }

    return super.save(score);
}
```

---

### 任务 2.3：异常分数警告机制 🔴

**状态：** 未开始
**工时：** 1天

#### 需求描述
- 检测离群值（与其他裁判差距过大）
- 生成警告提示
- 记录异常日志

#### 实现要点
```java
public void checkAnomalyScore(MartialScore newScore) {
    // 获取同一运动员的其他裁判评分
    List<MartialScore> scores = this.list(
        new QueryWrapper<MartialScore>()
            .eq("athlete_id", newScore.getAthleteId())
            .eq("project_id", newScore.getProjectId())
            .ne("judge_id", newScore.getJudgeId())
    );

    if (scores.size() < 2) {
        return;  // 评分数量不足，无法判断
    }

    // 计算其他裁判的平均分
    BigDecimal avgScore = scores.stream()
        .map(MartialScore::getScore)
        .reduce(BigDecimal.ZERO, BigDecimal::add)
        .divide(new BigDecimal(scores.size()), 3, RoundingMode.HALF_UP);

    // 判断偏差
    BigDecimal diff = newScore.getScore().subtract(avgScore).abs();
    if (diff.compareTo(new BigDecimal("1.000")) > 0) {
        // 偏差超过1.0分，记录警告
        log.warn("异常评分：裁判{}给运动员{}打分{}，偏离平均分{}超过1.0",
            newScore.getJudgeName(),
            newScore.getAthleteId(),
            newScore.getScore(),
            avgScore
        );
    }
}
```

---

### 任务 2.4：异常情况记录和处理 🔴

**状态：** 未开始
**工时：** 0.5天

#### 需求描述
- 新建异常事件表
- 记录异常类型、处理结果
- 支持查询统计

#### 数据库表设计
```sql
CREATE TABLE martial_exception_event (
    id BIGINT PRIMARY KEY,
    competition_id BIGINT NOT NULL COMMENT '赛事ID',
    schedule_id BIGINT COMMENT '赛程ID',
    athlete_id BIGINT COMMENT '运动员ID',
    event_type INT COMMENT '事件类型 1-器械故障 2-受伤 3-评分争议 4-其他',
    event_description VARCHAR(500) COMMENT '事件描述',
    handler_name VARCHAR(50) COMMENT '处理人',
    handle_result VARCHAR(500) COMMENT '处理结果',
    handle_time DATETIME COMMENT '处理时间',
    status INT DEFAULT 0 COMMENT '状态 0-待处理 1-已处理',
    create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
    is_deleted INT DEFAULT 0
) COMMENT '异常事件表';
```

---

### 任务 2.5：检录长角色权限管理 🔴

**状态：** 未开始
**工时：** 0.5天

#### 需求描述
- 定义检录长角色
- 赋予特殊权限（处理异常、调整赛程）
- 集成现有权限系统

#### 实现要点
- 利用 BladeX 框架的角色权限系统
- 新增角色：`ROLE_REFEREE_CHIEF`
- 权限：异常处理、成绩复核申请

---

### 任务 2.6：比赛状态流转管理 🔴

**状态：** 未开始
**工时：** 0.5天

#### 需求描述
- 状态机管理运动员比赛状态
- 防止非法状态转换
- 记录状态变更日志

#### 状态流转图
```
待出场(0) → 进行中(1) → 已完成(2)
     ↓          ↓
   已取消    暂停/异常
```

---

## 🎯 Controller 层接口

```java
@RestController
@RequestMapping("/martial/athlete")
public class MartialAthleteController {

    @PostMapping("/checkin")
    @Operation(summary = "运动员签到")
    public R checkIn(@RequestParam Long athleteId, @RequestParam Long scheduleId) {
        athleteService.checkIn(athleteId, scheduleId);
        return R.success("签到成功");
    }

    @PostMapping("/complete")
    @Operation(summary = "完成比赛")
    public R complete(@RequestParam Long athleteId) {
        athleteService.completePerformance(athleteId);
        return R.success("已标记为完成");
    }
}
```

---

## ✅ 验收标准

- [ ] 签到功能正常，状态更新准确
- [ ] 评分验证有效拦截非法分数
- [ ] 异常分数警告机制生效
- [ ] 异常事件可记录和查询
- [ ] 权限控制符合设计

---
