feat(m02-df): 재료 조건 찾기 검색어 틀 — 틀 칸 · 자리별 알약 · 지금 잡히는 재료 미리 보기
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ACSGaHdLgnkEkoA4LDtMU
This commit is contained in:
@@ -231,6 +231,16 @@ export function materialElement(
|
||||
export function checkMaterial(el: CfElementRef, others: CfElementRef[]): string | null {
|
||||
if (!el.name) return "자리 이름을 적어 주세요";
|
||||
if (others.some((o) => o.name === el.name)) return "같은 이름의 알약이 이미 있음";
|
||||
if (el.mode === "rule" && el.rule?.field === "검색어") {
|
||||
if (!el.rule.template?.trim() || !templateSlots(el.rule.template).length)
|
||||
return "검색어 틀에 자리 {이름} 이 하나는 있어야 함";
|
||||
if (
|
||||
(el.rule.slots ?? []).length < templateSlots(el.rule.template).length ||
|
||||
(el.rule.slots ?? []).some((x) => !x.from.name)
|
||||
)
|
||||
return "틀의 자리마다 변수 알약을 골라 주세요";
|
||||
return null;
|
||||
}
|
||||
if (el.mode === "rule" && !el.rule?.from.name) return "규칙에 쓸 변수 알약을 골라 주세요";
|
||||
if (
|
||||
el.mode !== "fixed" &&
|
||||
@@ -626,3 +636,46 @@ export function checkGroupRule(el: CfElementRef, others: CfElementRef[]): string
|
||||
if (!el.rule?.from.name) return "규칙에 쓸 변수 알약을 골라 주세요";
|
||||
return null;
|
||||
}
|
||||
|
||||
/* ── 재료 조건 찾기 field 「검색어」 — 틀(「레미콘 {굵은골재최대치수}-{강도}-{슬럼프}」) 의 자리마다 변수 알약 값을 끼운 글로 찾음 ── */
|
||||
|
||||
/** 틀 안 자리 이름들 — 나온 차례 · 겹침 없이 */
|
||||
export function templateSlots(template: string): string[] {
|
||||
return [
|
||||
...new Set([...template.matchAll(/\{([^{}]+)\}/g)].map((m) => m[1].trim()).filter(Boolean)),
|
||||
];
|
||||
}
|
||||
|
||||
/** 틀을 채운 글 — valueOf 가 알약 값을 줌 · 값이 빈 자리는 missing 에 모음(그 자리는 그대로 둠) */
|
||||
export function fillTemplate(
|
||||
template: string,
|
||||
slots: { name: string; from: CfPort }[],
|
||||
valueOf: (port: CfPort) => unknown,
|
||||
): { text: string; missing: string[] } {
|
||||
const missing: string[] = [];
|
||||
const text = template.replace(/\{([^{}]+)\}/g, (all, raw: string) => {
|
||||
const name = raw.trim();
|
||||
const slot = slots.find((x) => x.name === name);
|
||||
const v = slot ? valueOf(slot.from) : undefined;
|
||||
if (v === null || v === undefined || v === "") {
|
||||
if (!missing.includes(name)) missing.push(name);
|
||||
return all;
|
||||
}
|
||||
return String(v);
|
||||
});
|
||||
return { text, missing };
|
||||
}
|
||||
|
||||
/** 검색어 틀 규칙 — 첫 자리의 알약이 from(옛 Model 호환) */
|
||||
export function templateRule(
|
||||
template: string,
|
||||
slots: { name: string; from: CfPort }[],
|
||||
): CfMaterialRule {
|
||||
return {
|
||||
field: "검색어",
|
||||
op: "포함",
|
||||
from: slots[0]?.from ?? { box: "", name: "" },
|
||||
template,
|
||||
slots,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user