feat(est): reproduce native tables and calculations

This commit is contained in:
2026-11-05 06:07:05 +09:00
parent 646eab6245
commit 60ccedcd9a
30 changed files with 5249 additions and 22 deletions
+73
View File
@@ -0,0 +1,73 @@
// REA: 932984 (10^4 정수), 93281c (실수), 4037e8 (FPU Round).
const EstMath = (() => {
const components = ["NC", "GC", "JC", "SC"];
const units = ["NU", "GU", "JU", "SU"];
const num = (value) => (value == null || value === "" ? 0 : Number(value));
const sum = (row) => components.reduce((n, key) => n + num(row[key]), 0);
function even(value) {
const sign = Math.sign(value),
a = Math.abs(value),
i = Math.floor(a),
f = a - i;
return sign * (f > 0.5 ? i + 1 : f < 0.5 ? i : i % 2 ? i + 1 : i);
}
function half(value) {
return Math.trunc(value) + Math.trunc((value - Math.trunc(value)) * 2);
}
function mode(value, method) {
if (method === 1) return half(value);
if (method === 3) return half(value + 0.4);
return Math.trunc(value);
}
function fixed(value, digits = 0, method = 2) {
const v = even(value * 10000),
k = 10 ** digits;
return mode((v * k) / 10000, method) / k;
}
function floating(value, digits = 0, method = 2) {
const k = 10 ** digits;
return mode((value + Math.sign(value) * 2e-10) * k, method) / k;
}
function precision(row, fallback = 0) {
return num(row.DigetIndex)
? { digits: Math.max(0, num(row.Diget) - 1), method: num(row.DigetIndex) }
: { digits: fallback, method: 2 };
}
function amounts(row, digits = 0, totalFit = false) {
if ([1, 3].includes(num(row.CalcIndex))) return row;
const q = num(row.GN) / (["%", "%"].includes(row.Unite) ? 100 : 1);
const p = precision(row, digits),
raw = units.map((key) => num(row[key]) * q);
components.forEach((key, i) => (row[key] = fixed(raw[i], p.digits, p.method)));
row.TU = units.reduce((n, key) => n + num(row[key]), 0);
if (totalFit) {
const step = 10 ** -p.digits,
target = fixed(
raw.reduce((a, b) => a + b, 0),
p.digits,
p.method,
);
let difference = Math.round((target - sum(row)) / step);
const order = components
.map((key, i) => ({ key, remainder: raw[i] - row[key] }))
.sort((a, b) => (difference >= 0 ? b.remainder - a.remainder : a.remainder - b.remainder));
for (let i = 0; difference && i < 100; i++) {
row[order[i % 4].key] += Math.sign(difference) * step;
difference -= Math.sign(difference);
}
}
row.TC = sum(row);
return row;
}
function add(rows, predicate = (row) => num(row.CalcIndex) < 2) {
const result = Object.fromEntries(
components.map((key) => [
key,
floating(rows.filter(predicate).reduce((n, row) => n + num(row[key]), 0)),
]),
);
result.TC = sum(result);
return result;
}
return { components, units, num, sum, even, half, fixed, floating, precision, amounts, add };
})();