/*******************************************************************************
FILE		OLA5.CC
COURSE		CSCI-1170-006
AUTHOR		Patrick Riley Connor
INSTRUCTOR	Jungson Yoo
DUE DATE	27 October 2009
DESCRIPTION	This program is made to take the input of a teacher's file of test
			scores, format it in a nice table format, calculate the student's
			average, determine a letter grade, and calculate the class average.
INPUT		fileName
				An input file, containing the information of our teacher's test
				records in the format specified on 	the project sheet and given
				as examples in files ola5.1, ola5.2, and ola5.3.
OUTPUT		A table, listing each student's test scores, the student's average,
			and their letter grade. Afterwards, a class average is to be shown
			along with the count of the students in the record.
FORMULAS	Most of this is looping. However, there are 3 slightly complex
			formulas that I will explain.
			36 + 7 * testNumber
				This formula calculates the number of dashes needed to form our
				line seperating our headers from our student's test scores. The
				36 comes from our static header lines, where as 7 * testNumber
				comes from the fact that each test header takes up 7 spaces.
			averageStudent = averageStudent + testScore
			averageStudent = averageStudent / testNumber
				These two lines are used in conjunction. The first line simply
				adds each test score to the studentAverage variable, in a loop.
				After the loop is over, we divide by the total number of tests
				taken to get the average of them.
			averageClass = averageClass + averageStudent
			averageClass = averageClass / studentCount
				Similar in practice to our previous averaging formula, except
				modified in the fact that we are averaging together all of the
				student's average scores in the class together to find out the
				average of the entire class.
*******************************************************************************/

using namespace std;
#include <iostream>		// Needed for cout and cin.
#include <fstream>		// Needed for opening our teacher's file.
#include <string>		// Needed for tracking student's names and our file.
#include <iomanip> 		// Needed for setprecision(), fixed, and setw().

int main()
{
	string		fileName,		// The name of the file to parse our data with.
				studentName;	// The student's name printed on each line.
	int			tempCounter,	// Temporary counter variable, multiple uses.
				testNumber,		// The number of tests for each student.
				testCount,		// Test number counter.
				testScore,		// Read for each test score and manipulate.
				studentCount;	// Counts how many students in the file.
	float		averageStudent,	// Calculates the average for each student.
				averageClass;	// Calculates the class average.
	ifstream	inFile;			// Our input file stream.

	// Display the purpose of our program.
	cout	<<	"This program takes an input file for a teacher's grades in "
			<<	"order to format it\nin a table format and display other info,"
			<<	" such as the class size, student\naverage, and class average."
			<<	endl	<<	endl

	// Prompt user for their input file.	
			<<	"Please input the name of the input file: ";
	cin		>>	fileName;
	
	// Open our file.
	inFile.open(fileName.c_str());
	
	// Check if the file was opened successfully.
	if (!inFile)
	{
		// If file open fail, inform user of the error and quit.
		cout	<<	"There was an error with opening your file. Please check "
				<<	"for the file and try\nagain."	<<	endl;
		return 1;
	}
	
	// Read the first entry of the file, which is how many tests in the file.
	inFile	>>	testNumber;

	// Pad a little bit from the user input, and feed the information on the
	// number of test records found.
	cout	<<	endl	<<	endl
			<<	"This data file has "	<<	testNumber	<< " test records "
			<<	"for each student."	<<	endl	<<	endl
	
	// Start creating the table, the header obviously being formed on the top.
			<<	" Student name  ";
	
	// Initialize our temporary counter, and ready it for a loop.
	tempCounter = 1;
	
	// Print test1, test2,... testN up to the number of tests specified in the
	// file.
	while (tempCounter <= testNumber)
	{
		cout	<<	"  test"	<<	tempCounter;
		tempCounter++;
	}
	
	// Finish the final part of our table, the summary of each student's final
	// average score and their letter grade.
	cout	<<	"  final score  grade"	<<	endl;

	// Prepare our temporary counter variable for another loop.
	tempCounter = 1;
	
	// Create a line to seperate headings from scores. Note: 36 + 7 * testNumber
	// gives us a proper line length, as each test section takes 7 characters
	// for each one.
	while (tempCounter <= (36 + 7 * testNumber))
	{
		cout	<<	'-';
		tempCounter++;
	}
	
	cout	<<	endl;	// We're done with our line, move on to our students.
	

	// Initialize two variables that we're going to need for the end of our
	// looping structure here.
	averageClass = 0;		// Keeps track of the class average.
	studentCount = 0;		// Counts the number of students in the record.
	
	// Get a priming read to get our input file stream chugging along.
	inFile	>>	studentName;									
	
	// Start!
	while (inFile)		// As long as we have information left in our file...
	{
		// Print out our previous student name received. For our loop's first
		// iteration, this comes from our priming read. For each other, it is
		// coming from the end of the loop.
		cout	<<	' '	<<	setw(14)	<<	left	<<	studentName	<<	right;
		
		// Initialize our two variables needed for the student record section.
		testCount = 1;			// Counts the test number that is being parsed.
		averageStudent = 0;		// Keeps track of the student's average.
		
		// Continue looping for each number of tests in our input file...
		while (testCount <= testNumber)
		{
			inFile	>>	testScore;				// Get the next test score.

			cout	<<	setw(7)	<<	testScore;	// Print it.

			// Add the test score to our average variable. This will be divided
			// by the number of tests afterwards to give us our student's
			// test score average.
			averageStudent = averageStudent + testScore;
			testCount++;						// Increment our counter.
		}
		
		// Divide our summed score out to get an average of the 5 scores.
		averageStudent = averageStudent / testNumber;
		
		// Print out the student's average with 2 decimal places.		
		cout	<<	setw(13)	<<	fixed	<<	setprecision(2)
				<<	averageStudent;
		
		// Determine the student's letter grade.
		if (averageStudent >= 90)					// 90 or above == A
			cout	<<	setw(5)	<<	'A'	<<	endl;
		else if (averageStudent >= 80)				// 80 inclusive - 90 == B
			cout	<<	setw(5)	<<	'B'	<<	endl;
		else if (averageStudent >= 70)				// 70 inclusive - 80 == C
			cout	<<	setw(5)	<<	'C'	<<	endl;
		else if (averageStudent >= 60)				// 60 inclusive - 70 == D
			cout	<<	setw(5)	<<	'D'	<<	endl;
		else										// All other scores == F
			cout	<<	setw(5)	<<	'F'	<<	endl;
		
		// Similar to how we calculated our student's average score before, we
		// are going to do the same with the class average. Add them all up for
		// now, and at the end we'll divide it out to get the average.
		averageClass = averageClass + averageStudent;

		// Count the student. After finishing reading this student's record, we
		// now have one more student on our list.
		studentCount++;
		
		// Get another read for the student name. If another student name does
		// not exist, our file stream will be sent into a fail state, and we'll
		// stop reading from our file.
		inFile	>>	studentName;
	}
	
	// We have no more reading to do from our file. Close it up.
	inFile.close();
	
	// Same as our student's averages. After we've got all the student's
	// averages summed up into this variable, all we need to do is divide by
	// the number of students in order to get a class average.
	averageClass = averageClass / studentCount;
	
	// Feed the user the information on the class average and how many students
	// were in this record.
	cout	<<	"The class average is: "	<<	averageClass	<<	endl
			<<	"There are "	<<	studentCount	<<	" students in "
			<<	"this class record."	<<	endl;

	// Ta-da! Complete!
	return 0;
}
