feat(780-2): 엑셀 보기 단가산출 탭 오른쪽 = 단가산출 목록 — 판 바꾸기 · 거르기 · 목록 ↔ 시트 · 두 벌 맞춤(요구 627)
- 새 Hopyo_SheetSk: 탭(역할) 따라 오른쪽 판 바꿈 · 일위대가표 = 호표 목록 그대로 · 단가산출표 · 상세 = 마법사 단가산출 칸 좁은 꼴 한 벌(처음 올 때 지음 · 다른 층 · 권한 없음 = 보기만) · 시트 칸 → 목록 강조 · 목록 줄 → 지금 탭 블록 자리 - WizardSk: 좁은 꼴 옵션 · 부름 칸(일위대가 n 곳 · 일위대가 밖) · 거르기(전체 · 안 · 밖 · 고를 줄 있음) · 같은 캐시 두 벌 맞춤 알림 · 옮김 뒤 HOPYO_BUILT(열린 엑셀 보기 칠 다시) - SkPick: 줄 0 블록 = 「줄 없음」 확인 막음 · 거르기 · 끝내기 글 재료에 일위대가 밖 수 - SheetNav: role · blockAt · spotOf 내보냄 · SheetMap: 판정 없음 글 → 「일위대가 밖」 - Wizard [끝내기]: 막지 않음 · 물음창에 안 옮긴 단가산출 n(일위대가 밖 m) - 시험: 새 test_627_sheet_sk(판 바꿈 · 목록 지음 · 줄 0 막음 · 캐시 공유) · test_778_5 끝내기 재료 꼴에 밖 칸 더함 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -115,7 +115,7 @@ export function lineTone(
|
||||
export const worst = (tones: Tone[]): Tone =>
|
||||
tones.reduce<Tone>((a, b) => (RANK[b] > RANK[a] ? b : a), "muted");
|
||||
|
||||
/** 블록 칠 — 만든 SK 갈래 › 없으면 부르는 첫 줄 판정 「예상」 · 판정 없음 = 밖 */
|
||||
/** 블록 칠 — 만든 SK 갈래 › 없으면 부르는 첫 줄 판정 「예상」 · 판정 없음 = 「일위대가 밖」 */
|
||||
export function blockTone(m: BlockMark | undefined): { tone: Tone; 글: string } {
|
||||
if (!m) return { tone: "muted", 글: "안 불림" };
|
||||
if (m.SK) {
|
||||
@@ -123,7 +123,7 @@ export function blockTone(m: BlockMark | undefined): { tone: Tone; 글: string }
|
||||
const tone: Tone = lost ? "danger" : m.갈래 === "SK" ? "warning" : "success";
|
||||
return { tone, 글: `${m.SK} · ${m.갈래 ?? ""}${lost ? ` · 못옮김 ${lost}` : ""}` };
|
||||
}
|
||||
if (!m.판정) return { tone: "muted", 글: "판정 없음" };
|
||||
if (!m.판정) return { tone: "muted", 글: "일위대가 밖" }; // 부르는 일위대가 줄 없음(780-2)
|
||||
const tone: Tone = m.판정 === "맞음" ? "success" : m.판정 === "다른 점" ? "warning" : "info";
|
||||
return { tone, 글: `예상 — 부르는 첫 줄 ${m.판정}` };
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
* · 고름 캐시 `{고름 {번: {차례: 고름}}, 확인 [번]}` — 줄 고름이 서버 상태를 덮음(꼬리표 「내가 고름」)
|
||||
* · 블록 [확인] = 남은 고를 줄 0 일 때만 · 몸 = `{확인: [{번, 고름?}]}`(확인한 블록만 · 자동 확인 없음)
|
||||
* · 금액 · 판정 정본은 서버 — 여기는 캐시를 겹쳐 보이기 · 몸 짓기만
|
||||
* · 780-2(요구 627) — 블록 `부름 [호표 번]`(빈 = 일위대가 밖 · 칸 없음 = 옛 서버 = 안) · 줄 0 = 「줄 없음」 확인 막음 ·
|
||||
* 거르기(모두 · 안 · 밖 · 고를 줄 있음)
|
||||
* 화면 · fetch · sessionStorage 없음(`CLAUDE.md` 4장).
|
||||
* ========================================================================== */
|
||||
|
||||
@@ -65,6 +67,8 @@ export interface SkBlock {
|
||||
근거: { 로직: string; 이름: string | null; 판정: string | null } | null;
|
||||
만든: string | null;
|
||||
줄: SkLine[];
|
||||
/** 부르는 일위대가 호표 번(780-1) — [] = 일위대가 밖 · 없음 = 옛 서버(안) */
|
||||
부름?: number[];
|
||||
}
|
||||
|
||||
export interface SkJudged {
|
||||
@@ -91,6 +95,7 @@ export interface SkDraft {
|
||||
|
||||
export const MINE = "내가 고름";
|
||||
export const GOOD = "옮길 수 있음";
|
||||
export const NO_LINES = "줄 없음";
|
||||
export const LINKED = "이어짐";
|
||||
export const PICK = "고를 것";
|
||||
export const OUT = "밖";
|
||||
@@ -143,16 +148,17 @@ export function lineView(
|
||||
/** 그 블록 캐시 고름 `{차례: 고름}` */
|
||||
export const picksOf = (d: SkDraft, 번: number): Record<string, SkPick> => d.고름[String(번)] ?? {};
|
||||
|
||||
/** 남은 고를 줄 수 — 이어짐 · 밖 · 뺌 아닌 줄(캐시 고름 겹침) */
|
||||
/** 남은 고를 줄 수 — 이어짐 · 밖 · 뺌 아닌 줄(캐시 고름 겹침) · 줄 0 블록 = 1(서버 「줄 없음」 고를줄 1) */
|
||||
export const leftLines = (b: SkBlock, picks: Record<string, SkPick>): number =>
|
||||
b.줄.filter((l) => !DONE.has(lineView(l, picks[String(l.차례)]).상태)).length;
|
||||
b.줄.length ? b.줄.filter((l) => !DONE.has(lineView(l, picks[String(l.차례)]).상태)).length : 1;
|
||||
|
||||
/** [확인] 켜짐 — 고를 줄 0 */
|
||||
export const canConfirm = (b: SkBlock, picks: Record<string, SkPick>): boolean =>
|
||||
leftLines(b, picks) === 0;
|
||||
|
||||
/** 블록 판정 글 — 캐시 겹친 뒤 「옮길 수 있음」 · 「고를 줄 n」 */
|
||||
/** 블록 판정 글 — 캐시 겹친 뒤 「옮길 수 있음」 · 「고를 줄 n」 · 「줄 없음」 */
|
||||
export function verdictOf(b: SkBlock, picks: Record<string, SkPick>): string {
|
||||
if (!b.줄.length) return NO_LINES;
|
||||
const n = leftLines(b, picks);
|
||||
return n ? `고를 줄 ${n}` : GOOD;
|
||||
}
|
||||
@@ -201,10 +207,23 @@ export function sureBody(d: SkDraft, blocks: SkBlock[]): SkSure[] {
|
||||
});
|
||||
}
|
||||
|
||||
/** 마법사 [끝내기] 글 재료 — 아직 안 옮긴 블록 수 · 그 블록 고를 줄 합 */
|
||||
export function waiting(d: SkDraft, blocks: SkBlock[]): { 블록: number; 줄: number } {
|
||||
/** 일위대가 밖 블록 — `부름` 빈 배열 */
|
||||
export const outside = (b: SkBlock): boolean => !!b.부름 && !b.부름.length;
|
||||
|
||||
/** 마법사 [끝내기] 글 재료 — 아직 안 옮긴 블록 수 · 그중 일위대가 밖 · 그 블록 고를 줄 합 */
|
||||
export function waiting(d: SkDraft, blocks: SkBlock[]): { 블록: number; 밖: number; 줄: number } {
|
||||
const open = blocks.filter((b) => !b.만든);
|
||||
return { 블록: open.length, 줄: open.reduce((n, b) => n + leftLines(b, picksOf(d, b.번)), 0) };
|
||||
const 줄 = open.reduce((n, b) => n + leftLines(b, picksOf(d, b.번)), 0);
|
||||
return { 블록: open.length, 밖: open.filter(outside).length, 줄 };
|
||||
}
|
||||
|
||||
export type SkFilter = "all" | "in" | "out" | "open";
|
||||
/** 거르기 — 모두 · 일위대가 안 · 일위대가 밖 · 고를 줄 있음(안 옮긴 블록 · 캐시 겹침) */
|
||||
export function filterBlocks(blocks: SkBlock[], d: SkDraft, f: SkFilter): SkBlock[] {
|
||||
if (f === "in") return blocks.filter((b) => !outside(b));
|
||||
if (f === "out") return blocks.filter(outside);
|
||||
if (f === "open") return blocks.filter((b) => !b.만든 && leftLines(b, picksOf(d, b.번)) > 0);
|
||||
return blocks;
|
||||
}
|
||||
|
||||
/** 줄 고름 넣기 · 지움(null) — 새 캐시 */
|
||||
|
||||
Reference in New Issue
Block a user