Fast, clear, no-fuss calculators for life, work, and finance.

What do you like to
Calculate today?

Grade Percentage Calculator

Easily calculate your grade percentage based on total points and scores achieved.

Enter the points you earned
Enter the maximum possible points
Add all your assignments/tests to calculate overall grade
Add all weighted assignments (total weight should equal 100%)
`; gradeEntries.appendChild(newEntry); // Show remove buttons if there's more than one entry updateRemoveButtons(); }); // Add new weighted grade entry addWeightedEntryBtn.addEventListener('click', function() { const newEntry = document.createElement('div'); newEntry.className = 'weighted-entry'; newEntry.innerHTML = `
`; weightedEntries.appendChild(newEntry); // Show remove buttons if there's more than one entry updateRemoveButtons(); }); // Remove grade entry document.addEventListener('click', function(e) { if (e.target.classList.contains('remove-entry-btn')) { e.target.closest('.grade-entry, .weighted-entry').remove(); updateRemoveButtons(); } }); // Update remove buttons visibility function updateRemoveButtons() { const gradeEntryButtons = document.querySelectorAll('#grade-entries .remove-entry-btn'); const weightedEntryButtons = document.querySelectorAll('#weighted-entries .remove-entry-btn'); gradeEntryButtons.forEach(btn => { btn.style.display = gradeEntries.children.length > 1 ? 'flex' : 'none'; }); weightedEntryButtons.forEach(btn => { btn.style.display = weightedEntries.children.length > 1 ? 'flex' : 'none'; }); } // Calculate grade calculateBtn.addEventListener('click', function() { const type = calculationType.value; let isValid = true; // Validate inputs based on calculation type if (type === 'simple') { isValid = validateSimpleGrade(); } else if (type === 'multiple') { isValid = validateMultipleGrades(); } else if (type === 'weighted') { isValid = validateWeightedGrades(); } if (!isValid) return; // Calculate based on type let percentage, details; if (type === 'simple') { const result = calculateSimpleGrade(); percentage = result.percentage; details = result.details; } else if (type === 'multiple') { const result = calculateMultipleGrades(); percentage = result.percentage; details = result.details; } else if (type === 'weighted') { const result = calculateWeightedGrades(); percentage = result.percentage; details = result.details; } // Display results displayResults(percentage, details); }); // Reset form resetBtn.addEventListener('click', function() { // Clear all inputs document.querySelectorAll('.form-input').forEach(input => { input.value = ''; input.classList.remove('error'); }); // Clear error messages document.querySelectorAll('.error-message').forEach(msg => { msg.style.display = 'none'; }); // Reset to simple grade form with one entry calculationType.value = 'simple'; simpleGradeForm.classList.add('active'); multipleGradeForm.classList.remove('active'); weightedGradeForm.classList.remove('active'); // Remove additional entries while (gradeEntries.children.length > 1) { gradeEntries.lastChild.remove(); } while (weightedEntries.children.length > 1) { weightedEntries.lastChild.remove(); } updateRemoveButtons(); // Hide results resultsSection.style.display = 'none'; }); // Validation functions function validateSimpleGrade() { const pointsEarned = document.getElementById('points-earned').value; const totalPoints = document.getElementById('total-points').value; let isValid = true; if (!pointsEarned || isNaN(pointsEarned) { showError(document.getElementById('points-earned'), 'Please enter a valid points earned value'); isValid = false; } else if (parseFloat(pointsEarned) < 0) { showError(document.getElementById('points-earned'), 'Points cannot be negative'); isValid = false; } if (!totalPoints || isNaN(totalPoints)) { showError(document.getElementById('total-points'), 'Please enter a valid total points value'); isValid = false; } else if (parseFloat(totalPoints) <= 0) { showError(document.getElementById('total-points'), 'Total points must be greater than 0'); isValid = false; } if (isValid && parseFloat(pointsEarned) > parseFloat(totalPoints)) { showError(document.getElementById('points-earned'), 'Points earned cannot exceed total points'); isValid = false; } return isValid; } function validateMultipleGrades() { const entries = document.querySelectorAll('#grade-entries .grade-entry'); let isValid = true; entries.forEach((entry, index) => { const earned = entry.querySelector('.earned-points').value; const total = entry.querySelector('.total-points').value; if (!earned || isNaN(earned)) { showError(entry.querySelector('.earned-points'), `Please enter valid points for entry ${index + 1}`); isValid = false; } else if (parseFloat(earned) < 0) { showError(entry.querySelector('.earned-points'), `Points cannot be negative in entry ${index + 1}`); isValid = false; } if (!total || isNaN(total)) { showError(entry.querySelector('.total-points'), `Please enter valid total points for entry ${index + 1}`); isValid = false; } else if (parseFloat(total) <= 0) { showError(entry.querySelector('.total-points'), `Total points must be greater than 0 in entry ${index + 1}`); isValid = false; } if (isValid && parseFloat(earned) > parseFloat(total)) { showError(entry.querySelector('.earned-points'), `Points earned cannot exceed total points in entry ${index + 1}`); isValid = false; } }); return isValid; } function validateWeightedGrades() { const entries = document.querySelectorAll('#weighted-entries .weighted-entry'); let isValid = true; let totalWeight = 0; entries.forEach((entry, index) => { const earned = entry.querySelector('.earned-points').value; const total = entry.querySelector('.total-points').value; const weight = entry.querySelector('.weight-value').value; if (!earned || isNaN(earned)) { showError(entry.querySelector('.earned-points'), `Please enter valid points for entry ${index + 1}`); isValid = false; } else if (parseFloat(earned) < 0) { showError(entry.querySelector('.earned-points'), `Points cannot be negative in entry ${index + 1}`); isValid = false; } if (!total || isNaN(total)) { showError(entry.querySelector('.total-points'), `Please enter valid total points for entry ${index + 1}`); isValid = false; } else if (parseFloat(total) <= 0) { showError(entry.querySelector('.total-points'), `Total points must be greater than 0 in entry ${index + 1}`); isValid = false; } if (!weight || isNaN(weight)) { showError(entry.querySelector('.weight-value'), `Please enter valid weight for entry ${index + 1}`); isValid = false; } else if (parseFloat(weight) <= 0) { showError(entry.querySelector('.weight-value'), `Weight must be greater than 0 in entry ${index + 1}`); isValid = false; } if (isValid && parseFloat(earned) > parseFloat(total)) { showError(entry.querySelector('.earned-points'), `Points earned cannot exceed total points in entry ${index + 1}`); isValid = false; } if (isValid) { totalWeight += parseFloat(weight); } }); if (isValid && Math.abs(totalWeight - 100) > 0.1) { alert('Total weight must equal 100%. Current total: ' + totalWeight.toFixed(1) + '%'); isValid = false; } return isValid; } function showError(input, message) { input.classList.add('error'); let errorMsg = input.nextElementSibling; if (!errorMsg || !errorMsg.classList.contains('error-message')) { errorMsg = document.createElement('div'); errorMsg.className = 'error-message'; input.parentNode.insertBefore(errorMsg, input.nextSibling); } errorMsg.textContent = message; errorMsg.style.display = 'block'; } // Calculation functions function calculateSimpleGrade() { const earned = parseFloat(document.getElementById('points-earned').value); const total = parseFloat(document.getElementById('total-points').value); const percentage = (earned / total) * 100; const details = [{ name: 'Single Grade', earned: earned, total: total, percentage: percentage, weight: 100 }]; return { percentage, details }; } function calculateMultipleGrades() { const entries = document.querySelectorAll('#grade-entries .grade-entry'); let totalEarned = 0; let totalPossible = 0; const details = []; entries.forEach(entry => { const earned = parseFloat(entry.querySelector('.earned-points').value); const total = parseFloat(entry.querySelector('.total-points').value); const percentage = (earned / total) * 100; totalEarned += earned; totalPossible += total; details.push({ name: 'Grade Entry ' + (details.length + 1), earned: earned, total: total, percentage: percentage, weight: (total / totalPossible) * 100 }); }); const percentage = (totalEarned / totalPossible) * 100; return { percentage, details }; } function calculateWeightedGrades() { const entries = document.querySelectorAll('#weighted-entries .weighted-entry'); let weightedSum = 0; const details = []; entries.forEach(entry => { const earned = parseFloat(entry.querySelector('.earned-points').value); const total = parseFloat(entry.querySelector('.total-points').value); const weight = parseFloat(entry.querySelector('.weight-value').value); const percentage = (earned / total) * 100; const weightedValue = percentage * (weight / 100); weightedSum += weightedValue; details.push({ name: 'Weighted Entry ' + (details.length + 1), earned: earned, total: total, percentage: percentage, weight: weight, weightedValue: weightedValue }); }); const percentage = weightedSum; return { percentage, details }; } // Display results function displayResults(percentage, details) { // Round to 2 decimal places percentage = Math.round(percentage * 100) / 100; // Update percentage display finalPercentage.textContent = percentage + '%'; // Determine letter grade const grade = getLetterGrade(percentage); letterGrade.textContent = grade.letter; letterGrade.className = 'letter-grade ' + grade.className; // Update progress bar gradeProgressBar.style.width = percentage + '%'; gradeProgressBar.style.backgroundColor = grade.color; // Generate detailed results table let tableHTML = ''; if (calculationType.value === 'weighted') { tableHTML += ''; } tableHTML += ''; details.forEach(detail => { tableHTML += ``; if (calculationType.value === 'weighted') { tableHTML += ``; } tableHTML += ''; }); tableHTML += '
NameEarnedTotal%WeightWeighted %
${detail.name} ${detail.earned} ${detail.total} ${Math.round(detail.percentage * 100) / 100}%${detail.weight}% ${Math.round(detail.weightedValue * 100) / 100}%
'; detailedResults.innerHTML = tableHTML; // Show results section resultsSection.style.display = 'block'; } function getLetterGrade(percentage) { if (percentage >= 90) { return { letter: 'A', color: '#4CAF50', className: 'grade-a' }; } else if (percentage >= 80) { return { letter: 'B', color: '#00A8A3', className: 'grade-b' }; } else if (percentage >= 70) { return { letter: 'C', color: '#FF9800', className: 'grade-c' }; } else if (percentage >= 60) { return { letter: 'D', color: '#F44336', className: 'grade-d' }; } else { return { letter: 'F', color: '#D32F2F', className: 'grade-f' }; } } });
Scroll to Top