Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ public class Assignment implements Serializable, Comparable<Assignment> {
*/
private Double points;

/**
* the maximum letter grade for letter-grade entry mode, or null if not applicable.
*/
private String maxLetterGrade;

/**
* the due date for the assignment, or null if none is defined.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import lombok.Getter;
import lombok.Setter;
Expand Down Expand Up @@ -47,7 +49,7 @@ public class CategoryDefinition implements Serializable {
private Boolean equalWeight;
private Integer categoryOrder;
private Boolean dropKeepEnabled;
private List<Assignment> assignmentList;
private List<Assignment> assignmentList = new ArrayList<>();
public static Comparator<CategoryDefinition> orderComparator;

public CategoryDefinition() { }
Expand Down Expand Up @@ -104,19 +106,32 @@ public int compare(final CategoryDefinition c1, final CategoryDefinition c2) {
}

/**
* Helper method to get the total points associated with a category
* Helper method to get the total points associated with a category.
*
* @return the sum of all assignment totals associated with this category
* For POINTS or PERCENTAGE grade types, returns the sum of each
* assignment’s points as stored on the Assignment.
*
* For LETTER grade type, requires a uniform per-assignment maximum:
* total points = assignmentList.size() * maxPoints.
*
* @param gradeType the grading scheme in use
* @param maxPoints ignored for non-LETTER types; must be non-null and > 0 for LETTER
*
* @return total points for this category under the specified gradeType
*/
public Double getTotalPoints() {
BigDecimal totalPoints = new BigDecimal(0);

if (getAssignmentList() != null) {
for (final Assignment assignment : getAssignmentList()) {
totalPoints = totalPoints.add(BigDecimal.valueOf(assignment.getPoints()));
public Double getTotalPoints(GradeType gradeType, Double maxPoints) {

if (gradeType != GradeType.LETTER) {
return getAssignmentList().stream()
.filter(a -> a.getPoints() != null)
.mapToDouble(Assignment::getPoints)
.sum();
} else {
if (maxPoints == null || maxPoints <= 0D) {
throw new IllegalArgumentException("maxPoints must be > 0 for LETTER grade type");
}
return getAssignmentList().size() * maxPoints;
}
return totalPoints.doubleValue();
}

public boolean isAssignmentInThisCategory(String assignmentId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class GradeDefinition {
private Date dateRecorded;
private String grade;
private String gradeComment;
private Integer gradeEntryType;
private GradeType gradeEntryType;
private boolean gradeReleased;
private boolean excused;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2003-2022 The Apereo 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://opensource.org/licenses/ecl2
*
* 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.grading.api;

public enum GradeType {
POINTS,
PERCENTAGE,
LETTER,
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,24 @@ else if (StringUtils.startsWithAny(title, GradingService.INVALID_CHARS_AT_START_
/**
* Validate assignment points and name is valid
* @param assignmentDefition
* @param gradeType
* @throws InvalidGradeItemNameException
* @throws AssignmentHasIllegalPointsException
* @throws ConflictingAssignmentNameException
* @return validated name
*/

public static String validateAssignmentNameAndPoints(final org.sakaiproject.grading.api.Assignment assignmentDefinition)
public static String validateAssignmentNameAndPoints(Assignment assignmentDefinition, GradeType gradeType)
throws InvalidGradeItemNameException, AssignmentHasIllegalPointsException, ConflictingAssignmentNameException {
// Ensure that points is > zero.
final Double points = assignmentDefinition.getPoints();
if ((points == null) || (points <= 0)) {
throw new AssignmentHasIllegalPointsException("Points must be > 0");

if (gradeType != GradeType.LETTER) {
// Ensure that points is > zero.
final Double points = assignmentDefinition.getPoints();
if ((points == null) || (points <= 0)) {
throw new AssignmentHasIllegalPointsException("Points must be > 0");
}
}

return validateGradeItemName(assignmentDefinition.getName());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.sakaiproject.grading.api;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -46,11 +47,11 @@ public class GradebookInformation implements Serializable {
/**
* The grading schema map currently in use for the this gradebook. For example A+ = 100 etc.
*/
private Map<String, Double> selectedGradingScaleBottomPercents;
private Map<String, Double> selectedGradingScaleBottomPercents = new HashMap<>();

private Boolean displayReleasedGradeItemsToStudents;

private Integer gradeType = GradingConstants.GRADE_TYPE_POINTS;
private GradeType gradeType = GradeType.POINTS;

private Integer categoryType;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package org.sakaiproject.grading.api;

import java.util.ArrayList;
import java.util.List;

/**
Expand All @@ -42,10 +41,7 @@ public String toString() {
* @return
*/
public static List<String> getStandardPermissions() {
List<String> rval = new ArrayList<>();
rval.add(GraderPermission.VIEW.toString());
rval.add(GraderPermission.GRADE.toString());
return rval;
return List.of(GraderPermission.VIEW.toString(), GraderPermission.GRADE.toString());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@
import java.math.RoundingMode;

public interface GradingConstants {
Integer GRADE_TYPE_POINTS = 1;
Integer GRADE_TYPE_PERCENTAGE = 2;
Integer GRADE_TYPE_LETTER = 3;

Integer CATEGORY_TYPE_NO_CATEGORY = 1;
Integer CATEGORY_TYPE_ONLY_CATEGORY = 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ public Map<String,String> transferGradebook(GradebookInformation gradebookInform
* validating a list of student/grade pairs for a single gradebook (more efficient than calling gradeIsValid repeatedly).
* returns empty list if all grades are valid
*/
public List<String> identifyStudentsWithInvalidGrades(String gradebookUid, Map<String, String> studentIdToGradeMap);
public Set<String> identifyStudentsWithInvalidGrades(String gradebookUid, Map<String, String> studentIdToGradeMap);

/**
* Save a student score and comment for a gradebook item. The input score must be valid according to the given gradebook's grade entry
Expand Down Expand Up @@ -523,7 +523,7 @@ public void saveGradeAndExcuseForStudent(String gradebookUid, String siteId, Lon
* @param gradebookUid
* @return the constant representation of the grade entry type (ie points, %, letter grade)
*/
public Integer getGradeEntryType(String gradebookUid);
public GradeType getGradeEntryType(String gradebookUid);

/**
* Get student's assignment's score as string.
Expand Down Expand Up @@ -589,12 +589,11 @@ public void setAssignmentScoreString(String gradebookUid, String siteId, Long as
* @param studentUuid uuid of the student
* @param categoryId id of category
* @param isInstructor will determine whether category score includes non-released items
* @param categoryType category type of the gradebook
* @param equalWeightAssignments whether category is equal-weighting regardless of points
* @return percentage and dropped items, or empty if no calculations were made
*
*/
Optional<CategoryScoreData> calculateCategoryScore(Long gradebookId, String studentUuid, Long categoryId, boolean includeNonReleasedItems, Integer categoryType, Boolean equalWeightAssignments);
Optional<CategoryScoreData> calculateCategoryScore(Long gradebookId, String studentUuid, Long categoryId, boolean includeNonReleasedItems, Boolean equalWeightAssignments);

/**
* Calculate the category score for the given gradebook, category, assignments in the category and grade map. This doesn't do any
Expand All @@ -609,7 +608,7 @@ public void setAssignmentScoreString(String gradebookUid, String siteId, Long as
* @param includeNonReleasedItems relevant for student view
* @return percentage and dropped items, or empty if no calculations were made
*/
Optional<CategoryScoreData> calculateCategoryScore(Object gradebook, String studentUuid, CategoryDefinition category,
Optional<CategoryScoreData> calculateCategoryScore(Gradebook gradebook, String studentUuid, CategoryDefinition category,
final List<Assignment> categoryAssignments, Map<Long, String> gradeMap, boolean includeNonReleasedItems);

/**
Expand Down Expand Up @@ -1004,5 +1003,28 @@ public void updateExternalAssessmentComments(String gradebookUid, String siteId,
public List<String> getGradebookInstancesForUser(String siteId, String userId);
public void initializeGradebooksForSite(String siteId);
public Double convertStringToDouble(final String doubleAsString);

/**
* Fully remove a gradebook from the database. This removes all the associated data and is
* irreversible without a backup.
*
* @param siteId The siteId (aka gradebook uid) to delete.
*/
public void hardDeleteGradebook(String siteId);

/**
* Get the maximum letter grade for the given grade mapping
*
* @param gradeMap
* @return An optional containing the maximum letter grade
*/
public Optional<String> getMaxLetterGrade(Map<String, Double> gradeMap);

/**
* Get the maximum points for the given grade mapping
*
* @param gradeMap
* @return An optional containing the maximum points
*/
public Optional<Double> getMaxPoints(Map<String, Double> gradeMap);
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import org.sakaiproject.grading.api.GradeType;
import org.sakaiproject.springframework.data.PersistableEntity;

import lombok.Getter;
Expand Down Expand Up @@ -86,6 +87,12 @@ public abstract class AbstractGradeRecord implements PersistableEntity<Long>, Se
@Column(name = "POINTS_EARNED")
protected Double pointsEarned;

@Column(name = "LETTER_EARNED")
protected String letterEarned;

@Column(name = "GRADE_TYPE", nullable = false)
protected GradeType gradeType = GradeType.POINTS;

public abstract Double getGradeAsPercentage();

/**
Expand Down
Loading
Loading