/********************************************************************************** * * $Id: CourseGradeRecord.java 130402 2013-10-11 18:54:57Z matthew@longsight.com $ * *********************************************************************************** * * Copyright (c) 2005, 2006, 2007, 2008 The Sakai Foundation, The MIT Corporation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * **********************************************************************************/ package org.sakaiproject.tool.gradebook; import java.math.BigDecimal; import java.util.Comparator; import java.util.List; import org.apache.commons.lang.StringUtils; import org.sakaiproject.service.gradebook.shared.GradebookService; /** * A CourseGradeRecord is a grade record that can be associated with a CourseGrade. * * @author <a href="mailto:jholtzman@berkeley.edu">Josh Holtzman</a> */ public class CourseGradeRecord extends AbstractGradeRecord { private String enteredGrade; private Double autoCalculatedGrade; // Not persisted private Double calculatedPointsEarned; // Not persisted private Double totalPointsPossible; // Not persisted public static Comparator<CourseGradeRecord> calcComparator; static { calcComparator = new Comparator<CourseGradeRecord>() { public int compare(CourseGradeRecord cgr1, CourseGradeRecord cgr2) { if((cgr1 == null || cgr2 == null) || (cgr1.getGradeAsPercentage() == null && cgr2.getGradeAsPercentage() == null)) { return 0; } if(cgr1 == null || cgr1.getGradeAsPercentage() == null) { return -1; } if(cgr2 == null || cgr2.getGradeAsPercentage() == null) { return 1; } //SAK-12017 - Commented out as getPointsEarned is no longer an accurate comparator // due to nulls no longer being calculated in to the Course Grade //return cgr1.getPointsEarned().compareTo(cgr2.getPointsEarned()); // Better to use getGradeAsPercentage return cgr1.getGradeAsPercentage().compareTo(cgr2.getGradeAsPercentage()); } }; } public static Comparator<CourseGradeRecord> getOverrideComparator(final GradeMapping mapping) { return new Comparator<CourseGradeRecord>() { public int compare(CourseGradeRecord cgr1, CourseGradeRecord cgr2) { if(cgr1 == null && cgr2 == null) { return 0; } if(cgr1 == null) { return -1; } if(cgr2 == null) { return 1; } String enteredGrade1 = StringUtils.trimToEmpty(cgr1.getEnteredGrade()); String enteredGrade2 = StringUtils.trimToEmpty(cgr2.getEnteredGrade()); // Grading scales are always defined in descending order. List<String> grades = mapping.getGradingScale().getGrades(); int gradePos1 = -1; int gradePos2 = -1; for (int i = 0; (i < grades.size()) && ((gradePos1 == -1) || (gradePos2 == -1)); i++) { String grade = grades.get(i); if (grade.equals(enteredGrade1)) gradePos1 = i; if (grade.equals(enteredGrade2)) gradePos2 = i; } return gradePos2 - gradePos1; } }; } /** * The graderId and dateRecorded properties will be set explicitly by the * grade manager before the database is updated. * @param courseGrade * @param studentId */ public CourseGradeRecord(CourseGrade courseGrade, String studentId) { this.gradableObject = courseGrade; this.studentId = studentId; } /** * Default no-arg constructor */ public CourseGradeRecord() { super(); } /** * This method will fail unless this course grade was fetched "with statistics", * since it relies on having the total number of points possible available to * calculate the percentage. * * @see org.sakaiproject.tool.gradebook.AbstractGradeRecord#getGradeAsPercentage() */ public Double getGradeAsPercentage() { if(enteredGrade == null) { return autoCalculatedGrade; } else { return getCourseGrade().getGradebook().getSelectedGradeMapping().getValue(enteredGrade); } } /** * Convenience method to get the correctly cast CourseGrade that this * CourseGradeRecord references. * * @return CourseGrade referenced by this GradableObject */ public CourseGrade getCourseGrade() { return (CourseGrade)super.getGradableObject(); } /** * @return Returns the enteredGrade. */ public String getEnteredGrade() { return enteredGrade; } /** * @param enteredGrade The enteredGrade to set. */ public void setEnteredGrade(String enteredGrade) { this.enteredGrade = enteredGrade; } /** * @return Returns the autoCalculatedGrade. */ public Double getAutoCalculatedGrade() { return autoCalculatedGrade; } public Double getPointsEarned() { return calculatedPointsEarned; } /** * @return Returns the displayGrade. */ public String getDisplayGrade() { if(enteredGrade != null) { return enteredGrade; } else { return getCourseGrade().getGradebook().getSelectedGradeMapping().getGrade(autoCalculatedGrade); } } /** * @see org.sakaiproject.tool.gradebook.AbstractGradeRecord#isCourseGradeRecord() */ public boolean isCourseGradeRecord() { return true; } /** * For use by the Course Grade UI. */ public Double getNonNullAutoCalculatedGrade() { Double percent = getAutoCalculatedGrade(); if (percent == null) { percent = Double.valueOf(0); } return percent; } public void initNonpersistentFields(double totalPointsPossible, double totalPointsEarned) { Double percentageEarned; this.totalPointsPossible = totalPointsPossible; calculatedPointsEarned = totalPointsEarned; BigDecimal bdTotalPointsPossible = new BigDecimal(totalPointsPossible); BigDecimal bdTotalPointsEarned = new BigDecimal(totalPointsEarned); if (totalPointsPossible == 0.0) { percentageEarned = null; } else { percentageEarned = Double.valueOf(bdTotalPointsEarned.divide(bdTotalPointsPossible, GradebookService.MATH_CONTEXT).multiply(new BigDecimal("100")).doubleValue()); } autoCalculatedGrade = percentageEarned; } //Added by -Qu for totalPoints implementation in GB2 bugid:4371 9/2011 public void setCalculatedPointsEarned(double literalTotalPointsEarned){ this.calculatedPointsEarned = literalTotalPointsEarned; } public void initNonpersistentFields(double totalPointsPossible, double totalPointsEarned, double literalTotalPointsEarned) { Double percentageEarned; //calculatedPointsEarned = totalPointsEarned; calculatedPointsEarned = literalTotalPointsEarned; this.totalPointsPossible = totalPointsPossible; BigDecimal bdTotalPointsPossible = new BigDecimal(totalPointsPossible); BigDecimal bdTotalPointsEarned = new BigDecimal(totalPointsEarned); if (totalPointsPossible <= 0.0) { percentageEarned = null; } else { percentageEarned = Double.valueOf(bdTotalPointsEarned.divide(bdTotalPointsPossible, GradebookService.MATH_CONTEXT).multiply(new BigDecimal("100")).doubleValue()); } autoCalculatedGrade = percentageEarned; } public Double getCalculatedPointsEarned() { return calculatedPointsEarned; } public void setAutoCalculatedGrade(Double autoCalculatedGrade) { this.autoCalculatedGrade = autoCalculatedGrade; } public Double getTotalPointsPossible() { return totalPointsPossible; } public void setTotalPointsPossible(Double totalPointsPossible) { this.totalPointsPossible = totalPointsPossible; } }