import java.io.*;
import java.util.StringTokenizer;

/*---------------------------------------------------------------------------------------------	
CS100 P3: Q3

Asks user for the number of students in a classroom.  Then queries for each
student the name, whether the student is taking it for letter, and the 6 grades 
for the 6 assignments of each student.  Calculates a final grade for each student 
based on a weighting scheme.  Offers a menu of options to the user (described below).
After each choice except quit, the menu is shown again.

There are two classes in this file: Modified Classroom and ClassroomTools.  Not
shown, but implied, are the Student class and PassFail and Letter subclasses of 
Student.

Author 	:   Alan Renaud (ajr5@cornell.edu)
Date		:   23 July 1999	
------------------------------------------------------------------------------------------------*/
class ModifiedClassroom {

	final static int NUMASSIGNS = 6;
	final static double[] WEIGHTS = {0.1, 0.1, 0.25, 0.2, 0.05, 0.3};
	final static TokenReader IN = new TokenReader(System.in);
	static ClassroomTools forMyClass = new ClassroomTools();
	
	public static void main(String[] args) 
	{
		
		Student[] roster = forMyClass.takeRollCall(NUMASSIGNS, WEIGHTS);
		int val = makeChoice();
		while (val !=5)
		{	
			doChoice(val, roster);
			val = makeChoice();
		} 
		bye();
	}

	/*---------------------------------------------------------------------------------------------	
	makeChoice
	
	input	:   	none
	return	:	value input by user
	------------------------------------------------------------------------------------------------*/	
	private static int makeChoice() 
	{
		System.out.println("\n\n\n");
		System.out.println("Which of the following tasks would you like to perform: \n");
		System.out.println("1.\tSearch for a particular name and view that person's grades.");
		System.out.println("2.\tView the max, min and avg grades for the class.");
		System.out.println("3.\tView the names and grades of students taking it for letter.");
		System.out.println("4.\tView the entire list of students.");
		System.out.println("5.\tQuit\n");
		System.out.print("Your selection is: ");
		System.out.flush();
		int ans = IN.readInt();
		return ans;
	}

	/*---------------------------------------------------------------------------------------------	
	doChoice
	
	input	:   	value input by user
	return	:	none
	
	Executes appropriate method based on user output from makeChoice method.
	------------------------------------------------------------------------------------------------*/	
	private static void doChoice(int num, Student[] r)
	{
		switch (num) 
		{
			case 1:
				forMyClass.findStudent(r);
				break;
			case 2:
				forMyClass.showClassStats(r);
				break;
			case 3:
				forMyClass.showLetterStudents(r);
				break;
			case 4:
				 forMyClass.printClassData(r);
			case 5:
				break;
			default:
				System.out.println("\nInvalid selection.");
		}
		IN.waitUntilEnter();
	}

	/*---------------------------------------------------------------------------------------------	
	bye
	
	Prints goodbye message when user elects to quit.
	-----------------------------------------------------------------------------------------------*/		
	private static void bye() 
	{
		System.out.println("\n\nThanks for playing.  Have a nice day!" );
		IN.waitUntilEnter();
	}

} // end ModifiedClassroom

class ClassroomTools {

	static TokenReader in = new TokenReader(System.in);
 
	/*---------------------------------------------------------------------------------------------	
	takeRollCall
	
	input	:   	none
	return	:	array of students
	
	Prompts user for number of students then proceeds to construct an array of 
	Letter and PassFail Student objects, each prompted for and initialized by the user.
	-----------------------------------------------------------------------------------------------*/	
	public  Student[] takeRollCall(int numAssigns, double[] weights) 
	{
		int n = getInteger("Enter number of students: ");
		Student[] r = new Student[n];
		for (int count=0; count < n; count++) 
		{
			String name = getString("Student "+ (count+1)+ "'s name: ");
			boolean forLetter = isForLetter("Is the student taking it for grade? ");
			double[] scores = readScores(numAssigns);
			r[count] = (forLetter ? (Student) new LetterGrade(name, scores, weights) : 
				(Student) new PassFail(name, scores, weights));
		}
		return r;
	}

