package objects;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.text.DecimalFormat;
/**
* Course defines a actual teacher's course, with name, course ID, course number, section number,
* building, room number, meeting time, an ArrayList of Students, an ArrayList of AssignmentCategories,
* and a gradeBook object to hold all of the students grades as they will appear on the final html5 document
* screen in the application
*
* @Jesse W. Milburn
* @date 01 October, 2013
*/
public class MyCourse {
//course data kept private so only method calls can change them
private String courseName;
private String courseID;
private int courseNumber;
private String section;
private String building;
private String roomID;
private String meetingTime;
private String semester;
private Integer lastAssignmentIndex;
private Integer lastCategoryIndex;
private List<Student> students = new ArrayList<Student>();
private List<AssignmentCategory> categories = new ArrayList<AssignmentCategory>();
private List<GhostStudent> ghostStudents = new ArrayList<GhostStudent>();
private List<Object> allStudents = new ArrayList<Object>();
private final PseudoNameGenerator pnGenerator;
private DecimalFormat decimalFormat = new DecimalFormat("#.#");
private boolean isGradingWeighted;
private boolean isNewCourse = false;
/**
* Constructs a new MyCourse object, note there is no 'empty' constructor
*
* @param cn string denoting what the callee has named the course
*/
public MyCourse(String cn) {
this.pnGenerator = new PseudoNameGenerator();
courseName = cn;
lastAssignmentIndex = null;
lastCategoryIndex = null;
}
/**
* Takes an Assignment object as a parameter and assigns initial ghost grades
* to all of the ghost students based on the mean of the real students while
* keeping the ranges similar
*
* @param assignment
*/
public void assignGhostGrades(Assignment assignment) {
String[] ghostNames = new String[ghostStudents.size()];
populateNames(ghostNames);
assignment.setGhostGrades(ghostNames);
}
/**
*
*
* @param names
*/
private void populateNames(String[] names) {
for (int i = 0; i < names.length; i++) {
names[i] = ghostStudents.get(i).getPseudoName();
}
}
/**
* Set the name of the course.
*
* @param cn set the courseName
*/
public void setName(String cn) {
courseName = cn;
}
/**
* Set the course ID of the course
*
* @param cid set the courseID
*/
public void setCourseID(String cid) {
courseID = cid;
}
/**
* Set the course number of the course
*
* @param cnum set the course number
*/
public void setCourseNumber(int cnum) {
courseNumber = cnum;
}
/**
* Set the section identification of the course.
*
* @param sec set the section identification
*/
public void setSection(String sec) {
section = sec;
}
/**
* Set the building name
*
* @param bn set the building name
*/
public void setBuilding(String bn) {
building = bn;
}
/**
* Set the room number identification
*
* @param rn set the room identification
*/
public void setRoomID(String rn) {
roomID = rn;
}
/**
* Set the meeting time
*
* @param mt set the meeting time
*/
public void setMeetingTime(String mt) {
meetingTime = mt;
}
/**
* Set the meeting time
*
* @param sm set the semester
*/
public void setSemester(String sm) {
semester = sm;
}
/**
* Sets last assignment edited
*
* @param i index of last assignment
*/
public void setLastAssignmentIndex(Integer i) {
lastAssignmentIndex = i;
}
/**
* Sets last category edited
*
* @param i index of last category
*/
public void setLastCategoryIndex(Integer i) {
lastCategoryIndex = i;
}
/**
* Gets identifying name for file names and buttons in menu
*
* @return gets identifying string
*/
public String getIdentifier() {
return getCourseID() + getCourseNumber() + "-" +
getSection() + " " + getSemester();
}
/**
* Get the name of the course
*
* @return get the name of the course
*/
public String getName() {
return courseName;
}
/**
* Get the course identification
*
* @return course identification
*/
public String getCourseID() {
return courseID;
}
/**
* Get the course number
*
* @return course number
*/
public int getCourseNumber() {
return courseNumber;
}
/**
* Returns the course grade average, all return values are
* as a percentage not the actual grade.
* helper functions trail the main function
*
* @return Average course grade as a percentage
*/
public Double getCourseAverageGrade() {
double average = 0.0;
if (isGradingWeighted) {
return this.getCourseWeightedGrade();
}
double studentPoints = getTotalStudentPoints();
double totalPoints = getTotalCoursePoints();
average = studentPoints / totalPoints;
return Double.parseDouble(decimalFormat.format(average * 100));
}
public Double getTotalStudentPoints() {
double total = 0.0;
for (int i = 0; i < categories.size(); i++) {
total += categories.get(i).getTotalCategoryStudentPoints(students);
}
return total;
}
public Double getTotalCoursePoints() {
double total = 0.0;
for (int i = 0; i < categories.size(); i++) {
total += categories.get(i).getTotalPoints();
}
return total * students.size();
}
// The real work is done at the category level this just sums up the cat totals
public Double getStudentGradeStatistic(String pseudoName, String mode) {
double totalPoints = 0.0;
double totalWorth = 0.0;
for (int i=0; i < categories.size(); i++) {
Double[] res = categories.get(i).getStudentGradeStatistic(pseudoName, mode);
totalPoints += res[0];
totalWorth += res[1];
}
double ret = 0;
if (totalWorth != 0) ret = (totalPoints / totalWorth) * 100;
return Double.parseDouble(decimalFormat.format(ret));
}
// The real work is done at the category level this just sums up the cat totals
public Double getAverageGradeStatistic(String mode) {
double totalPoints = 0.0;
double totalWorth = 0.0;
for (int i=0; i < categories.size(); i++) {
Double[] res = categories.get(i).getAverageGradeStatistic(mode);
totalPoints += res[0];
totalWorth += res[1];
}
double ret = (totalPoints / totalWorth) * 100;
return Double.parseDouble(decimalFormat.format(ret));
}
/**
* Returns the total course average grade if the grade is weighted flag
* is set to true
*
* @return the courses average grade.
*/
private Double getCourseWeightedGrade() {
double weightedGrade = 0.0;
if (!verifyWeights()) return -1.0;
for (int i = 0; i < categories.size(); i++) {
weightedGrade += this.getAssignmentCategory(i).getAssignmentCategoryAverageGrade(students) *
(this.getAssignmentCategory(i).getGradingWeight() / 100);
}
return weightedGrade;
}
private boolean verifyWeights() {
double total = 0.0;
for (int i = 0; i < categories.size(); i++) {
total += categories.get(i).getGradingWeight();
}
if (total != 100.0) return false;
return true;
}
/**
* Get the section identification of the course
*
* @return section identification
*/
public String getSection() {
return section;
}
/**
* Get the name of the building where the course is held
*
* @return building name
*/
public String getBuilding() {
return building;
}
/**
* Get the room number of the course
*
* @return room number
*/
public String getRoomID() {
return roomID;
}
/**
* Get meeting time of the course
*
* @return meeting time
*/
public String getMeetingTime() {
return meetingTime;
}
/**
* Get meeting time of the course
*
* @return meeting time
*/
public String getSemester() {
return semester;
}
/**
* Get index of last assignment edited
*
* @return last assignment index
*/
public Integer getLastAssignmentIndex() {
return lastAssignmentIndex;
}
/**
* Get index of last category edited
*
* @return last category index
*/
public Integer getLastCategoryIndex() {
return lastCategoryIndex;
}
/**
* Returns a string of all of the information about a course
*
* @return complete course overview of description, location, time
*/
public String toString() {
return (courseName + ": " + courseID + " " + courseNumber + "-" + section + ", " + building +
" " + roomID + ", " + meetingTime);
}
/**
* Contstucts a new AssignmentCategory object and adds it into the categegories
* ArrayList structure.
*
* @param ac The name of the assignment category
*/
public void addAssignmentCategory(String ac) {
categories.add(new AssignmentCategory(ac));
}
/**
* Returns the AssignmentCategory object from the index in the categories ArrayList
*
* @return the requested AssignmentCategory object
*/
public AssignmentCategory getAssignmentCategory(int index) {
return categories.get(index);
}
/**
* Returns the List of AssignmentCategory objects
*
* @return the requested AssignmentCategory List
*/
public List<AssignmentCategory> getCategories() {
return categories;
}
/**
* Returns the index of the AssignmentCategory in the categories arrayList
*
* @param name the name of the AssignmentCategory
* @return the index of the AssignmentCategory object
*/
public int getAssignmentCategoryIndex(String name) {
//iterates through AssignmentCategor objects and performs name checking,
//returns index if successful else returns -1
for (int i = 0; i < categories.size(); i++) {
if (name.equals(categories.get(i).getName())) return i;
}
return -1;
}
/**
* Gets the total number of Assignment Categories in the Course
*
* @return the number of assignment categories
*/
public int getNumberOfAssignmentCategories() {
return categories.size();
}
/**
* Should always be used prior to adding a student to see if the name
* is available so there are no duplicates. The teacher will have to
* supply a slightly different name if they have two students with the
* same names.
*
* @param fn The first name of the student
* @param ln The last name of the student
* @return Returns true if the name is available, else false
*/
private boolean nameAvailable(String fn, String ln) {
for(Student x: students) {
if (fn.equals(x.getFirstName()) && ln.equals(x.getLastName())) {
return false;
}
}
return true;
}
/**
* Removes the AssignmentCategory object from the categories ArrayList
*
* @param name the string name of the object
* @return the AssignmentCategory object removed
*/
public AssignmentCategory removeAssignmentCategory(String name) {
try {
return categories.remove(getAssignmentCategoryIndex(name));
} catch (ArrayIndexOutOfBoundsException e) {
return null;
}
}
/**
* Checks name availability, if name is available constructs a new
* Student object and adds it into the students ArrayList structure
* and returns true. If the name is takene the function returns false.
*
* @param sn students actual name
* @param pn students pseudo-name
*/
public boolean addStudent(String fn, String ln) {
if (!nameAvailable(fn, ln)) {
return false;
}
students.add(new Student(fn, ln, pnGenerator.generateName()));
Random generator = new Random();
int ghostAmount = generator.nextInt(5) + 20; //Random number between 5 and 10
for (int i = 0; i < ghostAmount; i++) {
addGhostStudent();
}
return true;
}
/**
* Checks name availability, if name is available constructs a new
* Student object and adds it into the students ArrayList structure
* and returns true. If the name is takene the function returns false.
* Only takes input directly from XML.
*
* @param fn students first name
* @param ln students last name
* @param pn students pseudo-name
*/
public boolean addStudentXML(String fn, String ln, String pn) {
if (!nameAvailable(fn, ln)) {
return false;
}
students.add(new Student(fn, ln, pn));
return true;
}
/**
* Returns the Student object at the specified index
*
* @param index the index of a Student object
* @return the Student object
*/
public Student getStudent(int index) {
return students.get(index);
}
/**
* Returns the List of Student objects
*
* @return the Student object
*/
public List<Student> getStudents() {
return students;
}
public List<Object> getAllStudents() {
return allStudents;
}
/**
* Returns the index of the Student in the student arrayList
*
* @param name the name of the student
* @return the index of the Student object
*/
public int getStudentIndex(String name) {
//iterates through Student objects and performs name checking, returns index if successful else returns -1
for (int i = 0; i < students.size(); i++) {
if (name.equals(students.get(i).getFullName())) return i;
}
return -1;
}
/**
* Removes a Student object from the students ArrayList by a String name param by
* getting their index and calling removeStudent using that index.
*/
public void removeStudent(String name) {
removeStudent(getStudentIndex(name));
}
/**
* Removes a Student object from the students arrayList by the index number
* Archive's that students grades for the teacher's future records
* Turns student and grades into a ghost student
*
* @param index the integer index of the Student object in the students ArrayList
*/
public void removeStudent(int index) {
Student currentStudent = null;
try {
currentStudent = students.remove(index);
} catch (IndexOutOfBoundsException e) {
System.err.println("Caught IndexOutOfBoundsException: " + e.getMessage());
return;
}
currentStudent.archiveStudent(this);
ghostStudents.add(new GhostStudent(currentStudent.getPseudoName()));
}
/**
* Gets the total number of students in a course
*
* @return number of students
*/
public int getNumberOfStudents() {
return students.size();
}
/**
* Constructs a new GhostStudent object and adds it into the fakeStudents ArrayList structure
*/
public void addGhostStudent() {
ghostStudents.add(new GhostStudent(pnGenerator.generateName()));
}
/**
* Constructs a new GhostStudent object and adds it into the fakeStudents ArrayList structure
* using a predefined psuedoName from the XML file
* @param pn ghost students pseudo-name
*/
public void addGhostStudentXML(String pn) {
ghostStudents.add(new GhostStudent(pn));
}
/**
* Returns the GhostStudent object at the specified index
*
* @param index the index of a GhostStudent object
* @return the GhostStudent object
*/
public GhostStudent getGhostStudent(int index) {
return ghostStudents.get(index);
}
/**
* Returns the index of the GhostStudent in the student arrayList
*
* @param name the name of the ghost student
* @return the index of the GhostStudent object
*/
public int getGhostStudentIndex(String name) {
//iterates through GhostStudent objects and performs name checking,
//returns index if successful else returns -1
for (int i = 0; i < ghostStudents.size(); i++) {
if (name.equals(ghostStudents.get(i).getPseudoName())) return i;
}
return -1;
}
/**
* Removes a GhostStudent object from the students ArrayList
*
* @param name the String name of the ghost student in the GhostStudent object
* @return the GhostStudent object removed, null on the object was not in the list
*/
public GhostStudent removeGhostStudent(String name) {
try {
return ghostStudents.remove(getGhostStudentIndex(name));
} catch (ArrayIndexOutOfBoundsException e) {
return null;
}
}
/**
* Removes a GhostStudent object from the students arrayList by the index number
*
* @param index the integer index of the GhostStudent object in the ghostStudents ArrayList
* @return the GhostStudent object removed, null if the index passed is out of bounds
*/
public GhostStudent removeGhostStudent(int index) {
try {
return ghostStudents.remove(index);
} catch (IndexOutOfBoundsException e) {
return null;
}
}
public int getNumberOfGhostStudents() {
return ghostStudents.size();
}
public int getTotalStudents() {
return ghostStudents.size() + students.size();
}
public void setIsGradingWeighted(boolean is) {
isGradingWeighted = is;
}
public void setGhostGrades() {
allStudents.removeAll(allStudents);
Collections.sort(students, Student.PseudoNameComparator);
Collections.sort(ghostStudents, GhostStudent.PseudoNameComparator);
allStudents.addAll(students);
for (int j = 0; j < ghostStudents.size(); j++) {
for (int i = 0; i < allStudents.size(); i++) {
if (allStudents.get(i) instanceof Student) {
Student stud = (Student) allStudents.get(i);
if (ghostStudents.get(j).getPseudoName().compareTo(stud.getPseudoName()) < 0) {
allStudents.add(i, ghostStudents.get(j));
break;
}
}
else {
GhostStudent stud = (GhostStudent) allStudents.get(i);
if (ghostStudents.get(j).getPseudoName().compareTo(stud.getPseudoName()) < 0) {
allStudents.add(i, ghostStudents.get(j));
break;
}
}
}
}
String[] ghostNames = new String[getNumberOfGhostStudents()];
for (int k = 0; k < getNumberOfGhostStudents(); k++) {
ghostNames[k] = getGhostStudent(k).getPseudoName();
}
for (int i = 0; i < getCategories().size(); i++) {
for (int j = 0; j < getAssignmentCategory(i).getAssignments().size(); j++) {
getAssignmentCategory(i).getAssignment(j).setGhostGrades(ghostNames);
}
}
}
/**
* if the course is created in the UI, then set to ture
* @param newCourse set the true if the course is created in the UI
*/
public void setNewCourse(boolean newCourse) {
isNewCourse = newCourse;
}
/**
* Check if the course is new
* @return true if the course is new, otherwise false
*/
public boolean isNewCourse() {
return isNewCourse;
}
}