/**********************************************************************************
*
* $Id: GradebookSetupBean.java 20001 2007-04-01 19:41:33Z wagnermr@iupui.edu $
*
***********************************************************************************
*
* 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.ui;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.tool.gradebook.Assignment;
import org.sakaiproject.tool.gradebook.Category;
import org.sakaiproject.tool.gradebook.GradeMapping;
import org.sakaiproject.tool.gradebook.Gradebook;
import org.sakaiproject.tool.gradebook.LetterGradePercentMapping;
import org.sakaiproject.tool.gradebook.Permission;
import org.sakaiproject.tool.gradebook.jsf.FacesUtil;
import org.sakaiproject.service.gradebook.shared.ConflictingCategoryNameException;
import org.sakaiproject.service.gradebook.shared.GradebookService;
import org.sakaiproject.service.gradebook.shared.StaleObjectModificationException;
import org.sakaiproject.component.cover.ServerConfigurationService;
public class GradebookSetupBean extends GradebookDependentBean implements Serializable
{
private static final Log logger = LogFactory.getLog(GradebookSetupBean.class);
private String gradeEntryMethod;
private String categorySetting;
private boolean showDropHighestDisplayed;
private boolean showDropLowestDisplayed;
private boolean showKeepHighestDisplayed;
private boolean anyCategoriesWithDrops;
private List categories;
private Gradebook localGradebook;
private List categoriesToRemove;
private double regularTotal;
private double neededTotal;
private double adjustmentTotal;
private double grandTotal;
private String pageName;
private List letterGradeRows;
private List letterGradesList;
private LetterGradePercentMapping lgpm;
private LetterGradePercentMapping defaultLGPM;
private boolean enableLetterGrade = false;
private boolean isValidWithCourseGrade = true;
private boolean isLetterGrade = false;
private boolean isPointGrade = false;
private boolean isPercentageGrade = false;
private static final int NUM_EXTRA_CAT_ENTRIES = 50;
private static final String ENTRY_OPT_POINTS = "points";
private static final String ENTRY_OPT_PERCENT = "percent";
private static final String ENTRY_OPT_LETTER = "letterGrade";
private static final String CATEGORY_OPT_NONE = "noCategories";
private static final String CATEGORY_OPT_CAT_ONLY = "onlyCategories";
private static final String CATEGORY_OPT_CAT_AND_WEIGHT = "categoriesAndWeighting";
private static final String DROP_OPT_HIDE = "hideDrop";
private static final String DROP_OPT_SHOW = "showDrop";
private static final String GB_SETUP_PAGE = "gradebookSetup";
private static final String GB_OVERVIEW_PAGE = "overview";
private static final String ROW_INDEX_PARAM = "rowIndex";
protected void init()
{
if (localGradebook == null)
{
localGradebook = getGradebook();
categories = getGradebookManager().getCategoriesWithStats(getGradebookId(),Assignment.DEFAULT_SORT, true, Category.SORT_BY_NAME, true);
populateCategoryAssignments(categories);
convertWeightsFromDecimalsToPercentages();
intializeGradeEntryAndCategorySettings();
categoriesToRemove = new ArrayList();
}
calculateRunningTotal();
defaultLGPM = getGradebookManager().getDefaultLetterGradePercentMapping();
letterGradesList = new ArrayList(defaultLGPM.getGradeMap().keySet());
Collections.sort(letterGradesList, GradebookService.lettergradeComparator);
lgpm = getGradebookManager().getLetterGradePercentMapping(localGradebook);
if (lgpm != null && lgpm.getGradeMap().size() > 0) {
initLetterGradeRows();
}
if(getAnyCategoriesWithDropHighest()) {
showDropHighestDisplayed = true;
} else {
showDropHighestDisplayed = false;
}
if(getAnyCategoriesWithDropLowest()) {
showDropLowestDisplayed = true;
} else {
showDropLowestDisplayed = false;
}
if(getAnyCategoriesWithKeepHighest()) {
showKeepHighestDisplayed = true;
} else {
showKeepHighestDisplayed = false;
}
}
/*
* For category requests to drop scores, need their assignments populated
* so that system can determine eligibility of category to drop scores
* if assignments have unequal pointsPossible, then they cannot drop scores
*/
private void populateCategoryAssignments(List categories) {
if(categories != null) {
for(Object obj : categories) {
if(obj instanceof Category) {
Category category = (Category)obj;
List assignments = category.getAssignmentList();
if(category.isDropScores() && (assignments == null || assignments.size() == 0)) { // don't populate, if assignments are already in category (to improve performance)
assignments = getGradebookManager().getAssignmentsForCategory(category.getId());
List assignmentsToUpdate = new ArrayList();
// only include assignments which are not adjustments must not update adjustment item pointsPossible
for(Object o : assignments) {
if(o instanceof Assignment) {
Assignment assignment = (Assignment)o;
if(!Assignment.item_type_adjustment.equals(assignment.getItemType())) {
assignmentsToUpdate.add(assignment);
}
}
}
if(assignments != null && assignments.size() > 0) {
category.setAssignmentList(assignmentsToUpdate);
}
}
}
}
}
}
// private void removeDropHighestFromCategories() {
// if(categories != null) {
// for(Object obj : categories) {
// if(obj instanceof Category) {
// Category category = (Category)obj;
// category.setDropHighest(0);
// if(category.getDrop_lowest() == 0 && category.getKeepHighest() == 0) {
// category.setItemValue(0.0);
// }
// }
// }
// }
// }
//
// private void removeDropLowestFromCategories() {
// if(categories != null) {
// for(Object obj : categories) {
// if(obj instanceof Category) {
// Category category = (Category)obj;
// category.setDrop_lowest(0);
// if(category.getDropHighest() == 0 && category.getKeepHighest() == 0) {
// category.setItemValue(0.0);
// }
// }
// }
// }
// }
//
// private void removeKeepHighestFromCategories() {
// if(categories != null) {
// for(Object obj : categories) {
// if(obj instanceof Category) {
// Category category = (Category)obj;
// category.setKeepHighest(0);
// if(category.getDrop_lowest() == 0 && category.getDropHighest() == 0) {
// category.setItemValue(0.0);
// }
// }
// }
// }
// }
private void initLetterGradeRows() {
letterGradeRows = new ArrayList();
for (Iterator iter = letterGradesList.iterator(); iter.hasNext(); ) {
String grade = (String)iter.next();
// Bottom grades (with a lower bound of 0%)
Double d = defaultLGPM.getValue(grade);
boolean editable = ((d != null) && (d.doubleValue() > 0.0));
letterGradeRows.add(new LetterGradeRow(lgpm, grade, editable));
}
}
private void reset()
{
localGradebook = null;
categories = null;
categorySetting = null;
gradeEntryMethod = null;
isValidWithCourseGrade = true;
}
public Gradebook getLocalGradebook()
{
return localGradebook;
}
public String getGradeEntryMethod()
{
return gradeEntryMethod;
}
public void setGradeEntryMethod(String gradeEntryMethod)
{
this.gradeEntryMethod = gradeEntryMethod;
}
public String getCategorySetting()
{
return categorySetting;
}
public void setCategorySetting(String categorySetting)
{
this.categorySetting = categorySetting;
}
public boolean getShowDropHighestDisplayed() {
return showDropHighestDisplayed;
}
public void setShowDropHighestDisplayed(boolean showDropHighestDisplayed) {
this.showDropHighestDisplayed = showDropHighestDisplayed;
}
public boolean getShowDropLowestDisplayed() {
return showDropLowestDisplayed;
}
public void setShowDropLowestDisplayed(boolean showDropLowestDisplayed) {
this.showDropLowestDisplayed = showDropLowestDisplayed;
}
public boolean getShowKeepHighestDisplayed() {
return showKeepHighestDisplayed;
}
public void setShowKeepHighestDisplayed(boolean showKeepHighestDisplayed) {
this.showKeepHighestDisplayed = showKeepHighestDisplayed;
}
public void setAnyCategoriesWithDropHighest(boolean anyCategoriesWithDropHighest) {
}
public void setAnyCategoriesWithDropLowest(boolean anyCategoriesWithDropLowest) {
}
public void setAnyCategoriesWithKeepHighest(boolean anyCategoriesWithKeepHighest) {
}
public boolean getAnyCategoriesWithDropHighest() {
boolean anyDrops = false;
if(categories != null) {
for(Object obj : categories) {
if(obj instanceof Category) {
Category category = (Category)obj;
anyDrops = category.getDropHighest() > 0;
setShowDropHighestDisplayed(anyDrops);
if(anyDrops)
break;
}
}
}
return anyDrops;
}
public boolean getAnyCategoriesWithDropLowest() {
boolean anyDrops = false;
if(categories != null) {
for(Object obj : categories) {
if(obj instanceof Category) {
Category category = (Category)obj;
anyDrops = category.getDrop_lowest() > 0;
setShowDropLowestDisplayed(anyDrops);
if(anyDrops)
break;
}
}
}
return anyDrops;
}
public boolean getAnyCategoriesWithKeepHighest() {
boolean anyDrops = false;
if(categories != null) {
for(Object obj : categories) {
if(obj instanceof Category) {
Category category = (Category)obj;
anyDrops = category.getKeepHighest() > 0;
setShowKeepHighestDisplayed(anyDrops);
if(anyDrops)
break;
}
}
}
return anyDrops;
}
/**
*
* @return String value of display:none or display:block for initial display
* of grade entry scale
*/
public String getDisplayGradeEntryScaleStyle()
{
if (gradeEntryMethod != null && gradeEntryMethod.equals(ENTRY_OPT_LETTER))
return "display:block;";
else
return "display:none;";
}
/**
* Returns true if categories are used in gb
* @return
*/
public boolean isDisplayCategories()
{
return !categorySetting.equals(CATEGORY_OPT_NONE);
}
/**
* Returns true if weighting is used in gb
* @return
*/
public boolean isDisplayWeighting()
{
return categorySetting.equals(CATEGORY_OPT_CAT_AND_WEIGHT);
}
/**
* Save gradebook settings (including categories and weighting)
* @return
*/
public String processSaveGradebookSetup()
{
if (gradeEntryMethod == null || (!gradeEntryMethod.equals(ENTRY_OPT_POINTS) &&
!gradeEntryMethod.equals(ENTRY_OPT_PERCENT) && !gradeEntryMethod.equals(ENTRY_OPT_LETTER)))
{
FacesUtil.addErrorMessage(getLocalizedString("grade_entry_invalid"));
return "failure";
}
if(!isConflictWithCourseGrade())
{
isValidWithCourseGrade = false;
return null;
}
else
isValidWithCourseGrade = true;
int origialGradeType = localGradebook.getGrade_type();
if (gradeEntryMethod.equals(ENTRY_OPT_PERCENT))
{
localGradebook.setGrade_type(GradebookService.GRADE_TYPE_PERCENTAGE);
}
else if (gradeEntryMethod.equals(ENTRY_OPT_LETTER))
{
localGradebook.setGrade_type(GradebookService.GRADE_TYPE_LETTER);
}
else
{
localGradebook.setGrade_type(GradebookService.GRADE_TYPE_POINTS);
}
// SAK-10879 - comment out ability to customize lgpm
/*
if (lgpm != null) {
if (!isMappingValid(lgpm)) {
return "failure";
}
LetterGradePercentMapping originalLgpm = getGradebookManager().getLetterGradePercentMapping(localGradebook);
boolean lgpmUpdate = false;
for (Iterator iter = letterGradesList.iterator(); iter.hasNext(); ) {
String grade = (String) iter.next();
Double originalPercent = null;
if (originalLgpm != null)
originalPercent = (Double) originalLgpm.getValue(grade);
Double currentPercent = (Double) lgpm.getValue(grade);
if (!originalPercent.equals(currentPercent)) {
lgpmUpdate = true;
break;
}
}
if (lgpmUpdate) {
getGradebookManager().saveOrUpdateLetterGradePercentMapping(lgpm.getGradeMap(), localGradebook);
}
}*/
if (categorySetting == null || (!categorySetting.equals(CATEGORY_OPT_CAT_ONLY) &&
!categorySetting.equals(CATEGORY_OPT_CAT_AND_WEIGHT) && !categorySetting.equals(CATEGORY_OPT_NONE)))
{
FacesUtil.addErrorMessage(getLocalizedString("cat_setting_invalid"));
return "failure";
}
int origCategorySetting = localGradebook.getCategory_type();
if (categorySetting.equals(CATEGORY_OPT_NONE))
{
localGradebook.setCategory_type(GradebookService.CATEGORY_TYPE_NO_CATEGORY);
// remove current categories
List gbCategories = getGradebookManager().getCategories(localGradebook.getId());
if (gbCategories != null && !gbCategories.isEmpty())
{
Iterator removeIter = gbCategories.iterator();
while (removeIter.hasNext())
{
Category removeCat = (Category) removeIter.next();
getGradebookManager().removeCategory(removeCat.getId());
}
}
// check to see if any permissions need to be removed
List sections = getAllSections();
List gbPermissions = getGradebookManager().getPermissionsForGB(localGradebook.getId());
if (gbPermissions != null) {
for (Iterator permIter = gbPermissions.iterator(); permIter.hasNext();) {
Permission perm = (Permission) permIter.next();
// if there is a specific category associated with this permission or if
// there are no sections defined in the site, we need to delete this permission
if (perm.getCategoryId() != null || sections == null || sections.size() == 0) {
logger.debug("Permission " + perm.getId() + " was deleted b/c gb changed to no categories");
getGradebookManager().deletePermission(perm);
}
}
}
getGradebookManager().updateGradebook(localGradebook);
reset();
FacesUtil.addRedirectSafeMessage(getLocalizedString("gb_save_msg"));
return null;
}
// if we are going from no categories to having categories, we need to set
// counted = false for all existing assignments b/c the category will
// now be "unassigned"
/*if (localGradebook.getCategory_type() == GradebookService.CATEGORY_TYPE_NO_CATEGORY &&
(categorySetting.equals(CATEGORY_OPT_CAT_ONLY) || categorySetting.equals(CATEGORY_OPT_CAT_AND_WEIGHT))) {
List assignmentsInGb = getGradebookManager().getAssignments(getGradebookId(), Assignment.DEFAULT_SORT, true);
if (assignmentsInGb != null && !assignmentsInGb.isEmpty()) {
Iterator assignIter = assignmentsInGb.iterator();
while (assignIter.hasNext()) {
Assignment assignment = (Assignment) assignIter.next();
assignment.setCounted(false);
getGradebookManager().updateAssignment(assignment);
}
}
} */
if (categorySetting.equals(CATEGORY_OPT_CAT_ONLY))
{
localGradebook.setCategory_type(GradebookService.CATEGORY_TYPE_ONLY_CATEGORY);
// set all weighting to 0 for existing categories
Iterator unweightIter = categories.iterator();
while (unweightIter.hasNext())
{
Category unweightCat = (Category) unweightIter.next();
unweightCat.setWeight(new Double(0));
}
}
else if (categorySetting.equals(CATEGORY_OPT_CAT_AND_WEIGHT))
{
// we need to make sure all of the weights add up to 100
calculateRunningTotal();
if (neededTotal != 0)
{
FacesUtil.addErrorMessage(getLocalizedString("cat_weight_total_not_100"));
return "failure";
}
localGradebook.setCategory_type(GradebookService.CATEGORY_TYPE_WEIGHTED_CATEGORY);
}
// if(getShowDropHighestDisplayed() == false
// || localGradebook.getGrade_type()==GradebookService.GRADE_TYPE_LETTER // when Grade Entry change from Points/Percentage to Letter Grades also remove drops from categories
// && (origialGradeType==GradebookService.GRADE_TYPE_POINTS
// || origialGradeType==GradebookService.GRADE_TYPE_PERCENTAGE)) { // handles the case when user switches grade entry method
// removeDropHighestFromCategories();
// }
// if(getShowDropLowestDisplayed() == false
// || localGradebook.getGrade_type()==GradebookService.GRADE_TYPE_LETTER // when Grade Entry change from Points/Percentage to Letter Grades also remove drops from categories
// && (origialGradeType==GradebookService.GRADE_TYPE_POINTS
// || origialGradeType==GradebookService.GRADE_TYPE_PERCENTAGE)) { // handles the case when user switches grade entry method
// removeDropLowestFromCategories();
// }
// if(getShowKeepHighestDisplayed() == false
// || localGradebook.getGrade_type()==GradebookService.GRADE_TYPE_LETTER // when Grade Entry change from Points/Percentage to Letter Grades also remove drops from categories
// && (origialGradeType==GradebookService.GRADE_TYPE_POINTS
// || origialGradeType==GradebookService.GRADE_TYPE_PERCENTAGE)) { // handles the case when user switches grade entry method
// removeKeepHighestFromCategories();
// }
// do drop scores validation before on all categories before the database transactions begins
Iterator itr = categories.iterator();
while (itr.hasNext()) {
Object obj = itr.next();
if(!(obj instanceof Category)) {
continue;
}
Category uiCategory = (Category) obj;
Long categoryId = uiCategory.getId();
String categoryName = uiCategory.getName();
// do cross validation
if((uiCategory.getDrop_lowest() > 0 || uiCategory.getDropHighest() > 0) && uiCategory.getKeepHighest() > 0) {
FacesUtil.addErrorMessage(getLocalizedString("cat_keep_and_drop_mutually_exclusive"));
return "failure";
}
if(uiCategory.getItemValue() < 0 && (uiCategory.getDrop_lowest() > 0 || uiCategory.getDropHighest() > 0 || uiCategory.getKeepHighest() > 0)) {
FacesUtil.addErrorMessage(getLocalizedString("cat_pointvalue_not_valid"));
return "failure";
}
if(uiCategory.isDropScores()) {
if (!uiCategory.isAssignmentsEqual()) {
if(gradeEntryMethod != null && gradeEntryMethod.equals(ENTRY_OPT_POINTS)) {
FacesUtil.addErrorMessage(getLocalizedString("cat_pointvalue_not_valid"));
} else if(gradeEntryMethod != null && gradeEntryMethod.equals(ENTRY_OPT_PERCENT)) {
FacesUtil.addErrorMessage(getLocalizedString("cat_relativeweight_not_valid"));
}
return "failure";
}
}
// we will be updating an existing category
if (categoryId != null) {
Category updatedCategory = getGradebookManager().getCategory(categoryId);
if(updatedCategory.isDropScores()) {
if(!updatedCategory.isAssignmentsEqual()) {
if (gradeEntryMethod != null && gradeEntryMethod.equals(ENTRY_OPT_POINTS)) {
FacesUtil.addErrorMessage(getLocalizedString("cat_point_values_unequal"));
}
if (gradeEntryMethod != null && gradeEntryMethod.equals(ENTRY_OPT_PERCENT)) {
FacesUtil.addErrorMessage(getLocalizedString("cat_rel_weights_unequal"));
}
return "failure";
}
}
}
}
/* now we need to iterate through the categories and
1) remove categories
2) add any new categories
3) update existing categories */
Iterator catIter = categories.iterator();
while (catIter.hasNext())
{
try {
Object obj = catIter.next();
if(!(obj instanceof Category)){
continue;
}
Category uiCategory = (Category) obj;
Long categoryId = uiCategory.getId();
String categoryName = uiCategory.getName();
if ((categoryName == null || categoryName.trim().length() < 1) && categoryId != null)
{
categoriesToRemove.add(categoryId);
}
if (categoryName != null && categoryName.length() > 0)
{
// treat blank weight fields as 0
if (localGradebook.getCategory_type() == GradebookService.CATEGORY_TYPE_WEIGHTED_CATEGORY &&
uiCategory.getWeight() == null) {
uiCategory.setWeight(new Double(0));
}
if ((localGradebook.getCategory_type() != GradebookService.CATEGORY_TYPE_WEIGHTED_CATEGORY
&& localGradebook.getCategory_type() != GradebookService.CATEGORY_TYPE_ONLY_CATEGORY)
|| uiCategory.isExtraCredit() == null)
{
uiCategory.setExtraCredit(null);
}
if (categoryId == null) {
// must be a new or blank category
if (uiCategory.getWeight() != null && uiCategory.getWeight().doubleValue() > 0) {
getGradebookManager().createCategory(localGradebook.getId(), categoryName.trim(), new Double(uiCategory.getWeight().doubleValue()/100), uiCategory.getDrop_lowest(), uiCategory.getDropHighest(), uiCategory.getKeepHighest(), uiCategory.isExtraCredit());
} else {
getGradebookManager().createCategory(localGradebook.getId(), categoryName.trim(), uiCategory.getWeight(), uiCategory.getDrop_lowest(), uiCategory.getDropHighest(), uiCategory.getKeepHighest(), uiCategory.isExtraCredit());
}
}
else {
// we are updating an existing category
Category updatedCategory = getGradebookManager().getCategory(categoryId);
updatedCategory.setName(categoryName.trim());
if (uiCategory.getWeight() != null && uiCategory.getWeight().doubleValue() > 0) {
updatedCategory.setWeight(new Double (uiCategory.getWeight().doubleValue()/100));
} else {
updatedCategory.setWeight(uiCategory.getWeight());
}
if (uiCategory.isExtraCredit()!=null)
{
updatedCategory.setExtraCredit(uiCategory.isExtraCredit());
}
updatedCategory.setDrop_lowest(uiCategory.getDrop_lowest());
updatedCategory.setDropHighest(uiCategory.getDropHighest());
updatedCategory.setKeepHighest(uiCategory.getKeepHighest());
// if(uiCategory.getItemValue() != null && uiCategory.getItemValue().doubleValue() > 0) {
// updatedCategory.setItemValue(uiCategory.getItemValue());
// } else {
// updatedCategory.setItemValue(0.0);
// }
if(updatedCategory.isDropScores() && updatedCategory.isAssignmentsEqual()) {
if((updatedCategory.getAssignmentList() == null || updatedCategory.getAssignmentList().size() == 0)) { // don't populate, if assignments are already in category (to improve performance)
List assignments = getGradebookManager().getAssignmentsForCategory(updatedCategory.getId());
List assignmentsToUpdate = new ArrayList();
for(Object o : assignments) { // must not update adjustment item pointsPossible
if(o instanceof Assignment) {
Assignment assignment = (Assignment)o;
if(!Assignment.item_type_adjustment.equals(assignment.getItemType())) {
assignmentsToUpdate.add(assignment);
}
}
}
updatedCategory.setAssignmentList(assignmentsToUpdate);
}
// now update the pointsPossible of any assignments within the category that drop scores
getGradebookManager().updateCategoryAndAssignmentsPointsPossible(localGradebook.getId(), updatedCategory);
} else {
getGradebookManager().updateCategory(updatedCategory);
}
}
}
}
catch (ConflictingCategoryNameException cne) {
FacesUtil.addErrorMessage(getLocalizedString("cat_same_name_error"));
return "failure";
}
catch (StaleObjectModificationException e) {
logger.error(e);
FacesUtil.addErrorMessage(getLocalizedString("cat_locking_failure"));
return "failure";
}
}
// remove any categories marked to remove
if (categoriesToRemove != null && categoriesToRemove.size() > 0) {
Iterator removeIter = categoriesToRemove.iterator();
while (removeIter.hasNext()) {
Long removeId = (Long) removeIter.next();
getGradebookManager().removeCategory(removeId);
}
List permsToRemove = getGradebookManager().getPermissionsForGBForCategoryIds(localGradebook.getId(), categoriesToRemove);
if (!permsToRemove.isEmpty()) {
for (Iterator permIter = permsToRemove.iterator(); permIter.hasNext();) {
Permission perm = (Permission) permIter.next();
logger.debug("Permission " + perm.getId() + " was deleted b/c category deleted");
getGradebookManager().deletePermission(perm);
}
}
}
//SAK-22417 When changing to a category gradebook, items that move to unassigned still have included in course grade as YES
//This also includes the case where a GB category is deleted and the item is set to uncategorized.
if((GradebookService.CATEGORY_TYPE_ONLY_CATEGORY == localGradebook.getCategory_type() || GradebookService.CATEGORY_TYPE_WEIGHTED_CATEGORY == localGradebook.getCategory_type())
&& (GradebookService.CATEGORY_TYPE_NO_CATEGORY == origCategorySetting || (categoriesToRemove != null && categoriesToRemove.size() > 0))){
setUncategoriedAssignmentsToNotCounted(localGradebook.getId());
}
getGradebookManager().updateGradebook(localGradebook);
FacesUtil.addRedirectSafeMessage(getLocalizedString("gb_save_msg"));
reset();
return null;
}
private void setUncategoriedAssignmentsToNotCounted(Long gradebookId){
List assigns = getGradebookManager().getAssignmentsWithNoCategory(gradebookId, null, true);
for(Iterator iter = assigns.iterator(); iter.hasNext();)
{
Assignment assignment = (Assignment) iter.next();
assignment.setCounted(false);
getGradebookManager().updateAssignment(assignment);
}
}
/**
* Removes the selected category from the local list. If category
* exists in gb, retains id for future use if/when setup is saved
* @param event
* @return
*/
public String processRemoveCategory(ActionEvent event)
{
if (categories == null || categories.isEmpty())
return GB_SETUP_PAGE;
try
{
Map params = FacesUtil.getEventParameterMap(event);
Integer index = (Integer) params.get(ROW_INDEX_PARAM);
if (index == null) {
return GB_SETUP_PAGE;
}
int indexToRemove = index.intValue();
Category catToRemove = (Category)categories.get(indexToRemove);
// new categories will not have an id yet so don't need to be retained
if (catToRemove.getId() != null)
{
categoriesToRemove.add(catToRemove.getId());
}
categories.remove(indexToRemove);
}
catch(Exception e)
{
// do nothing
}
return GB_SETUP_PAGE;
}
public String processCategorySettingChange(ValueChangeEvent vce)
{
String changeAssign = (String) vce.getNewValue();
if (changeAssign != null && (changeAssign.equals(CATEGORY_OPT_NONE) ||
changeAssign.equals(CATEGORY_OPT_CAT_AND_WEIGHT) ||
changeAssign.equals(CATEGORY_OPT_CAT_ONLY)))
{
categorySetting = changeAssign;
}
return GB_SETUP_PAGE;
}
public String processGradeEntryMethodChange(ValueChangeEvent vce)
{
// Object changeAssign = (Object) vce.getNewValue();
// if(changeAssign instanceof String) {
// String newValue = (String) vce.getNewValue();
// if (newValue != null && (newValue.equals(ENTRY_OPT_POINTS) ||
// newValue.equals(ENTRY_OPT_PERCENT) ||
// newValue.equals(ENTRY_OPT_LETTER)))
// {
// gradeEntryMethod = newValue;
// if(categories != null) {
// for(Object obj : categories) {
// if(obj instanceof Category) {
// Category category = (Category)obj;
// category.setItemValue(0.0);
// }
// }
// }
// }
// }
return GB_SETUP_PAGE;
}
public String processCancelGradebookSetup()
{
reset();
return GB_OVERVIEW_PAGE;
}
/*
* Returns list of categories
* Also includes blank categories to allow the user to enter new categories
*/
public List getCategories()
{
//first, iterate through the list and remove blank lines
for (int i=0; i < categories.size(); i++)
{
Object obj = categories.get(i);
if(!(obj instanceof Category)){
categories.remove(i);
continue;
}
Category cat = (Category)categories.get(i);
int assignmentCount = 0;
if(cat.getAssignmentList() != null){
assignmentCount = cat.getAssignmentList().size();
}
cat.setAssignmentCount(assignmentCount);
if (cat.getName() == null || cat.getName().trim().length() == 0)
{
if (cat.getId() != null)
{
// this will take care of instances where user just deleted cat name
// instead of hitting "remove"
categoriesToRemove.add(cat.getId());
}
categories.remove(cat);
i--;
}
}
// always display 5 blank entries for new categories
for (int i=0; i < NUM_EXTRA_CAT_ENTRIES; i++)
{
Category blankCat = new Category();
categories.add(blankCat);
}
return categories;
}
public String getRowClasses()
{
StringBuilder rowClasses = new StringBuilder();
//first add the row class "bogus" for current categories
for (int i=0; i<categories.size(); i++){
Object obj = categories.get(i);
if(!(obj instanceof Category)){
continue;
}
Category cat = (Category)categories.get(i);
if (cat.getName() != null && cat.getName().trim().length() != 0)
{
if(i != 0){
rowClasses.append(",");
}
rowClasses.append("bogus");
}
}
//add row class "bogus_hide" for blank categories
for (int i=0; i < NUM_EXTRA_CAT_ENTRIES; i++){
if(i == 0 && categories.size() == 0){
rowClasses.append("bogus");
}
rowClasses.append(",");
rowClasses.append("bogus hide");
}
return rowClasses.toString();
}
/**
* Returns sum of all category weights minus the adjustment categories. This one must be 100% to process correctly.
* @return
*/
public double getRegularTotal()
{
return regularTotal;
}
/**
* Returns % needed to reach 100% for category weights
* @return
*/
public double getNeededTotal()
{
return neededTotal;
}
/**
* Returns sum of the adjustment category weights
* @return
*/
/**
* Returns sum of all category weights
* @return
*/
public double getGrandTotal()
{
return grandTotal;
}
/**
* Simplifies some javascript/rendering relationships. The highlight
* class is only applied if the running total not equal to 100%
* @return
*/
public String getRegularTotalStyle()
{
if (regularTotal != 100)
return "highlight";
return "";
}
/**
* For retaining the pageName variable upon save or cancel
*/
public String getPageName() {
return pageName;
}
public void setPageName(String pageName) {
this.pageName = pageName;
}
/**
* Grading scale used if grade entry by letter
* @return
*/
public List getLetterGradeRows() {
return letterGradeRows;
}
public void setLetterGradeRows(List letterGradeRows) {
this.letterGradeRows = letterGradeRows;
}
/**
* Set gradeEntryType and categorySetting
*
*/
private void intializeGradeEntryAndCategorySettings()
{
// Grade entry setting
int gradeEntryType = localGradebook.getGrade_type();
if (gradeEntryType == GradebookService.GRADE_TYPE_PERCENTAGE)
gradeEntryMethod = ENTRY_OPT_PERCENT;
else if (gradeEntryType == GradebookService.GRADE_TYPE_LETTER)
gradeEntryMethod = ENTRY_OPT_LETTER;
else
gradeEntryMethod = ENTRY_OPT_POINTS;
// Category setting
int categoryType = localGradebook.getCategory_type();
if (categoryType == GradebookService.CATEGORY_TYPE_ONLY_CATEGORY)
categorySetting = CATEGORY_OPT_CAT_ONLY;
else if (categoryType == GradebookService.CATEGORY_TYPE_WEIGHTED_CATEGORY)
categorySetting = CATEGORY_OPT_CAT_AND_WEIGHT;
else
categorySetting = CATEGORY_OPT_NONE;
}
/**
* Calculates the sum of the category weights
* @return
*/
private void calculateRunningTotal()
{
double total = 0;
double extraCredit = 0;
if (categories != null && categories.size() > 0)
{
Iterator catIter = categories.iterator();
while (catIter.hasNext())
{
Object obj = catIter.next();
if(!(obj instanceof Category)){
continue;
}
Category cat = (Category) obj;
Boolean iec = cat.isExtraCredit();
if (iec!=null)
{
if (cat.getWeight() != null && !cat.isExtraCredit())
{
double weight = cat.getWeight().doubleValue();
total += weight;
}
else if (cat.getWeight() != null && cat.isExtraCredit())
{
double weight = cat.getWeight().doubleValue();
extraCredit += weight;
}
}
else
{
if (cat.getWeight() != null)
{
double weight = cat.getWeight().doubleValue();
total += weight;
}
}
}
}
regularTotal = total; // this will probably change later, but make it function to spec for now
grandTotal = total + extraCredit;
adjustmentTotal = extraCredit;
neededTotal = 100 - total;
}
/**
* Because we display input as "percentage" to user but store it as
* decimal, we need a way to convert our weights from decimal to %
*/
private void convertWeightsFromDecimalsToPercentages() {
if (!getWeightingEnabled())
return;
if (categories != null && !categories.isEmpty()) {
Iterator iter = categories.iterator();
while (iter.hasNext()) {
Object obj = iter.next();
if(!(obj instanceof Category)){
continue;
}
Category myCat = (Category) obj;
Double weight = myCat.getWeight();
if (weight != null && weight.doubleValue() > 0) {
myCat.setWeight(new Double(weight.doubleValue() * 100));
}
}
}
}
private boolean isMappingValid(LetterGradePercentMapping lgpm) {
boolean valid = true;
Double previousPercentage = null;
for (Iterator iter = letterGradesList.iterator(); iter.hasNext(); ) {
String grade = (String)iter.next();
Double percentage = (Double)lgpm.getValue(grade);
if (logger.isDebugEnabled()) logger.debug("checking percentage " + percentage + " for validity");
// Grades that are percentage-based need to remain percentage-based,
// be in descending order, and end with 0.
if (percentage == null) {
FacesUtil.addUniqueErrorMessage(getLocalizedString("gb_setup_require_all_values"));
valid = false;
} else if (percentage.doubleValue() < 0) {
FacesUtil.addUniqueErrorMessage(getLocalizedString("gb_setup_require_positive"));
valid = false;
} else if ((previousPercentage != null) && (previousPercentage.doubleValue() < percentage.doubleValue())) {
FacesUtil.addUniqueErrorMessage(getLocalizedString("gb_setup_require_descending_order"));
valid = false;
}
previousPercentage = percentage;
}
return valid;
}
/**
* UI for the letter grade entry scale
*/
public class LetterGradeRow implements Serializable {
private String grade;
private boolean editable;
private LetterGradePercentMapping lgpm;
public LetterGradeRow() {
}
public LetterGradeRow(LetterGradePercentMapping lgpm, String grade, boolean editable) {
this.lgpm = lgpm;
this.grade = grade;
this.editable = editable;
}
public String getGrade() {
return grade;
}
public Double getMappingValue() {
return (Double)lgpm.getGradeMap().get(grade);
}
public void setMappingValue(Double value) {
lgpm.getGradeMap().put(grade, value);
}
public boolean isEditable() {
return editable;
}
}
public boolean getEnableLetterGrade()
{
enableLetterGrade = ServerConfigurationService.getBoolean(GradebookService.enableLetterGradeString, false);
return enableLetterGrade;
}
public void setEnableLetterGrade(boolean enableLetterGrade)
{
this.enableLetterGrade = enableLetterGrade;
}
public boolean getIsValidWithCourseGrade()
{
return isValidWithCourseGrade;
}
public void setIsValidWithCourseGrade(boolean isValidWithCourseGrade)
{
this.isValidWithCourseGrade = isValidWithCourseGrade;
}
public boolean isConflictWithCourseGrade()
{
Gradebook gb = getGradebookManager().getGradebookWithGradeMappings(getGradebookManager().getGradebook(localGradebook.getUid()).getId());
if (gradeEntryMethod.equals(ENTRY_OPT_LETTER))
{
if((gb.getSelectedGradeMapping().getGradingScale() != null && gb.getSelectedGradeMapping().getGradingScale().getUid().equals("LetterGradeMapping"))
|| (gb.getSelectedGradeMapping().getGradingScale() == null && gb.getSelectedGradeMapping().getName().equals("Letter Grades")))
{
return false;
}
Set mappings = gb.getGradeMappings();
for(Iterator iter = mappings.iterator(); iter.hasNext();)
{
GradeMapping gm = (GradeMapping) iter.next();
if(gm != null)
{
if((gm.getGradingScale() != null && (gm.getGradingScale().getUid().equals("LetterGradeMapping") || gm.getGradingScale().getUid().equals("LetterGradePlusMinusMapping")))
|| (gm.getGradingScale() == null && (gb.getSelectedGradeMapping().getName().equals("Letter Grades") || gb.getSelectedGradeMapping().getName().equals("Letter Grades with +/-"))))
{
Map defaultMapping = gm.getDefaultBottomPercents();
for (Iterator gradeIter = gm.getGrades().iterator(); gradeIter.hasNext(); )
{
String grade = (String)gradeIter.next();
Double percentage = (Double)gm.getValue(grade);
Double defautPercentage = (Double)defaultMapping.get(grade);
if (percentage != null && !percentage.equals(defautPercentage))
{
return false;
}
}
}
}
}
}
return true;
}
public String navigateToDeleteAllGrades() {
return "delteAllGrades";
}
public boolean getIsLetterGrade() {
isLetterGrade = gradeEntryMethod.equals(ENTRY_OPT_LETTER);
return isLetterGrade;
}
public void setIsLetterGrade(boolean isLetterGrade) {
this.isLetterGrade = isLetterGrade;
}
public boolean getIsPointGrade() {
isPointGrade = gradeEntryMethod.equals(ENTRY_OPT_POINTS);
return isPointGrade;
}
public void setPointGrade(boolean isPointGrade) {
this.isPointGrade = isPointGrade;
}
public boolean getIsPercentageGrade() {
isPercentageGrade = gradeEntryMethod.equals(ENTRY_OPT_PERCENT);
return isPercentageGrade;
}
public void setPercentageGrade(boolean isPercentageGrade) {
this.isPercentageGrade = isPercentageGrade;
}
}