Jayd Saucedo

Blog

GPA Calculator

Click here to access the script!

I am going to transfer from my California Community College to a university sometime soon, but in order to do that I have to know exactly what my "transfer GPA" is. The program that most community colleges use, WebAdvisor, provides you with an unofficial transcript of your classes that gives you a cumulative GPA, but it gives you the cumulative GPA of all your classes. Not just your transferable ones. So of course the easiest thing to do is to copy that all into excel and try and arrange the data in its respective places (due to excel's parsing problems) and then try and make the dynamic calculations yourself based off the columns that you've created.

Sure, that's easy for someone who knows how to do it. Not so easy for someone who doesn't know, and it's not so easy for me to explain how to do that for someone who's not completely familiar with excel. The existing GPA calculators online are nothing special. From what I've seen they have a fixed amount of inputs, you enter each class manually, select grade, enter units, etc. Then press calculate. That's a lot of work if you've taken 5 classes a semester for the past 6 semesters. So I made a GPA calculator that accepts and translates unofficial transcripts from WebAdvisor and then allows you to delete whatever classes you want to exclude. It's all dynamic too, there's no fixed amount of inputs, you have as many or as few classes as you want in your calculation.

This seemed like something best suited for JavaScript. No need for anything fancy. My first step was dynamically creating input boxes for each class. This is my entire function for doing so:

function new_course(name, units, grade){	
	//alert(course_num);
	// creating elements
	mTR = document.createElement('TR');
	name_td = document.createElement('TD');
	units_td = document.createElement('TD');
	grade_td = document.createElement('TD');
	remove_td = document.createElement('TD');
	
	// give this tr an ID!
	mTR.id = 'course'+course_num;
	courses.push('course'+course_num);
	
	// make inputs
	name_input = document.createElement('input');
	// give an ID
	name_input.id = 'name_course'+course_num;
	// set name input size
	name_input.size = 20;
	// set value of name
	name_input.value = name;
	units_input = document.createElement('input');
	// give units an ID
	units_input.id = 'units_course'+course_num;
	// set unit input size
	units_input.size = 5;
	// set value of units
	units_input.value = units;
	// set change event for units
	units_input.onkeypress = function(e){calc_gpa();}
	units_input.onkeyup = function(e){calc_gpa();}
	grade_select = document.createElement('select');
	// give grade an ID
	grade_select.id = 'grade_course'+course_num;
	// set change event for grade
	grade_select.onchange = function(e){calc_gpa();}
	// remove img
	remove_x = document.createElement('img');
	remove_x.src = "x.png";
	remove_x.style.cursor = "pointer";
	// remove class inputs and remove class from array
	remove_x.onclick = function(e){ 
		document.getElementById('mainStuff').removeChild(this.parentNode.parentNode); 
		courses = removeFromArray(this.parentNode.parentNode.id, courses);
		calc_gpa();		
	}
	
	//add remove row text
	remove_td.appendChild(remove_x);
	
	// append inputs to table
	name_td.appendChild(name_input);
	units_td.appendChild(units_input);
	
	
	grade_td.appendChild(grade_select);
	// adding the options...
	addOption(grade_select, 'Select', -1);
	for(i=0; i < grades.length; i++){
		addOption(grade_select, grades[i][0], grades[i][1]);
	}
	// set value of grade
	grade_select.selectedIndex = grade;
	
	// append to TR - order matters!
	mTR.appendChild(name_td);
	mTR.appendChild(units_td);
	mTR.appendChild(grade_td);
	mTR.appendChild(remove_td);
	
	// main area element
	stuffBox = document.getElementById('mainStuff');
	// append to main area
	stuffBox.appendChild(mTR);
	
	course_num++;
	
}
78 lines of awesome. I set all this up in a table. There are three inputs boxes for each class: name, units, and grade. Then there's a remove button. You'll notice that for my grade selection I have a for loop:
addOption(grade_select, 'Select', -1);
	for(i=0; i < grades.length; i++){
		addOption(grade_select, grades[i][0], grades[i][1]);
	}
This is because I stored my grade values in an array. I did this because I have two separate functions that access those grades. If I decide to add another grade, I only want to edit it in one place. All in all my global variables look like this:
var course_num = 0;
var courses = Array();
var grades = Array(
	Array('A', 4.0),
	Array('A-', 3.7),
	Array('B+', 3.3),
	Array('B', 3.0),
	Array('B-', 2.7),
	Array('C+', 2.3),
	Array('C', 2.0),
	Array('C-', 1.7),
	Array('D+', 1.3),
	Array('D', 1.0),
	Array('D-', 0.7),
	Array('F', 0),
	Array('P', -1),
	Array('NP', -1),
	Array('I', -1),
	Array('W', -1)
	)

What makes my script unique, other than the dynamic amount of input boxes, is the ability to translate transcripts. My method isn't perfect, because you have to copy them exactly or else the program won't read them correctly. When you copy the transcript and paste it into a textbox it simply puts everything on a new line. You have the course name, then on a new line the grade, then on a new line the units, and then on a new line the term. That's 4 things per class, and using that you can easily tell which thing goes where. No fancy regular expressions needed. All in all my translate_Transcript function looks like this:

function translate_Transcript(textbox){

	text = document.getElementById(textbox).value;
	broken = text.split("\n");
	
	grade_num = 0;
	for(n = 0; n < broken.length; n=n+4){
		
		for(i=0; i < grades.length; i++){
			if(broken[n+1] == grades[i][0]){
				// add 1 because it uses the options index, and Select isn't one!
				grade_num = (i+1);
			}
		}
		
		if(broken[n].length > 1){
			new_course(broken[n], broken[n+2], grade_num);
		}
	}
	calc_gpa();
}

As you can see this script also accesses my grades array. Unfortunately, dom select objects can only have their current option assigned to them by telling it what index value its at, and if I see a class has a B, how am I supposed to know what index number that's at in the options? Well, I have to look through the grades array and try and find a match for "B" and then note what index I found it at. It's stupid, but less stupid than hard coding the indexes in. The rest of the program is simple math to calculate GPA. Nothing to it!

You can check out the script here!