fix(B06 횡단): 넘어간 사면이 원지반과 못 만나도 고름 유지 — 같은 쪽 사면 선이 이어받음 (370-5)

- pickedLineAt — 키가 사라지면 같은 쪽 교차점 손잡이 → 그것도 없으면(사면 미교차) 같은 쪽 첫 절·성토 사면 선
- 손잡이(toe:) 를 고른 채 넘어가도 이어받음 — 고름이 풀려 공용 칸이 암 경계로 넘어가던 흠
- 시험: helper_370_2 「손잡이 없는 넘어감」 사례(성토 사면 · 「사면 이동 (우)」 · ◀↺▶)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
This commit is contained in:
2026-10-17 16:19:51 +09:00
co-authored by Claude Opus 5.5
parent 5b993ddded
commit f050dcc08d
3 changed files with 44 additions and 3 deletions
@@ -299,9 +299,12 @@ export function pickedLineAt(stationId: string): number | null {
if (picked?.stationId !== stationId) return null;
const keys = keysByStation.get(stationId);
let index = keys ? keys.indexOf(picked.key) : Number(picked.key);
// 사면이 절 ↔ 성으로 넘어가 키가 바뀌거나 길이 0 으로 사라지면 같은 쪽 교차점 손잡이(370-2)
const slope = /^(?:cut|fill)(?:\+s)?:(left|right):/.exec(picked.key);
if (index < 0 && keys && slope) index = keys.indexOf(`toe:${slope[1]}`);
// 사면이 절 ↔ 성으로 넘어가 키가 바뀌거나 길이 0 으로 사라지면 같은 쪽 교차점 손잡이(370-2) ·
// 손잡이도 없으면(사면 미교차) 같은 쪽 첫 사면 선(370-5) — 고름이 풀려 암 칸으로 넘어가지 않게
const side = /^(?:(?:cut|fill)(?:\+s)?|toe):(left|right)/.exec(picked.key)?.[1];
if (index < 0 && keys && side) index = keys.indexOf(`toe:${side}`);
if (index < 0 && keys && side)
index = keys.findIndex((k) => k === `cut:${side}:0` || k === `fill:${side}:0`);
return index >= 0 ? index : null;
}
export function setPickedLine(stationId: string, index: number | null): void {
@@ -318,6 +318,34 @@ out.inherit = {
after.handle.setActive(afterIndex);
out.inherit.label = cellOf(after.handle).title;
// ⑤ 370-5 — 손잡이를 고른 뒤 넘어간 사면이 원지반과 못 만나면(손잡이 없음) 같은 쪽 첫 사면 선이 이어받음
pick.setPickedLine("S1", null);
{
const again = attach(near, []);
again.layer.children.filter((k) => k.classList.contains("b06-chart__toe-hit"))[1].click();
pick.setPickedLine("S1", again.picks[0]);
let extend = crossing[1];
let open = null;
while (extend < 10 && !open) {
extend = Math.round((extend + 0.5) * 10) / 10;
const sec = section(extend);
if (!pick.designLineMoves(sec, () => undefined).toes.right) open = sec;
}
const lost = attach(open, []);
const index = pick.pickedLineAt("S1");
const piece = index === null ? null : lost.handle.pieces[index];
lost.handle.setActive(index);
const cell = cellOf(lost.handle);
out.noToe = {
extend,
toeGone: !!open,
index,
zone: piece && pick.pieceZone(open.design, piece),
title: cell.title,
buttons: ["left", "reset", "right"].filter((slot) => cell.button(slot)),
};
}
// ④ 정확히 0 자리(379-1) — 노견 끝 = 원지반(±5 mm = 절·성토 없음) · 손잡이 · 누르면 사면처럼 ◀↺▶ · 방향키
// 조각 0 은 안 봄 — 그림 규칙(노견 끝 → 첫 접점 보호 구간)이 지반 위 짧은 선을 남김(브레인 A)
const zero = section(out.stop.value);
+10
View File
@@ -60,6 +60,16 @@ def test_반올림이_교차_앞이어도_다음_걸음은_넘어감(out) -> Non
assert abs(got["got"] - got["next"]) < 1e-9 # 0.936 → 1.036 꼴(제자리 아님)
def test_손잡이_없는_넘어감도_고름_유지(out) -> None:
"""370-5 — 넘어간 사면이 원지반과 못 만나 손잡이가 사라져도 같은 쪽 사면 선 · 암 칸으로 안 넘어감."""
got = out["noToe"]
assert got["toeGone"] is True
assert got["index"] is not None
assert got["zone"] == {"zone": "fill", "side": "right"}
assert got["title"] == "사면 이동 (우)"
assert got["buttons"] == ["left", "reset", "right"] # ◀↺▶ 남음
def test_교차점_손잡이_쪽마다_늘_보임(out) -> None:
toe = out["toe"]
assert toe["count"] == len(toe["sides"]) == 2