import java.io.*;
import java.text.*;

//--------------------------------------------------------------
// Grades.java
// CS100 P3Q2
//
// Wei Tsang Ooi 16 July 1999
//
// This program prompts the user for a list of students and their
// grades, then summarises their final score and pass/fail status.
// The classes used by this program is as follows :
//
// - Class - encapsulate a class with a fixed number of students.
//         - we can add students into the class, and print out
//           information about the students.
//
// - Student - encapsulate a student, with a series of grades.
//           - we can get various information about the student.
//
// - LetterStudent - students taking the class for a letter grade.
//
// - PassFailStudent - students taking the class for a pass/fail grade.
//
//--------------------------------------------------------------

class Grades
{
	static BufferedReader stdin;

	//--------------------------------------------------------------
	// getName
	// 
	// prompt the user for a name and returns a string entered by user.
	//--------------------------------------------------------------

	static String getName() throws IOException
	{
		System.out.println("Name : ");
        return stdin.readLine();
	}

	//--------------------------------------------------------------
	// getInt
	// 
	// input : a message to print
	// output : an integer input by the user 
	// read an positive int from user and returns it.
	//--------------------------------------------------------------

	static int getInt(String message) throws IOException
	{
        String errMessage = "ERROR : input must be positive. " + 
            "Try again :";

        // prompt and read in the grade.

		System.out.println(message);
		int input =  Integer.parseInt(stdin.readLine());

        // make sure that grade is valid.

        while (input < 0) 
        {
            System.out.println(errMessage);
            System.out.println(message);
		    input =  Integer.parseInt(stdin.readLine());
        }

        // invariant : input is positive.  Return the input.

        return input;
	}


	//--------------------------------------------------------------
	// getGrade
	// 
	// input : a message to print
	// output : an double input by the user 
	// read a double between 0 and 100 from a user and returns it.
	//--------------------------------------------------------------

	static double getGrade(String message) throws IOException
	{
        String errMessage = "ERROR : grade must be between 0 and 100. " + 
            "Try again :";

        // prompt and read in the grade.

		System.out.println(message);
		double grade =  Double.valueOf(stdin.readLine()).doubleValue();

        // make sure that grade is valid.

        while (grade < 0 || grade > 100) 
        {
            System.out.println(errMessage);
            System.out.println(message);
            grade =  Double.valueOf(stdin.readLine()).doubleValue();
        }

        // invariant : grade is >= 0 and <= 100.  We can be sure at this
        // line that grade is valid.  Return the grade.

        return grade;
	}


	//--------------------------------------------------------------
	// getPassFail
	// 
	// input : none
	// prompt the user to see if this student enroll as a Pass/Fail
    // student.
	//--------------------------------------------------------------

	static boolean getPassFail() throws IOException
	{
        // prompt and read the name of the student.

        System.out.print("Enroll as Pass/Fail ? ([y]/n) ");
        String reply = stdin.readLine();

        if (reply.equals("") || reply.equals("y") || reply.equals("Y")) {
            // default answer is yes.
            return true;
        } else {
            // all other replies are considered as "no"
            return false;
        }
	}


	//--------------------------------------------------------------
	// createClass
	// 
	// input : none
	// prompt the user informations about students, add them into
	// a Class object and returns the Class object.
	//--------------------------------------------------------------

	static Class createClass() throws IOException
	{
        double grade[]= new double[Student.NUM_OF_GRADES];
		int    numOfStudent = getInt("Enter the number of students : ");

        // Create a new class with appropiate number of students.

		Class cls = new Class(numOfStudent);

        // Prompt and get students name and grades

		for (int i = 0; i < numOfStudent; i++)
		{
			// prompt and read the name of the student.
			String name = getName();

			// prompt and see if the student enroll as Pass/Fail student
			boolean passFail = getPassFail();

			// read the grades of the students.
			for (int j = 0; j < Student.NUM_OF_GRADES; j++)
			{
				grade[j] = getGrade("Grade for " + Student.GRADE_DESCRIPTION[j]);
			}

            if (passFail) 
            {
                cls.addStudent(new PassFailStudent(name, grade));
            } 
            else 
            {
                cls.addStudent(new LetterStudent(name, grade));
            }
		}

        return cls;

	}

