feat(stmate-test): REA MCP(Ghidra) 계산 엔진 — 표준시장단가(A 코드 COSTA) 내역 연결 · EXRNM 켜짐 경로 · 손료 반올림 MROUNDUD · 적용기준 콤보 값
- A 코드 = COSTA · S_JDA 참 = 저장 단가 · 거짓 = AAMTn 노무비율 나눔 · ACTTYP·ACTOPT = PRJLST · calcBoq·api_load 연결 - EXRNM 참 = S 줄만 단가×율/1000 · ECD 자리 버림 · 천원 · 전각 $ - 손료 계수 반올림 = 첫 버림 자리 5 이상 올림 - 적용기준 국가 2·지방 0·행자부 1 · 행자부 RATE_M 조회 rateMLookup - 지식DB 36번 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+150
@@ -0,0 +1,150 @@
|
||||
# 36 계산 엔진 잔여 규칙 — 표준시장단가 연결 · 환율 EXRNM 두 경로 · 수량 계산기 반올림 · 적용기준 콤보
|
||||
|
||||
## 0. 범위·방법·한계
|
||||
|
||||
- 대상 항목: F2-61 표준시장단가 · F2-04 환율 EXRNM · F1-36 손료(수량 계산기) 반올림 · F2-24 적용기준 콤보·행자부 RATE_M.
|
||||
- 방법: REA MCP(rea-agents 6.7.0 · Ghidra 12.1.4) — STmate.Cpm · ST_KanJub.CPM 디컴파일·어셈블리·xrefs·read_bytes. 원본 실행 없음.
|
||||
- 근거 파일: `REA_MCP/` (evidence_ids.txt 에 증거 ID).
|
||||
- 실물 대조: 실무 STC 7건 — COSTA.DBF 행 0 건(A 코드 표본 없음) · 외화 줄은 울진 3건($ · EXRNM 참)만.
|
||||
|
||||
## 1. 표준시장단가(A 코드) 단가 읽기 (F2-61) — 확인
|
||||
|
||||
### 1.1 자료 자리
|
||||
|
||||
- A 코드 단가표 = COSTA.DBF(실적단가 표 · 암호 0x06 꼴).
|
||||
- 칸: AAMT1~4 · RATE_L · RATE_M · RATE_S · LAMT1~4·MAMT1~4·SAMT1~4·TAMT1~4 · LAMT1_R~LAMT4_R(·MAMTn_R·SAMTn_R) · DOLLOR 등.
|
||||
- 구성(일위대가·중기) 줄 단가 다시 읽기 Main 0x43307c → 0x437a13:
|
||||
- 계산 종류 1~3 · 6(계열 > 1) · 7·8(계열 3·칸 3)일 때 줄마다 0x430c60 호출.
|
||||
- 줄 코드 첫 글자 'A' → 자료집합 [[0x5e6090]+0xc](COSTA) · 깃발 1. 그 밖 → [+8](COSTN) · 깃발 0.
|
||||
|
||||
### 1.2 0x430c60 (깃발 1)
|
||||
|
||||
- 설정 +0x7c8 = Start8x.Ini [Start] S_JDA(ReadBool 기본 거짓 · 로더 0x42afd9) 참 → 저장 LAMTn·MAMTn·SAMTn·TAMTn 그대로.
|
||||
- 거짓 → L·M·S = 0 · T = AAMTn.
|
||||
- T ≠ 0 · RATE_L = 0 · LAMTn_R ≠ 0 → L = LAMTn_R.
|
||||
- 0x45a468(T 묶음, R = RATE_L, ACTTYP, ACTOPT) 호출 — 나눔 규칙은 34 §6 그대로.
|
||||
- 끝(0x4312ad): T = L + M + S + 넷째 칸(+0x1e8 · OPTIMIZ 묶음의 A 칸).
|
||||
|
||||
### 1.3 ACTTYP·ACTOPT 출처
|
||||
|
||||
- 계산이 읽는 공사 레코드 +0x172c·+0x1730 = PRJLST 행 ACTTYP·ACTOPT (로더 0x45c848 · 0x45c938~0x45c956 · 같은 로더가 PCLASS → +0x1750).
|
||||
- 34 §6 의 「화면 기본 1·2(PCLASS ≠ 9)」는 화면 0x528ac0 의 콤보 채우기 — 계산값은 PRJLST 저장값.
|
||||
- 실물: 6건 ACTTYP 1·ACTOPT 2 · 울진 2025 1건 0·0.
|
||||
|
||||
### 1.4 미확인
|
||||
|
||||
- COSTA 칸 5(변경 4차 · 계열 5) 이름 없음 — 계열 5 의 A 줄 값.
|
||||
- 넷째 칸 A 가 원가계산서(제잡비) 밑수에 들어가는 자리.
|
||||
- 내역(ST_Boq) A 줄 금액 끝수 — 같은 몸 0x45d534 · 줄 금액 절사는 다른 비목과 같다고 둠.
|
||||
|
||||
## 2. 환율 적용 범위 EXRNM 두 경로 (F2-04) — 규칙 확인 · 금액은 같지 않음
|
||||
|
||||
### 2.1 설정 자리 (로더 0x42a828)
|
||||
|
||||
| 키 | 자리 |
|
||||
|---|---|
|
||||
| [EQUIPMENT] EXLNMn | +0x718 + n×8 |
|
||||
| EXHNMn | +0x728 + n×8 |
|
||||
| EXYENn | +0x738 + n×8 |
|
||||
| EXEURn | +0x748 + n×8 |
|
||||
| EXRNM | +0x7c9 (ReadBool) |
|
||||
| [Start] ECDNM | +8 |
|
||||
| [Start] S_JDA | +0x7c8 |
|
||||
|
||||
- n = 1·2 · 계산 쪽 첨자 = 단가 칸 번호([in_stack+0x18]).
|
||||
|
||||
### 2.2 경로 A — EXRNM 참 (0x437aa2~0x437e2f)
|
||||
|
||||
- 조건: 계산 종류 3~8·10 · 줄 코드 'S' · 줄 단위 $·$·€·¥.
|
||||
- 율 r:
|
||||
- € = EXEUR/1000.
|
||||
- ¥ = EXYEN/100000.
|
||||
- $·$ = IIF(줄 T < 100000, EXL, EXH)/1000.
|
||||
- S = MROUNDUD(S × r, ECD, 0) — 천원 단위 · ECD 자리 아래 버림.
|
||||
- 단위 → 「천원」 · T = S.
|
||||
- 상위 B·천원 갈래(2.3 과 같은 자리 0x435600~0x43590d)에서는 수량 칸 = 1.0 · 단위 「천원」.
|
||||
|
||||
### 2.3 경로 B — EXRNM 거짓 (0x435600~0x43590d)
|
||||
|
||||
- 조건: 상위 코드 B · 「천원」 비교 참.
|
||||
- 줄 단위:
|
||||
- 「천원」 → 수량 칸(+0x128[계열]) = 1.0.
|
||||
- $·$·€·¥ → 수량 칸 = r(2.2 와 같은 율) · 단가는 외화 그대로.
|
||||
- 유효수량 +0x1a0 = 수량 칸(0x43590d).
|
||||
- 비목 금액 = ADDBJVAL(단가 × 유효수량)(0x437303~).
|
||||
- 상수: 0x439d2c 「천원」 · 0x439d3c 「$」 · 0x439d48 「$」 · 0x439d70 「€」 · 0x439d80 「¥」 · 0x439d64 100000.0f · 0x439d74 1000.0f.
|
||||
|
||||
### 2.4 두 경로 금액
|
||||
|
||||
- A = 줄끝수(1.0 × MROUNDUD(S × r, ECD, 0)) · B = 줄끝수(r × S).
|
||||
- S × r 이 ECD 자리 안에서 끝나면 같음. 아니면 A 가 버린 만큼 작음.
|
||||
- 예: $123.45 · EXL 1289 · ECD 0 → A 159 · B 159.12705(BPN 1 → 159.1).
|
||||
- ⇒ 같지 않음(ECD 버림 차이).
|
||||
|
||||
### 2.5 미확인
|
||||
|
||||
- 경로 B 첫 「천원」 비교 문자열의 출처(상위 단위로 추정되나 SmallString 인자 미복원).
|
||||
- EXRNM 거짓 · 상위 X 등 그 밖 줄의 금액 단계 환산 0x438130~(율 [in_stack−0x98]) 금액식.
|
||||
|
||||
## 3. 수량 계산기 반올림 (F1-36) — 확인
|
||||
|
||||
- wM_Edit_XRate 일일수량 Q_11 · 적용수량 Q_p = MROUNDUD(x, d, 선택 1) (REA 30).
|
||||
- MROUNDUD 선택 1 = 첫 버림 자리 ≥ 5 이면 한 단위 올림 · 0 반대쪽 (REA 32 §1.1 · DP_Common 0x4544f0).
|
||||
- 예: 1 ÷ 8 = 0.125 · 2자리 → 0.13.
|
||||
|
||||
## 4. 적용기준 콤보 · 행자부 RATE_M (F2-24) — 짝 확인 · 조회 규칙 확인
|
||||
|
||||
### 4.1 콤보 값
|
||||
|
||||
- TWM_KANJUB.dfm cmBx_Set_Base(태그 65):
|
||||
- Items = 일반(국가계약법) · 일반(지방계약법) · 행자부기준.
|
||||
- Values = 2 · 0 · 1.
|
||||
- 34 §5.2·§17.5 「DFM 에 Values 없음」 정정.
|
||||
- 저장 = TwCombo.GetInteger = Values 값.
|
||||
- 방증: 같은 방식으로 읽는 공사종류를 원본이 8·9 와 비교(0x47fa24) — 8 항목 콤보 순번으로는 나올 수 없는 값.
|
||||
- 방증: 건설기계 구분 −1 갈래.
|
||||
- ⇒ I_SET_BASE 1 = 행자부기준 · 0 = 지방계약법 · 2 = 국가계약법.
|
||||
- 실물 7건 모두 0.
|
||||
|
||||
### 4.2 행자부(SET_BASE 1) 조회 (ST_KanJub 0x47a1bc · 0x47acd8~0x47b100)
|
||||
|
||||
- 규모 b:
|
||||
- 밑수 < G[2](50억) → 0 · < G[3](300억) → 1 · 그 밖 2.
|
||||
- 밑수 = 원가 칸 0x4e4260 첫 값 — RATE_R 규모 조회와 같은 칸.
|
||||
- 간접노무비 RATE_M:
|
||||
- 공사종류 < 5 · I_ILBAN ≠ 1 → Go(b+11) · 칸 `RATE{기간 + IIF(공사종류 ∈ {1,3}, 5, 0)}`.
|
||||
- I_ILBAN 1 또는 공사종류 ≥ 5 → Go(b+15) · `RATE{기간+5}`.
|
||||
- 기간 = [0x504840].
|
||||
- 일반관리비 = Go(23) RATE1.
|
||||
- 이윤 = Go(24) RATE0.
|
||||
- 그 밖 갈래(SET_BASE ≠ 1):
|
||||
- 일반관리비 = RATE_R Go(21) RATE_11 · 공사종류 5 = Go(1) RATE_31.
|
||||
- 이윤 = Go(21) RATE_16.
|
||||
- 이윤 상한 10: (전역 [0x4d26cc+1] ≠ 0 또는 (S_JDA 거짓 · PCLASS 9)) · 이윤 > 10.
|
||||
- 실물 RATE_M(25×10): 11~13·15~17 줄 간접노무비 · 23 줄 RATE1 6.0 · 24 줄 RATE0 15.0 → 줄 번호 1부터와 맞음.
|
||||
|
||||
### 4.3 앱과 다른 점(보고만)
|
||||
|
||||
- 앱 RATE_R 조회는 일반관리비·이윤을 규모 묶음 머리 줄에서 읽음 · 전문공사 일반관리비 15열.
|
||||
- 원본 0x47a1bc 는 21줄 고정 · 전문공사 갈래 없음 → 50억 이상·전문공사에서 갈릴 수 있음.
|
||||
- 실물 7건은 모두 50억 미만·I_ILBAN 0.
|
||||
|
||||
## 5. 앱 반영
|
||||
|
||||
- calc.js:
|
||||
- `stdMarketUnit`(S_JDA · ACTTYP · ACTOPT · 칸 n).
|
||||
- calcBoq A 줄 → COSTA 나눔 · 넷째 칸 A(aAmt · directA · T 포함).
|
||||
- smt_engine.js:
|
||||
- costnLookup 이 COSTA A 줄을 나눔 단가로 돌려줌.
|
||||
- fxOf 키 없음 = 1000.
|
||||
- compositionOptions.exrnm.
|
||||
- smt_eval.js:
|
||||
- EXRNM 참 → S 줄만 MROUNDUD(·, ECD, 0) · $ 인식 · 고액 환율 0 대체 제거.
|
||||
- server.py api_load:
|
||||
- COSTA 풀어 읽기(costa_rows) · sim_state.stdMarketItems · sysConfig.stdMarket.
|
||||
- A 임시 일위대가 걷기.
|
||||
- calc_xrate.js: q = MROUNDUD 선택 1(exec_calc 원형).
|
||||
- kanjub_parts.js NATIVE: `SET_BASE`(Values↔Items) · `rateMLookup`.
|
||||
- 시험:
|
||||
- resources/tester/test_stmate_std_market.py.
|
||||
- resources/tester/test_stmate_xrate_round.py.
|
||||
+1104
File diff suppressed because it is too large
Load Diff
+621
@@ -0,0 +1,621 @@
|
||||
|
||||
|
||||
/* WARNING: Removing unreachable block (ram,0x0042a950) */
|
||||
|
||||
|
||||
|
||||
void FUN_0042a828(void)
|
||||
|
||||
|
||||
|
||||
{
|
||||
|
||||
undefined1 *puVar1;
|
||||
|
||||
char cVar2;
|
||||
|
||||
undefined1 uVar3;
|
||||
|
||||
short sVar4;
|
||||
|
||||
int *piVar5;
|
||||
|
||||
undefined4 uVar6;
|
||||
|
||||
LPCSTR lpLibFileName;
|
||||
|
||||
FARPROC pFVar7;
|
||||
|
||||
int iVar8;
|
||||
|
||||
undefined4 *in_FS_OFFSET;
|
||||
|
||||
float10 in_ST0;
|
||||
|
||||
float10 in_ST1;
|
||||
|
||||
float10 in_ST2;
|
||||
|
||||
float10 in_ST3;
|
||||
|
||||
float10 in_ST4;
|
||||
|
||||
float10 in_ST5;
|
||||
|
||||
float10 in_ST6;
|
||||
|
||||
float10 in_ST7;
|
||||
|
||||
float10 fVar9;
|
||||
|
||||
undefined *puStackY_22c;
|
||||
|
||||
undefined4 uStack_21c;
|
||||
|
||||
undefined **ppuStack_218;
|
||||
|
||||
char *pcStack_1f4;
|
||||
|
||||
undefined4 uStack_1ec;
|
||||
|
||||
undefined4 ***local_184;
|
||||
|
||||
undefined4 local_180;
|
||||
|
||||
undefined4 local_17c;
|
||||
|
||||
undefined4 local_178;
|
||||
|
||||
undefined **local_174;
|
||||
|
||||
undefined *local_170;
|
||||
|
||||
undefined4 *local_16c;
|
||||
|
||||
undefined4 local_168;
|
||||
|
||||
undefined4 **local_164;
|
||||
|
||||
undefined4 local_160;
|
||||
|
||||
undefined **local_15c;
|
||||
|
||||
undefined4 local_158;
|
||||
|
||||
undefined **local_154;
|
||||
|
||||
undefined4 uStack_150;
|
||||
|
||||
undefined4 **ppuStack_14c;
|
||||
|
||||
undefined4 uStack_148;
|
||||
|
||||
undefined **local_144;
|
||||
|
||||
char *local_140;
|
||||
|
||||
undefined4 local_13c;
|
||||
|
||||
undefined ***local_138;
|
||||
|
||||
undefined4 ***local_134;
|
||||
|
||||
undefined *local_130;
|
||||
|
||||
undefined4 ***local_12c;
|
||||
|
||||
undefined4 ***local_128;
|
||||
|
||||
undefined *local_124;
|
||||
|
||||
undefined *local_120;
|
||||
|
||||
undefined **local_11c;
|
||||
|
||||
undefined *local_118;
|
||||
|
||||
undefined **local_114;
|
||||
|
||||
undefined ***local_110;
|
||||
|
||||
undefined *local_10c;
|
||||
|
||||
undefined ***local_108;
|
||||
|
||||
undefined4 ***local_104;
|
||||
|
||||
undefined *local_100;
|
||||
|
||||
undefined *local_fc;
|
||||
|
||||
undefined **local_f8;
|
||||
|
||||
undefined *local_f4;
|
||||
|
||||
undefined ***local_f0;
|
||||
|
||||
undefined4 ***local_ec;
|
||||
|
||||
undefined *local_e8;
|
||||
|
||||
undefined4 local_e4;
|
||||
|
||||
undefined4 *local_e0;
|
||||
|
||||
undefined *local_dc;
|
||||
|
||||
undefined *local_d8;
|
||||
|
||||
undefined **local_d4;
|
||||
|
||||
undefined *local_d0;
|
||||
|
||||
undefined ***local_cc;
|
||||
|
||||
undefined4 ***local_c8;
|
||||
|
||||
undefined *local_c4;
|
||||
|
||||
undefined **local_c0;
|
||||
|
||||
undefined ***local_bc;
|
||||
|
||||
undefined *local_b8;
|
||||
|
||||
undefined ***local_b4;
|
||||
|
||||
undefined4 local_b0;
|
||||
|
||||
undefined *local_ac;
|
||||
|
||||
undefined ***local_a8;
|
||||
|
||||
undefined4 ***local_a4;
|
||||
|
||||
undefined *local_a0;
|
||||
|
||||
undefined ***local_9c;
|
||||
|
||||
undefined4 ***local_98;
|
||||
|
||||
undefined *local_94;
|
||||
|
||||
undefined *local_90;
|
||||
|
||||
undefined ***local_8c;
|
||||
|
||||
undefined4 ***local_88;
|
||||
|
||||
undefined *local_84;
|
||||
|
||||
undefined *local_80;
|
||||
|
||||
undefined **local_7c;
|
||||
|
||||
undefined *puStack_78;
|
||||
|
||||
undefined *puStack_74;
|
||||
|
||||
undefined **ppuStack_70;
|
||||
|
||||
undefined *local_6c;
|
||||
|
||||
undefined **local_68;
|
||||
|
||||
undefined ***local_64;
|
||||
|
||||
undefined *local_60;
|
||||
|
||||
undefined *local_5c;
|
||||
|
||||
undefined **local_58;
|
||||
|
||||
undefined *local_54;
|
||||
|
||||
HMODULE local_50;
|
||||
|
||||
undefined4 ***local_4c;
|
||||
|
||||
HMODULE local_48;
|
||||
|
||||
undefined4 ***local_44;
|
||||
|
||||
undefined4 *local_40;
|
||||
|
||||
HMODULE local_3c;
|
||||
|
||||
HMODULE *local_38;
|
||||
|
||||
HMODULE local_34;
|
||||
|
||||
undefined4 *local_30;
|
||||
|
||||
HMODULE local_2c;
|
||||
|
||||
int local_28;
|
||||
|
||||
undefined4 local_24;
|
||||
|
||||
undefined1 *local_20;
|
||||
|
||||
undefined1 *local_1c;
|
||||
|
||||
undefined4 local_8;
|
||||
|
||||
|
||||
|
||||
local_1c = &stack0xfffffffc;
|
||||
|
||||
iVar8 = 0x30;
|
||||
|
||||
do {
|
||||
|
||||
local_8 = 0;
|
||||
|
||||
iVar8 = iVar8 + -1;
|
||||
|
||||
} while (iVar8 != 0);
|
||||
|
||||
local_20 = &LAB_0042b6f3;
|
||||
|
||||
local_24 = *in_FS_OFFSET;
|
||||
|
||||
*in_FS_OFFSET = &local_24;
|
||||
|
||||
puVar1 = &stack0xfffffffc;
|
||||
|
||||
if (*(int *)(*(int *)PTR_DAT_005e5f8c + 0x5c) != 0) {
|
||||
|
||||
local_28 = 0x42a868;
|
||||
|
||||
_Sysutils_FreeAndNil_qqrpv(*(int *)PTR_DAT_005e5f8c + 0x5c);
|
||||
|
||||
puVar1 = local_1c;
|
||||
|
||||
}
|
||||
|
||||
local_1c = puVar1;
|
||||
|
||||
local_28 = 0x42a87f;
|
||||
|
||||
_System__LStrCat3_qqrv(&local_30,*(undefined4 *)(*(int *)PTR_DAT_005e5f8c + 0x38),"STini.MEM");
|
||||
|
||||
local_28 = 0x42a887;
|
||||
|
||||
cVar2 = _Sysutils_FileExists_qqrx17System_AnsiString(local_30);
|
||||
|
||||
if (cVar2 == '\0') {
|
||||
|
||||
local_28 = 1;
|
||||
|
||||
local_2c = (HMODULE)0x42a8a4;
|
||||
|
||||
_System__LStrCat3_qqrv(&local_34,*(undefined4 *)(*(int *)PTR_DAT_005e5f8c + 0x38),"STini.MEM");
|
||||
|
||||
local_2c = local_34;
|
||||
|
||||
local_30 = (undefined4 *)0x42a8bf;
|
||||
|
||||
_System__LStrCat3_qqrv(&local_38,*(undefined4 *)(*(int *)PTR_DAT_005e5f8c + 0x38),"START8X.INI")
|
||||
|
||||
;
|
||||
|
||||
local_30 = local_38;
|
||||
|
||||
local_34 = (HMODULE)0x42a8c8;
|
||||
|
||||
COPY_FILE();
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
local_28 = 1;
|
||||
|
||||
local_2c = (HMODULE)0x42a8e3;
|
||||
|
||||
_System__LStrCat3_qqrv(&local_3c,*(undefined4 *)(*(int *)PTR_DAT_005e5f8c + 0x38),"Start8x.Ini")
|
||||
|
||||
;
|
||||
|
||||
local_2c = local_3c;
|
||||
|
||||
local_30 = (undefined4 *)0x42a8fe;
|
||||
|
||||
_System__LStrCat3_qqrv(&local_40,*(undefined4 *)(*(int *)PTR_DAT_005e5f8c + 0x38),"STini.MEM");
|
||||
|
||||
local_30 = local_40;
|
||||
|
||||
local_34 = (HMODULE)0x42a907;
|
||||
|
||||
COPY_FILE();
|
||||
|
||||
}
|
||||
|
||||
local_34 = (HMODULE)0x42a91e;
|
||||
|
||||
_System__LStrCat3_qqrv(&local_44,*(undefined4 *)(*(int *)PTR_DAT_005e5f8c + 0x38),"STini.MEM");
|
||||
|
||||
local_34 = (HMODULE)0x42a92d;
|
||||
|
||||
piVar5 = (int *)_Inifiles_TCustomIniFile__bctr_qqrx17System_AnsiString
|
||||
|
||||
(_Inifiles_TIniFile__exref,1,local_44);
|
||||
|
||||
*(int **)(*(int *)PTR_DAT_005e5f8c + 0x5c) = piVar5;
|
||||
|
||||
puVar1 = *(undefined1 **)PTR_DAT_005e6148;
|
||||
|
||||
puVar1[1] = 1;
|
||||
|
||||
local_34 = (HMODULE)&DAT_0042b74c;
|
||||
|
||||
local_38 = &local_48;
|
||||
|
||||
local_3c = (HMODULE)0x42a96d;
|
||||
|
||||
(**(code **)*piVar5)(piVar5,"Start","ACDNM");
|
||||
|
||||
local_3c = local_48;
|
||||
|
||||
local_40 = (undefined4 *)0x42a976;
|
||||
|
||||
MSTRTODBL();
|
||||
|
||||
local_40 = (undefined4 *)0x42a97b;
|
||||
|
||||
uVar3 = _System__ROUND_qqrv();
|
||||
|
||||
puVar1[2] = uVar3;
|
||||
|
||||
local_40 = (undefined4 *)&DAT_0042b74c;
|
||||
|
||||
local_44 = (undefined4 ***)&local_50;
|
||||
|
||||
local_48 = (HMODULE)0x42a997;
|
||||
|
||||
(**(code **)*piVar5)(piVar5,"Start","ACDNM");
|
||||
|
||||
local_48 = local_50;
|
||||
|
||||
local_4c = &local_4c;
|
||||
|
||||
local_50 = (HMODULE)0x42a9af;
|
||||
|
||||
(**(code **)*piVar5)(piVar5,"Start","BPNNM");
|
||||
|
||||
local_50 = (HMODULE)local_4c;
|
||||
|
||||
local_54 = (undefined *)0x42a9b8;
|
||||
|
||||
MSTRTODBL();
|
||||
|
||||
local_54 = (undefined *)0x42a9bd;
|
||||
|
||||
uVar3 = _System__ROUND_qqrv();
|
||||
|
||||
puVar1[9] = uVar3;
|
||||
|
||||
local_54 = &DAT_0042b788;
|
||||
|
||||
local_58 = &local_54;
|
||||
|
||||
local_5c = (undefined *)0x42a9d9;
|
||||
|
||||
(**(code **)*piVar5)(piVar5,"Start","YCDNM");
|
||||
|
||||
local_5c = local_54;
|
||||
|
||||
local_60 = (undefined *)0x42a9e2;
|
||||
|
||||
MSTRTODBL();
|
||||
|
||||
local_60 = (undefined *)0x42a9e7;
|
||||
|
||||
uVar6 = _System__ROUND_qqrv();
|
||||
|
||||
*(undefined4 *)(puVar1 + 0x7c0) = uVar6;
|
||||
|
||||
local_60 = &DAT_0042b788;
|
||||
|
||||
local_64 = &local_58;
|
||||
|
||||
local_68 = (undefined **)0x42aa06;
|
||||
|
||||
(**(code **)*piVar5)(piVar5,"Start","BCDNM");
|
||||
|
||||
local_68 = local_58;
|
||||
|
||||
local_6c = (undefined *)0x42aa0f;
|
||||
|
||||
MSTRTODBL();
|
||||
|
||||
local_6c = (undefined *)0x42aa14;
|
||||
|
||||
uVar6 = _System__ROUND_qqrv();
|
||||
|
||||
*(undefined4 *)(puVar1 + 0x7a0) = uVar6;
|
||||
|
||||
local_6c = &DAT_0042b788;
|
||||
|
||||
ppuStack_70 = &local_5c;
|
||||
|
||||
puStack_74 = (undefined *)0x42aa33;
|
||||
|
||||
(**(code **)*piVar5)(piVar5,"Start","DCDNM");
|
||||
|
||||
puStack_74 = local_5c;
|
||||
|
||||
puStack_78 = (undefined *)0x42aa3c;
|
||||
|
||||
MSTRTODBL();
|
||||
|
||||
puStack_78 = (undefined *)0x42aa41;
|
||||
|
||||
uVar6 = _System__ROUND_qqrv();
|
||||
|
||||
*(undefined4 *)(puVar1 + 0x7a4) = uVar6;
|
||||
|
||||
puStack_78 = &DAT_0042b788;
|
||||
|
||||
local_7c = &local_60;
|
||||
|
||||
local_80 = (undefined *)0x42aa60;
|
||||
|
||||
(**(code **)*piVar5)(piVar5,"Start","ICDNM");
|
||||
|
||||
local_80 = local_60;
|
||||
|
||||
local_84 = (undefined *)0x42aa69;
|
||||
|
||||
MSTRTODBL();
|
||||
|
||||
local_84 = (undefined *)0x42aa6e;
|
||||
|
||||
uVar6 = _System__ROUND_qqrv();
|
||||
|
||||
*(undefined4 *)(puVar1 + 0x7a8) = uVar6;
|
||||
|
||||
local_84 = &DAT_0042b74c;
|
||||
|
||||
local_88 = &local_64;
|
||||
|
||||
local_8c = (undefined ***)0x42aa8d;
|
||||
|
||||
(**(code **)*piVar5)(piVar5,"Start","KCDNM");
|
||||
|
||||
local_8c = local_64;
|
||||
|
||||
local_90 = (undefined *)0x42aa96;
|
||||
|
||||
MSTRTODBL();
|
||||
|
||||
local_90 = (undefined *)0x42aa9b;
|
||||
|
||||
uVar3 = _System__ROUND_qqrv();
|
||||
|
||||
puVar1[5] = uVar3;
|
||||
|
||||
local_90 = (undefined *)0x42aabe;
|
||||
|
||||
_System__VarFromPStr_qqrr14System_Variantrx28System__SmallString_iuc_255_(&local_8c,&local_90);
|
||||
|
||||
local_90 = local_80;
|
||||
|
||||
local_94 = local_84;
|
||||
|
||||
local_98 = local_88;
|
||||
|
||||
local_9c = local_8c;
|
||||
|
||||
local_a4 = (undefined4 ***)CONCAT22(local_a4._2_2_,0x3200);
|
||||
|
||||
local_a4 = (undefined4 ***)CONCAT31(local_a4._1_3_,1);
|
||||
|
||||
local_a0 = (undefined *)0x42aaf0;
|
||||
|
||||
uVar6 = _System__VarFromPStr_qqrr14System_Variantrx28System__SmallString_iuc_255_
|
||||
|
||||
(&local_a0,&local_a4);
|
||||
|
||||
local_a0 = local_94;
|
||||
|
||||
local_a4 = local_98;
|
||||
|
||||
local_a8 = local_9c;
|
||||
|
||||
local_ac = local_94;
|
||||
|
||||
local_b0 = CONCAT31((int3)((uint)uVar6 >> 8),puVar1[5] == '\x02');
|
||||
|
||||
local_b4 = &local_7c;
|
||||
|
||||
local_b8 = (undefined *)0x42ab19;
|
||||
|
||||
IIF();
|
||||
|
||||
local_b8 = (undefined *)0x42ab24;
|
||||
|
||||
_System__VarToLStr_qqrr17System_AnsiStringrx14System_Variant(&local_6c,&local_7c);
|
||||
|
||||
local_b8 = local_6c;
|
||||
|
||||
local_bc = &local_68;
|
||||
|
||||
local_c0 = (undefined **)0x42ab3c;
|
||||
|
||||
(**(code **)*piVar5)(piVar5,"Start","JCDNM");
|
||||
|
||||
local_c0 = local_68;
|
||||
|
||||
local_c4 = (undefined *)0x42ab45;
|
||||
|
||||
MSTRTODBL();
|
||||
|
||||
local_c4 = (undefined *)0x42ab4a;
|
||||
|
||||
uVar3 = _System__ROUND_qqrv();
|
||||
|
||||
puVar1[7] = uVar3;
|
||||
|
||||
local_c4 = &DAT_0042b788;
|
||||
|
||||
local_c8 = &local_a8;
|
||||
|
||||
local_cc = (undefined ***)0x42ab69;
|
||||
|
||||
(**(code **)*piVar5)(piVar5,"Start","ECDNM");
|
||||
|
||||
local_cc = local_a8;
|
||||
|
||||
local_d0 = (undefined *)0x42ab75;
|
||||
|
||||
MSTRTODBL();
|
||||
|
||||
local_d0 = (undefined *)0x42ab7a;
|
||||
|
||||
uVar3 = _System__ROUND_qqrv();
|
||||
|
||||
puVar1[8] = uVar3;
|
||||
|
||||
local_d0 = &DAT_0042b788;
|
||||
|
||||
local_d4 = &local_ac;
|
||||
|
||||
local_d8 = (undefined *)0x42ab99;
|
||||
|
||||
(**(code **)*piVar5)(piVar5,"Start","LCDNM");
|
||||
|
||||
local_d8 = local_ac;
|
||||
|
||||
local_dc = (undefined *)0x42aba5;
|
||||
|
||||
MSTRTODBL();
|
||||
|
||||
local_dc = (undefined *)0x42abaa;
|
||||
|
||||
uVar6 = _System__ROUND_qqrv();
|
||||
|
||||
*(undefined4 *)(puVar1 + 0x7ac) = uVar6;
|
||||
|
||||
local_dc = &DAT_0042b788;
|
||||
|
||||
local_e0 = &local_b0;
|
||||
|
||||
local_e4 = 0x42abcc;
|
||||
|
||||
(**(code **)*piVar5)(piVar5,"Start","MCDNM");
|
||||
|
||||
local_e4 = local_b0;
|
||||
|
||||
local_e8 = (undefined *)0x42abd8;
|
||||
|
||||
MSTRTODBL();
|
||||
|
||||
local_e8 = (undefined *)0x42abdd;
|
||||
|
||||
uVar6 = _System__ROUND_qqrv();
|
||||
|
||||
*(undefined4 *)(puVar1 + 0x7b0) = uVar6;
|
||||
|
||||
local_e8 = &DAT_0042b824;
|
||||
+526
@@ -0,0 +1,526 @@
|
||||
# Ghidra main 0x43307c 발췌 — 줄 단가 다시 읽기(0x437a13) · 상위 B·천원 환율 칸(0x435600~0x43590d) · EXRNM 참 S 환산(0x437aa2~)
|
||||
## 1205-1232 (줄 수량 칸 +0x128[계열])
|
||||
*(undefined2 *)(iVar15 + 0x1d5 + *puVar16 * 0x550) = 0x2001;
|
||||
*(undefined2 *)(iVar15 + 0x1d9 + *puVar16 * 0x550) = 0x2001;
|
||||
}
|
||||
}
|
||||
LAB_004353d3:
|
||||
uVar5 = local_7c._2_2_;
|
||||
uVar13 = *(int *)(in_stack_00000004 + 0x10) - 3;
|
||||
local_7c._2_2_ = (undefined2)((uint)puVar16 >> 0x10);
|
||||
uVar6 = local_7c._2_2_;
|
||||
if ((uVar13 < 6) || (uVar13 == 7)) {
|
||||
fVar26 = (float10)*(double *)(iVar15 + *puVar16 * 0x550 + 0x128 + *puVar19 * 8);
|
||||
local_2c = (uint *)0x435407;
|
||||
_System__VarFromReal_qqrv(local_608);
|
||||
local_2c = local_5fc;
|
||||
local_30._0_2_ = SUB42(local_608[2],0);
|
||||
local_30._2_2_ = (undefined2)((uint)local_608[2] >> 0x10);
|
||||
local_34._0_2_ = SUB42(local_608[1],0);
|
||||
local_34._2_2_ = (undefined2)((uint)local_608[1] >> 0x10);
|
||||
local_38 = local_608[0];
|
||||
fVar28 = (float10)*(double *)(iVar15 + *puVar16 * 0x550 + 0x128 + *puVar19 * 8) /
|
||||
(float10)100.0;
|
||||
local_3c = 0x5442;
|
||||
uStack_3a = 0x43;
|
||||
in_ST6 = in_ST4;
|
||||
_System__VarFromReal_qqrv(local_618);
|
||||
local_3c = (undefined2)local_60c;
|
||||
uStack_3a = (undefined2)((uint)local_60c >> 0x10);
|
||||
local_40 = local_610;
|
||||
## 1300-1490
|
||||
local_7c._0_2_ = 0x5595;
|
||||
local_7c._2_2_ = 0x43;
|
||||
IIF();
|
||||
local_7c._0_2_ = 0x55a0;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__VarToReal_qqrrx14System_Variant(local_628);
|
||||
*(double *)(iVar15 + 0x1a8 + *puVar16 * 0x550) = (double)fVar28;
|
||||
}
|
||||
else {
|
||||
local_7c._2_2_ = uVar5;
|
||||
if (*(char *)(*(int *)PTR_DAT_005e5f8c + 0x69) == 'B') {
|
||||
uVar22 = *(int *)PTR_DAT_005e5f8c == -0x179;
|
||||
local_2c = (uint *)0x4355de;
|
||||
_System__LStrFromString_qqrr17System_AnsiStringrx28System__SmallString_iuc_255_
|
||||
(&local_650);
|
||||
local_2c = (uint *)0x4355ef;
|
||||
_Sysutils_Trim_qqrx17System_AnsiString(local_650,&local_64c);
|
||||
local_2c = (uint *)0x4355ff;
|
||||
_System__LStrCmp_qqrv(local_64c,&DAT_00439d2c);
|
||||
if ((bool)uVar22) {
|
||||
local_2c = (uint *)0x43561f;
|
||||
_Apodset_TApolloTable_GetString_qqr17System_AnsiString
|
||||
(*(undefined4 *)(*(int *)PTR_DAT_005e6090 + 8),&DAT_00439c10,&local_654);
|
||||
local_2c = (uint *)0x43562d;
|
||||
_Sysutils_Trim_qqrx17System_AnsiString(local_654,&stack0xffffffe4);
|
||||
local_2c = (uint *)0x43563a;
|
||||
_System__LStrCmp_qqrv(unaff_EDI,&DAT_00439d2c);
|
||||
if ((bool)uVar22) {
|
||||
iVar12 = iVar15 + *puVar16 * 0x550;
|
||||
uVar13 = *puVar19;
|
||||
*(undefined4 *)(iVar12 + 0x128 + uVar13 * 8) = 0;
|
||||
*(undefined4 *)(iVar12 + 300 + uVar13 * 8) = 0x3ff00000;
|
||||
local_a0 = (undefined1 *)CONCAT22(local_a0._2_2_,(short)local_a0);
|
||||
}
|
||||
else {
|
||||
local_7c._0_2_ = 0x566d;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__LStrCmp_qqrv(unaff_EDI,&DAT_00439d3c);
|
||||
if (!(bool)uVar22) {
|
||||
local_7c._0_2_ = 0x567c;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__LStrCmp_qqrv(unaff_EDI,&DAT_00439d48);
|
||||
if (!(bool)uVar22) {
|
||||
local_7c._0_2_ = 0x57ea;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__LStrCmp_qqrv(unaff_EDI,&DAT_00439d70);
|
||||
if ((bool)uVar22) {
|
||||
if ((*(int *)PTR_DAT_005e6148 == 0) ||
|
||||
(*(char *)(*(int *)PTR_DAT_005e6148 + 0x7c9) == '\0')) {
|
||||
*(double *)(iVar15 + *puVar16 * 0x550 + 0x128 + *puVar19 * 8) =
|
||||
*(double *)
|
||||
(*(int *)PTR_DAT_005e6148 + 0x748 +
|
||||
*(int *)(in_stack_00000004 + 0x18) * 8) / 1000.0;
|
||||
local_a0 = (undefined1 *)CONCAT22(local_a0._2_2_,(short)local_a0);
|
||||
}
|
||||
else {
|
||||
iVar12 = iVar15 + *puVar16 * 0x550;
|
||||
uVar13 = *puVar19;
|
||||
*(undefined4 *)(iVar12 + 0x128 + uVar13 * 8) = 0;
|
||||
*(undefined4 *)(iVar12 + 300 + uVar13 * 8) = 0x3ff00000;
|
||||
puVar18 = (undefined4 *)(iVar15 + 0x1c6 + *puVar16 * 0x550);
|
||||
*puVar18 = 0xbfb5c304;
|
||||
*(undefined1 *)(puVar18 + (uint)bVar25 * -2 + 1) =
|
||||
(&DAT_00439d50)[(uint)bVar25 * -8];
|
||||
local_80 = puVar19;
|
||||
local_7c._2_2_ = uVar6;
|
||||
local_a0 = (undefined1 *)CONCAT22(local_a0._2_2_,(short)local_a0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
local_7c._0_2_ = 0x5886;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__LStrCmp_qqrv(unaff_EDI,&DAT_00439d80);
|
||||
local_a0 = (undefined1 *)CONCAT22(local_a0._2_2_,(short)local_a0);
|
||||
if ((bool)uVar22) {
|
||||
if ((*(int *)PTR_DAT_005e6148 == 0) ||
|
||||
(*(char *)(*(int *)PTR_DAT_005e6148 + 0x7c9) == '\0')) {
|
||||
*(double *)(iVar15 + *puVar16 * 0x550 + 0x128 + *puVar19 * 8) =
|
||||
*(double *)
|
||||
(*(int *)PTR_DAT_005e6148 + 0x738 +
|
||||
*(int *)(in_stack_00000004 + 0x18) * 8) / 100000.0;
|
||||
local_a0 = (undefined1 *)CONCAT22(local_a0._2_2_,(short)local_a0);
|
||||
}
|
||||
else {
|
||||
iVar12 = iVar15 + *puVar16 * 0x550;
|
||||
uVar13 = *puVar19;
|
||||
*(undefined4 *)(iVar12 + 0x128 + uVar13 * 8) = 0;
|
||||
*(undefined4 *)(iVar12 + 300 + uVar13 * 8) = 0x3ff00000;
|
||||
puVar18 = (undefined4 *)(iVar15 + 0x1c6 + *puVar16 * 0x550);
|
||||
*puVar18 = 0xbfb5c304;
|
||||
*(undefined1 *)(puVar18 + (uint)bVar25 * -2 + 1) =
|
||||
(&DAT_00439d50)[(uint)bVar25 * -8];
|
||||
local_80 = puVar19;
|
||||
local_7c._2_2_ = uVar6;
|
||||
local_a0 = (undefined1 *)CONCAT22(local_a0._2_2_,(short)local_a0);
|
||||
}
|
||||
}
|
||||
}
|
||||
goto LAB_0043590d;
|
||||
}
|
||||
}
|
||||
if ((*(int *)PTR_DAT_005e6148 == 0) ||
|
||||
(*(char *)(*(int *)PTR_DAT_005e6148 + 0x7c9) == '\0')) {
|
||||
fVar30 = (float10)*(double *)
|
||||
(*(int *)PTR_DAT_005e6148 + 0x728 +
|
||||
*(int *)(in_stack_00000004 + 0x18) * 8);
|
||||
local_7c._0_2_ = 0x56f8;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__VarFromReal_qqrv(local_674);
|
||||
local_7c._0_2_ = (undefined2)local_668;
|
||||
local_7c._2_2_ = (undefined2)((uint)local_668 >> 0x10);
|
||||
local_80 = local_66c;
|
||||
local_84._0_2_ = (undefined2)local_674._4_4_;
|
||||
local_84._2_2_ = SUB42(local_674._4_4_,2);
|
||||
local_88._0_2_ = (undefined2)local_674._0_4_;
|
||||
local_88._2_2_ = SUB42(local_674._0_4_,2);
|
||||
fVar28 = (float10)*(double *)
|
||||
(*(int *)PTR_DAT_005e6148 + 0x718 +
|
||||
*(int *)(in_stack_00000004 + 0x18) * 8);
|
||||
local_8c = 0x435730;
|
||||
_System__VarFromReal_qqrv(local_684);
|
||||
local_8c = local_678;
|
||||
local_90._0_2_ = (undefined2)local_684[2];
|
||||
local_90._2_2_ = (undefined2)((uint)local_684[2] >> 0x10);
|
||||
local_94 = (undefined2)local_684[1];
|
||||
uStack_92 = (undefined2)((uint)local_684[1] >> 0x10);
|
||||
local_98 = local_684[0];
|
||||
local_9c = 0x5767;
|
||||
uStack_9a = 0x43;
|
||||
_System__LStrCat3_qqrv
|
||||
(&local_688,&DAT_00439d5c,
|
||||
*(undefined4 *)
|
||||
(PTR_PTR_005e5f40 + *(int *)(in_stack_00000004 + 0x18) * 4));
|
||||
local_9c = 0x577c;
|
||||
uStack_9a = 0x43;
|
||||
_Apodset_TApolloTable_GetDouble_qqr17System_AnsiString
|
||||
(*(undefined4 *)(*(int *)PTR_DAT_005e6090 + 8),local_688);
|
||||
fVar26 = (float10)100000.0;
|
||||
local_9c = (undefined2)
|
||||
CONCAT31((int3)(CONCAT22(extraout_var,
|
||||
(ushort)(fVar28 < fVar26) << 8 |
|
||||
(ushort)(NAN(fVar28) || NAN(fVar26)) << 10 |
|
||||
(ushort)(fVar28 == fVar26) << 0xe) >> 8),
|
||||
fVar28 < fVar26 != 0);
|
||||
local_a0 = local_664;
|
||||
local_a4._0_2_ = 0x5795;
|
||||
local_a4._2_2_ = 0x43;
|
||||
in_ST6 = in_ST5;
|
||||
uStack_9a = extraout_var;
|
||||
IIF();
|
||||
local_a4 = local_664;
|
||||
puStack_a8 = (undefined1 *)0x4357ae;
|
||||
_System__VarFromInt_qqrr14System_Variantxixi(local_698,1000,2);
|
||||
puVar10 = local_a4;
|
||||
local_a4._0_2_ = 0x57ba;
|
||||
local_a4._2_2_ = 0x43;
|
||||
_System__VarRDiv_qqrr14System_Variantrx14System_Variant(puVar10,local_698);
|
||||
local_a4._0_2_ = 0x57c5;
|
||||
local_a4._2_2_ = 0x43;
|
||||
_System__VarToReal_qqrrx14System_Variant(local_664);
|
||||
*(double *)(iVar15 + *puVar16 * 0x550 + 0x128 + *puVar19 * 8) = (double)fVar30;
|
||||
}
|
||||
else {
|
||||
iVar12 = iVar15 + *puVar16 * 0x550;
|
||||
uVar13 = *puVar19;
|
||||
*(undefined4 *)(iVar12 + 0x128 + uVar13 * 8) = 0;
|
||||
*(undefined4 *)(iVar12 + 300 + uVar13 * 8) = 0x3ff00000;
|
||||
puVar18 = (undefined4 *)(iVar15 + 0x1c6 + *puVar16 * 0x550);
|
||||
*puVar18 = 0xbfb5c304;
|
||||
*(undefined1 *)(puVar18 + (uint)bVar25 * -2 + 1) =
|
||||
(&DAT_00439d50)[(uint)bVar25 * -8];
|
||||
local_80 = puVar19;
|
||||
local_7c._2_2_ = uVar6;
|
||||
local_a0 = (undefined1 *)CONCAT22(local_a0._2_2_,(short)local_a0);
|
||||
}
|
||||
}
|
||||
LAB_0043590d:
|
||||
uVar13 = *puVar16;
|
||||
puVar18 = (undefined4 *)(iVar15 + *puVar16 * 0x550 + 0x128 + *puVar19 * 8);
|
||||
*(undefined4 *)(iVar15 + 0x1a0 + uVar13 * 0x550) = *puVar18;
|
||||
*(undefined4 *)(iVar15 + 0x1a4 + uVar13 * 0x550) = puVar18[1];
|
||||
uVar13 = *puVar16;
|
||||
uVar4 = *puVar16;
|
||||
*(undefined4 *)(iVar15 + 0x1a8 + uVar13 * 0x550) =
|
||||
*(undefined4 *)(iVar15 + 0x1a0 + uVar4 * 0x550);
|
||||
*(undefined4 *)(iVar15 + 0x1ac + uVar13 * 0x550) =
|
||||
*(undefined4 *)(iVar15 + 0x1a4 + uVar4 * 0x550);
|
||||
goto LAB_00436222;
|
||||
}
|
||||
}
|
||||
local_2c = *(uint **)(*(int *)PTR_DAT_005e5f8c + 4);
|
||||
## 1770-1800 · 1905-1930 (수량 칸 → 유효수량 +0x1a0)
|
||||
*(undefined4 *)(iVar15 + 0x1a8 + uVar13 * 0x550) =
|
||||
*(undefined4 *)(iVar15 + 0x1a0 + uVar4 * 0x550);
|
||||
*(undefined4 *)(iVar15 + 0x1ac + uVar13 * 0x550) =
|
||||
*(undefined4 *)(iVar15 + 0x1a4 + uVar4 * 0x550);
|
||||
}
|
||||
else {
|
||||
if (*(double *)(iVar15 + *puVar16 * 0x550 + 0x128 + *puVar19 * 8) == 0.0) {
|
||||
uVar13 = *puVar16;
|
||||
*(undefined4 *)(iVar15 + 0x1a0 + uVar13 * 0x550) = 0;
|
||||
*(undefined4 *)(iVar15 + 0x1a4 + uVar13 * 0x550) = 0;
|
||||
}
|
||||
else {
|
||||
*(double *)(iVar15 + 0x1a0 + *puVar16 * 0x550) =
|
||||
(double)(1.0 / (float)*(double *)
|
||||
(iVar15 + *puVar16 * 0x550 + 0x128 +
|
||||
*puVar19 * 8));
|
||||
}
|
||||
uVar13 = *puVar16;
|
||||
uVar4 = *puVar16;
|
||||
*(undefined4 *)(iVar15 + 0x1a8 + uVar13 * 0x550) =
|
||||
*(undefined4 *)(iVar15 + 0x1a0 + uVar4 * 0x550);
|
||||
*(undefined4 *)(iVar15 + 0x1ac + uVar13 * 0x550) =
|
||||
*(undefined4 *)(iVar15 + 0x1a4 + uVar4 * 0x550);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LAB_00435fbd:
|
||||
iVar12 = *(int *)PTR_DAT_005e6148;
|
||||
puVar18 = (undefined4 *)(iVar15 + *puVar16 * 0x550 + 0x128 + *puVar19 * 8);
|
||||
*puVar18 = *(undefined4 *)(iVar12 + 0x790);
|
||||
puVar18[1] = *(undefined4 *)(iVar12 + 0x794);
|
||||
}
|
||||
}
|
||||
LAB_00436222:
|
||||
fVar26 = in_ST0;
|
||||
if (*(double *)(iVar15 + 0x428 + *puVar16 * 0x550) != 0.0) {
|
||||
local_7c._0_2_ = 0;
|
||||
local_7c._2_2_ = 0;
|
||||
local_80 = (uint *)0xb;
|
||||
fVar26 = (float10)*(double *)(iVar15 + 0x1a0 + *puVar16 * 0x550) *
|
||||
(float10)*(double *)(iVar15 + 0x428 + *puVar16 * 0x550);
|
||||
local_8c = SUB104(fVar26,0);
|
||||
local_88._0_2_ = (undefined2)((unkuint10)fVar26 >> 0x20);
|
||||
local_88._2_2_ = (undefined2)((unkuint10)fVar26 >> 0x30);
|
||||
local_84._0_2_ = (undefined2)((unkuint10)fVar26 >> 0x40);
|
||||
local_90._0_2_ = 0x6264;
|
||||
local_90._2_2_ = 0x43;
|
||||
fVar26 = in_ST1;
|
||||
in_ST1 = in_ST2;
|
||||
in_ST2 = in_ST3;
|
||||
in_ST3 = in_ST4;
|
||||
in_ST4 = in_ST5;
|
||||
in_ST5 = in_ST6;
|
||||
MROUNDUD();
|
||||
*(double *)(iVar15 + 0x1a0 + *puVar16 * 0x550) = (double)in_ST0;
|
||||
}
|
||||
if (*(char *)(iVar15 + 0x1bd + *puVar16 * 0x550) == '%') {
|
||||
## 2640-2725 (비목별 줄 금액 = 단가 × 유효수량 → ADDBJVAL)
|
||||
_System__VarAdd_qqrr14System_Variantrx14System_Variant(puVar10,local_78c);
|
||||
uStack_e4._0_2_ = 0x6675;
|
||||
uStack_e4._2_2_ = 0x43;
|
||||
_System__VarToReal_qqrrx14System_Variant(local_77c);
|
||||
*(double *)(*(int *)PTR_DAT_005e5d84 + 200 + *puVar19 * 0x30) = (double)fVar28;
|
||||
uVar13 = *puVar19;
|
||||
iVar12 = *(int *)PTR_DAT_005e5d84;
|
||||
*(undefined4 *)(iVar12 + 0xe8 + uVar13 * 0x30) = 0;
|
||||
*(undefined4 *)(iVar12 + 0xec + uVar13 * 0x30) = 0;
|
||||
*(double *)(*(int *)PTR_DAT_005e5d84 + 0xc0 + *puVar19 * 0x30) =
|
||||
*(double *)(*(int *)PTR_DAT_005e5d84 + 200 + *puVar19 * 0x30) +
|
||||
*(double *)(*(int *)PTR_DAT_005e5d84 + 0xd0 + *puVar19 * 0x30) +
|
||||
*(double *)(*(int *)PTR_DAT_005e5d84 + 0xd8 + *puVar19 * 0x30) +
|
||||
*(double *)(*(int *)PTR_DAT_005e5d84 + 0xe0 + *puVar19 * 0x30);
|
||||
}
|
||||
}
|
||||
LAB_00437303:
|
||||
fVar28 = (float10)*(double *)(*(int *)PTR_DAT_005e5d84 + 200 + *puVar19 * 0x30) *
|
||||
(float10)*(double *)(iVar15 + 0x1a0 + *puVar16 * 0x550);
|
||||
uStack_c4 = SUB104(fVar28,0);
|
||||
uStack_c0 = (undefined4)((unkuint10)fVar28 >> 0x20);
|
||||
uStack_bc._0_2_ = (undefined2)((unkuint10)fVar28 >> 0x40);
|
||||
uStack_c8 = 0x7332;
|
||||
uStack_c6 = 0x43;
|
||||
fVar28 = in_ST6;
|
||||
ADDBJVAL();
|
||||
*(double *)(in_stack_00000004 + -0x70) = (double)fVar26;
|
||||
fVar26 = in_ST1;
|
||||
if ((*(char *)(*(int *)PTR_DAT_005e5e7c + 0x19ba) == '\x01') &&
|
||||
(*(char *)(*(int *)PTR_DAT_005e5f8c + 0x57) == '\x05')) {
|
||||
fVar26 = (float10)*(double *)(*(int *)PTR_DAT_005e5d84 + 0xe8 + *puVar19 * 0x30) *
|
||||
(float10)*(double *)(iVar15 + 0x1a0 + *puVar16 * 0x550);
|
||||
puStack_d0 = SUB104(fVar26,0);
|
||||
uStack_cc = (undefined4)((unkuint10)fVar26 >> 0x20);
|
||||
uStack_c8 = (undefined2)((unkuint10)fVar26 >> 0x40);
|
||||
uStack_d4._0_2_ = 0x7385;
|
||||
uStack_d4._2_2_ = 0x43;
|
||||
fVar26 = in_ST2;
|
||||
in_ST2 = in_ST3;
|
||||
in_ST3 = in_ST4;
|
||||
in_ST4 = in_ST5;
|
||||
in_ST5 = in_ST6;
|
||||
in_ST6 = fVar28;
|
||||
ADDBJVAL();
|
||||
*(double *)(in_stack_00000004 + -0x50) = (double)in_ST1;
|
||||
}
|
||||
fVar30 = (float10)*(double *)(*(int *)PTR_DAT_005e5d84 + 0xd0 + *puVar19 * 0x30) *
|
||||
(float10)*(double *)(iVar15 + 0x1a0 + *puVar16 * 0x550);
|
||||
puStack_d0 = SUB104(fVar30,0);
|
||||
uStack_cc = (undefined4)((unkuint10)fVar30 >> 0x20);
|
||||
uStack_c8 = (undefined2)((unkuint10)fVar30 >> 0x40);
|
||||
uStack_d4._0_2_ = 0x73bb;
|
||||
uStack_d4._2_2_ = 0x43;
|
||||
ADDBJVAL();
|
||||
*(double *)(in_stack_00000004 + -0x68) = (double)fVar26;
|
||||
fVar26 = (float10)*(double *)(*(int *)PTR_DAT_005e5d84 + 0xd8 + *puVar19 * 0x30) *
|
||||
(float10)*(double *)(iVar15 + 0x1a0 + *puVar16 * 0x550);
|
||||
uStack_dc = SUB104(fVar26,0);
|
||||
uStack_d8 = (undefined2)((unkuint10)fVar26 >> 0x20);
|
||||
uStack_d6 = (undefined2)((unkuint10)fVar26 >> 0x30);
|
||||
uStack_d4._0_2_ = (undefined2)((unkuint10)fVar26 >> 0x40);
|
||||
uStack_e0._0_2_ = 0x73f1;
|
||||
uStack_e0._2_2_ = 0x43;
|
||||
ADDBJVAL();
|
||||
*(double *)(in_stack_00000004 + -0x60) = (double)in_ST2;
|
||||
fVar26 = (float10)*(double *)(*(int *)PTR_DAT_005e5d84 + 0xe0 + *puVar19 * 0x30) *
|
||||
(float10)*(double *)(iVar15 + 0x1a0 + *puVar16 * 0x550);
|
||||
uStack_e8 = SUB104(fVar26,0);
|
||||
uStack_e4._0_2_ = (undefined2)((unkuint10)fVar26 >> 0x20);
|
||||
uStack_e4._2_2_ = (undefined2)((unkuint10)fVar26 >> 0x30);
|
||||
uStack_e0._0_2_ = (undefined2)((unkuint10)fVar26 >> 0x40);
|
||||
uStack_ec = 0x7427;
|
||||
uStack_ea = 0x43;
|
||||
ADDBJVAL();
|
||||
*(double *)(in_stack_00000004 + -0x58) = (double)in_ST3;
|
||||
fVar26 = (float10)*(double *)(*(int *)PTR_DAT_005e5d84 + 0xc0 + *puVar19 * 0x30) *
|
||||
(float10)*(double *)(iVar15 + 0x1a0 + *puVar16 * 0x550);
|
||||
uStack_f4 = SUB104(fVar26,0);
|
||||
uStack_f0 = (undefined2)((unkuint10)fVar26 >> 0x20);
|
||||
uStack_ee = (undefined2)((unkuint10)fVar26 >> 0x30);
|
||||
uStack_ec = (undefined2)((unkuint10)fVar26 >> 0x40);
|
||||
uStack_f8 = 0x43745d;
|
||||
ADDBJVAL();
|
||||
*(double *)(in_stack_00000004 + -0x78) = (double)in_ST4;
|
||||
cVar8 = *(char *)(iVar15 + 0x1d4 + *puVar16 * 0x550);
|
||||
if (((byte)(cVar8 + 0xb4U) < 2) || (cVar8 == 'S')) {
|
||||
## 2970-3100 (A 줄 = COSTA · EXRNM 참 환산)
|
||||
}
|
||||
}
|
||||
else {
|
||||
LAB_00437a13:
|
||||
if (((*(int *)(in_stack_00000004 + 0x10) - 1U < 3) ||
|
||||
((*(int *)(in_stack_00000004 + 0x10) == 6 && (1 < (int)*puVar19)))) ||
|
||||
((*(int *)(in_stack_00000004 + 0x10) - 7U < 2 &&
|
||||
((*(int *)(in_stack_00000004 + 0x18) == 3 && (*puVar19 == 3)))))) {
|
||||
if (*(char *)(iVar15 + 0x1b + *puVar16 * 0x550) == 'A') {
|
||||
local_7c._0_2_ = (undefined2)*puVar19;
|
||||
local_7c._2_2_ = (undefined2)(*puVar19 >> 0x10);
|
||||
local_80 = (uint *)0x1;
|
||||
local_84._0_2_ = 0x7a7c;
|
||||
local_84._2_2_ = 0x43;
|
||||
FUN_00430c60(iVar15 + *puVar16 * 0x550,*(undefined4 *)(*(int *)PTR_DAT_005e6090 + 0xc),
|
||||
*(undefined4 *)(in_stack_00000004 + 0x18));
|
||||
}
|
||||
else {
|
||||
local_7c._0_2_ = (undefined2)*puVar19;
|
||||
local_7c._2_2_ = (undefined2)(*puVar19 >> 0x10);
|
||||
local_80 = (uint *)0x0;
|
||||
local_84._0_2_ = 0x7aa2;
|
||||
local_84._2_2_ = 0x43;
|
||||
FUN_00430c60(iVar15 + *puVar16 * 0x550,*(undefined4 *)(*(int *)PTR_DAT_005e6090 + 8),
|
||||
*(undefined4 *)(in_stack_00000004 + 0x18));
|
||||
}
|
||||
}
|
||||
uVar13 = *(int *)(in_stack_00000004 + 0x10) - 3;
|
||||
if ((uVar13 < 6) || (uVar13 == 7)) {
|
||||
if ((*(int *)PTR_DAT_005e6148 != 0) &&
|
||||
((*(char *)(*(int *)PTR_DAT_005e6148 + 0x7c9) != '\0' &&
|
||||
(uVar22 = *(char *)(iVar15 + 0x1b + *puVar16 * 0x550) == 'S', (bool)uVar22)))) {
|
||||
local_7c._0_2_ = 0x7b04;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__LStrFromString_qqrr17System_AnsiStringrx28System__SmallString_iuc_255_
|
||||
(&local_ad0,iVar15 + 0x1bb + *puVar16 * 0x550);
|
||||
local_7c._0_2_ = 0x7b15;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_Sysutils_Trim_qqrx17System_AnsiString(local_ad0,&local_acc);
|
||||
local_7c._0_2_ = 0x7b25;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__LStrCmp_qqrv(local_acc,&DAT_00439d3c);
|
||||
if (!(bool)uVar22) {
|
||||
local_7c._0_2_ = 0x7b43;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__LStrFromString_qqrr17System_AnsiStringrx28System__SmallString_iuc_255_
|
||||
(&local_ad8,iVar15 + 0x1bb + *puVar16 * 0x550);
|
||||
local_7c._0_2_ = 0x7b54;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_Sysutils_Trim_qqrx17System_AnsiString(local_ad8,&local_ad4);
|
||||
local_7c._0_2_ = 0x7b64;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__LStrCmp_qqrv(local_ad4,&DAT_00439d48);
|
||||
if (!(bool)uVar22) {
|
||||
local_7c._0_2_ = 0x7b7e;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__LStrFromString_qqrr17System_AnsiStringrx28System__SmallString_iuc_255_
|
||||
(&local_ae0,iVar15 + 0x1bb + *puVar16 * 0x550);
|
||||
local_7c._0_2_ = 0x7b8f;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_Sysutils_Trim_qqrx17System_AnsiString(local_ae0,&local_adc);
|
||||
local_7c._0_2_ = 0x7b9f;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__LStrCmp_qqrv(local_adc,&DAT_00439d70);
|
||||
if (!(bool)uVar22) {
|
||||
local_7c._0_2_ = 0x7bb9;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__LStrFromString_qqrr17System_AnsiStringrx28System__SmallString_iuc_255_
|
||||
(&local_ae8,iVar15 + 0x1bb + *puVar16 * 0x550);
|
||||
local_7c._0_2_ = 0x7bca;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_Sysutils_Trim_qqrx17System_AnsiString(local_ae8,&local_ae4);
|
||||
local_7c._0_2_ = 0x7bda;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__LStrCmp_qqrv(local_ae4,&DAT_00439d80);
|
||||
if (!(bool)uVar22) goto LAB_00437e32;
|
||||
}
|
||||
}
|
||||
}
|
||||
local_7c._0_2_ = 0x7bf8;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__LStrFromString_qqrr17System_AnsiStringrx28System__SmallString_iuc_255_
|
||||
(&local_af0,iVar15 + 0x1bb + *puVar16 * 0x550);
|
||||
local_7c._0_2_ = 0x7c09;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_Sysutils_Trim_qqrx17System_AnsiString(local_af0,&local_aec);
|
||||
local_7c._0_2_ = 0x7c19;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__LStrCmp_qqrv(local_aec,&DAT_00439d70);
|
||||
if ((bool)uVar22) {
|
||||
*(double *)(in_stack_00000004 + -0x98) =
|
||||
*(double *)
|
||||
(*(int *)PTR_DAT_005e6148 + 0x748 + *(int *)(in_stack_00000004 + 0x18) * 8) /
|
||||
1000.0;
|
||||
fVar28 = in_ST1;
|
||||
in_ST1 = in_ST3;
|
||||
in_ST3 = in_ST5;
|
||||
}
|
||||
else {
|
||||
local_7c._0_2_ = 0x7c5d;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__LStrFromString_qqrr17System_AnsiStringrx28System__SmallString_iuc_255_
|
||||
(&local_af8,iVar15 + 0x1bb + *puVar16 * 0x550);
|
||||
local_7c._0_2_ = 0x7c6e;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_Sysutils_Trim_qqrx17System_AnsiString(local_af8,&local_af4);
|
||||
local_7c._0_2_ = 0x7c7e;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__LStrCmp_qqrv(local_af4,&DAT_00439d80);
|
||||
if ((bool)uVar22) {
|
||||
*(double *)(in_stack_00000004 + -0x98) =
|
||||
*(double *)
|
||||
(*(int *)PTR_DAT_005e6148 + 0x738 + *(int *)(in_stack_00000004 + 0x18) * 8) /
|
||||
100000.0;
|
||||
fVar28 = in_ST1;
|
||||
in_ST1 = in_ST3;
|
||||
in_ST3 = in_ST5;
|
||||
}
|
||||
else {
|
||||
fVar31 = (float10)*(double *)
|
||||
(*(int *)PTR_DAT_005e6148 + 0x728 +
|
||||
*(int *)(in_stack_00000004 + 0x18) * 8);
|
||||
local_7c._0_2_ = 0x7cca;
|
||||
local_7c._2_2_ = 0x43;
|
||||
_System__VarFromReal_qqrv(local_b18);
|
||||
local_7c._0_2_ = (undefined2)local_b0c;
|
||||
local_7c._2_2_ = (undefined2)((uint)local_b0c >> 0x10);
|
||||
local_80 = (uint *)local_b10;
|
||||
local_84._0_2_ = (undefined2)local_b18._4_4_;
|
||||
local_84._2_2_ = SUB42(local_b18._4_4_,2);
|
||||
local_88._0_2_ = (undefined2)local_b18._0_4_;
|
||||
## 4525-4550
|
||||
_Sysutils_Trim_qqrx17System_AnsiString(local_1d0,&local_1cc);
|
||||
local_30._0_2_ = 0x3635;
|
||||
local_30._2_2_ = 0x43;
|
||||
_System__LStrCmp_qqrv(local_1cc,&DAT_00439b64);
|
||||
if ((bool)uVar22) {
|
||||
uVar13 = *puVar16;
|
||||
puVar18 = (undefined4 *)(iVar15 + *puVar16 * 0x550 + 0x128 + *puVar19 * 8);
|
||||
*(undefined4 *)(iVar15 + 0x1a0 + uVar13 * 0x550) = *puVar18;
|
||||
*(undefined4 *)(iVar15 + 0x1a4 + uVar13 * 0x550) = puVar18[1];
|
||||
}
|
||||
else {
|
||||
*(double *)(iVar15 + 0x1a0 + *puVar16 * 0x550) =
|
||||
*(double *)(iVar15 + *puVar16 * 0x550 + 0x128 + *puVar19 * 8) / 100.0;
|
||||
}
|
||||
}
|
||||
else if (*(double *)(iVar15 + *puVar16 * 0x550 + 0x128 + *puVar19 * 8) == 0.0) {
|
||||
uVar13 = *puVar16;
|
||||
*(undefined4 *)(iVar15 + 0x1a0 + uVar13 * 0x550) = 0;
|
||||
*(undefined4 *)(iVar15 + 0x1a4 + uVar13 * 0x550) = 0;
|
||||
}
|
||||
else {
|
||||
*(double *)(iVar15 + 0x1a0 + *puVar16 * 0x550) =
|
||||
(double)(1.0 / (float)*(double *)(iVar15 + *puVar16 * 0x550 + 0x128 + *puVar19 * 8));
|
||||
}
|
||||
if ((*(char *)(*(int *)PTR_DAT_005e5e7c + 0x19ba) == '\x01') &&
|
||||
(*(char *)(*(int *)PTR_DAT_005e5f8c + 0x57) == '\x05')) {
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
0x45c848: PUSH EBP
|
||||
0x45c849: MOV EBP, ESP
|
||||
0x45c84b: PUSH 0x0
|
||||
0x45c84d: PUSH 0x0
|
||||
0x45c84f: PUSH 0x0
|
||||
0x45c851: PUSH EBX
|
||||
0x45c852: PUSH ESI
|
||||
0x45c853: MOV ESI, EAX
|
||||
0x45c855: XOR EAX, EAX
|
||||
0x45c857: PUSH EBP
|
||||
0x45c858: PUSH 0x45c977
|
||||
0x45c85d: PUSH dword ptr FS:[EAX]
|
||||
0x45c860: MOV dword ptr FS:[EAX], ESP
|
||||
0x45c863: MOV EAX, [0x005e5dfc]
|
||||
0x45c868: MOV EAX, dword ptr [EAX]
|
||||
0x45c86a: MOV EBX, EAX
|
||||
0x45c86c: LEA ECX, [EBP + -0x8]
|
||||
0x45c86f: MOV EDX, 0x45c98c
|
||||
0x45c874: MOV EAX, ESI
|
||||
0x45c876: CALL 0x00404790
|
||||
0x45c87b: MOV EAX, dword ptr [EBP + -0x8]
|
||||
0x45c87e: LEA EDX, [EBP + -0x4]
|
||||
0x45c881: CALL 0x00401e40
|
||||
0x45c886: MOV EDX, dword ptr [EBP + -0x4]
|
||||
0x45c889: LEA EAX, [EBX + 0x928]
|
||||
0x45c88f: MOV ECX, 0xff
|
||||
0x45c894: CALL 0x00401298
|
||||
0x45c899: LEA ECX, [EBP + -0xc]
|
||||
0x45c89c: MOV EDX, 0x45c99c
|
||||
0x45c8a1: MOV EAX, ESI
|
||||
0x45c8a3: CALL 0x00404790
|
||||
0x45c8a8: MOV EDX, dword ptr [EBP + -0xc]
|
||||
0x45c8ab: LEA EAX, [EBX + 0x128]
|
||||
0x45c8b1: MOV ECX, 0xff
|
||||
0x45c8b6: CALL 0x00401298
|
||||
0x45c8bb: MOV EDX, 0x45c9ac
|
||||
0x45c8c0: MOV EAX, ESI
|
||||
0x45c8c2: CALL 0x00404778
|
||||
0x45c8c7: MOV word ptr [EBX + 0x1750], AX
|
||||
0x45c8ce: MOV EDX, 0x45c9bc
|
||||
0x45c8d3: MOV EAX, ESI
|
||||
0x45c8d5: CALL 0x00404778
|
||||
0x45c8da: MOV word ptr [EBX + 0x1752], AX
|
||||
0x45c8e1: MOV EDX, 0x45c9cc
|
||||
0x45c8e6: MOV EAX, ESI
|
||||
0x45c8e8: CALL 0x00404778
|
||||
0x45c8ed: MOV word ptr [EBX + 0x1754], AX
|
||||
0x45c8f4: MOV EDX, 0x45c9dc
|
||||
0x45c8f9: MOV EAX, ESI
|
||||
0x45c8fb: CALL 0x00404780
|
||||
0x45c900: CMP AX, 0x1
|
||||
0x45c904: SBB EAX, EAX
|
||||
0x45c906: INC EAX
|
||||
0x45c907: MOV byte ptr [EBX + 0x52bd], AL
|
||||
0x45c90d: MOV EDX, 0x45c9ec
|
||||
0x45c912: MOV EAX, ESI
|
||||
0x45c914: CALL 0x00404780
|
||||
0x45c919: CMP AX, 0x1
|
||||
0x45c91d: SBB EAX, EAX
|
||||
0x45c91f: INC EAX
|
||||
0x45c920: MOV byte ptr [EBX + 0x52be], AL
|
||||
0x45c926: MOV EDX, 0x45c9fc
|
||||
0x45c92b: MOV EAX, ESI
|
||||
0x45c92d: CALL 0x00404778
|
||||
0x45c932: MOV dword ptr [EBX + 0x52b8], EAX
|
||||
0x45c938: MOV EDX, 0x45ca0c
|
||||
0x45c93d: MOV EAX, ESI
|
||||
0x45c93f: CALL 0x00404778
|
||||
0x45c944: MOV dword ptr [EBX + 0x172c], EAX
|
||||
0x45c94a: MOV EDX, 0x45ca1c
|
||||
0x45c94f: MOV EAX, ESI
|
||||
0x45c951: CALL 0x00404778
|
||||
0x45c956: MOV dword ptr [EBX + 0x1730], EAX
|
||||
0x45c95c: XOR EAX, EAX
|
||||
0x45c95e: POP EDX
|
||||
0x45c95f: POP ECX
|
||||
0x45c960: POP ECX
|
||||
0x45c961: MOV dword ptr FS:[EAX], EDX
|
||||
0x45c964: PUSH 0x45c97e
|
||||
0x45c969: LEA EAX, [EBP + -0xc]
|
||||
0x45c96c: MOV EDX, 0x3
|
||||
0x45c971: CALL 0x00401258
|
||||
0x45c976: RET
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
kj_47a1bc ev_4ded8d98d2a16037b53d3b40a8e7b733e5cc9b14d52aa0896f6c7fc1c44c596a
|
||||
loader_42b166 ev_8112ff8e59578982e808a3ccd9a95c381010288faf9fb7ed48ccccfa3f165951
|
||||
main_43307c ev_6a03bc19fb86d1f061dd4ccc6c3f9c8347924d406cf81a28294dcb93bef671a2
|
||||
open_main
|
||||
open_kj
|
||||
as_0x45c938 ev_03492f4e870a253f1a153291962a982e91a70f934d28c231c497117d05de240e
|
||||
xr_0x45ca0c ev_b47e243fa2378a168088bfb5ca2f687127dc8292fc50c686aab4a35279959d56
|
||||
ss_acttyp ev_72931dd7a5ce247a89d29048e5af4bb76eecf82ee7ef88d48ab97c3debc65ed1
|
||||
rb_439d28 ev_70b05c0574df5ec386ca25cdd756707ba26c912824f55cf0eeeae24e5f6f5333
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
ev_70b05c0574df5ec386ca25cdd756707ba26c912824f55cf0eeeae24e5f6f5333
|
||||
04000000c3b5bff800000000ffffffff0100000024000000ffffffff02000000a3a4000004c3b5bff8000000ffffffff0400000054414d54000000000050c347ffffffff02000000a2e6000000007a44ffffffff02000000a1cd0000ffffffff02000000c0ce0000012c000001200000
|
||||
@@ -0,0 +1,48 @@
|
||||
// STMATE 재현 앱 — 표준시장단가(A) 내역·구성 · 외화 환산(EXRNM) · 행자부 RATE_M 조회 · stdin {mode, ...} → 결과
|
||||
// boq: calc.calculateAll 내역 줄 · comp: smt_engine 단가 읽기(costnLookup) + 구성 조립 · ratem: kanjub_parts.NATIVE.rateMLookup
|
||||
globalThis.window = globalThis;
|
||||
const C = require("../../tools/stmate-test/calc.js");
|
||||
const Parts = require("../../tools/stmate-test/kanjub_parts.js");
|
||||
require("../../tools/stmate-test/smt_eval.js");
|
||||
require("../../tools/stmate-test/smt_engine.js");
|
||||
const E = window.STMATE_ENGINE;
|
||||
const V = window.STMATE_SMT_EVAL;
|
||||
|
||||
const MODES = {
|
||||
boq({ items, rows, std, slot }) {
|
||||
const st = C.createDefaultState();
|
||||
Object.assign(st, { stdMarketItems: items, boqItems: rows });
|
||||
st.sysConfig.stdMarket = std;
|
||||
const res = C.calculateAll(st);
|
||||
const boq = slot === 2 ? res.boqRev : res.boqOrig;
|
||||
const pick = (r) => ({ M: r.M, L: r.L, S: r.S, A: r.A, T: r.T, uL: r.lUnit, uM: r.mUnit });
|
||||
return { rows: boq.rows.map(pick), directA: boq.directA, directT: boq.directT };
|
||||
},
|
||||
comp({ cases }) {
|
||||
return cases.map((c) => {
|
||||
const ctx = {
|
||||
dbfData: Object.assign({ start_ini: {}, costn_rows: [], costa_rows: [] }, c.data),
|
||||
state: { sysConfig: {} },
|
||||
};
|
||||
const code = c.code || "B00001";
|
||||
const opts = E.compositionOptions(ctx, code, {});
|
||||
const { lookup } = E.costnLookup(ctx);
|
||||
const ev = V.evaluateComposition(c.rows, lookup, opts);
|
||||
return { M: ev.M, L: ev.L, S: ev.S, unit: c.peek ? lookup(c.peek) : null };
|
||||
});
|
||||
},
|
||||
ratem({ rows, cases }) {
|
||||
return {
|
||||
setBase: Parts.NATIVE.SET_BASE,
|
||||
out: cases.map((o) => Parts.NATIVE.rateMLookup(rows, o)),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
let buf = "";
|
||||
process.stdin.setEncoding("utf8");
|
||||
process.stdin.on("data", (d) => (buf += d));
|
||||
process.stdin.on("end", () => {
|
||||
const req = JSON.parse(buf);
|
||||
process.stdout.write(JSON.stringify(MODES[req.mode](req)));
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
"""STMATE 재현 앱 계산 도구 — 노무·장비 수량 계산기(wM_Edit_XRate) · 실적→일식 비목율(wM_Conv_A2W).
|
||||
|
||||
근거: REA 30 labor_equipment_quantity_rules.json · REA 27 conversion_component_rate_rules.json — 손셈 대조.
|
||||
수량 계산기 반올림(MROUNDUD) 방향은 미확정 — 반올림으로 둔 값은 경계가 아닌 수로만 봄.
|
||||
수량 계산기 반올림 = MROUNDUD 선택 1(사사오입 · REA 32 §1.1) — 경계 값은 test_stmate_xrate_round.
|
||||
"""
|
||||
|
||||
import json
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
"""STMATE 재현 앱 — 표준시장단가(A 코드) 내역·구성 연결 · 외화 환산 EXRNM · 행자부 RATE_M 조회 · 적용기준 콤보 짝.
|
||||
|
||||
근거(지식DB REA 36 · 34 §6·§11·§17):
|
||||
표준시장단가 단가 읽기 Main 0x430c60 — A 줄 = COSTA(0x437a4b) · S_JDA 참 = 저장 단가 · 거짓 = 0x45a468 나눔
|
||||
L0 = T×R/100 · X = T×(100−R)/100 · ACTOPT 0 절사 · 1 OPTIMIZ{L0,0,0,X}[0] · 2 OPTIMIZ{X,0,0,L0}[3](동률 = 앞 칸)
|
||||
R = 0 이고 LAMTn_R 있으면 그 값이 노무 · 나머지 ACTTYP 1 재료 · 2 경비 · 0 넷째 칸(A) · ACTTYP·ACTOPT = PRJLST(0x45c938)
|
||||
EXRNM 참 — S 줄 단가 = MROUNDUD(단가 × 환율/1000, ECD, 0)(0x437aa2~0x437df2) · $ 10만 미만 EXL · € /1000 · ¥ /100000
|
||||
행자부(SET_BASE 1) — ST_KanJub 0x47a1bc: 줄 b+11 / b+15 · 칸 RATE{기간(+5)} · 일반관리비 줄 23 RATE1 · 이윤 줄 24 RATE0
|
||||
적용기준 콤보 = TWM_KANJUB.dfm cmBx_Set_Base Items/Values
|
||||
기대값은 위 규칙 손셈 또는 실물 STC(RATE_M 표 · PRJLST 값) · DFM 원자료에서 읽음.
|
||||
"""
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
sys.path.insert(0, str(ROOT / "tools/stmate-test"))
|
||||
import server # noqa: E402
|
||||
|
||||
HELPER = Path(__file__).with_name("helper_stmate_std.cjs")
|
||||
DOCS = ROOT / "resources/knowledge/original/실무문서"
|
||||
STC = DOCS / (
|
||||
"25년 산불진화임도(기번8)(울진소광)/2025년 산불진화임도 신설사업(기번8 울진.금강송.소광.산29외).STC"
|
||||
)
|
||||
DFM = (
|
||||
ROOT / "resources/knowledge/original/경쟁사 프로그램/STmate/REA 분석/"
|
||||
"21_제경비_입력화면연결_작업자료_20261025/ST_KanJub/resource-TWM_KANJUB.dfm.json"
|
||||
)
|
||||
|
||||
|
||||
def run(req):
|
||||
out = subprocess.check_output(
|
||||
["node", str(HELPER)],
|
||||
input=json.dumps(req, ensure_ascii=False),
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
)
|
||||
return json.loads(out)
|
||||
|
||||
|
||||
def item(aamt, rate_l, lamt_r=(0, 0, 0, 0), stored=None):
|
||||
st = stored or {"L": [0] * 4, "M": [0] * 4, "S": [0] * 4}
|
||||
base = {"code": "A00001", "name": "표준", "unit": "m", "aamt": aamt, "rateL": rate_l}
|
||||
return base | {"lamtR": list(lamt_r), "stored": st}
|
||||
|
||||
|
||||
ROW = [{"id": "BOQ_1", "code": "A00001", "refId": "A00001", "qty": 3, "changedQty": 3}]
|
||||
|
||||
|
||||
def boq(it, std, slot=1, rows=ROW):
|
||||
return run({"mode": "boq", "items": [it], "rows": rows, "std": std, "slot": slot})
|
||||
|
||||
|
||||
def test_std_market_boq_actopt_tie():
|
||||
# T 10001 · R 50 → L0 = X = 5000.5(동률) — 0 절사 5000 · 1 노무 칸 앞 → 5001 · 2 노무 칸 뒤 → 5000
|
||||
it = item([10001, 0, 0, 0], 50)
|
||||
r0, r1, r2 = (boq(it, {"acttyp": 1, "actopt": op})["rows"][0] for op in (0, 1, 2))
|
||||
assert (r0["uL"], r0["uM"]) == (5000, 5001)
|
||||
assert (r1["uL"], r1["uM"]) == (5001, 5000)
|
||||
assert (r2["uL"], r2["uM"]) == (5000, 5001)
|
||||
# 수량 3 — 비목별 원 미만 절사 · 합계 = 단가 합 × 3
|
||||
assert (r1["L"], r1["M"], r1["S"], r1["T"]) == (15003, 15000, 0, 30003)
|
||||
|
||||
|
||||
def test_std_market_boq_rest_column_and_preset():
|
||||
it = item([10001, 0, 0, 0], 50)
|
||||
s = boq(it, {"acttyp": 2, "actopt": 0})["rows"][0]
|
||||
assert (s["L"], s["M"], s["S"]) == (15000, 0, 15003)
|
||||
a = boq(it, {"acttyp": 0, "actopt": 0})
|
||||
# ACTTYP 0 — 나머지는 넷째 칸 A(비목 밖) · 줄·내역 합계에는 들어감
|
||||
assert (a["rows"][0]["M"], a["rows"][0]["A"], a["rows"][0]["T"]) == (0, 15003, 30003)
|
||||
assert a["directA"] == 15003 and a["directT"] == 30003
|
||||
# R 0 · LAMT1_R 4000 → 노무 4000 그대로 · 나머지 6001 재료
|
||||
p = boq(item([10001, 0, 0, 0], 0, (4000, 0, 0, 0)), {"acttyp": 1, "actopt": 2})["rows"][0]
|
||||
assert (p["uL"], p["uM"]) == (4000, 6001)
|
||||
|
||||
|
||||
def test_std_market_boq_stored_and_slot2():
|
||||
stored = {"L": [111, 0, 0, 0], "M": [222, 0, 0, 0], "S": [33, 0, 0, 0]}
|
||||
s = boq(item([10001, 0, 0, 0], 50, stored=stored), {"useStored": True})["rows"][0]
|
||||
assert (s["uL"], s["uM"], s["T"]) == (111, 222, (111 + 222 + 33) * 3)
|
||||
# 변경(2칸) = AAMT2 로 다시 나눔
|
||||
r = boq(item([10001, 20000, 0, 0], 50), {"acttyp": 1, "actopt": 0}, slot=2)["rows"][0]
|
||||
assert (r["uL"], r["uM"]) == (10000, 10000)
|
||||
|
||||
|
||||
COSTA = {"CODE": "A00001", "NAME": "표준", "UNIT": "m", "AAMT1": "10001", "RATE_L": "50"}
|
||||
|
||||
|
||||
def test_std_market_composition_lookup():
|
||||
data = {"costa_rows": [COSTA], "prjlst": {"ACTTYP": "1", "ACTOPT": "1"}}
|
||||
(r,) = run(
|
||||
{
|
||||
"mode": "comp",
|
||||
"cases": [
|
||||
{"data": data, "rows": [{"CODE": "A00001", "QTY1": 2}], "peek": "A00001"},
|
||||
],
|
||||
}
|
||||
)
|
||||
assert (r["unit"]["L"], r["unit"]["M"], r["unit"]["S"]) == (5001, 5000, 0)
|
||||
assert (r["L"], r["M"], r["S"]) == (10002, 10000, 0)
|
||||
|
||||
|
||||
def test_exrnm_unit_price_rounds_to_ecd():
|
||||
# $123.45 × 1289/1000 = 159.12705 천원 · 수량 10
|
||||
costn = [{"CODE": "S00001", "UNIT": "$", "SAMT1": "123.45", "TAMT1": "123.45"}]
|
||||
ini = {"EXLNM1": "1289", "EXHNM1": "1300"}
|
||||
rows = [{"CODE": "S00001", "QTY1": 10}]
|
||||
cases = [
|
||||
{"data": {"costn_rows": costn, "start_ini": ini | {"EXRNM": "1"}}, "rows": rows},
|
||||
{
|
||||
"data": {"costn_rows": costn, "start_ini": ini | {"EXRNM": "1", "ECDNM": "2"}},
|
||||
"rows": rows,
|
||||
},
|
||||
# 키 없음 = 로더 기본 1000.00 → 123.45 × 1 → ECD 0 절사 123
|
||||
{"data": {"costn_rows": costn, "start_ini": {"EXRNM": "1"}}, "rows": rows},
|
||||
]
|
||||
a, b, c = run({"mode": "comp", "cases": cases})
|
||||
assert a["S"] == 1590 # 159(ECD 0 버림) × 10
|
||||
assert b["S"] == 1591 # 159.12 × 10 = 1591.2
|
||||
assert c["S"] == 1230
|
||||
|
||||
|
||||
def test_exrnm_only_s_lines_and_fullwidth_dollar():
|
||||
ini = {"EXRNM": "1", "EXLNM1": "1500", "EXHNM1": "1500"}
|
||||
costn = [
|
||||
{"CODE": "M00009", "UNIT": "$", "MAMT1": "100", "TAMT1": "100"},
|
||||
{"CODE": "S00002", "UNIT": "$", "SAMT1": "10", "TAMT1": "10"},
|
||||
]
|
||||
data = {"costn_rows": costn, "start_ini": ini}
|
||||
m, s = run(
|
||||
{
|
||||
"mode": "comp",
|
||||
"cases": [
|
||||
{"data": data, "rows": [{"CODE": "M00009", "QTY1": 1}]},
|
||||
{"data": data, "rows": [{"CODE": "S00002", "QTY1": 1}]},
|
||||
],
|
||||
}
|
||||
)
|
||||
# 원본 환산 조건 = 줄 코드 S(0x437adb) — 재료 $ 줄은 그대로 · 전각 $ 도 $ 와 같음
|
||||
assert m["M"] == 100 and s["S"] == 15
|
||||
|
||||
|
||||
def _rate_m_rows():
|
||||
files = server.read_project_files(str(STC))
|
||||
return server.parse_dbf_bytes(files["RATE_M.DBF"])[1]
|
||||
|
||||
|
||||
def test_rate_m_lookup_against_stc_table():
|
||||
rows = _rate_m_rows()
|
||||
cases = [
|
||||
{"scale": 40e8, "kongType": 0, "ilban": 0, "kikan": 1},
|
||||
{"scale": 100e8, "kongType": 3, "ilban": 0, "kikan": 2},
|
||||
{"scale": 500e8, "kongType": 0, "ilban": 1, "kikan": 0},
|
||||
{"scale": 10e8, "kongType": 5, "ilban": 0, "kikan": -1},
|
||||
]
|
||||
res = run({"mode": "ratem", "rows": rows, "cases": cases})["out"]
|
||||
want = [(11, 1), (12, 7), (17, 5), (15, 5)] # (줄, 칸) = 규칙 손셈
|
||||
for got, (line, col) in zip(res, want):
|
||||
assert got["cells"]["KANNO"] == [line, col]
|
||||
assert got["rates"]["KANNO"] == server.fnum(rows[line - 1][f"RATE{col}"])
|
||||
assert got["rates"]["ILBAN"] == server.fnum(rows[22]["RATE1"])
|
||||
assert got["rates"]["IYUN"] == server.fnum(rows[23]["RATE0"])
|
||||
assert [g["band"] for g in res] == [0, 1, 2, 0]
|
||||
|
||||
|
||||
def test_set_base_combo_pairs_from_dfm():
|
||||
nodes = json.loads(DFM.read_text(encoding="utf-8"))["nodes"]
|
||||
combo = next(o for o in _walk(nodes) if o.get("name") == "cmBx_Set_Base")
|
||||
p = combo["properties"]
|
||||
want = [[int(v), t] for v, t in zip(p["Values.Strings"], p["Items.Strings"])]
|
||||
got = run({"mode": "ratem", "rows": [], "cases": []})["setBase"]
|
||||
assert got == want
|
||||
|
||||
|
||||
def _walk(x):
|
||||
if isinstance(x, dict):
|
||||
if "name" in x and "properties" in x:
|
||||
yield x
|
||||
for v in x.values():
|
||||
yield from _walk(v)
|
||||
elif isinstance(x, list):
|
||||
for v in x:
|
||||
yield from _walk(v)
|
||||
|
||||
|
||||
def test_api_load_passes_std_market_settings():
|
||||
loaded = server.api_load(server.LoadReq(source_path=str(STC)))
|
||||
files = server.read_project_files(str(STC))
|
||||
prj = server.parse_dbf_bytes(files["PRJLST.DBF"])[1][0]
|
||||
ini = server.parse_ini_bytes(files.get("START8X.INI") or b"")
|
||||
std = loaded["sim_state"]["sysConfig"]["stdMarket"]
|
||||
assert std["acttyp"] == int(server.fnum(prj["ACTTYP"]))
|
||||
assert std["actopt"] == int(server.fnum(prj["ACTOPT"]))
|
||||
assert std["useStored"] == (ini.get("S_JDA", "").strip() == "1")
|
||||
costa = server.parse_dbf_bytes(files["COSTA.DBF"])[1]
|
||||
assert len(loaded["sim_state"]["stdMarketItems"]) == len(costa)
|
||||
assert len(loaded["costa_rows"]) == len(costa)
|
||||
@@ -0,0 +1,34 @@
|
||||
"""STMATE 재현 앱 수량 계산기(wM_Edit_XRate) 반올림 방향 — Q_d = MROUNDUD(x, d, 선택 1).
|
||||
|
||||
근거: REA 30 labor_equipment_quantity_rules.json(0x442f97 일일수량 Q_11 · 0x442fec 적용수량 Q_p · 선택 1)
|
||||
REA 32 §1.1 MROUNDUD(DP_Common 0x454044) — 선택 1 = 첫 버림 자리 ≥ 5 이면 한 단위 올림(0 반대쪽)
|
||||
기대값은 이 규칙의 손셈 — 경계(첫 버림 자리 5)에서 절사·은행가 반올림과 갈림.
|
||||
"""
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
HELPER = Path(__file__).with_name("helper_stmate_smt_tools.cjs")
|
||||
|
||||
|
||||
def call(*calls):
|
||||
payload = [{"fn": f, "args": list(a)} for f, *a in calls]
|
||||
out = subprocess.check_output(
|
||||
["node", str(HELPER)], input=json.dumps(payload), text=True, encoding="utf-8"
|
||||
)
|
||||
return json.loads(out)
|
||||
|
||||
|
||||
def test_applied_quantity_half_rounds_away_from_zero():
|
||||
lab, eq, mid = call(
|
||||
("compute", {"qty1": 8, "cond": "", "hrat": 100, "lqty": 1, "labor": True, "point": 2}),
|
||||
("compute", {"qty1": 64, "cond": "", "hrat": 100, "lqty": 1, "labor": False, "point": 2}),
|
||||
("compute", {"qty1": 16, "cond": "", "hrat": 100, "lqty": 1, "labor": True, "point": 3}),
|
||||
)
|
||||
# 1 ÷ 8 = 0.125 → 2자리 첫 버림 자리 5 → 0.13(절사 0.12 · 은행가 0.12)
|
||||
assert lab["qday"] == 8 and lab["cqty"] == 0.13
|
||||
# 장비 1 × 8 ÷ 64 = 0.125 → 0.13
|
||||
assert eq["cqty"] == 0.13
|
||||
# 1 ÷ 16 = 0.0625 → 3자리 첫 버림 자리 5 → 0.063
|
||||
assert mid["cqty"] == 0.063
|
||||
+36
-10
@@ -333,7 +333,13 @@ const StmateCalc = (() => {
|
||||
const sys = data.sysConfig || {},
|
||||
chnMode = sys.chnMode || "bimok",
|
||||
optOrder = (sys.optOrder || "SML").toUpperCase();
|
||||
const stdMap = Object.fromEntries((data.stdMarketItems || []).map((x) => [x.code, x]));
|
||||
const lookupUnit = (refId) => {
|
||||
const sm = stdMap[refId];
|
||||
if (sm) {
|
||||
const meta = { name: sm.name, code: sm.code, spec: sm.spec || "", unit: sm.unit || "" };
|
||||
return Object.assign(stdMarketUnit(sm, slot, sys.stdMarket || {}), meta);
|
||||
}
|
||||
const r = ilwiMap[refId] || sanMap[refId] || machMap[refId] || resMap[refId];
|
||||
if (!r) return { M: 0, L: 0, S: 0, T: 0, name: "미연결", code: "-", spec: "", unit: "" };
|
||||
const pick = (k, iProp, prop) =>
|
||||
@@ -354,6 +360,7 @@ const StmateCalc = (() => {
|
||||
let directM = 0,
|
||||
directL = 0,
|
||||
directS = 0,
|
||||
directA = 0,
|
||||
govRawTotal = 0,
|
||||
govFeeTotal = 0;
|
||||
// 내역 비율 줄(PR) 밑수 — 표시(PRPT) 줄 금액 누적 · PR 줄을 지나면 비움(영월 조달수수료 4줄 대조)
|
||||
@@ -370,7 +377,7 @@ const StmateCalc = (() => {
|
||||
}
|
||||
const su = slot > 1 && row.units && row.units[slot];
|
||||
const u = su
|
||||
? Object.assign({}, lookupUnit(row.refId), { M: su[0], L: su[1], S: su[2] })
|
||||
? Object.assign({}, lookupUnit(row.refId), { M: su[0], L: su[1], S: su[2], A: 0 })
|
||||
: lookupUnit(row.refId);
|
||||
// 행 고정 단가(fixedUnit) · 내역 할증율(wBoqRate RATE/RM·RL·RS = 비목별 단가 가산, 원 단위 절사)
|
||||
// — 금액 가산(BDQTY X_QTY·X_HAL 은 손료계수 칸 · REA 정정)(07번 §4 · 34번 wBoqRate) · 저장 차수 단가는 이미 반영된 값이라 건너뜀
|
||||
@@ -384,7 +391,8 @@ const StmateCalc = (() => {
|
||||
(c) => pct(c) && (u[c] = Math.trunc(u[c] * Math.fround((100 + pct(c)) / 100))),
|
||||
);
|
||||
}
|
||||
u.T = u.M + u.L + u.S;
|
||||
u.A = num(u.A);
|
||||
u.T = u.M + u.L + u.S + u.A;
|
||||
const qty =
|
||||
Number(
|
||||
slot > 1 && row.qtys
|
||||
@@ -397,16 +405,18 @@ const StmateCalc = (() => {
|
||||
rawL = u.L * qty,
|
||||
rawS = u.S * qty,
|
||||
rawT = u.T * qty;
|
||||
// 넷째 칸 A(표준시장단가 비목 밖 금액) — 다른 비목과 같은 줄 금액 절사 · 합계 T 에 넣음(0x4312ad)
|
||||
let M = roundDown(rawM, 0),
|
||||
L = roundDown(rawL, 0),
|
||||
S = roundDown(rawS, 0),
|
||||
T = M + L + S;
|
||||
A = roundDown(u.A * qty, 0),
|
||||
T = M + L + S + A;
|
||||
// 코드 붙은 % 줄(조달수수료 M%·T%) = 같은 상위 공종 안 앞 말단 줄 비목 합 × 율 → 제 비목(server pct_row_base)
|
||||
if (row.pctBase) {
|
||||
const k = row.pctComp,
|
||||
base = row.pctBase.reduce((a, id) => a + ((doneById[id] || {})[k] || 0), 0);
|
||||
const own = /^L/.test(row.code) ? "L" : /^S/.test(row.code) ? "S" : "M";
|
||||
((M = 0), (L = 0), (S = 0));
|
||||
((M = 0), (L = 0), (S = 0), (A = 0));
|
||||
const amt = roundDown((base * num((row.prQtys || [])[slot - 1])) / 100, 0);
|
||||
if (own === "L") L = amt;
|
||||
else if (own === "S") S = amt;
|
||||
@@ -426,7 +436,7 @@ const StmateCalc = (() => {
|
||||
.filter((k) => got[k] !== { M, L, S }[k])
|
||||
.map((k) => `${k}(+${got[k] - { M, L, S }[k]})`)
|
||||
.join("");
|
||||
((M = got.M), (L = got.L), (S = got.S), (T = M + L + S));
|
||||
((M = got.M), (L = got.L), (S = got.S), (T = M + L + S + A));
|
||||
}
|
||||
}
|
||||
doneById[row.id] = { M, L, S, T };
|
||||
@@ -437,7 +447,7 @@ const StmateCalc = (() => {
|
||||
((prBase.M += M), (prBase.L += L), (prBase.S += S));
|
||||
if (row.rowType === "gov_mat") govRawTotal += T;
|
||||
else if (row.rowType === "gov_fee") govFeeTotal += T;
|
||||
else ((directM += M), (directL += L), (directS += S));
|
||||
else ((directM += M), (directL += L), (directS += S), (directA += A));
|
||||
const out = Object.assign({}, row, {
|
||||
spec: row.spec || u.spec || "",
|
||||
unit: row.unit || u.unit || "",
|
||||
@@ -451,13 +461,14 @@ const StmateCalc = (() => {
|
||||
sUnit: u.S,
|
||||
tUnit: u.T,
|
||||
};
|
||||
const u2 = { mAmt: M, lAmt: L, sAmt: S, tAmt: T, M, L, S, T, optimizDiff, optimizTarget };
|
||||
const u2 = { mAmt: M, lAmt: L, sAmt: S, aAmt: A, tAmt: T, M, L, S, A, T };
|
||||
Object.assign(u2, { aUnit: u.A, optimizDiff, optimizTarget });
|
||||
return Object.assign(out, u1, u2, { aggM, aggL, aggS, aggT: aggM + aggL + aggS });
|
||||
});
|
||||
const directT = directM + directL + directS,
|
||||
const directT = directM + directL + directS + directA,
|
||||
govCombinedRaw = govRawTotal + govFeeTotal;
|
||||
const totals = Object.assign(
|
||||
{ directM, directL, directS, directT },
|
||||
{ directM, directL, directS, directA, directT },
|
||||
{ govRawTotal, govMatTotal: govRawTotal, govFeeTotal, govCombinedRaw },
|
||||
);
|
||||
return Object.assign({ rows, directTotal: directT, totals }, totals);
|
||||
@@ -508,6 +519,21 @@ const StmateCalc = (() => {
|
||||
return Object.assign(out, { T: out.L + out.M + out.S + out.N });
|
||||
}
|
||||
|
||||
// 표준시장단가 코드(A · COSTA) 한 칸 단가 — 단가 읽기 Main 0x430c60(A 줄 = COSTA 자료집합 · 0x437a4b)
|
||||
// S_JDA(Start8x.Ini · 설정 +0x7c8) 참 = 저장 LAMTn·MAMTn·SAMTn 그대로 · 거짓 = AAMTn 을 RATE_L 로 나눔(splitStdMarket)
|
||||
// ACTTYP·ACTOPT = PRJLST 값(로더 0x45c938 → 공사 레코드 +0x172c·+0x1730) · 넷째 칸 A = 비목 밖 금액(합계엔 포함)
|
||||
// item: { aamt[1..4], rateL, lamtR[1..4], stored: { L, M, S }[1..4] } · cfg: { acttyp, actopt, useStored }
|
||||
function stdMarketUnit(item, slot = 1, cfg = {}) {
|
||||
const at = (arr) => num((arr || [])[slot - 1]);
|
||||
const st = (item && item.stored) || {};
|
||||
if (cfg.useStored) {
|
||||
const [L, M, S] = ["L", "M", "S"].map((k) => at(st[k]));
|
||||
return { L, M, S, A: 0, T: L + M + S };
|
||||
}
|
||||
const sp = splitStdMarket(at(item.aamt), item.rateL, at(item.lamtR), cfg.acttyp, cfg.actopt);
|
||||
return { L: sp.L, M: sp.M, S: sp.S, A: sp.N, T: sp.T };
|
||||
}
|
||||
|
||||
function evalKOrdTransition(pclass, regMode, flag, currentK) {
|
||||
const K = Number(currentK) || 1;
|
||||
const nextK =
|
||||
@@ -620,7 +646,7 @@ const StmateCalc = (() => {
|
||||
const api = { KINDS, KIND_KEYS, num, fmt, evalFormula, evalLeftToRight };
|
||||
Object.assign(api, { roundDown, roundUp, roundHalfUp, roundBanker });
|
||||
Object.assign(api, { evalWageFormulaLeftToRight, evalQFormula, evalKOrdTransition });
|
||||
Object.assign(api, { optimizParts, splitStdMarket });
|
||||
Object.assign(api, { optimizParts, splitStdMarket, stdMarketUnit });
|
||||
return Object.assign(api, { createDefaultState, calculateAll, computeAll: calculateAll });
|
||||
})();
|
||||
|
||||
|
||||
@@ -6,15 +6,22 @@
|
||||
* 적용수량 = 일일수량 0 이면 0 · 아니면 Qp(조수량 × (노무 1 · 장비 8) ÷ 일일수량)
|
||||
* 자동 자리 = 기준수량 정수부 자릿수 + 1 (2~6 사이로 묶음) · 일일수량이 아니라 기준수량을 봄
|
||||
* 조건식 = 빈칸 걷은 뒤 * + - . / 0~9 ^ 만 허용(괄호 없음) · 빈 식 = 1
|
||||
* Q_d = DP_Common.MROUNDUD(x, d, 1) — 반올림 방향 미확정(REA 15 · 14) · 여기서는 반올림으로 둠(가정)
|
||||
* Q_d = DP_Common.MROUNDUD(x, d, 1) — 선택 1 = 첫 버림 자리 ≥ 5 이면 한 단위 올림(0 반대쪽 · 사사오입)
|
||||
* 근거: REA 32 §1.1(DP_Common 0x454044 · 0x4544f0 올림 판정) · 원형 = exec_calc.js mroundud(한 벌)
|
||||
*/
|
||||
const StmateXRate = (() => {
|
||||
const EV = () =>
|
||||
(typeof window !== "undefined" && window.STMATE_SMT_EVAL) ||
|
||||
(typeof require !== "undefined" ? require("./smt_eval.js") : null);
|
||||
|
||||
// 반올림(가정) — 이진 오차를 십진 자리로 맞춤
|
||||
const EX = () =>
|
||||
(typeof window !== "undefined" && window.STMATE_EXEC) ||
|
||||
(typeof require !== "undefined" ? require("./exec_calc.js") : null);
|
||||
|
||||
// Q_d = MROUNDUD(v, d, 1) — 원형(exec_calc) 이 안 실렸으면 같은 방향(사사오입 · 0 반대쪽)으로
|
||||
function q(v, d) {
|
||||
const ex = EX();
|
||||
if (ex && ex.mroundud) return ex.mroundud(v, d, 1);
|
||||
const f = 10 ** d,
|
||||
r = Math.floor(Math.abs(Number(v) || 0) * f + 0.5 + 1e-9) / f;
|
||||
return v < 0 ? -r : r;
|
||||
|
||||
@@ -63,7 +63,34 @@ const STMATE_KANJUB_NATIVE = (() => {
|
||||
const bf = on && Number(keys.I_KUNBO) !== 1 && Number(keys.I_YUNBO) !== 1 ? 1 : 0;
|
||||
return { I_ANJUNAUTO: on ? 2 : 1, I_BF_CH_BO: bf };
|
||||
}
|
||||
return { chasuList, firstSeries, chgGate, CHG_ITEMS, changeDefaults };
|
||||
// 적용기준 I_SET_BASE — cmBx_Set_Base(TWM_KANJUB.dfm) Items 순번 ↔ Values · 저장 = TwCombo.GetInteger = Values 값
|
||||
// (같은 GetInteger 로 읽는 공사종류·건설기계 구분을 원본이 8·9·−1 값으로 비교 — 순번이면 나올 수 없는 값)
|
||||
const SET_BASE = [
|
||||
[2, "일반(국가계약법)"],
|
||||
[0, "일반(지방계약법)"],
|
||||
[1, "행자부기준"],
|
||||
];
|
||||
// 행자부기준(SET_BASE 1) 요율 조회 — ST_KanJub 0x47a1bc(0x47acd8~0x47b100) · RATE_M(JB_M) 줄 = Go 번호(1부터)
|
||||
// 규모 b = 밑수 < 50억 → 0 · < 300억 → 1 · 그 밖 2(G[2]·G[3] · 밑수 = RATE_R 조회와 같은 원가 칸 0x4e4260)
|
||||
// 간접노무비 = 공사종류 < 5 · I_ILBAN ≠ 1 → 줄 b+11 · 칸 RATE{기간 + (공사종류 1·3 이면 5)}
|
||||
// I_ILBAN 1 또는 공사종류 ≥ 5 → 줄 b+15 · 칸 RATE{기간+5} (기간 = max(0, 화면순번−1))
|
||||
// 일반관리비 = 줄 23 RATE1 · 이윤 = 줄 24 RATE0 · 그 밖 요율은 RATE_R 그대로
|
||||
// rows: RATE_M 행(1번 줄 = rows[0]) · o: { scale, kongType, ilban, kikan }
|
||||
function rateMLookup(rows, o = {}) {
|
||||
const n = (v) => Number(v) || 0;
|
||||
const at = (line, col) => n(((rows || [])[line - 1] || {})[`RATE${col}`]);
|
||||
const b = n(o.scale) < 50e8 ? 0 : n(o.scale) < 300e8 ? 1 : 2;
|
||||
const kt = n(o.kongType),
|
||||
kik = Math.max(0, n(o.kikan));
|
||||
const wide = n(o.ilban) === 1 || kt >= 5;
|
||||
const line = b + (wide ? 15 : 11),
|
||||
col = kik + (wide || kt === 1 || kt === 3 ? 5 : 0);
|
||||
const cells = { KANNO: [line, col], ILBAN: [23, 1], IYUN: [24, 0] };
|
||||
const rates = Object.fromEntries(Object.entries(cells).map(([k, [r, c]]) => [k, at(r, c)]));
|
||||
return { band: b, rates, cells };
|
||||
}
|
||||
const out = { chasuList, firstSeries, chgGate, CHG_ITEMS, changeDefaults };
|
||||
return Object.assign(out, { SET_BASE, rateMLookup });
|
||||
})();
|
||||
|
||||
const StmateKanjubParts = ({ num, fmt, roundDown, roundUp, roundBanker }) => {
|
||||
|
||||
@@ -491,6 +491,37 @@ def api_load(req: LoadReq):
|
||||
c for c in (conld[i : i + 6].strip() for i in range(0, len(conld), 6)) if c
|
||||
)
|
||||
sim_state["sysConfig"]["rxFormula"] = ini.get("RXXNM") or sim_state["sysConfig"]["rxFormula"]
|
||||
# 표준시장단가(A 코드 · COSTA.DBF) — 노무비율 나눔 설정 = PRJLST ACTTYP·ACTOPT(Main 0x45c938) ·
|
||||
# S_JDA 참 = 저장 단가 그대로(설정 +0x7c8 · 기본 거짓) — calc.stdMarketUnit
|
||||
costa_rows = parse_dbf_bytes(files["COSTA.DBF"])[1] if "COSTA.DBF" in files else []
|
||||
prj0 = prj_rows[0] if prj_rows else {}
|
||||
sim_state["sysConfig"]["stdMarket"] = {
|
||||
"acttyp": int(fnum(prj0.get("ACTTYP"))),
|
||||
"actopt": int(fnum(prj0.get("ACTOPT"))),
|
||||
"useStored": str(ini.get("S_JDA", "")).strip().upper() in ("1", "T", "TRUE", "Y"),
|
||||
}
|
||||
std_items = [
|
||||
{
|
||||
"id": (r.get("CODE") or "").strip(),
|
||||
"code": (r.get("CODE") or "").strip(),
|
||||
"name": r.get("NAME") or "",
|
||||
"spec": r.get("SIZE") or "",
|
||||
"unit": r.get("UNIT") or "",
|
||||
"aamt": [fnum(r.get(f"AAMT{n}")) for n in range(1, 5)],
|
||||
"rateL": fnum(r.get("RATE_L")),
|
||||
"lamtR": [fnum(r.get(f"LAMT{n}_R")) for n in range(1, 5)],
|
||||
"stored": {c: [fnum(r.get(f"{c}AMT{n}")) for n in range(1, 5)] for c in "LMS"},
|
||||
}
|
||||
for r in costa_rows
|
||||
if (r.get("CODE") or "").strip()
|
||||
]
|
||||
sim_state["stdMarketItems"] = std_items
|
||||
# 내역의 A 줄은 COSTA 로 계산 — 저장 단가로 만든 임시 일위대가·자원은 걷음
|
||||
std_codes = {x["code"] for x in std_items}
|
||||
sim_state["ilwiItems"] = [x for x in sim_state["ilwiItems"] if x["id"] not in std_codes]
|
||||
sim_state["resources"] = [
|
||||
x for x in sim_state["resources"] if str(x["id"]).rsplit("_", 1)[0] not in std_codes
|
||||
]
|
||||
return {
|
||||
"source_path": req.source_path,
|
||||
"boq_table_name": boq_name,
|
||||
@@ -510,6 +541,7 @@ def api_load(req: LoadReq):
|
||||
"start_ini": ini,
|
||||
"sim_state": sim_state,
|
||||
**extra_tables(files),
|
||||
"costa_rows": costa_rows, # 암호 표도 풀어 읽은 행(smt_engine A 줄 단가)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,17 +13,51 @@
|
||||
// 낙찰률(NAGCD) 단가는 2칸 원단가로 산근을 셈 — 1칸은 원단가 × 낙찰률
|
||||
const costSlot = (r) => (num(r.NAGCD) > 0 ? 2 : 1);
|
||||
|
||||
// 표준시장단가(A) 줄 단가 설정 — PRJLST ACTTYP·ACTOPT(로더 0x45c938) · Start8x.Ini S_JDA(설정 +0x7c8, 기본 거짓)
|
||||
const iniBool = (v) =>
|
||||
["1", "T", "TRUE", "Y"].includes(
|
||||
String(v ?? "")
|
||||
.trim()
|
||||
.toUpperCase(),
|
||||
);
|
||||
function stdMarketCfg(ctx) {
|
||||
const d = ctx.dbfData || {},
|
||||
prj = d.prjlst || {};
|
||||
const useStored = iniBool((d.start_ini || {}).S_JDA);
|
||||
return { acttyp: num(prj.ACTTYP), actopt: num(prj.ACTOPT), useStored };
|
||||
}
|
||||
// COSTA 행 → calc.stdMarketUnit 꼴(AAMTn · RATE_L · LAMTn_R · 저장 LAMTn·MAMTn·SAMTn)
|
||||
const ns = [1, 2, 3, 4];
|
||||
const stdItem = (r) => ({
|
||||
aamt: ns.map((n) => num(r[`AAMT${n}`])),
|
||||
rateL: num(r.RATE_L),
|
||||
lamtR: ns.map((n) => num(r[`LAMT${n}_R`])),
|
||||
stored: Object.fromEntries(
|
||||
"LMS".split("").map((k) => [k, ns.map((n) => num(r[`${k}AMT${n}`]))]),
|
||||
),
|
||||
});
|
||||
|
||||
function costnLookup(ctx) {
|
||||
const byCode = {};
|
||||
const byCode = {},
|
||||
byA = {};
|
||||
((ctx.dbfData && ctx.dbfData.costn_rows) || []).forEach((r) => (byCode[rowCode(r)] = r));
|
||||
((ctx.dbfData && ctx.dbfData.costa_rows) || []).forEach((r) => (byA[rowCode(r)] = r));
|
||||
const smCfg = stdMarketCfg(ctx);
|
||||
const lookup = (code) => {
|
||||
// A 줄 = COSTA 에서 읽어 노무비율로 나눔(Main 0x437a4b → 0x430c60 → 0x45a468) · 넷째 칸 A 는 구성 합계 밖
|
||||
const a = code && code[0] === "A" && !byCode[code] ? byA[code] : null;
|
||||
if (a) {
|
||||
const u = Calc.stdMarketUnit(stdItem(a), 1, smCfg);
|
||||
const meta = { unit: String(a.UNIT || "").trim(), name: String(a.NAME || "") };
|
||||
return Object.assign({ M: u.M, L: u.L, S: u.S, A: u.A }, meta);
|
||||
}
|
||||
const r = byCode[code];
|
||||
if (!r) return null;
|
||||
const s = costSlot(r);
|
||||
const out = { M: num(r[`MAMT${s}`]), L: num(r[`LAMT${s}`]), S: num(r[`SAMT${s}`]) };
|
||||
return Object.assign(out, { unit: String(r.UNIT || "").trim(), name: String(r.NAME || "") });
|
||||
};
|
||||
return { byCode, lookup };
|
||||
return { byCode, byA, lookup };
|
||||
}
|
||||
|
||||
// 결과금액조정(COSTN S_ADJ · ADJ_M/L/S) — 표시된 것만
|
||||
@@ -61,13 +95,15 @@
|
||||
const digitOf = (v, def = 1) => (/^[0-2]$/.test(String(v ?? "").trim()) ? Number(v) : def);
|
||||
|
||||
// 외산장비 환율 — 단가의 조사시점(ARENM 1 당초 · 2 변경)의 EXLNM·EXHNM·EXEUR·EXYEN(REA 14 cmBx_ARE)
|
||||
// 키가 없으면 로더 기본 "1000.00"(Main 0x42b0xx [EQUIPMENT])
|
||||
function fxOf(ini) {
|
||||
const n = String(ini.ARENM || "1").trim() === "2" ? 2 : 1;
|
||||
const v = (k) => (ini[k] == null || String(ini[k]).trim() === "" ? 1000 : num(ini[k]));
|
||||
return {
|
||||
usd: num(ini[`EXLNM${n}`]),
|
||||
usdHigh: num(ini[`EXHNM${n}`]),
|
||||
eur: num(ini[`EXEUR${n}`]),
|
||||
yen: num(ini[`EXYEN${n}`]),
|
||||
usd: v(`EXLNM${n}`),
|
||||
usdHigh: v(`EXHNM${n}`),
|
||||
eur: v(`EXEUR${n}`),
|
||||
yen: v(`EXYEN${n}`),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -163,6 +199,8 @@
|
||||
rx: ini.RXXNM || sys.rxFormula,
|
||||
usdRate: num(ini.EXLNM1),
|
||||
fx: fxOf(ini),
|
||||
// 환율 적용 범위 EXRNM([EQUIPMENT] · 설정 +0x7c9 · 기본 거짓) — 참이면 S 줄 단가를 천원으로 미리 환산(0x437aa2)
|
||||
exrnm: iniBool(ini.EXRNM),
|
||||
// 줄 금액 자리 = 중기 KCD · 일위대가 BPN · 중기 노임 단가 JCD · $장비 단가 ECD(22 §3.4 · REA 14 안내문)
|
||||
lineDigits: digitOf(code[0] === "X" ? ini.KCDNM : ini.BPNNM),
|
||||
// JCD 빈칸 기본 = KCD 2 이면 2 · 아니면 0(Main 0x42ab08)
|
||||
|
||||
@@ -397,9 +397,10 @@ const StmateSmtEval = (() => {
|
||||
// opts.fx = { usd, usdHigh, eur, yen } · 옛 opts.usdRate 는 usd 로 봄
|
||||
function foreignUnit(unit, price, opts) {
|
||||
const fx = opts.fx || { usd: opts.usdRate };
|
||||
// $·$ = 단가 10만 미만 EXL · 그 밖 EXH(Main 0x437caa~0x437d45 · 고액 환율이 안 주어진 옛 호출만 EXL)
|
||||
const rate =
|
||||
unit === "$"
|
||||
? Number(price) >= 100000 && Number(fx.usdHigh) > 0
|
||||
unit === "$" || unit === "$"
|
||||
? Number(price) >= 100000 && fx.usdHigh != null
|
||||
? fx.usdHigh
|
||||
: fx.usd
|
||||
: unit === "€"
|
||||
@@ -467,7 +468,12 @@ const StmateSmtEval = (() => {
|
||||
p = { M: 0, L: hourlyWage(r.L, rx, Number(opts.wageDigits) || 0), S: 0 };
|
||||
}
|
||||
const fxRate = foreignUnit(unit, r.M + r.L + r.S, opts);
|
||||
if (fxRate !== null)
|
||||
// EXRNM 참 — S 줄만 단가 = MROUNDUD(단가 × 환율/1000, ECD, 0)(천원 · ECD 자리 버림 · Main 0x437aa2~0x437df2)
|
||||
// 거짓 — 원본은 상위 B·천원 줄 수량 칸에 환율/1000 을 넣는 다른 경로(0x435660) · 여기는 옛 환산 유지(미확인)
|
||||
if (fxRate !== null && opts.exrnm) {
|
||||
if (code[0] === "S")
|
||||
p = Object.assign({}, p, { S: trunc((p.S * fxRate) / 1000, Number(opts.fxDigits) || 0) });
|
||||
} else if (fxRate !== null)
|
||||
for (const k of "MLS")
|
||||
p[k] =
|
||||
opts.fxDigits == null
|
||||
|
||||
Reference in New Issue
Block a user