Files
joywayerandClaude Opus 5 503ad4b374 二七王:SeatMap 座位号显式校验,去掉恒真断言
- toDisplay 此前不校验入参:toDisplay(seat, undefined) 会算出 NaN,NaN 既不等于 0
  也不等于 1,最后落到 return 'LEFT'——一个看起来很合理的错误答案。现与兄弟方法
  toSeat 一样对非 0/1/2 显式抛错;toSeat 的 mySeat 同样校验(否则算出 NaN 座位号)。
  补 8 条反面用例 + 1 条「合法组合不被误伤」的正面用例。
- test_cardcodec.js 删掉 t.eq('deck1/deck2 全部同帧', true, true) 这条恒真断言,
  改为收集不匹配项后断言为空——恒真断言在上面的循环被删掉后仍会 PASS。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 22:27:05 +08:00

66 lines
3.1 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 服务端座位 ↔ 显示位(清单 §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);
// ---- 反面:非法座位号显式抛错 ----
// toDisplay 曾不做校验:((NaN)%3+3)%3 = NaN,既不等于 0 也不等于 1,最后落到 return 'LEFT'
// ——一个看起来很合理的错误答案,比抛错难查得多
t.eq('toDisplay mySeat=undefined 抛错', throws(() => EQW_SeatMap.toDisplay(0, undefined)), true);
t.eq('toDisplay seat=undefined 抛错', throws(() => EQW_SeatMap.toDisplay(undefined, 0)), true);
t.eq('toDisplay seat=3 抛错', throws(() => EQW_SeatMap.toDisplay(3, 0)), true);
t.eq('toDisplay seat=-1 抛错', throws(() => EQW_SeatMap.toDisplay(-1, 0)), true);
t.eq('toDisplay seat=1.5 抛错', throws(() => EQW_SeatMap.toDisplay(1.5, 0)), true);
t.eq('toDisplay seat 是字符串 抛错', throws(() => EQW_SeatMap.toDisplay('1', 0)), true);
t.eq('toDisplay seat=null 抛错', throws(() => EQW_SeatMap.toDisplay(null, 0)), true);
t.eq('toSeat mySeat=undefined 抛错', throws(() => EQW_SeatMap.toSeat('SELF', undefined)), true);
t.eq('toSeat mySeat=3 抛错', throws(() => EQW_SeatMap.toSeat('LEFT', 3)), true);
// 正面:合法的 9 种组合都不抛错(上面已逐条断言过返回值,这里确认校验没误伤)
let legalOk = true;
for (let my = 0; my < 3; my++) {
for (let s = 0; s < 3; s++) {
if (throws(() => EQW_SeatMap.toDisplay(s, my))) { legalOk = false; }
}
}
t.eq('合法座位号不被误伤', legalOk, true);
process.exit(t.done('seatmap') ? 0 : 1);