	public static void main (String args[]) throws IOException
	{
		// This program just create a class and print it out.
		stdin = new BufferedReader(new InputStreamReader(System.in));
		Class cs100 = createClass();
		cs100.printAllStudents();
	}
}


//--------------------------------------------------------------
// class Class
// 
// This encapsulates a class with some number of students.  We
// can add a student in a class,  print the information about
// all the student, or query the average score of the class.
// 
// Wei Tsang Ooi 16 July 1999
//--------------------------------------------------------------

class Class {

	Student [] students;
	int numOfStudents;
    double totalScore;
	double min;
	double max;
	int studentCounter;

	private static DecimalFormat formatter = 
		new DecimalFormat("##0.##");


	//--------------------------------------------------------------
	// contructor
	// 
	// Receive a number of student as input, and creates the
	// array of students.
	//--------------------------------------------------------------

	public Class (int numOfStudents)
	{
        this.numOfStudents = numOfStudents;
		students = new Student[numOfStudents];
		totalScore = 0;
		min = Double.MAX_VALUE;
		max = Double.MIN_VALUE;
	}


	//--------------------------------------------------------------
	// printAllStudent
	// 
	// Output the name of the students as well as the list of grades,
	// weighted average, and pass/fail status (in neccessary).
	//--------------------------------------------------------------

	void printAllStudents()
	{	
		printHeader();
        for (int i = 0; i < numOfStudents; i++)
        {

         	System.out.println(
                students[i].getName() + 
                students[i].getAllGrades() +
                students[i].getFormattedWeightedAverage() +
				students[i].getFinalGrade()
				);
		}
        System.out.println();
        System.out.println("TOTAL NUMBER OF STUDENTS : " + 
			studentCounter);
        System.out.println("AVERAGE SCORE : " + 
			formatter.format(getClassAverage()));
	}


	//--------------------------------------------------------------
	// addStudent
	// 
	// add a new student into the class.  We make sure that the total
    // number of student does not exceed the number specified when
    // the class is created.  We return true if the student is added
    // successfully, and return false otherwise.
	//--------------------------------------------------------------

	boolean addStudent(Student student)
	{
        // check if we have exceed the limit of the class

        if (studentCounter >= numOfStudents) 
        {
            return false;
        }

        // add a new student

        students[studentCounter] = student;
        studentCounter++;

		double weightedAverage = student.getWeightedAverage();
        totalScore += weightedAverage;
		if (min > weightedAverage)
		{
			min = weightedAverage;
		}
		if (max < weightedAverage)
		{
			max = weightedAverage;
		}
		

        return true;
	}


	//--------------------------------------------------------------
	// getClassAverage
	// 
    // return the average score of the class, using the data entered
    // so far.  (i.e. if there are less student than specified, we
    // do not take in to consideration the "phantom students" when 
    // we calculate the average.
	//--------------------------------------------------------------

    double getClassAverage()
    {
        return totalScore/studentCounter;
    }


	//--------------------------------------------------------------
	// printStats
	// 
    // print the maximum, minimum and average value.
	//--------------------------------------------------------------

    void printStats()
    {
        System.out.println("MAX : " + max);
        System.out.println("MIN : " + min);
        System.out.println("MEAN : " + formatter.format(getClassAverage()));
    }


	//--------------------------------------------------------------
	// findStudent
	// 
	// input : name of a student
    // return the student with this name, if exists. return null
	// otherwise.
	//--------------------------------------------------------------

