feat(est): reproduce native tables and calculations
This commit is contained in:
@@ -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 };
|
||||
})();
|
||||
Reference in New Issue
Block a user