diff --git a/resources/tester/test_est_text_units.py b/resources/tester/test_est_text_units.py new file mode 100644 index 000000000..e9810b048 --- /dev/null +++ b/resources/tester/test_est_text_units.py @@ -0,0 +1,71 @@ +"""원본 가시설·측량설계 산근에서 발췌한 단위와 설명 열의 계산 시험.""" + +from test_est_rea_parity import run + + +def test_text_units_and_description_columns_preserve_numeric_assignments(): + result = run( + "math", + r"""EstText.calculate([ + {Index:1,Code:'units',LineData:'units'}, + {LineData:' G2 = 3.14 / 4 ×0.105^2 ×1.50M × 2배 = \x120.026\x12 ㎥',Precision:3}, + {LineData:' N = 2 set'}, + {LineData:' 1. 재료비 : D=16mm, 1본당 4.0m'}, + {LineData:' Q = D × N = \x1232\x12'}, + {LineData:' V = G2 × 1000 = \x1226\x12'} + ])""", + ) + assert result["errors"] == [] + assert result["rows"][1]["TC"] == 0.026 + assert result["rows"][4]["TC"] == 32 + assert result["rows"][5]["TC"] == 26 + + +def test_text_unit_changes_propagate_without_reusing_stored_results(): + result = run( + "math", + r"""EstText.calculate([ + {Index:1,Code:'changed',LineData:'changed'}, + {LineData:' N = 3 set'}, + {LineData:' 1. 재료비 : D=25mm, 1본당 4.0m'}, + {LineData:' Q = D × N = \x1232\x12'}, + {LineData:' V = 1.5M × 3배 = \x123\x12',Precision:2} + ])""", + ) + assert result["errors"] == [] + assert result["rows"][3]["TC"] == 75 + assert result["rows"][4]["TC"] == 4.5 + + +def test_per_set_unicode_millimetres_and_starred_weight_declarations(): + result = run( + "math", + r"""EstText.calculate([ + {Index:1,Code:'source_units',LineData:'source_units'}, + {LineData:' * 본당 중량 W = 0.553톤/본*'}, + {LineData:' T = 20㎜ A = 0.95 × 0.95 = \x120.9\x12㎡',Precision:1}, + {LineData:' 재료비 : \x031,690\x03 × 0.005kg/set = \x128.4\x12',SCheck:-2}, + {LineData:' Q = W × T = \x1211.06\x12',Precision:2} + ])""", + ) + assert result["errors"] == [] + assert result["rows"][2]["TC"] == 0.9 + assert result["rows"][3]["TC"] == 8.4 + assert result["rows"][4]["TC"] == 11.06 + + +def test_parenthesized_volume_and_count_units_recalculate_from_variables(): + result = run( + "math", + r"""EstText.calculate([ + {Index:1,Code:'volume',LineData:'volume'}, + {LineData:' A = 80㎡ B = 16㎡'}, + {LineData:' 새끼 : L =0.05m × 4배 × 4번 × 1줄 = \x120.8\x12m',Precision:1}, + {LineData:' 노무비 : \x0358,122\x03 × 0.1 × (A+B)㎥ = 58,122 × 0.1 × (80+16) = \x12557,971.2\x12',SCheck:-1}, + {LineData:' Q = L × (A+B)㎡ = \x1276.8\x12',Precision:1} + ])""", + ) + assert result["errors"] == [] + assert result["rows"][2]["TC"] == 0.8 + assert result["rows"][3]["TC"] == 557971.2 + assert result["rows"][4]["TC"] == 76.8 diff --git a/tools/est-test/README.md b/tools/est-test/README.md index 1149f7edc..cfdcdf1b9 100644 --- a/tools/est-test/README.md +++ b/tools/est-test/README.md @@ -36,12 +36,14 @@ Ctrl+S는 입력 중인 셀도 확정한 뒤 저장합니다. 연속 저장 요 설계변경 비교는 웹에서 확정한 당초 사본이 없을 때 원본 파일의 당초 수량·금액을 사용합니다. 별도 당초 확정 사본이 있으면 그 사본이 우선합니다. 원본 당초 전체 자료와 원가 서식의 활성 선택을 자동 추정하지는 않습니다. +원본 산근의 `배`·`번`·`줄`·`set`·`kg/set`·`㎜`, 괄호 뒤 면적·체적 단위와 별표로 감싼 중량 선언도 계산합니다. 측량설계 저장값 대조는 80,658/80,682 일치·해석 오류 10건, 가시설은 13,978/13,979 일치·해석 오류 4건입니다. 범위 조건과 누락된 참조 등은 임의 값으로 대체하지 않습니다. + **전체 원본 동등성은 아직 확보하지 못했습니다.** 기성·물가변동·연차 등은 분석 분기와 합성 시나리오를 시험했으며 원본 업무 샘플 대조는 없습니다. 원본 화면 실행 비교는 못했습니다. 원본 페이지·도면 배치, CAD/VEC0650 편집, 원본 인쇄 서식, Excel/XML/JDL 변환, ESTX 수정 저장은 미구현입니다. 원본 대체품의 완료 판정으로 보지 않습니다. 검사: ```powershell -./venv/Scripts/python.exe -m pytest resources/tester/test_est_rea_parity.py resources/tester/test_est_business.py resources/tester/test_est_standalone.py resources/tester/test_est_history.py -q +./venv/Scripts/python.exe -m pytest resources/tester/test_est_rea_parity.py resources/tester/test_est_business.py resources/tester/test_est_standalone.py resources/tester/test_est_history.py resources/tester/test_est_text_units.py -q ``` `native-*.js`가 현재 화면·계산 엔진이며 브라우저와 로컬 서버가 같은 계산 코드를 사용합니다. `build_sample.py`는 REA 자료에서 입력·기대값을 재생성합니다. 기존 `app.js`, `calc.js`, `formula.js`, `workflows.js`는 이전 데모의 회귀 시험용이며 현재 진입 화면에서 사용하지 않습니다. diff --git a/tools/est-test/native-text.js b/tools/est-test/native-text.js index ad19bea1f..2d40e8a12 100644 --- a/tools/est-test/native-text.js +++ b/tools/est-test/native-text.js @@ -22,12 +22,12 @@ const EstText = (() => { ), ) .replace( - /(? { const assignment = assignments[j], end = assignments[j + 1]?.index ?? text.length; let body = text.slice(assignment.index + assignment[0].length, end); - if (!matched && /^\s*\*.*\*\s*$/.test(text)) body = body.replace(/\s+\*\s*$/, ""); + if (!matched && /^\s*\*.*\*\s*$/.test(text)) body = body.replace(/\*\s*$/, ""); body = body.replace(/\{[^}]*\}/g, ""); if (!matched) body = body.split("{")[0]; body = body.split(/\s+[::]\s*/)[0].replace(/[,,]\s*$/, ""); @@ -337,7 +337,8 @@ const EstText = (() => { body = expression(body) .trim() .replace(/\s+(?:min|hr|sec)\s*$/i, "") - .split(/\s{2,}(?=\d+\s*[가-힣]|[가-힣])/)[0]; + .split(/\s{2,}(?=\d+\s*[가-힣]|[가-힣])/)[0] + .replace(/[,,]\s*$/, ""); if (!result) body = body .replace(/\s*,\s+[가-힣].*$/, "")