119 lines
4.4 KiB
JavaScript
119 lines
4.4 KiB
JavaScript
// STMATE 재현 앱 기성 계산(progress_calc.js) — 원본 정적 분석 규칙 시험용 stdin JSON 실행기
|
|
// 입력 { mode, args } → 출력 JSON · 근거: 지식DB STmate/REA 분석/33_기성준공단계_작업자료_20261114
|
|
const Progress = require("../../tools/stmate-test/progress_calc.js");
|
|
|
|
// 합성 계약 기준 — leaves [{id, qty, m, l, s, pct, gov}] · lines [{code, amount}] · direct · contractFinal
|
|
function mkBase(spec) {
|
|
const leaves = spec.leaves.map((x, i) => {
|
|
const amt = {
|
|
mAmt: Math.trunc(x.m * x.qty + 1e-9),
|
|
lAmt: Math.trunc(x.l * x.qty + 1e-9),
|
|
sAmt: Math.trunc(x.s * x.qty + 1e-9),
|
|
};
|
|
amt.tAmt = amt.mAmt + amt.lAmt + amt.sAmt;
|
|
return {
|
|
id: x.id,
|
|
recno: i,
|
|
code: x.id,
|
|
name: x.id,
|
|
spec: "",
|
|
unit: x.pct ? "%" : "식",
|
|
gov: !!x.gov,
|
|
pct: !!x.pct,
|
|
qty: x.qty,
|
|
u: { m: x.m, l: x.l, s: x.s },
|
|
amt,
|
|
};
|
|
});
|
|
const direct =
|
|
spec.direct != null
|
|
? spec.direct
|
|
: leaves.filter((l) => !l.gov).reduce((a, l) => a + l.amt.tAmt, 0);
|
|
const lines = spec.lines.map((l) => ({ code: l.code, label: l.code, amount: l.amount }));
|
|
const ratePct = Object.fromEntries(lines.map((l) => [l.code, (l.amount / direct) * 100]));
|
|
const rates = Object.fromEntries(lines.map((l) => [l.code, ratePct[l.code] / 100]));
|
|
return {
|
|
leaves,
|
|
lines,
|
|
rates,
|
|
ratePct,
|
|
direct,
|
|
kj: { contractFinal: spec.contractFinal || 0 },
|
|
nodes: [],
|
|
};
|
|
}
|
|
|
|
const MODES = {
|
|
cap: ({ cases }) => cases.map((c) => Progress.capCur(c[0], c[1], c[2], c[3])),
|
|
jab: ({ spec, cur, opt, prev, accDirect }) =>
|
|
Progress.jabFor(mkBase(spec), cur, opt || {}, prev || null, accDirect),
|
|
run: ({ spec, rounds, seed }) => Progress.run(mkBase(spec), rounds, seed),
|
|
store({ spec, rounds }) {
|
|
const base = mkBase(spec);
|
|
const all = Progress.run(base, rounds);
|
|
const st = Progress.toStorage(base, all[0]);
|
|
const rows = st.boq.map((u) => Object.assign({}, u));
|
|
const fs = Progress.fromStorage(base, rows, st.prjlst, st.smt);
|
|
// 제 1 회 저장본을 「전회」로 다시 읽어 제 2 회를 셈 — STmate 회차 생성(전회<-누계, 금회=0)과 같은 흐름
|
|
const seedRows = st.boq.map((u) =>
|
|
Object.assign({}, u, {
|
|
QTY3: u.QTY2,
|
|
QTY4: 0,
|
|
M_AMT3: u.M_AMT2,
|
|
L_AMT3: u.L_AMT2,
|
|
S_AMT3: u.S_AMT2,
|
|
T_AMT3: u.T_AMT2,
|
|
}),
|
|
);
|
|
const smt3 = Object.fromEntries(
|
|
Object.entries(st.smt["2_KANJUB"]).map(([k, v]) => [k.replace(/^2_/, "3_"), v]),
|
|
);
|
|
const fs2 = Progress.fromStorage(base, seedRows, { K_ORD: 2 }, smt3);
|
|
const next = Progress.run(base, [rounds[1]], fs2.seed);
|
|
// 원본 회차 등록 규칙(nextRound)으로 만든 저장본에서 다시 읽은 제 2 회
|
|
const nr = Progress.nextRound(st);
|
|
const fs3 = Progress.fromStorage(
|
|
base,
|
|
nr.boq,
|
|
nr.prjlst,
|
|
Object.assign({}, ...Object.values(nr.smt)),
|
|
);
|
|
const next2 = Progress.run(base, [rounds[1]], fs3.seed);
|
|
return { all, st, fs, fs2, next, nr, next2 };
|
|
},
|
|
// 실제 STC(설계 판) → 계약 기준 → 회차 → 저장 형식
|
|
real({ load, opts, rounds }) {
|
|
const Calc = require("../../tools/stmate-test/calc.js");
|
|
const Change = require("../../tools/stmate-test/change_calc.js");
|
|
const Contract = require("../../tools/stmate-test/contract_calc.js");
|
|
const state = load.sim_state;
|
|
const comp = Calc.calculateAll(state);
|
|
const tree = Change.buildTree(load.boq_rows, state, comp, [1]);
|
|
const conv = Contract.convert(tree, opts, 1, null);
|
|
const kj = Contract.contractKanjub(conv, state.kanjubStages[1] || state.kanjubConfig);
|
|
const base = Progress.contractBase(conv, kj);
|
|
const all = Progress.run(base, rounds);
|
|
const last = all[all.length - 1];
|
|
const st = Progress.toStorage(base, last);
|
|
const lv = Progress.aggregate(base, last, 3).map((nd) => nd.level);
|
|
return {
|
|
direct: base.direct,
|
|
lines: base.lines.map((l) => [l.code, l.amount]),
|
|
cur: all.map((r) => r.totals.cur),
|
|
accT: all.map((r) => r.totals.acc.tAmt),
|
|
rounds: all.map((r) => r.jab),
|
|
st,
|
|
lv,
|
|
gov: base.leaves.map((l) => l.gov),
|
|
};
|
|
},
|
|
};
|
|
|
|
let buf = "";
|
|
process.stdin.setEncoding("utf8");
|
|
process.stdin.on("data", (d) => (buf += d));
|
|
process.stdin.on("end", () => {
|
|
const inp = JSON.parse(buf);
|
|
process.stdout.write(JSON.stringify(MODES[inp.mode](inp.args || {})));
|
|
});
|