二七王:前端删掉 9 处阶段/控制权推导,一律读服务端包字段
I-3 前端不再持有对局状态机(配合服务端上一提交的下发面补齐): - 删掉 5 处按 rpc 名硬编码的 aset.step(Deal=1 / Call=2 / Main=3 / Bury=5 / Result=6), 一律改 _apply 读包里的 step - 删掉 4 处 turn.seat = aset.banker(CallHandler / MainHandler / ResyncHandler×2), 增量路径读 nextseat、重连路径读分组里的 seat;同一条规则不再有 4 个写入处 I-2 ResyncHandler._applyBalance 由只接 aset 扩为接 aset/bottom/account, 结算面板开着时重连/硬刷新不再丢抠底明细与末局大结算。 一致性测试 EXCLUDE 随之从 4 条收缩为 2 条(去掉 result.bottom / result.account, 只留一次性事件 table.ancard3s 与归下一轮的 result.chupai),未新增任何豁免条目。 夹具按新包结构重跑(种子不变,牌局不变):diff 纯为 67 行新增字段、0 行删除; test_fixture 补上 step/nextseat/Balance 同源断言(68→82 checks)。 export_packets.js 里关于 playproc/seatlist 活引用的注释已过时,更正为仍存在的 Balance.readystate 与三份结算快照。 各 handler 单测补齐新字段并新增守卫用例:刻意构造 nextseat != banker、 step 为非预期值的包,使「退回硬编码/banker 反推」的写法必然转红(11/11 已验证)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -73,25 +73,67 @@ t.eq('三家叫分', S.call.calls, [null, 0, 65]);
|
||||
S.reset(); evts.length = 0;
|
||||
EQW_ResyncHandler.handleDeskinfo({
|
||||
count: 6, idx: 1, PlayerInfo: [0,0,0], step: 2, MyCards: [1,2],
|
||||
ChooseMain: { banker: 0, call: 70, multiple: 2, countdown: 20,
|
||||
ChooseMain: { seat: 0, banker: 0, call: 70, multiple: 2, countdown: 20,
|
||||
bottomcards: [1,2,3,4,5,6,7,8], touxiang: 1 }
|
||||
});
|
||||
t.eq('选主阶段', S.aset.step, 2);
|
||||
t.eq('底牌', S.my.bottomCards, [1,2,3,4,5,6,7,8]);
|
||||
t.eq('允许投降', S.aset.touxiang, 1);
|
||||
t.eq('控制权归庄家', S.turn.seat, 0);
|
||||
t.eq('控制权读 ChooseMain.seat', S.turn.seat, 0);
|
||||
|
||||
// 重连【不重放】70 分开底:deskinfo 里没有 ancard3s
|
||||
t.eq('重连不重放开底', S.table.ancard3s, 0);
|
||||
|
||||
// 【守卫】控制权取分组里的 seat(服务端权威),不用本地 banker 反推。
|
||||
// 真实链路里 ChooseMain.seat 恒 == banker,相等时"读哪个"分辨不出来;这里刻意让它们不同,
|
||||
// 退回 `turn.seat = aset.banker` 的写法必转红。
|
||||
S.reset();
|
||||
EQW_ResyncHandler.handleDeskinfo({
|
||||
count: 6, idx: 1, PlayerInfo: [0,0,0], step: 2, MyCards: [1,2],
|
||||
ChooseMain: { seat: 2, banker: 0, call: 70, multiple: 2, countdown: 20, touxiang: 1 }
|
||||
});
|
||||
t.eq('ChooseMain 控制权取 seat,不取 banker', S.turn.seat, 2);
|
||||
|
||||
// ================= deskinfo:step 3 埋牌阶段 =================
|
||||
S.reset();
|
||||
EQW_ResyncHandler.handleDeskinfo({
|
||||
count: 6, idx: 1, PlayerInfo: [0,0,0], step: 3, MyCards: [1,2],
|
||||
BuryCards: { seat: 0, banker: 0, call: 65, multiple: 2, flower: 1, countdown: 25,
|
||||
bottomcards: [1,2,3,4,5,6,7,8], curmultiple: 3 }
|
||||
});
|
||||
t.eq('埋牌阶段', S.aset.step, 3);
|
||||
t.eq('控制权读 BuryCards.seat', S.turn.seat, 0);
|
||||
// 同样的守卫:seat 与 banker 刻意不同
|
||||
S.reset();
|
||||
EQW_ResyncHandler.handleDeskinfo({
|
||||
count: 6, idx: 1, PlayerInfo: [0,0,0], step: 3, MyCards: [1,2],
|
||||
BuryCards: { seat: 1, banker: 0, call: 65, multiple: 2, flower: 1, countdown: 25 }
|
||||
});
|
||||
t.eq('BuryCards 控制权取 seat,不取 banker', S.turn.seat, 1);
|
||||
|
||||
// ================= deskinfo:step 6 结算阶段 =================
|
||||
S.reset(); evts.length = 0;
|
||||
EQW_ResyncHandler.handleDeskinfo({
|
||||
count: 6, idx: 6, PlayerInfo: [12,-6,-6], step: 6, MyCards: [],
|
||||
Balance: { readystate: [1,0,0], aset: { banker: 0, upgrade: 1, seatlist: [] } }
|
||||
Balance: { readystate: [1,0,0], aset: { banker: 0, upgrade: 1, seatlist: [] },
|
||||
bottom: { cards: [1,2,3,4,5,6,7,8], multiple: 2, grade1: 20, grade2: 40 },
|
||||
account: [{ score: 12 }, { score: -6 }, { score: -6 }] }
|
||||
});
|
||||
t.eq('结算阶段', S.aset.step, 6);
|
||||
t.eq('小局结算数据', S.result.aset.upgrade, 1);
|
||||
// I-2:结算面板还开着时重连,抠底明细与大局结算必须一并恢复(与 jiesuan 推送同一份数据)。
|
||||
// 漏接会让重连后抠底明细、末局大结算全部空白
|
||||
t.eq('重连恢复抠底明细', S.result.bottom.grade2, 40);
|
||||
t.eq('重连恢复大局结算', S.result.account.length, 3);
|
||||
|
||||
// 反面:非末局 / 投降局的 Balance 没有 bottom / account,缺字段保持 null,不兜底造分组
|
||||
S.reset();
|
||||
EQW_ResyncHandler.handleDeskinfo({
|
||||
count: 6, idx: 2, PlayerInfo: [0,0,0], step: 6, MyCards: [],
|
||||
Balance: { readystate: [0,0,0], aset: { banker: 0, upgrade: -99, seatlist: [] } }
|
||||
});
|
||||
t.eq('无抠底分组时保持 null', S.result.bottom, null);
|
||||
t.eq('无大局结算时保持 null', S.result.account, null);
|
||||
|
||||
// ================= StartWar:差异化下发 =================
|
||||
S.reset(); S.room.mySeat = 2; evts.length = 0;
|
||||
|
||||
Reference in New Issue
Block a user