const EstResources = (() => { const { num, components } = EstMath; function calculate(input) { const project = EstNative.calculate({ ...structuredClone(input), options: { ...input.options, SourceRefresh: 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 = 0) { 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, }; row.quantity += quantity; row.amount += 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; for (const row of group.rows.slice(1)) { if (num(row.CalcIndex) >= 2 || [51, 52, 58, 62, 68].includes(num(row.LinkIndex))) continue; const quantity = (multiplier * num(row.GN) * rate) / (["%", "%"].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)); } 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; expand(num(row.LinkIndex), row.Code, num(row.GN), []); } const rows = [...output.values()]; for (const row of rows) if (row.kind === 105 && row.amount) { const price = num(tables.MachTitleDat.find((r) => r.Code === row.Code)?.TC); if (price) { row.quantity += row.amount / price; row.Unite = "HR"; } else { row.Unite = "제외금액"; row.quantity = 0; } } return { rows, errors: [...new Set(errors)] }; } return { calculate }; })();