    Student findStudent(String name)
    {
		// Since the student list is not sorted, we perform a linear
		// search.
		for (int i = 0; i < numOfStudents; i++)
		{
			if (students[i].nameIs(name))
			{
				return students[i];
			}
		}

		// invariant : no students with that name is available
		return null;
    }


	//--------------------------------------------------------------
	// printStudent
	// 
	// input : name of a student
    // print information about this student 
	//--------------------------------------------------------------

    void printStudent(String name)
	{
		Student student = findStudent(name);
		if (student == null)
			System.out.println("ERROR : No such student : " + name);
		else {
			printHeader();
			System.out.println(
                student.getName() + 
                student.getAllGrades() +
                student.getFormattedWeightedAverage() + 
                student.getFinalGrade());
		}
    }

	
	//--------------------------------------------------------------
	// printHeader
	// 
    // print a header for the list of grades.
	//--------------------------------------------------------------

	static void printHeader()
	{
		System.out.println("NAME\tASS 1\tASS 2\tMIDTERM\tASS 3\tASS 4\tFINAL\tAVERAGE\tFINAL");	
	}
	

	//--------------------------------------------------------------
	// printLetterGradeStudents
	// 
    // print name and average grades of the students who were taking
    // this class for a letter grade.
	//--------------------------------------------------------------

    void printLetterGradeStudents()
    {
		System.out.println("NAME\tAVERAGE");
		for (int i = 0; i < numOfStudents; i++)
		{
			if (students[i].takeLetterGrade())
			{
				System.out.println(students[i].getName() +
                    students[i].getFormattedWeightedAverage());
			}
		}
    }
}


//--------------------------------------------------------------
// Student
//
// Encapsulates the data about a student, including its name, 
// and the grades for six assignment.
//
// Wei Tsang Ooi 16 July 1999
//--------------------------------------------------------------

class Student {

	// The name of this student, and an array of six for storing
	// his/her grades.
	private String name;           
	private double grades[];         
	protected double weightedAverage;

    // Number of grades for each student 
    public  final static int NUM_OF_GRADES = 6;

	// These constant represents the weight of each assignment.
	private final static double WEIGHT[] = {0.1, 0.1, 0.25, 0.2, 0.05, 0.3};
    
    // Grade description : This describes what each grade is for.
    public  final static String GRADE_DESCRIPTION[] = {
        "Assignment 1", "Assignment 2", "MidTerm", "Assignment 3", 
        "Assignment 4", "Final"};

    // This beautify the output of doubles
	protected static DecimalFormat formatter = new DecimalFormat("##0.##");
        

	//--------------------------------------------------------------
	// constructor
	// 
	// Initializes the members in the class with the name, and 
	// grades.   The grades should be an array of size 
    // Student.NUM_OF_GRADE.  If there are more grades than that,
    // extra grades will be thrown away.  If there are less, 
    // default grade (0) will be assign.
	//--------------------------------------------------------------

	Student(String name, double grades[])
	{
		this.name = name;
		this.grades = new double[NUM_OF_GRADES];

        // how many grades are we going to copy ?

        int howMany = (grades.length > NUM_OF_GRADES) ? 
            NUM_OF_GRADES :
            grades.length;

        // copy the grades. 
        // invariant : both grades and this.grades have at least
        // howMany elements.  So the following loop won't exceed
        // the array bounds.

        for (int i = 0; i < howMany; i++)
        {
            this.grades[i] = grades[i];
        }

        // calculate the weighted average of the students.

		weightedAverage = calcWeightedAverage();
	}

	
	//--------------------------------------------------------------
	// calcWeightedAverage
	// 
	// Returns the weighted average grade for this student.
	//--------------------------------------------------------------

	private double calcWeightedAverage()
	{
		double average = 0;
		for (int i = 0; i < grades.length; i++)
		{
			average += grades[i]*WEIGHT[i];
		}
		return average;
	}


