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

/*---------------------------------------------------------------------------------------------	
CS100 P3: Q2

Asks user for the number of students in a classroom.  Then for each student 
queries the user for the name, whether the student is taking it for letter, and the
6 grades corresponding to the 6 assignments for the student.  Calculates a final
grade for each students based on a weighting scheme then prints each student's
name, their 6 grades, and their weighted average (PASS/FAIL for non-letter grade
students).


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

	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);
	
	public static void main(String[] args) 
	{
		Student[] roster = takeRollCall();
		printClassData(roster);
		IN.waitUntilEnter();
	}

	/*---------------------------------------------------------------------------------------------	
	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.
	------------------------------------------------------------------------------------------------*/	
	private static Student[] takeRollCall() 
	{
		prompt("Enter number of students: ");
		int n = IN.readInt();
		Student[] r = new Student[n];
		for (int count=0; count < n; count++) 
		{
			String name = getString("Student "+ (count+1)+ "'s name: ");
			boolean forLetter = isForLetter();
			double[] scores = readScores(NUMASSIGNS);
			r[count] = (forLetter ? (Student) new LetterGrade(name, scores, WEIGHTS) : 
				(Student) new PassFail(name, scores, WEIGHTS));
		}
		return r;
	}

	/*---------------------------------------------------------------------------------------------	
	printClassData
	
	input	:   	array of students
	return	:	none
	
	Prints to screen the names and grades of each student, and the "classroom" average.
	------------------------------------------------------------------------------------------------*/	
	private static void printClassData(Student[] r) 
	{
		double sum=0, avg;
		System.out.println();
		for (int counter=0; counter < r.length; counter++)
		{
			r[counter].printData();
			sum += r[counter].grade;
		}
		avg = sum/r.length;
		System.out.println("\nThe average for the class is " + Math.floor(avg)) ;
	}

	/*---------------------------------------------------------------------------------------------	
	readScores
	
	input	:   	number of assignments
	return	:	array representing the scores for each assignment
	------------------------------------------------------------------------------------------------*/		
	private static 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 static boolean isForLetter()
	{
		String typ = getString("Is the student taking it for grade? ");
		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 static String getString(String message) 
	{
		prompt(message);
		return IN.readString();
	}

	/*---------------------------------------------------------------------------------------------	
	prompt
	
	input	:   	message string
	return	:	none
	
	Prints message prompt
	------------------------------------------------------------------------------------------------*/	
	private static void prompt(String message) 
	{
		System.out.print(message);
		System.out.flush();
	}

}

/*---------------------------------------------------------------------------------------------	
ABSTRACT Class Student
Represents a student with a final grade and a number of assignment scores.
------------------------------------------------------------------------------------------------*/	
abstract class Student 
{
	String type;			// type of student (eg, letter)
	protected String name;	// name of student
	double [] scores;		// assignment scores
	double grade;			// final grade
	
	/*	constructor 	*/		
	Student(String n, double[] s, double[] w) 
	{
		name = new String(n);
		scores = new double[s.length];
		scores = (double[]) s.clone();
		grade = computeGrade(w);
	}
	
	/*---------------------------------------------------------------------------------------------	
	computeGrade
	
	input	:   	an array representing the weighting scheme
	return	:	value of final grade
	
	Calculates final grade.
	------------------------------------------------------------------------------------------------*/	
	private double computeGrade(double[] w) 
	{
		double fGrade=0;
		for (int k=0; k<w.length; k++) {
			fGrade+=scores[k]*w[k];
		}
		return Math.floor(fGrade);
	}
	
	/*---------------------------------------------------------------------------------------------	
	printData
	
	input	:   	none
	return	:	none
	
	Outputs to screen student's name, assignment scores, and final grade.
	------------------------------------------------------------------------------------------------*/	
	public void printData() 
	{
		System.out.print(name + "   ");
		for (int k=0; k<scores.length; k++) 
		{
			System.out.print(scores[k] + " ");
		}
		System.out.println("   "  + finalGrade());
	}
	
	/*---------------------------------------------------------------------------------------------	
	finalGrade
	
	input	:   	none
	return	:	String representing manner of grade
	
	To be implemented in subclass, returns string representation of final grade.
	------------------------------------------------------------------------------------------------*/	
	abstract String finalGrade(); 
} // end Student


class PassFail extends Student 
{
	PassFail(String n, double[] s, double[] w) 
	{
		super(n, s, w);
		type = new String("passfail");
	}

	/*---------------------------------------------------------------------------------------------	
	finalGrade
	
	Returns "PASS" if student's final grade is >= 70, "FAIL" otherwise.
	------------------------------------------------------------------------------------------------*/
	public String finalGrade() 
	{
		return (grade>=70 ? "PASS" : "FAIL");
	}	
} // end PassFail


class LetterGrade extends Student 
{
	LetterGrade(String n, double[] s, double[] w) 
	{
		super(n, s, w);
		type = new String("letter");
	} 

	/*---------------------------------------------------------------------------------------------	
	finalGrade
	
	Returns rounded finalGrade of student.
	------------------------------------------------------------------------------------------------*/
	public String finalGrade() 
	{
		return new Double(Math.floor(grade)).toString();
	}	
} // end LetterGrade

/*

SAMPLE OUTPUT:

Enter number of students: 3
Student 1's name: alan
Is the student taking it for grade? yes
Enter the student's scores: 90 98 84 87 99 95
Student 2's name: alex
Is the student taking it for grade? no
Enter the student's scores: 78 77 76 80 81 90
Student 3's name: alfred
Is the student taking it for grade? no
Enter the student's scores: 50 60 70 65 72 30

alan   90.0 98.0 84.0 87.0 99.0 95.0    90.0
alex   78.0 77.0 76.0 80.0 81.0 90.0    PASS
alfred   50.0 60.0 70.0 65.0 72.0 30.0    FAIL

The average for the class is 75.0

Press Enter to continue.
*/