feat(m01-easycalc): usesOf 회사 · 개인 층 조합까지 — M02 층 길 읽기만
- 내 층 /combos/all · 남의 회사 /layers/company/owners · 회사마다 사람 /layers/personal/owners → 층 조합 하나씩 읽어 담은 것만 - EasyUse.where(「회사 · 이름」 · 「개인 · 이름」) · 못 읽은 층은 「일부를 못 읽음」 한 줄 - 시험 — holding 견본(담은 것만 · 자리 글) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KmELpdXFDRZHhfbGuRhSmL
This commit is contained in:
@@ -53,9 +53,12 @@ export interface EasySaved {
|
||||
row: LogicRow;
|
||||
}
|
||||
|
||||
/** 쓰는 곳 한 줄 — 일위대가 조합 · 이 로직을 부르는 다른 로직 */
|
||||
/** 쓰는 곳 한 줄 — 일위대가 조합 · 이 로직을 부르는 다른 로직
|
||||
* `where` = 회사 · 개인 층 조합의 자리 글(「회사 · 산림조합」) · 마스터 층 · 로직은 없음
|
||||
* 층을 못 읽었으면 `key` "" · `name` = 「일부를 못 읽음」 한 줄(지우기 전에 확인하게) */
|
||||
export interface EasyUse {
|
||||
kind: "combo" | "logic";
|
||||
where?: string;
|
||||
key: string;
|
||||
name: string;
|
||||
}
|
||||
@@ -158,6 +161,14 @@ const TEXT = {
|
||||
"이 기계는 시간당 값을 셀 자료가 없음 — 다른 기계를 골라 주세요",
|
||||
"No hourly cost data for this machine — pick another",
|
||||
],
|
||||
AtCompany: ["회사 · {name}", "Company · {name}"],
|
||||
AtPerson: ["개인 · {name}", "Personal · {name}"],
|
||||
MyCompany: ["내 회사", "My company"],
|
||||
Me: ["나", "Me"],
|
||||
Unseen: [
|
||||
"회사 · 개인 조합 일부를 못 읽음 — 지우기 전에 확인 필요",
|
||||
"Some company or personal combos could not be read — check before deleting",
|
||||
],
|
||||
} as const satisfies Record<string, readonly [string, string]>;
|
||||
|
||||
type SayKey = keyof typeof TEXT;
|
||||
@@ -256,6 +267,26 @@ export function machineCall(m: MachineLogic, code: string): EasyMachineElement {
|
||||
const rest = needInputs.map((i) => `, ${quote(i.이름)}=${quote(i.이름)}`).join("");
|
||||
return { element: `로직(${m.key}, ${MACHINE}='${code}'${rest})`, needInputs };
|
||||
}
|
||||
|
||||
/** 층 조합 줄 통째(`담은로직` 포함) */
|
||||
export interface LayerCombo {
|
||||
키: string;
|
||||
이름?: string;
|
||||
담은로직?: { 로직?: string }[];
|
||||
}
|
||||
|
||||
/** 이 로직을 담은 층 조합 — `layer` = company · personal · `name` = 층 주인 이름 */
|
||||
export function holding(
|
||||
combos: LayerCombo[],
|
||||
key: string,
|
||||
layer: "company" | "personal",
|
||||
name: string,
|
||||
): EasyUse[] {
|
||||
const where = say(layer === "company" ? "AtCompany" : "AtPerson", { name });
|
||||
return combos
|
||||
.filter((c) => (c.담은로직 ?? []).some((one) => one?.로직 === key))
|
||||
.map((c): EasyUse => ({ kind: "combo", where, key: c.키, name: c.이름 ?? "" }));
|
||||
}
|
||||
/* ── 순수 끝 ── */
|
||||
|
||||
const OWN = "로직_자체.json"; // 내가 만든 것 한 자리(서버 `Store_Make.OWN`)
|
||||
@@ -263,10 +294,15 @@ const OWNER = "현장";
|
||||
const CALC_WAIT_MS = 300;
|
||||
const MACHINE_FILE = "건설기계"; // 기계 시간당 경비 로직이 든 장 파일(「08장 건설기계」)
|
||||
|
||||
async function request<T>(path: string, body?: unknown): Promise<T> {
|
||||
/** `/api/m01` 길 · M02 층 조합 읽기는 `m02` */
|
||||
const request = <T>(path: string, body?: unknown): Promise<T> =>
|
||||
send<T>(`${API_BASE_URL}/m01${path}`, body);
|
||||
const m02 = <T>(path: string): Promise<T> => send<T>(`${API_BASE_URL}/m02${path}`);
|
||||
|
||||
async function send<T>(url: string, body?: unknown): Promise<T> {
|
||||
let response: Response;
|
||||
try {
|
||||
response = await fetch(`${API_BASE_URL}/m01${path}`, {
|
||||
response = await fetch(url, {
|
||||
method: body === undefined ? "GET" : "POST",
|
||||
credentials: "include",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
@@ -385,13 +421,15 @@ export async function deleteEasy(key: string, version: string): Promise<{ versio
|
||||
return { version: got.version };
|
||||
}
|
||||
|
||||
/** 쓰는 곳 — 담은 일위대가 조합(마스터 층) + 이 로직을 부르는 내가 만든 것.
|
||||
/** 쓰는 곳 — 담은 일위대가 조합(마스터 · 회사 · 개인 층) + 이 로직을 부르는 내가 만든 것.
|
||||
* 지우기 누를 때 부름(무거움) · 서버 지우기 검사는 마스터 층 조합만 막음.
|
||||
* ponytail: 부르는 로직은 내가 만든 것만 하나씩 받아 훑음(품셈 기본은 내 것을 안 부름) —
|
||||
* 내 것이 수백이 되면 서버에 「부르는 로직」 길을 더할 것 */
|
||||
export async function usesOf(key: string): Promise<EasyUse[]> {
|
||||
const [combos, mine] = await Promise.all([
|
||||
const [combos, mine, layered] = await Promise.all([
|
||||
request<{ combos: { 키: string; 이름: string }[] }>(`/logic/combos?${query({ key })}`),
|
||||
request<{ logics: Summary[] }>(`/logics?${query({ sub: "자체" })}`),
|
||||
layerUses(key),
|
||||
]);
|
||||
const call = `로직(${key}`;
|
||||
const others = mine.logics.filter((s) => s.키 !== key);
|
||||
@@ -401,10 +439,73 @@ export async function usesOf(key: string): Promise<EasyUse[]> {
|
||||
.map((one): EasyUse => ({ kind: "logic", key: one.logic.키, name: one.logic.이름 }));
|
||||
return [
|
||||
...combos.combos.map((c): EasyUse => ({ kind: "combo", key: c.키, name: c.이름 })),
|
||||
...layered,
|
||||
...callers,
|
||||
];
|
||||
}
|
||||
|
||||
interface LayerTarget {
|
||||
layer: "company" | "personal";
|
||||
owner: string;
|
||||
name: string;
|
||||
rows?: { 키: string }[];
|
||||
}
|
||||
|
||||
/** 회사 · 개인 층 조합 가운데 이 로직을 담은 것 — M02 층 길 읽기만(시스템 관리자는 모든 층).
|
||||
* 내 층 = `/combos/all` · 남의 회사 = `/layers/company/owners` · 회사마다 사람 = `/layers/personal/owners`.
|
||||
* 못 읽은 층이 있으면 「일부를 못 읽음」 한 줄을 더함.
|
||||
* ponytail: 층마다 조합 하나씩 받아 훑음 — 조합이 수천이면 서버에 「이 로직을 담은 층 조합」 길을 더할 것 */
|
||||
async function layerUses(key: string): Promise<EasyUse[]> {
|
||||
let missed = false;
|
||||
const soft = <T>(p: Promise<T>, empty: T): Promise<T> =>
|
||||
p.catch(() => {
|
||||
missed = true;
|
||||
return empty;
|
||||
});
|
||||
type Own = { layer: string; owner: string | null; 줄: { 키: string }[] };
|
||||
type Owner = { owner: string; name: string };
|
||||
const own = await soft(m02<Own[]>("/combos/all"), []);
|
||||
const targets: LayerTarget[] = [];
|
||||
let myCompany = "";
|
||||
for (const one of own) {
|
||||
if (one.layer === "system" || !one.owner) continue;
|
||||
const company = one.layer === "company";
|
||||
if (company) myCompany = one.owner;
|
||||
targets.push({
|
||||
layer: company ? "company" : "personal",
|
||||
owner: one.owner,
|
||||
name: say(company ? "MyCompany" : "Me"),
|
||||
rows: one.줄,
|
||||
});
|
||||
}
|
||||
const companies = await soft(m02<Owner[]>("/layers/company/owners"), []);
|
||||
for (const c of companies) targets.push({ layer: "company", ...c });
|
||||
const people = await Promise.all(
|
||||
[myCompany, ...companies.map((c) => c.owner)]
|
||||
.filter(Boolean)
|
||||
.map((c) => soft(m02<Owner[]>(`/layers/personal/owners?${query({ company: c })}`), [])),
|
||||
);
|
||||
for (const p of people.flat()) targets.push({ layer: "personal", ...p });
|
||||
|
||||
const found = await Promise.all(
|
||||
targets.map(async (t) => {
|
||||
const at = `/layers/${t.layer}/combos`;
|
||||
const own = `?${query({ owner: t.owner })}`;
|
||||
const rows = t.rows ?? (await soft(m02<{ 줄: { 키: string }[] }>(at + own), { 줄: [] })).줄;
|
||||
const combos = await Promise.all(
|
||||
rows.map((r) =>
|
||||
soft(m02<{ combo: LayerCombo }>(`${at}/${encodeURIComponent(r.키)}${own}`), null),
|
||||
),
|
||||
);
|
||||
const full = combos.flatMap((x) => (x ? [x.combo] : []));
|
||||
return holding(full, key, t.layer, t.name);
|
||||
}),
|
||||
);
|
||||
const out = found.flat();
|
||||
if (missed) out.push({ kind: "combo", key: "", name: say("Unseen") });
|
||||
return out;
|
||||
}
|
||||
|
||||
let family: Promise<MachineLogic[]> | null = null;
|
||||
|
||||
/** 기계 시간당 경비 로직 묶음 — 한 번 받아 둠(실패하면 다음에 다시) */
|
||||
|
||||
Reference in New Issue
Block a user