二七王:前端 SeatMap,服务端座位与显示位互换

清单 §0.1:下家 (seat+1)%3 显示在右上,与服务端 get_nextseat 同源。
3×3 全组合 + 互逆 + 非法键抛错都已覆盖。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-26 19:57:02 +08:00
co-authored by Claude Opus 5
parent 65a73c5c2a
commit e9333303d5
2 changed files with 75 additions and 0 deletions
+44
View File
@@ -0,0 +1,44 @@
// 服务端座位 ↔ 显示位(清单 §0.1)
const { load, throws } = require('./_load');
const t = require('./_assert')();
load('client/js/01_SubGame/codes/core/SeatMap.js');
// ---- 3×3 全组合 ----
// mySeat=0: 自己0、下家1在右上、上家2在左上
t.eq('my0 seat0', EQW_SeatMap.toDisplay(0, 0), 'SELF');
t.eq('my0 seat1', EQW_SeatMap.toDisplay(1, 0), 'RIGHT');
t.eq('my0 seat2', EQW_SeatMap.toDisplay(2, 0), 'LEFT');
t.eq('my1 seat1', EQW_SeatMap.toDisplay(1, 1), 'SELF');
t.eq('my1 seat2', EQW_SeatMap.toDisplay(2, 1), 'RIGHT');
t.eq('my1 seat0', EQW_SeatMap.toDisplay(0, 1), 'LEFT');
t.eq('my2 seat2', EQW_SeatMap.toDisplay(2, 2), 'SELF');
t.eq('my2 seat0', EQW_SeatMap.toDisplay(0, 2), 'RIGHT');
t.eq('my2 seat1', EQW_SeatMap.toDisplay(1, 2), 'LEFT');
// ---- 反向 ----
t.eq('my1 -> RIGHT 是座位2', EQW_SeatMap.toSeat('RIGHT', 1), 2);
t.eq('my2 -> RIGHT 是座位0', EQW_SeatMap.toSeat('RIGHT', 2), 0);
t.eq('my2 -> LEFT 是座位1', EQW_SeatMap.toSeat('LEFT', 2), 1);
t.eq('my0 -> SELF 是座位0', EQW_SeatMap.toSeat('SELF', 0), 0);
// ---- 互逆:任意 mySeat/seat 组合 toSeat(toDisplay(s)) == s ----
let ok = true;
for (let my = 0; my < 3; my++) {
for (let s = 0; s < 3; s++) {
if (EQW_SeatMap.toSeat(EQW_SeatMap.toDisplay(s, my), my) !== s) { ok = false; }
}
}
t.eq('toDisplay/toSeat 互逆', ok, true);
// ---- 与服务端 get_nextseat 一致:下家恒在 RIGHT ----
let nextOk = true;
for (let my = 0; my < 3; my++) {
if (EQW_SeatMap.toDisplay((my + 1) % 3, my) !== 'RIGHT') { nextOk = false; }
}
t.eq('下家(seat+1)%3 恒在右上', nextOk, true);
// ---- 反面:非法显示位显式抛错,不静默返回 ----
t.eq('非法显示位抛错', throws(() => EQW_SeatMap.toSeat('TOP', 0)), true);
process.exit(t.done('seatmap') ? 0 : 1);