# 成绩 CSV 清洗与报告

前置：第 00—13 章

读取含坏数据的成绩表。逐条检查 ID、姓名、分数和重复 ID，保留有效记录，把无效行及原因写入错误报告，输出人数、平均分、通过率与排名。CSV 的逻辑记录可能跨物理行，因此报告记录号不伪称绝对物理行号。

### 1 列出数据约定
必需列为 student_id、name、score；ID 和姓名非空；score 是 0—100 的整数字符串；相同 ID 首条有效记录保留，后续重复记错。

### 2 手算样本
先查看 data/scores.csv。有效分数为 80、60、100、59、0，总分 299，平均 59.8；达到 60 有 3 人，通过率 60%。有 4 条错误记录。

### 3 一条一条验证
先处理字段缺失，再转整数，再检查范围，最后检测已保留 ID 是否重复。错误放入列表并继续，不让一条坏数据阻止所有正常记录。

### 4 统计与排序
只对有效数据计算。空数据平均分与通过率为 None，排名为空。sorted 用负分数与 ID 组成 key，保证同分顺序稳定可说明。

### 5 保存并核验
写 report.json 和 errors.csv，读回来确认 valid_count+invalid_count 等于输入数据记录数。修改一条坏记录后重跑，确认计数相应变化。

### 运行命令

从学习包根目录执行。Windows 用 py，Mac 用 python3，激活环境后可用 python。

```terminal
python projects/02_score_report/app.py
python projects/02_score_report/app.py --help
```

### 预期结果

显示：有效 5 条，无效 4 条；平均分 59.8；通过率 60.0%。outputs/report.json 保存完整结果，outputs/errors.csv 保存记录号与错误原因。重复运行覆盖这两个专用输出文件。

### 验收

运行学习包的 python tools/check_projects.py 核验参考实现；自己的实现按上面手算结果和边界逐项验证。


## 独立实现记录

- 输入约定：
- 输出约定：
- 最小样例手算：
- 空数据测试：
- 边界测试：
- 错误输入测试：
- 我的新增功能：