	//--------------------------------------------------------------
	// nameIs()
	// 
	// input : a name
	// Returns true if this student's name is name
	//--------------------------------------------------------------

	public boolean nameIs(String name)
	{
		return this.name.equals(name);
	}


	//--------------------------------------------------------------
	// getName
	// 
	// Returns the name of the student.
	//--------------------------------------------------------------

    public String getName()
    {
        return name + "\t";
    }


	//--------------------------------------------------------------
	// getAllGrades
	// 
	// Format the grades of this student as a string and returns.
	//--------------------------------------------------------------

    public String getAllGrades()
    {
        String description = "";
        for (int i = 0; i < NUM_OF_GRADES; i++) 
        {
            description += formatter.format(grades[i]) + "\t";
        }

        return description;
    }

	
	//--------------------------------------------------------------
	// getWeightedAverage
	// 
	// Format the grades of this student as a string and returns.
	//--------------------------------------------------------------

    public String getFormattedWeightedAverage()
    {
        return formatter.format(weightedAverage) + "\t";
    }


	//--------------------------------------------------------------
	// getWeightedAverage
	// 
	// Returns the weightedAverage of this student
	//--------------------------------------------------------------

    public double getWeightedAverage()
    {
        return weightedAverage;
    }


	//--------------------------------------------------------------
	// getFinalGrade
	// 
	// This returns the final grade of a student.  It should be 
    // overwritten by the subclass to return the appropiate thing.
	//
	// A better way to do this is to define this as abstract.
	//--------------------------------------------------------------

    public String getFinalGrade()
    {
        return "";
    }	


	//--------------------------------------------------------------
	// takeLetterGrade
	// 
	// Return true if this student takes this class for a letter grade.
	// By default the student does not take the class for letter grade.
	// 
	// A better way to do this is to define this as abstract.
	//--------------------------------------------------------------

	public boolean takeLetterGrade()
	{
		return false;
	}

}


//--------------------------------------------------------------
// PassFailStudent
//
// Encapsulates the data about a student that takes the class
// as pass/fail.
//
// Wei Tsang Ooi 16 July 1999
//--------------------------------------------------------------

class PassFailStudent extends Student {

	final static double PASS_WATERMARK = 70;

    public PassFailStudent(String name, double grades[])
    {
        super(name, grades);
    }


	//--------------------------------------------------------------
	// takeLetterGrade
	// 
	// Return true if this student takes this class for a letter grade.
	//--------------------------------------------------------------

	public boolean takeLetterGrade()
	{
		return false;
	}

	//--------------------------------------------------------------
	// pass
	// 
	// Returns true if this student have pass the class.
	//--------------------------------------------------------------

	private boolean pass()
	{
		return weightedAverage >= PASS_WATERMARK;
	}


	//--------------------------------------------------------------
	// getFinalGrade
	// 
	// Format the data of this student for printing.  This just call
    // the super class toString and append a PASS/FAIL to the string.
	//--------------------------------------------------------------

    public String getFinalGrade()
    {
        return pass() ? "PASS" : "FAIL";
    }
}


//--------------------------------------------------------------
// LetterStudent
//
// Encapsulates the data about a student that takes the class
// for a letter grade.
//
// Wei Tsang Ooi 16 July 1999
//--------------------------------------------------------------

class LetterStudent extends Student {

    public LetterStudent(String name, double grades[])
    {
        super(name, grades);
    }

	//--------------------------------------------------------------
	// takeLetterGrade
	// 
	// Return true if this student takes this class for a letter grade.
	//--------------------------------------------------------------

	public boolean takeLetterGrade()
	{
		return true;
	}


	//--------------------------------------------------------------
	// getFinalGrade
	// 
	// This should returns a letter grade (A, B, C, D, E) absed on
	// the weighted average.  But now we just return nothing since
	// the question did not specify how to calculate the letter grade.
	//--------------------------------------------------------------

    public String getFinalGrade()
    {
        return "";
    }
}