fix(est): parse units in original calculation notes
This commit is contained in:
@@ -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
|
||||
@@ -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`는 이전 데모의 회귀 시험용이며 현재 진입 화면에서 사용하지 않습니다.
|
||||
|
||||
@@ -22,12 +22,12 @@ const EstText = (() => {
|
||||
),
|
||||
)
|
||||
.replace(
|
||||
/(?<![A-Za-z0-9_가-힣.])(\d[\d,.]*|\.\d+)\s*(?:공\/?㎥|공|단|면|겹|경간|개월|월|년|인|㎥|㎢|㎠|㎡|hr|sec|min|kwh|kw|km|ton|kg|㎏|㎞|ℓ|회|개소|개|대|분|초|본|장|매|병|조|식|일|시간|원|포|동|주|톤|μ|₩|EA|mm|cm|m3|m2|m|g|L|a)(?:\/(?:개소|경간|개|대|본|인|분|포|매|주|톤|공|회|조|span|ton|\$|hr|일|㎥|㎡|m3|m2|m|a|EA))?/gi,
|
||||
/(?<![A-Za-z0-9_가-힣.])(\d[\d,.]*|\.\d+)\s*(?:공\/?㎥|공|단|면|겹|경간|개월|월|년|인|㎥|㎢|㎠|㎡|hr|sec|min|set|kwh|kw|km|ton|kg|㎏|㎞|ℓ|회|개소|개|대|분|초|본|장|매|병|조|식|일|시간|원|포|동|주|톤|배|번|줄|μ|₩|EA|㎜|㎝|mm|cm|m3|m2|m|g|L|a)(?:\/(?:개소|경간|개|대|본|인|분|포|매|주|톤|공|회|조|span|set|ton|\$|hr|일|㎥|㎡|m3|m2|m|a|EA))?/gi,
|
||||
"$1",
|
||||
)
|
||||
.replace(/(?<=\d)\s*\/\s*(?:일|㎥|㎡|hr)(?=\s|$|[×*+)])/gi, "")
|
||||
.replace(/[】]〕]\s*$/, "")
|
||||
.replace(/(?<=\))\s*(?:개|인|본|면|단|회)(?:\/(?:㎡|㎥|hr))?/g, "")
|
||||
.replace(/(?<=\))\s*(?:개|인|본|면|단|회|㎥|㎡)(?:\/(?:㎡|㎥|hr))?/g, "")
|
||||
.replace(/^\s*[-*•]?\s*[가-힣][가-힣\s]*\s+(?=[\d.(])/, "")
|
||||
.replace(/[①-⑳]/g, "")
|
||||
.replace(/=\s*$/, "");
|
||||
@@ -323,7 +323,7 @@ const EstText = (() => {
|
||||
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+[가-힣].*$/, "")
|
||||
|
||||
Reference in New Issue
Block a user