feat(est-test): 단가산출 전역변수·새내역서 파일로저장·산출서 삽입과 선택 삭제
- 전역변수: 표지 대입 변수를 호표 넘어 유지, 지정·해제, 목록·이동 - 새내역서 파일로저장: 당초값·신규 표시·당초 사본 지운 새 작업 따로 저장 - 수량산출서 삽입(공종명칭·규격)·선택공종 삭제 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
// REA f2a1fc/f254c8: LineData 표지와 일반·성분·마지막 합계의 정밀도.
|
||||
// 전역변수(spec_cost_tools §2 · 0x93c22c): \x05이름\x05 표지로 대입한 변수는 호표가 바뀌어도 남아(전역표) 다른 호표에서 표지 없이 써도 찾는다.
|
||||
// 찾는 차례 = 그 호표 변수 → 전역표. 표지는 계산 동안 떼고 계산 뒤 같은 낱말에 다시 붙인다.
|
||||
const EstText = (() => {
|
||||
const { num, components, floating, sum } = EstMath;
|
||||
const marker = /\x12([-\d.,]+)\x12/;
|
||||
@@ -6,7 +8,7 @@ const EstText = (() => {
|
||||
const clean = (s) =>
|
||||
String(s || "")
|
||||
.replace(/[\x06\x07][^\x06\x07]*[\x06\x07]/g, "")
|
||||
.replace(/[\x03\x0c\x0e\x11\x12\x13\x15\x1a]/g, "");
|
||||
.replace(/[\x03\x05\x0c\x0e\x11\x12\x13\x15\x1a]/g, "");
|
||||
const numeric = (s) => Number(String(s).replaceAll(",", ""));
|
||||
const sumCurrency = (values) =>
|
||||
values.reduce((n, value) => n + EstMath.even(num(value) * 10000), 0) / 10000;
|
||||
@@ -56,8 +58,10 @@ const EstText = (() => {
|
||||
titles = [],
|
||||
errors = [],
|
||||
checks = [];
|
||||
const globals = Object.create(null),
|
||||
globalList = [];
|
||||
let head = null,
|
||||
variables = Object.create(null),
|
||||
variables = Object.create(globals),
|
||||
changed = new Map(),
|
||||
currentSource = null,
|
||||
finalOverride = null,
|
||||
@@ -94,7 +98,7 @@ const EstText = (() => {
|
||||
if (num(row.Index) > 0) {
|
||||
finish();
|
||||
head = row;
|
||||
variables = Object.create(null);
|
||||
variables = Object.create(globals);
|
||||
changed = new Map();
|
||||
currentSource = null;
|
||||
finalOverride = null;
|
||||
@@ -170,7 +174,10 @@ const EstText = (() => {
|
||||
errors.push(`${head.Code}:${index + 1} ${error.message}`);
|
||||
}
|
||||
}
|
||||
let text = original.replace(/\{([+-])\}/g, "$1");
|
||||
const globalNames = [...original.matchAll(/\x05([A-Za-z][A-Za-z0-9_]*)\x05/g)].map(
|
||||
(m) => m[1],
|
||||
);
|
||||
let text = original.replace(/\x05/g, "").replace(/\{([+-])\}/g, "$1");
|
||||
let selectionError = "";
|
||||
if (num(row.LinkIndex) === 62) {
|
||||
text = text.replace(/(\x07([A-Z])\x07\s*)\x1a[^\x1a]*\x1a/g, (whole, reference, group) => {
|
||||
@@ -599,16 +606,28 @@ const EstText = (() => {
|
||||
errors.push(`${head.Code}:${index + 1} ${error.message}`);
|
||||
row.Error = error.message;
|
||||
}
|
||||
for (const name of globalNames) {
|
||||
if (Object.hasOwn(variables, name)) {
|
||||
globals[name] = variables[name];
|
||||
globalList.push({ name, value: variables[name], index });
|
||||
}
|
||||
if (!String(row.LineData).includes(`\x05${name}\x05`))
|
||||
row.LineData = String(row.LineData).replace(
|
||||
new RegExp(`(?<![A-Za-z0-9_])${name}(?![A-Za-z0-9_])`),
|
||||
`\x05${name}\x05`,
|
||||
);
|
||||
}
|
||||
if (!hasAutoTotals && component[sc])
|
||||
plainTotals[component[sc]] = num(plainTotals[component[sc]]) + num(row.TC);
|
||||
}
|
||||
finish();
|
||||
return { rows, titles, errors, checks };
|
||||
return { rows, titles, errors, checks, globals: globalList };
|
||||
}
|
||||
const names = {
|
||||
"\x06": "구간지정",
|
||||
"\x07": "구간합계",
|
||||
"\x03": "단가",
|
||||
"\x05": "전역",
|
||||
"\x0c": "다른줄",
|
||||
"\x0e": "품명",
|
||||
"\x11": "변수",
|
||||
@@ -620,7 +639,7 @@ const EstText = (() => {
|
||||
};
|
||||
const display = (text) =>
|
||||
String(text || "").replace(
|
||||
/[\x03\x06\x07\x0c\x0e\x11\x12\x13\x15\x16\x1a]/g,
|
||||
/[\x03\x05\x06\x07\x0c\x0e\x11\x12\x13\x15\x16\x1a]/g,
|
||||
(ch) => `⟦${names[ch]}⟧`,
|
||||
);
|
||||
const encode = (text) =>
|
||||
|
||||
Reference in New Issue
Block a user