二七王:修正出牌 handler 注释并补强 grade 累加与 nextseat 测试

审查发现简报本身两处缺陷:
1. grade 累加测试断言力不足,无法区分"累加"与"仅在字段存在时赋值"两种
   实现——补一条跨包连续收两个 grade 的用例(10 再 15,断言最终 25)钉住
   累加语义。
2. chupai3 实际也带 nextseat(服务端在 switch 前统一设置三个包),简报
   注释误写成"chupai1/2 独有";修正文件头注释,并给 chupai3 测试用例补
   上 nextseat 与对应的 turn.seat 断言,使包结构与真实下发一致。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-27 17:58:42 +08:00
co-authored by Claude Opus 5
parent 5637d63c3b
commit 5a77e4b132
2 changed files with 18 additions and 4 deletions
@@ -4,10 +4,10 @@
// 协议 §11–§13。三个包字段不完全相同: // 协议 §11–§13。三个包字段不完全相同:
// chupai1 首家独有:shuaicuo 甩错标志 / count 出牌数量 / flower 出牌花色 / // chupai1 首家独有:shuaicuo 甩错标志 / count 出牌数量 / flower 出牌花色 /
// cardtype 牌型 / shuai 甩牌分量构成 // cardtype 牌型 / shuai 甩牌分量构成
// chupai1/2 有:nextseat 下一个出牌者 / mustcard 必出牌(只发给 nextseat 那一家)
// chupai3 末家独有:maxseat 本轮谁最大 / grade 本轮闲家得分 // chupai3 末家独有:maxseat 本轮谁最大 / grade 本轮闲家得分
// 共有:seat / cards / seatlist(仅可查牌) / countdown / baozhu / // 共有:seat / cards / seatlist(仅可查牌) / countdown / baozhu / nextseat /
// cardsinhand(仅出牌者自己有) / curmultiple(1 和 3 有) // cardsinhand(仅出牌者自己有) / curmultiple(1 和 3 有)
// mustcard:三个包都可能带,但只发给 nextseat 那一家(其余两家无此属性)
// //
// 【cardsinhand 只有出牌者自己有】:收到就更新自己的手牌;别人出牌时没这个字段, // 【cardsinhand 只有出牌者自己有】:收到就更新自己的手牌;别人出牌时没这个字段,
// 绝不能抹掉自己的手牌——这正是「缺字段不兜底」要防的。 // 绝不能抹掉自己的手牌——这正是「缺字段不兜底」要防的。
+16 -2
View File
@@ -45,21 +45,35 @@ EQW_PlayHandler.handle({ success: true, seat: 1, cards: [5,6], nextseat: 0, coun
t.eq('无 mustcard 时清空', S.my.mustCard, []); t.eq('无 mustcard 时清空', S.my.mustCard, []);
// ================= chupai3(末家出牌,本轮结束)================= // ================= chupai3(末家出牌,本轮结束)=================
// 真实的 chupai3 也带 nextseat(下一轮首家):服务端在 switch 前统一设置,
// 只有整轮结束进入结算时才会整体换成 jiesuan rpc(不会以 chupai3 到达 handler)
S.reset(); evts.length = 0; S.reset(); evts.length = 0;
EQW_PlayHandler.handle({ success: true, seat: 2, cards: [9,10], maxseat: 0, grade: 25, EQW_PlayHandler.handle({ success: true, seat: 2, cards: [9,10], maxseat: 0, grade: 25,
countdown: 15, baozhu: 1, curmultiple: -2 }, 3); nextseat: 0, countdown: 15, baozhu: 1, curmultiple: -2 }, 3);
t.eq('本轮最大者', S.result.chupai.maxseat, 0); t.eq('本轮最大者', S.result.chupai.maxseat, 0);
t.eq('本轮闲家得分', S.result.chupai.grade, 25); t.eq('本轮闲家得分', S.result.chupai.grade, 25);
t.eq('累计捡分', S.aset.grade, 25); t.eq('累计捡分', S.aset.grade, 25);
t.eq('报无主标志', S.aset.baozhu, 1); t.eq('报无主标志', S.aset.baozhu, 1);
t.eq('抓分倍数(带符号)', S.aset.curmultiple, -2); t.eq('抓分倍数(带符号)', S.aset.curmultiple, -2);
t.eq('下一轮首家', S.turn.seat, 0);
t.eq('本轮结束发事件', evts.indexOf('EQW_TRICK_END') >= 0, true); t.eq('本轮结束发事件', evts.indexOf('EQW_TRICK_END') >= 0, true);
// 本轮闲家没得分时不带 grade,累计分不该被抹 // 本轮闲家没得分时不带 grade,累计分不该被抹
S.reset(); S.aset.grade = 40; S.reset(); S.aset.grade = 40;
EQW_PlayHandler.handle({ success: true, seat: 2, cards: [9,10], maxseat: 1, countdown: 15 }, 3); EQW_PlayHandler.handle({ success: true, seat: 2, cards: [9,10], maxseat: 1,
nextseat: 1, countdown: 15 }, 3);
t.eq('无 grade 时累计分保持', S.aset.grade, 40); t.eq('无 grade 时累计分保持', S.aset.grade, 40);
// grade 是「本轮」得分,要跨包累加进小局捡分,不是赋值——
// 若实现改成 aset.grade = data.grade,这条会把 25 覆盖成 15 而非累加到 25
S.reset();
EQW_PlayHandler.handle({ success: true, seat: 2, cards: [1,2], maxseat: 0, grade: 10,
nextseat: 0, countdown: 15 }, 3);
t.eq('第一轮捡分', S.aset.grade, 10);
EQW_PlayHandler.handle({ success: true, seat: 2, cards: [3,4], maxseat: 1, grade: 15,
nextseat: 1, countdown: 15 }, 3);
t.eq('第二轮跨包累加捡分', S.aset.grade, 25);
// ================= 甩错 ================= // ================= 甩错 =================
S.reset(); evts.length = 0; S.reset(); evts.length = 0;
EQW_PlayHandler.handle({ success: true, seat: 0, cards: [11], shuaicuo: 1, count: 1, EQW_PlayHandler.handle({ success: true, seat: 0, cards: [11], shuaicuo: 1, count: 1,