# Achievement Report Mastery Hit Rate Implementation Plan > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** Rename the achievement-report metric from `真题生词命中率` to `试卷掌握度命中率`, and derive its displayed value from `试卷熟词提升 ÷ 词汇量提升`, rounded to 1 decimal place as a percentage, with `0%` when `词汇量提升 = 0`. **Architecture:** Keep the existing report DTO/placeholder shape intact and change only the application-layer mapping logic plus presentation text. Compute the percentage inside `AchievementReportContentMapper` from the existing delta fields so infrastructure rendering continues to consume the same `unknownWordHitRateText` placeholders without contract changes. **Tech Stack:** Java, Maven, JUnit 5, AssertJ, HTML template rendering. --- ### Task 1: Replace payload-driven metric with derived mastery hit rate **Files:** - Modify: `abilities/exam-sprint/application/src/main/java/cn/yunzhixue/ability/center/examsprint/application/report/AchievementReportContentMapper.java` - Test: `abilities/exam-sprint/application/src/test/java/cn/yunzhixue/ability/center/examsprint/application/report/AchievementReportContentMapperTest.java` - Test: `abilities/exam-sprint/application/src/test/java/cn/yunzhixue/ability/center/examsprint/application/report/ExamSprintReportApplicationServiceTest.java` **Step 1: Write the failing tests** - Update mapper/service expectations so the metric is derived from `TestPaperImprovedWordCount ÷ StudentImproveWordCount` instead of `PaperMasteryHitRate`. - Use the existing sample payload to expect `4 ÷ 19 = 21.1%`. - Add a zero-denominator case expecting `0%` when `StudentImproveWordCount = 0`. - Make at least one test keep `PaperMasteryHitRate` at a deliberately mismatched value so RED proves the old field is no longer the source. **Step 2: Run tests to verify they fail** Run: ```bash mvn -pl abilities/exam-sprint/application -am -Dtest=AchievementReportContentMapperTest,ExamSprintReportApplicationServiceTest test ``` Expected: FAIL because the mapper still uses `PaperMasteryHitRate` and formats `1.93%` instead of `21.1%` / `0%`. **Step 3: Write the minimal implementation** - Add a small helper in `AchievementReportContentMapper` that: - reads `payload.testPaperImprovedWordCount()` as numerator - reads `payload.studentImproveWordCount()` as denominator - returns `"0%"` when denominator is zero - otherwise computes `(numerator / denominator) * 100` - rounds half up to 1 decimal place - formats non-zero denominator results with exactly 1 decimal place so `20%` becomes `20.0%` while `21.1%` stays `21.1%` - Reuse the computed string for both `summaryMetrics.unknownWordHitRateText` and `examUnknownWordsHitStatus.unknownWordHitRateText`. **Step 4: Run tests to verify they pass** Run: ```bash mvn -pl abilities/exam-sprint/application -am -Dtest=AchievementReportContentMapperTest,ExamSprintReportApplicationServiceTest test ``` Expected: PASS. **Step 5: Do not commit** - Leave changes uncommitted unless the user explicitly asks for a commit. ### Task 2: Rename the displayed metric label everywhere in achievement report outputs **Files:** - Modify: `abilities/exam-sprint/infrastructure/src/main/resources/templates/achievement-exam-sprint-report-template.html` - Test: `abilities/exam-sprint/infrastructure/src/test/java/cn/yunzhixue/ability/center/examsprint/infrastructure/report/rendering/achievement/ClasspathAchievementExamSprintReportRendererTest.java` - Test: `abilities/exam-sprint/infrastructure/src/test/java/cn/yunzhixue/ability/center/examsprint/infrastructure/report/pdf/PlaywrightExamSprintReportPdfGeneratorTest.java` **Step 1: Write the failing tests** - Update assertions from `真题生词命中率` to `试卷掌握度命中率`. - Update rendered value expectations from `1.93%` to `21.1%` based on the shared sample payload. **Step 2: Run tests to verify they fail** Run: ```bash mvn -pl abilities/exam-sprint/infrastructure -am -Dtest=ClasspathAchievementExamSprintReportRendererTest,PlaywrightExamSprintReportPdfGeneratorTest test ``` Expected: FAIL because the template still shows the old label and existing fixture-derived values still render `1.93%`. **Step 3: Write the minimal implementation** - Change the two achievement-template labels from `真题生词命中率` to `试卷掌握度命中率`. - Keep placeholder names unchanged. **Step 4: Run tests to verify they pass** Run: ```bash mvn -pl abilities/exam-sprint/infrastructure -am -Dtest=ClasspathAchievementExamSprintReportRendererTest,PlaywrightExamSprintReportPdfGeneratorTest test ``` Expected: PASS. **Step 5: Do not commit** - Leave changes uncommitted unless the user explicitly asks for a commit. ### Task 3: End-to-end verification of the final achievement report behavior **Files:** - Verify only: no new files expected **Step 1: Run the combined verification suite** Run: ```bash mvn -pl abilities/exam-sprint/infrastructure,abilities/exam-sprint/application -am -Dtest=AchievementReportContentMapperTest,ExamSprintReportApplicationServiceTest,ClasspathAchievementExamSprintReportRendererTest,PlaywrightExamSprintReportPdfGeneratorTest test ``` Expected: PASS with zero failures. **Step 2: Inspect the final diff** Run: ```bash git diff -- abilities/exam-sprint/application/src/main/java/cn/yunzhixue/ability/center/examsprint/application/report/AchievementReportContentMapper.java abilities/exam-sprint/application/src/test/java/cn/yunzhixue/ability/center/examsprint/application/report/AchievementReportContentMapperTest.java abilities/exam-sprint/application/src/test/java/cn/yunzhixue/ability/center/examsprint/application/report/ExamSprintReportApplicationServiceTest.java abilities/exam-sprint/infrastructure/src/main/resources/templates/achievement-exam-sprint-report-template.html abilities/exam-sprint/infrastructure/src/test/java/cn/yunzhixue/ability/center/examsprint/infrastructure/report/rendering/achievement/ClasspathAchievementExamSprintReportRendererTest.java abilities/exam-sprint/infrastructure/src/test/java/cn/yunzhixue/ability/center/examsprint/infrastructure/report/pdf/PlaywrightExamSprintReportPdfGeneratorTest.java ``` Expected: Only the derived-metric logic, renamed labels, and directly related test updates appear. **Step 3: Do not commit** - Stop after reporting verification evidence unless the user explicitly asks for a commit.