// PAIRS: indices into VARS array [0=안정성, 1=수익_가능성, 2=자금_효율성, 3=사업_계획_완성도, 4=사회적_가치] const AHP_PAIRS = [ [0,1],[0,2],[0,3],[0,4], [1,2],[1,3],[1,4], [2,3],[2,4], [3,4] ]; function buildMatrix(pairwiseResults) { const n = 5; const matrix = Array.from({length: n}, () => Array(n).fill(1)); AHP_PAIRS.forEach(([i, j], idx) => { const val = pairwiseResults[idx]; if (val >= 1) { matrix[i][j] = val; matrix[j][i] = 1 / val; } else { matrix[j][i] = Math.abs(val); matrix[i][j] = 1 / Math.abs(val); } }); return matrix; } function powerMethod(matrix, maxIter = 1000, threshold = 1e-6) { const n = matrix.length; let v = Array(n).fill(1 / n); for (let iter = 0; iter < maxIter; iter++) { const Av = Array(n).fill(0); for (let i = 0; i < n; i++) for (let j = 0; j < n; j++) Av[i] += matrix[i][j] * v[j]; const sum = Av.reduce((a, b) => a + b, 0); const vNew = Av.map(x => x / sum); const maxDiff = Math.max(...vNew.map((x, k) => Math.abs(x - v[k]))); v = vNew; if (maxDiff < threshold) break; } return v; } function calcConsistency(matrix, weights) { const n = matrix.length; const RI = [0, 0, 0.58, 0.90, 1.12, 1.24, 1.32, 1.41, 1.45]; const Aw = Array(n).fill(0); for (let i = 0; i < n; i++) for (let j = 0; j < n; j++) Aw[i] += matrix[i][j] * weights[j]; const lambdaMax = Aw.reduce((s, v, i) => s + v / weights[i], 0) / n; const CI = (lambdaMax - n) / (n - 1); const CR = CI / RI[n]; return { lambdaMax, CI, CR }; } function calcModelScore(caseData, weights) { return VARS.reduce((sum, varKey, i) => sum + caseData[varKey] * weights[i], 0); } // Slider positions -4 to +4 map to AHP odd values 1,3,5,7,9 // pos=0 → 1 (equal) // pos<0 → left more important, AHP value = 2*|pos|+1 (1,3,5,7,9) // pos>0 → right more important, stored as negative: -(2*pos+1) function sliderToStored(sliderPos) { if (sliderPos === 0) return 1; if (sliderPos < 0) return 2 * Math.abs(sliderPos) + 1; return -(2 * sliderPos + 1); } function storedToSlider(val) { if (val === 1) return 0; if (val > 1) return -((val - 1) / 2); // left was important return (Math.abs(val) - 1) / 2; // right was important } function ahpValueToScale(absVal) { // absVal is 2-9 const levels = { 2: '2', 3: '3', 4: '4', 5: '5', 6: '6', 7: '7', 8: '8', 9: '9' }; return absVal; } function runAHP(pairwiseRaw) { const matrix = buildMatrix(pairwiseRaw); const weights = powerMethod(matrix); const { lambdaMax, CI, CR } = calcConsistency(matrix, weights); return { weights, lambdaMax, CI, CR, matrix }; }