Credit Scoring Model
Understand how financial factors contribute to your credit score.
---
---
Score Factor Analysis
Contribution to Score
How each category's weight impacts the overall score.
Enter Your Financial Data
Adjust Scoring Model Weights
Modify the importance of each factor. Total must equal 100%.
Total Weight: 100%
${scoreCategory}
`; const gaugeCtx = document.getElementById('scoreGaugeChart').getContext('2d'); if(scoreGaugeChart) scoreGaugeChart.destroy(); scoreGaugeChart = new Chart(gaugeCtx, { type: 'doughnut', data: { datasets: [{ data: [finalScore - 300, 850 - finalScore], backgroundColor: [scoreColor, '#e2e8f0'], borderWidth: 0, }] }, options: { rotation: -90, circumference: 180, cutout: '70%', responsive: true, plugins: { legend: { display: false }, tooltip: { enabled: false } } } }); // Factor Analysis document.getElementById('factor-analysis-list').innerHTML = Object.keys(subScores).map(key => { const score = subScores[key]; let impactClass = score > 70 ? 'text-green-600 bg-green-100' : (score > 40 ? 'text-amber-600 bg-amber-100' : 'text-red-600 bg-red-100'); let impactText = score > 70 ? 'Positive' : (score > 40 ? 'Neutral' : 'Negative'); return `
${factorLabels[key]}
${impactText} Impact
`;
}).join('');
// Contribution Chart
const contributionCtx = document.getElementById('contributionChart').getContext('2d');
if(contributionChart) contributionChart.destroy();
contributionChart = new Chart(contributionCtx, {
type: 'pie',
data: {
labels: weightedContributions.map(c => c.label),
datasets: [{
data: weightedContributions.map(c => appData.weights[Object.keys(factorLabels).find(key => factorLabels[key] === c.label)]),
backgroundColor: ['#4338ca', '#6366f1', '#818cf8', '#a5b4fc', '#c7d2fe'],
}]
},
options: { responsive: true, plugins: { legend: { position: 'right' } } }
});
}
// --- EVENT HANDLING ---
document.getElementById('profile-form').addEventListener('input', e => {
appData.profile[e.target.id.replace('-', '')] = parseFloat(e.target.value) || 0;
updateDashboard();
});
document.getElementById('weights-form').addEventListener('input', e => {
const updatedKey = e.target.dataset.key;
const newValue = parseInt(e.target.value);
const oldValue = appData.weights[updatedKey];
const diff = newValue - oldValue;
appData.weights[updatedKey] = newValue;
// Auto-adjust other weights
let total = Object.values(appData.weights).reduce((a, b) => a + b, 0);
if (total !== 100) {
const otherKeys = Object.keys(appData.weights).filter(k => k !== updatedKey);
let remainder = 100 - newValue;
let currentOtherTotal = total - newValue;
otherKeys.forEach(key => {
const proportion = appData.weights[key] / currentOtherTotal;
appData.weights[key] = Math.round(proportion * remainder);
});
// Final check to ensure it sums to 100 due to rounding
total = Object.values(appData.weights).reduce((a, b) => a + b, 0);
if (total !== 100) {
appData.weights[otherKeys[0]] += (100 - total);
}
}
Object.keys(appData.weights).forEach(key => {
document.getElementById(`weight-${key}`).value = appData.weights[key];
document.getElementById(`weight-val-${key}`).textContent = `${appData.weights[key]}%`;
});
document.getElementById('total-weight-display').textContent = `Total Weight: ${Object.values(appData.weights).reduce((a,b)=>a+b, 0)}%`;
updateDashboard();
});
// --- PDF GENERATION ---
document.getElementById('download-pdf-btn').addEventListener('click', () => {
const { finalScore, subScores } = calculateCreditScore();
const doc = new jsPDF();
let cursorY = 20;
doc.setFontSize(22); doc.setFontStyle('bold'); doc.setTextColor('#312e81');
doc.text('Confidential Credit Score Report', 105, cursorY, { align: 'center' });
cursorY += 15;
doc.addImage(scoreGaugeChart.toBase64Image('image/png', 1.0), 'PNG', 75, cursorY, 60, 35);
cursorY += 25;
const scoreText = document.getElementById('score-text').innerText.split('\n');
doc.setFontSize(36); doc.text(scoreText[0], 105, cursorY, { align: 'center' });
cursorY += 10;
doc.setFontSize(14); doc.text(scoreText[1], 105, cursorY, { align: 'center' });
cursorY += 20;
doc.setFontSize(16); doc.setTextColor('#111827'); doc.text('Credit Factor Breakdown', 14, cursorY);
cursorY += 8;
const tableBody = Object.keys(subScores).map(key => {
let impact = subScores[key] > 70 ? 'Positive' : (subScores[key] > 40 ? 'Neutral' : 'Negative');
return [factorLabels[key], `${appData.weights[key]}%`, impact];
});
doc.autoTable({
startY: cursorY,
head: [['Factor', 'Model Weight', 'Impact']],
body: tableBody,
theme: 'grid', headStyles: { fillColor: '#4f46e5' }
});
cursorY = doc.autoTable.previous.finalY + 15;
doc.setFontSize(12); doc.setTextColor('#64748b');
doc.text('This report is a simulation based on a generalized credit scoring model. Actual scores from bureaus may vary.', 105, cursorY, { align: 'center', maxWidth: 180 });
doc.save('Credit-Score-Report.pdf');
});
// --- INITIALIZATION ---
function runAllUpdates() {
renderWeightsForm();
updateDashboard();
}
runAllUpdates();
setActiveTab('dashboard');
});
