/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/gradebook/trunk/app/standalone-app/src/test/org/sakaiproject/tool/gradebook/test/GradeMappingTest.java $
* $Id: GradeMappingTest.java 105079 2012-02-24 23:08:11Z ottenhoff@longsight.com $
***********************************************************************************
*
* Copyright (c) 2006, 2007 The Sakai Foundation
*
* 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.test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import junit.framework.Assert;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.service.gradebook.shared.GradingScaleDefinition;
import org.sakaiproject.tool.gradebook.CourseGrade;
import org.sakaiproject.tool.gradebook.CourseGradeRecord;
import org.sakaiproject.tool.gradebook.GradeMapping;
import org.sakaiproject.tool.gradebook.Gradebook;
import org.sakaiproject.tool.gradebook.GradingScale;
import org.sakaiproject.tool.gradebook.LetterGradePlusMinusMapping;
import org.sakaiproject.tool.gradebook.test.support.BackwardCompatabilityBusiness;
public class GradeMappingTest extends GradebookTestBase {
private static Log log = LogFactory.getLog(GradeMappingTest.class);
private BackwardCompatabilityBusiness backwardCompatabilityBusiness;
protected void onSetUpInTransaction() throws Exception {
super.onSetUpInTransaction();
backwardCompatabilityBusiness = (BackwardCompatabilityBusiness)applicationContext.getBean("backwardCompatabilityBusiness");
}
public void testSetGradeMappings() throws Exception {
GradeMapping gradeMapping;
// By default, we get Letter Grades as a default mapping,
// and three possible mappings per gradebook.
String gradebook1Name = "SetGradeMappingsTest1";
gradebookFrameworkService.addGradebook(gradebook1Name, gradebook1Name);
Gradebook gradebook1 = gradebookManager.getGradebook(gradebook1Name);
gradeMapping = gradebook1.getSelectedGradeMapping();
GradeMapping oldStaticDefault = new LetterGradePlusMinusMapping();
Assert.assertTrue(gradeMapping.getName().equals(oldStaticDefault.getName()));
Assert.assertTrue(gradebook1.getGradeMappings().size() == 3);
// Now make LetterGradeMapping the default.
gradebookFrameworkService.setDefaultGradingScale("LetterGradeMapping");
String gradebook2Name = "SetGradeMappingsTest2";
gradebookFrameworkService.addGradebook(gradebook2Name, gradebook2Name);
Gradebook gradebook2 = gradebookManager.getGradebook(gradebook2Name);
gradeMapping = gradebook2.getSelectedGradeMapping();
GradingScale letterGradingScale = gradeMapping.getGradingScale();
Assert.assertTrue(gradeMapping.getName().equals("Letter Grades"));
Assert.assertTrue(gradeMapping.getValue("A").equals(new Double(90)));
// Now replace the LetterGradePlusMinusMapping with LoseWinScale...
ArrayList newMappings = new ArrayList();
GradingScaleDefinition def = new GradingScaleDefinition();
def.setUid("LoseWinScale");
def.setName("Win, Lose, or Draw");
def.setGrades(Arrays.asList(new String[] {"Win", "Draw", "Lose"}));
def.setDefaultBottomPercents(Arrays.asList(new Object[] {new Double(80), new Double(40), new Double(0)}));
newMappings.add(def);
// ... and change the default values of LetterGradeMapping.
def = new GradingScaleDefinition();
def.setUid(letterGradingScale.getUid());
def.setName(letterGradingScale.getName());
List gradesList = letterGradingScale.getGrades();
def.setGrades(new ArrayList(gradesList));
Map bottomPercentsMap = letterGradingScale.getDefaultBottomPercents();
List bottomPercentsList = new ArrayList();
for (int i = 0; i < gradesList.size(); i++) {
String grade = (String)gradesList.get(i);
Double bottomPercent = (Double)bottomPercentsMap.get(grade);
if (i == 0) {
bottomPercent = new Double(89);
}
bottomPercentsList.add(bottomPercent);
}
def.setDefaultBottomPercents(bottomPercentsList);
newMappings.add(def);
gradebookFrameworkService.setAvailableGradingScales(newMappings);
// Make sure a new gradebook is as expected.
String gradebook3Name = "SetGradeMappingsTest3";
gradebookFrameworkService.addGradebook(gradebook3Name, gradebook3Name);
Gradebook gradebook3 = gradebookManager.getGradebook(gradebook3Name);
gradeMapping = gradebook3.getSelectedGradeMapping();
Assert.assertTrue(gradeMapping.getValue("A").equals(new Double(89)));
Assert.assertTrue(gradebook3.getGradeMappings().size() == 2);
GradeMapping newGradeMapping = null;
for (Iterator iter = gradebook3.getGradeMappings().iterator(); iter.hasNext() && (newGradeMapping == null); ) {
GradeMapping gm = (GradeMapping)iter.next();
if (!gm.getId().equals(gradeMapping.getId())) {
newGradeMapping = gm;
}
}
gradebook3.setSelectedGradeMapping(newGradeMapping);
gradebookManager.updateGradebook(gradebook3);
Assert.assertTrue(gradebook3.getSelectedGradeMapping().getName().equals("Win, Lose, or Draw"));
// Make sure the old gradebook doesn't change until we tell it to.
gradebook2 = gradebookManager.getGradebook(gradebook2Name);
gradeMapping = gradebook2.getSelectedGradeMapping();
Assert.assertTrue(gradeMapping.getValue("A").equals(new Double(90)));
gradeMapping.setDefaultValues();
Assert.assertTrue(gradeMapping.getValue("A").equals(new Double(89)));
}
public void testBackwardCompatability() throws Exception {
String gradebookName = "PreTemplateGB";
backwardCompatabilityBusiness.addGradebook(gradebookName, gradebookName);
Gradebook gradebook = gradebookManager.getGradebook(gradebookName);
// Play the old songs.
GradeMapping gradeMapping = gradebook.getSelectedGradeMapping();
GradeMapping oldStaticDefault = new LetterGradePlusMinusMapping();
Assert.assertTrue(gradeMapping.getName().equals(oldStaticDefault.getName()));
Assert.assertTrue(gradebook.getGradeMappings().size() == 3);
}
public void testBadDefaultGradingScale() throws Exception {
List newMappings = new ArrayList();
GradingScaleDefinition def = new GradingScaleDefinition();
def.setUid("JustOneScale");
def.setName("Just One Grading Scale");
def.setGrades(Arrays.asList(new String[] {"Win", "Draw", "Lose"}));
def.setDefaultBottomPercents(Arrays.asList(new Object[] {new Double(80), new Double(40), new Double(0)}));
newMappings.add(def);
gradebookFrameworkService.setAvailableGradingScales(newMappings);
gradebookFrameworkService.setDefaultGradingScale("NoSuchGradeMapping");
String gradebook1Name = "SetGradeMappingsTest1";
if (log.isInfoEnabled()) log.info("Ignore the upcoming warning about no default...");
gradebookFrameworkService.addGradebook(gradebook1Name, gradebook1Name);
Gradebook gradebook1 = gradebookManager.getGradebook(gradebook1Name);
GradeMapping gradeMapping = gradebook1.getSelectedGradeMapping();
// The service should have defaulted the mapping to the only
// one available.
Assert.assertTrue(gradeMapping.getName().equals(def.getName()));
}
public void testManualOnlyGrades() throws Exception {
String scaleUid = "TheNineties";
List<GradingScaleDefinition> newMappings = new ArrayList<GradingScaleDefinition>();
GradingScaleDefinition def = new GradingScaleDefinition();
def.setUid(scaleUid);
def.setName("Nineties Grading");
def.setGrades(Arrays.asList(new String[] {"Wicked", "Slacker", "Whatever", "Whoa", "As If"}));
def.setDefaultBottomPercents(Arrays.asList(new Object[] {new Double(100), new Double(0), null, "", null}));
newMappings.add(def);
gradebookFrameworkService.setAvailableGradingScales(newMappings);
gradebookFrameworkService.setDefaultGradingScale(scaleUid);
String gradebookUid = "ManualGB";
gradebookFrameworkService.addGradebook(gradebookUid, gradebookUid);
integrationSupport.createCourse(gradebookUid, gradebookUid, false, false, false);
Gradebook gradebook = gradebookManager.getGradebook(gradebookUid);
GradeMapping gradeMapping = gradebook.getSelectedGradeMapping();
Assert.assertTrue(gradeMapping.getName().equals(def.getName()));
// Make sure the ordering sticks.
Collection<String> grades = gradeMapping.getGrades();
int pos = 0;
for (String grade : grades) {
Assert.assertTrue(grade.equals(def.getGrades().get(pos++)));
}
// Make sure we get the right bottom grade.
String grade = gradeMapping.getGrade(1.0);
Assert.assertTrue(grade.equals("Slacker"));
grade = gradeMapping.getGrade(0.0);
Assert.assertTrue(grade.equals("Slacker"));
// To make testing dead-simple, we make student UIDs equal to
// the grades we intent to give them.
Set<String> students = new HashSet<String>(def.getGrades());
addUsersEnrollments(gradebook, students);
CourseGrade courseGrade = gradebookManager.getCourseGrade(gradebook.getId());
List<CourseGradeRecord> gradeRecords = new ArrayList<CourseGradeRecord>();
for (String studentAndGrade : students) {
CourseGradeRecord record = new CourseGradeRecord(courseGrade, studentAndGrade);
record.setEnteredGrade(studentAndGrade);
gradeRecords.add(record);
}
gradebookManager.updateCourseGradeRecords(courseGrade, gradeRecords);
// Make sure we can assign a manual-only grade to a student.
CourseGradeRecord gradeRecord = gradebookManager.getStudentCourseGradeRecord(gradebook, "Whoa");
Assert.assertTrue(gradeRecord.getDisplayGrade().equals("Whoa"));
// Test the sorting of assigned grades. Need to make sure that the manual-only
// entered grades keep their positions relative to the bottom of the grading scale.
gradeRecords = gradebookManager.getPointsEarnedCourseGradeRecordsWithStats(courseGrade, students);
// a) Shuffle the records by sorting them alphabetically.
Comparator<CourseGradeRecord> comparator = new Comparator<CourseGradeRecord>() {
public int compare(CourseGradeRecord cgr1, CourseGradeRecord cgr2) {
return cgr1.getStudentId().compareTo(cgr2.getStudentId());
}
};
Collections.sort(gradeRecords, comparator);
Assert.assertTrue(gradeRecords.get(0).getStudentId().equals("As If"));
// b) Now try the "override grade" sort, which should be percentage based except
// for the manual-only grades.
Collections.sort(gradeRecords, CourseGradeRecord.getOverrideComparator(gradeMapping));
Collections.reverse(gradeRecords); // Grading scale is highest to lowest.
pos = 0;
for (String gradeCode : grades) {
Assert.assertTrue(gradeCode.equals(gradeRecords.get(pos++).getDisplayGrade()));
}
// Make sure we can't accidentally get a letter grade from a null input.
grade = gradeMapping.getGrade(null);
Assert.assertTrue(grade == null);
// Make sure manual-only grades aren't included in calculating the average course grade,
// but that null (calculated) grades are.
List<CourseGradeRecord> newGradeRecords = new ArrayList<CourseGradeRecord>();
gradeRecord = gradeRecords.remove(0);
gradeRecord.setEnteredGrade("Wicked"); // Worth 100%
newGradeRecords.add(gradeRecord);
gradeRecord = gradeRecords.remove(0);
gradeRecord.setEnteredGrade(null); // Worth 0
newGradeRecords.add(gradeRecord);
for (CourseGradeRecord record : gradeRecords) {
record.setEnteredGrade("Whatever"); // Manual-only
newGradeRecords.add(record);
}
gradebookManager.updateCourseGradeRecords(courseGrade, newGradeRecords);
gradebookManager.getPointsEarnedCourseGradeRecordsWithStats(courseGrade, students);
//comment it out because of new calculation method
// Assert.assertTrue(courseGrade.getMean() == 50.0);
}
public void testResetDefaultGradeScale() throws Exception {
// Because the default grading scale is set via a Java property rather than through
// the database, the last value set by these tests will hang around polluting the JVM.
// Do a little cleanup before leaving.
gradebookFrameworkService.setDefaultGradingScale("LetterGradePlusMinusMapping");
}
}