Files
Aislo/tools/est-test/native-resources.js
T

128 lines
4.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const EstResources = (() => {
const { num, components } = EstMath;
function calculate(input) {
const project = EstNative.calculate({
...structuredClone(input),
options: { ...input.options, ResourceTracing: true },
});
const tables = project.tables,
heads = EstNative.groups(tables.HeadMainDat),
costs = EstNative.groups(tables.CostMainDat),
output = new Map(),
errors = [...project.calculation.errors];
function record(kind, code, quantity, amount = null) {
const source = (tables[EstNative.sourceTables[kind]] || []).find((row) => row.Code === code);
if (!source) {
errors.push(`동원 원천 없음: ${kind}/${code}`);
return;
}
const id = `${kind}:${code}`;
const row = output.get(id) || {
Code: code,
Name: source.Name,
Size: source.Size,
Unite: source.Unite,
kind,
quantity: 0,
amount: 0,
amountForHours: 0,
};
row.quantity += quantity;
row.amount += amount ?? num(source.TC) * quantity;
if (kind === 105 && quantity === 0 && amount !== null) row.amountForHours += amount;
output.set(id, row);
}
function expand(kind, code, multiplier, path) {
const id = `${kind}:${code}`;
if (path.includes(id)) {
errors.push(`동원 순환 참조: ${id}`);
return;
}
if (kind === 104) {
const group = costs.get(code);
if (!group) {
errors.push(`산근 없음: ${code}`);
return;
}
for (const row of group.rows) {
if (!row.ResourceCode || row.ResourceFactor == null) continue;
if ([103, 104].includes(num(row.ResourceKind)))
expand(num(row.ResourceKind), row.ResourceCode, multiplier * num(row.ResourceFactor), [
...path,
id,
]);
else if (num(row.ResourceKind) === 105)
record(105, row.ResourceCode, 0, multiplier * num(row.TC));
else
record(
num(row.ResourceKind),
row.ResourceCode,
multiplier * num(row.ResourceFactor),
multiplier * num(row.TC),
);
}
return;
}
if (kind === 103) {
const group = heads.get(code);
if (!group) {
errors.push(`일위 없음: ${code}`);
return;
}
let rate = 1;
const bid = group.rows.find((row) => num(row.LinkIndex) === 52);
if (bid) rate = num(bid.GN) / 100;
const conversion = group.rows.find((row) => num(row.LinkIndex) === 68);
if (conversion)
rate *= num(conversion.GN) / (["%", "%"].includes(conversion.Unite) ? 100 : 1);
for (const row of group.rows.slice(1)) {
if (num(row.CalcIndex) >= 2 || [51, 52, 58, 62, 68].includes(num(row.LinkIndex)))
continue;
const source = tables[EstNative.sourceTables[num(row.LinkIndex)]]?.find(
(r) => r.Code === row.Code,
);
const unitRatio = row.ApplyNacChal && num(source?.TC) ? num(row.TU) / num(source.TC) : 1;
const quantity =
(multiplier * num(row.GN) * rate * unitRatio) /
(["%", "%"].includes(row.Unite) ? 100 : 1);
if ([103, 104].includes(num(row.LinkIndex)))
expand(num(row.LinkIndex), row.Code, quantity, [...path, id]);
else if (EstNative.sourceTables[num(row.LinkIndex)])
record(num(row.LinkIndex), row.Code, quantity, multiplier * num(row.TC) * rate);
}
return;
}
record(kind, code, multiplier);
}
for (const row of tables.EstMainDat) {
if (num(row.LinkIndex) === 54) break;
if (
num(row.Level) > 0 ||
num(row.CalcIndex) >= 2 ||
!EstNative.sourceTables[num(row.LinkIndex)]
)
continue;
const source = tables[EstNative.sourceTables[num(row.LinkIndex)]]?.find(
(r) => r.Code === row.Code,
);
const unitRatio = row.ApplyNacChal && num(source?.TC) ? num(row.TU) / num(source.TC) : 1;
expand(num(row.LinkIndex), row.Code, num(row.GN) * unitRatio, []);
}
const rows = [...output.values()];
for (const row of rows)
if (row.kind === 105 && row.amountForHours) {
const price = num(tables.MachTitleDat.find((r) => r.Code === row.Code)?.TC);
if (price) {
row.quantity += row.amountForHours / price;
row.Unite = "HR";
} else {
row.Unite = "제외금액";
row.quantity = 0;
}
}
rows.forEach((row) => delete row.amountForHours);
return { rows, errors: [...new Set(errors)] };
}
return { calculate };
})();