Files
frontend/apps/wr/components/lib/func/calculateConstCost .tsx
T

102 lines
2.6 KiB
TypeScript

export const findBounds = (
data: any[],
fctCd: string,
dataCode: string,
qtyCode:string,
qty: number
): { lower: any; upper: any } => {
const filtered = data.filter((item) => item[dataCode] === fctCd);
const lowers = filtered.filter((item) => Number(item[qtyCode]) <= qty);
const uppers = filtered.filter((item) => Number(item[qtyCode]) > qty);
const lower =
lowers.length > 0
? lowers.reduce((acc, curr) =>
Number(curr[qtyCode]) > Number(acc[qtyCode]) ? curr : acc
)
: undefined;
const upper =
uppers.length > 0
? uppers.reduce((acc, curr) =>
Number(curr[qtyCode]) < Number(acc[qtyCode]) ? curr : acc
)
: undefined;
// ✅ 바운더리 하나만 있을 경우 대체 처리
if (!lower && upper) return { lower: upper, upper };
if (!upper && lower) return { lower, upper: lower };
// ✅ 정상 보간 구간
if (lower && upper) return { lower, upper };
// ❌ 둘 다 없을 경우 (fctCd 필터 결과가 없음)
throw new Error(`No matching bounds found for fctCd: ${fctCd}, qty: ${qty}`);
};
// (기울기) a = (y2 - y1) / (x2 - x1)
// (절편) b = y1 - a * x1
// ↓
// 결과값 y = a * x + b
export const getInterpolation = (
Upper: { stdCost: number; fctCpc: number },
Lower: { stdCost: number; fctCpc: number },
qtyYear: number
): number => {
const x1 = Number(Lower.fctCpc); // 최소 처리 용량
const y1 = Number(Lower.stdCost); // 최소 공사비/요율
const x2 = Number(Upper.fctCpc); // 최대 처리 용량
const y2 = Number(Upper.stdCost); // 최대 공사비/요율
if (qtyYear <= x1) return y1; // 최소 이하면 y1 반환
if (qtyYear >= x2) return y2; // 최대 이상이면 y2 반환
const slope = (y2 - y1) / (x2 - x1); // 기울기 a
const intercept = y1 - slope * x1; // 절편 b
return slope * qtyYear + intercept; // 보간 계산
};
export const transformAndInterpolate = (
rawData: any,
dmndQtyYear: number
): any => {
const result: any = {};
for (const key in rawData) {
const item = rawData[key];
const range = {
Lower: {
fctCpc: item.lower?.stdCost,
stdCost: item.lower?.rt,
},
Upper: {
fctCpc: item.upper?.stdCost,
stdCost: item.upper?.rt,
},
};
result[key] = getInterpolation(range.Upper, range.Lower, dmndQtyYear);
}
return result;
};
export const getConstFctCode = (fctCd: string) => {
const fctMap: { [key: string]: string } = {
총인처리시설: "001",
염소소독: "002",
UV소독: "003",
전처리시설: "004",
RO: "005",
};
return fctMap[fctCd];
};