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]; };