	/*---------------------------------------------------------------------------------------------	
	findStudent
	
	input	:   	array of students
	return	:	none
	
	Prompts user for the name of a student, then searches the array to find him. Prints 
	to screen the names and grades of the student if found; an error message otherwise.
	-----------------------------------------------------------------------------------------------*/	
	public void findStudent(Student[] r) 
	{
		String n = getString("\nEnter the person's name: ");
		int index=0;
		prompt("Searching.....");
		while ((index < (r.length-1))&&(!r[index].name.equals(n))) 
		{
			index++;
		}
		if (!r[index].name.equals(n))
			System.out.println("\n\nWe're sorry but " + n + " is not in this class.");
		else 
		{
			System.out.print("\n\nGrades for " + n + ": ");
			for (int count = 0; count < r[index].scores.length; count++) 
			{
				System.out.print(r[index].scores[count] + "  ");
			}
			System.out.println("\n");
		}
	}
	
	/*---------------------------------------------------------------------------------------------	
	showClassStats
	
	input	:   	array of students
	return	:	none
	
	Prints to screen the lowest and highest grades, and the "classroom" average.
	------------------------------------------------------------------------------------------------*/	
	public void showClassStats(Student[] r) 
	{
		double sum, avg, max,  min;
		sum = 0;
		max = min = r[0].grade;
		for (int i=0; i<r.length; i++) 
		{
			sum += r[i].grade;
			if (r[i].grade > max) max = r[i].grade;
			if (r[i].grade < min)  min = r[i].grade;
		}
		avg = sum/r.length;
		System.out.println("\n\nThe highest grade in the class is " + max);
		System.out.println("The lowest grade in the class is " + min);		
		System.out.println("The average for the class is " + Math.floor(avg)) ;
	}

	/*---------------------------------------------------------------------------------------------	
	showLetterStudents
	
	input	:   	array of students
	return	:	none
	
	Prints to the screen the names and grades of each Letter student.
	------------------------------------------------------------------------------------------------*/	
	public  void showLetterStudents(Student[] r) 
	{
		System.out.println("\n\n");
		for(int index=0; index < r.length; index++) 
		{
			if (r[index] instanceof LetterGrade) 
				System.out.println(r[index].name + "  " + r[index].finalGrade());
		}
	}

	/*---------------------------------------------------------------------------------------------	
	printClassData
	
	input	:   	array of students
	return	:	none
	
	Prints to screen the names and grades of each student.
	------------------------------------------------------------------------------------------------*/	
	public void printClassData(Student[] r) 
	{
		System.out.println("\n\n");
		for (int counter=0; counter < r.length; counter++)
			r[counter].printData();
	}
	
	/*---------------------------------------------------------------------------------------------	
	readScores
	
	input	:   	number of assignments
	return	:	array representing the scores for each assignment
	------------------------------------------------------------------------------------------------*/	
	private double[] readScores(int n) 
	{	
		prompt("Enter the student's scores: ");
		String grInput = in.readLine();
		StringTokenizer gr = new StringTokenizer(grInput);
		double[] s = new double[n];
		if (gr.countTokens() != n)
			System.out.println("\nToo few or too many scores. Surplus set to 0.\n");	
		String hold;
		for (int index=0; index < n; index ++)
		{	
			hold = (gr.hasMoreTokens() ? gr.nextToken() : "0");
			s[index] = Double.valueOf(hold).doubleValue();
		}
		return s;
	} 

	/*---------------------------------------------------------------------------------------------	
	isForLetter
	
	input	:   	message string
	return	:	true IF student is taking class for letter
	------------------------------------------------------------------------------------------------*/			
	private boolean isForLetter(String message)
	{
		String typ = getString(message);
		while ((!typ.toLowerCase().startsWith("y")) && (!typ.toLowerCase().startsWith("n")))
		{
			typ = getString("yes or no? ");
		} 
		return (typ.toLowerCase().startsWith("y"));
	}

	/*---------------------------------------------------------------------------------------------	
	getString
	
	input	:   	message string
	return	:	string message input by user
	
	Returns string input by user. 
	------------------------------------------------------------------------------------------------*/		
	private String getString(String message) 
	{
		prompt(message);
		return in.readString();
	}

	/*---------------------------------------------------------------------------------------------	
	getInteger
	
	input	:   	message string
	return	:	value input by user
	
	Returns value of user's input if it is positive.
	------------------------------------------------------------------------------------------------*/
	private int getInteger(String message) 
	{
		prompt(message);
		int val = in.readInt();
		while (val<0)
		{
			prompt("Enter a positive number: ");
			val = in.readInt();
		}
		return val;
	} 
	
	/*---------------------------------------------------------------------------------------------	
	prompt
	
	input	:   	message string
	return	:	none
	
	Prints message prompt
	------------------------------------------------------------------------------------------------*/	
	private void prompt(String message) 
	{
		System.out.print(message);
		System.out.flush();
	}
} // end ClassroomTools