org.sakaiproject.tool.gradebook.business.impl.GradebookCalculationImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.sakaiproject.tool.gradebook.business.impl.GradebookCalculationImpl.java

Source

/**********************************************************************************
*
* $Id: GradebookCalculationImpl.java 63658 2009-06-15 13:49:40Z wagnermr@iupui.edu $
*
***********************************************************************************
*
* Copyright (c) 2005, 2006 The Regents of the University of California, The MIT Corporation
*
* Licensed under the Educational Community License, Version 1.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/ecl1.php
*
* 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.business.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.sakaiproject.service.gradebook.shared.GradebookService;
import org.sakaiproject.tool.gradebook.Assignment;
import org.sakaiproject.tool.gradebook.AssignmentGradeRecord;
import org.sakaiproject.tool.gradebook.Category;
import org.sakaiproject.tool.gradebook.CourseGrade;
import org.sakaiproject.tool.gradebook.CourseGradeRecord;
import org.sakaiproject.tool.gradebook.Gradebook;
import org.sakaiproject.tool.gradebook.business.GradebookManager;
import org.springframework.orm.hibernate3.HibernateCallback;

public class GradebookCalculationImpl extends GradebookManagerHibernateImpl implements GradebookManager {
    private static final Log log = LogFactory.getLog(GradebookCalculationImpl.class);

    @Override
    public List getPointsEarnedCourseGradeRecords(final CourseGrade courseGrade, final Collection studentUids) {
        HibernateCallback hc = new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException {
                if (studentUids == null || studentUids.size() == 0) {
                    if (log.isDebugEnabled())
                        log.debug(
                                "Returning no grade records for an empty collection of student UIDs in GradebookCalculationImpl.getPointsEarnedCourseGradeRecords(CourseGrade, Collection).");
                    return new ArrayList();
                }

                Long gradebookId = courseGrade.getGradebook().getId();

                // get all of the AssignmentGradeRecords here to avoid repeated db calls
                Map<String, List<AssignmentGradeRecord>> studentIdGradeRecordsMap = getGradeRecordMapForStudents(
                        session, gradebookId, studentUids);

                // get all of the counted assignments
                List<Assignment> countedAssigns = getCountedAssignments(session, gradebookId);

                return getPointsEarnedCourseGradeRecords(session, courseGrade, studentUids, countedAssigns,
                        studentIdGradeRecordsMap);
            }
        };
        return (List) getHibernateTemplate().execute(hc);
    }

    @Override
    public List getPointsEarnedCourseGradeRecords(final CourseGrade courseGrade, final Collection studentUids,
            final Collection assignments, final Map gradeRecordMap) {
        HibernateCallback hc = new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException {
                if (studentUids == null || studentUids.size() == 0) {
                    if (log.isDebugEnabled())
                        log.debug(
                                "Returning no grade records for an empty collection of student UIDs in GradebookCalculationImpl.getPointsEarnedCourseGradeRecords");
                    return new ArrayList();
                }

                // let's make the grade map more manageable here.  it starts out as
                // Map of studentId --> Map of assignment id --> corresponding AssignmentGradeRecord
                Map<String, List<AssignmentGradeRecord>> studentIdGradeRecordsMap = new HashMap<String, List<AssignmentGradeRecord>>();
                if (gradeRecordMap != null) {
                    for (Iterator stIter = studentUids.iterator(); stIter.hasNext();) {
                        String studentUid = (String) stIter.next();
                        Map<Long, AssignmentGradeRecord> studentMap = (Map<Long, AssignmentGradeRecord>) gradeRecordMap
                                .get(studentUid);
                        if (studentMap != null) {
                            List<AssignmentGradeRecord> studentGradeRecs = new ArrayList<AssignmentGradeRecord>(
                                    studentMap.values());
                            studentIdGradeRecordsMap.put(studentUid, studentGradeRecs);
                        }
                    }
                }

                return getPointsEarnedCourseGradeRecords(session, courseGrade, studentUids, assignments,
                        studentIdGradeRecordsMap);
            }
        };
        return (List) getHibernateTemplate().execute(hc);
    }

    /**
     * 
     * @param session
     * @param courseGrade
     * @param studentUids
     * @param studentIdGradeRecordsMap map of studentId --> List of that student's AssignmentGradeRecords
     * @return a list of the CourseGradeRecords with nonpersisted fields populated for the given students and
     * associated AssignmentGradeRecords
     */
    private List<CourseGradeRecord> getPointsEarnedCourseGradeRecords(Session session, CourseGrade courseGrade,
            Collection<String> studentUids, Collection<Assignment> assignments,
            Map<String, List<AssignmentGradeRecord>> studentIdGradeRecordsMap) {

        List<CourseGradeRecord> courseGradeRecs = new ArrayList<CourseGradeRecord>();

        if (studentUids != null && !studentUids.isEmpty()) {

            int gbGradeType = getGradebook(courseGrade.getGradebook().getId()).getGrade_type();

            Query q = session
                    .createQuery("from CourseGradeRecord as cgr where cgr.gradableObject.id=:gradableObjectId");
            q.setLong("gradableObjectId", courseGrade.getId().longValue());
            courseGradeRecs = filterAndPopulateCourseGradeRecordsByStudents(courseGrade, q.list(), studentUids);

            Long gradebookId = courseGrade.getGradebook().getId();
            Gradebook gradebook = getGradebook(gradebookId);
            List cates = getCategories(gradebookId);

            List<Assignment> countedAssigns = new ArrayList<Assignment>();
            // let's filter the passed assignments to make sure they are all counted
            if (assignments != null) {
                for (Assignment assign : assignments) {
                    if (assign.isIncludedInCalculations()) {
                        countedAssigns.add(assign);
                    }
                }
            }

            // no need to calculate anything for non-calculating gradebook
            if (gbGradeType != GradebookService.GRADE_TYPE_LETTER) {
                Map<String, Set<Assignment>> visibleExternals = getVisibleExternalAssignments(
                        courseGrade.getGradebook(), studentUids, countedAssigns);

                for (CourseGradeRecord cgr : courseGradeRecs) {
                    // Filter out external activities that are not visible to this student, considering them "uncounted"
                    List<Assignment> studentCountedAssigns = new ArrayList<Assignment>();
                    String studentId = cgr.getStudentId();
                    for (Assignment a : countedAssigns) {
                        if (!a.isExternallyMaintained() || (visibleExternals.containsKey(studentId)
                                && visibleExternals.get(studentId).contains(a))) {
                            studentCountedAssigns.add(a);
                        }
                    }

                    //double totalPointsEarned = getTotalPointsEarnedInternal(gradebookId, cgr.getStudentId(), session);
                    List<AssignmentGradeRecord> studentGradeRecs;
                    if (studentIdGradeRecordsMap == null) {
                        studentGradeRecs = new ArrayList<AssignmentGradeRecord>();
                    } else {
                        studentGradeRecs = studentIdGradeRecordsMap.get(cgr.getStudentId());
                    }

                    applyDropScores(studentGradeRecs);

                    List totalEarned = getTotalPointsEarnedInternal(cgr.getStudentId(), gradebook, cates,
                            studentGradeRecs, studentCountedAssigns);
                    double totalPointsEarned = ((Double) totalEarned.get(0)).doubleValue();
                    double literalTotalPointsEarned = ((Double) totalEarned.get(1)).doubleValue();
                    double totalPointsPossible = getTotalPointsInternal(gradebook, cates, cgr.getStudentId(),
                            studentGradeRecs, studentCountedAssigns, false);
                    cgr.initNonpersistentFields(totalPointsPossible, totalPointsEarned, literalTotalPointsEarned);
                    if (log.isDebugEnabled())
                        log.debug("Points earned = " + cgr.getPointsEarned());
                }
            }
        }
        return courseGradeRecs;
    }

    @Override
    List getTotalPointsEarnedInternal(final String studentId, final Gradebook gradebook, final List categories,
            final List<AssignmentGradeRecord> gradeRecs, List<Assignment> countedAssigns) {
        int gbGradeType = gradebook.getGrade_type();
        if (gbGradeType != GradebookService.GRADE_TYPE_POINTS
                && gbGradeType != GradebookService.GRADE_TYPE_PERCENTAGE) {
            if (log.isInfoEnabled())
                log.error("Wrong grade type in GradebookCalculationImpl.getTotalPointsEarnedInternal");
            return new ArrayList();
        }

        if (gradeRecs == null || countedAssigns == null) {
            if (log.isDebugEnabled())
                log.debug("getTotalPointsEarnedInternal for " + "studentId=" + studentId
                        + " returning 0 because null gradeRecs or countedAssigns");
            List returnList = new ArrayList();
            returnList.add(new Double(0));
            returnList.add(new Double(0));
            returnList.add(new Double(0)); // 3rd one is for the pre-adjusted course grade
            return returnList;
        }

        double totalPointsEarned = 0;
        BigDecimal literalTotalPointsEarned = new BigDecimal(0d);

        Map cateScoreMap = new HashMap();
        Map cateTotalScoreMap = new HashMap();

        Set assignmentsTaken = new HashSet();
        for (AssignmentGradeRecord gradeRec : gradeRecs) {
            if (gradeRec.getPointsEarned() != null && !gradeRec.getPointsEarned().equals("")
                    && !gradeRec.getDroppedFromGrade()) {
                Assignment go = gradeRec.getAssignment();
                if (go.isIncludedInCalculations() && countedAssigns.contains(go)) {
                    Double pointsEarned = new Double(gradeRec.getPointsEarned());
                    //if(gbGradeType == GradebookService.GRADE_TYPE_POINTS)
                    //{
                    if (gradebook.getCategory_type() == GradebookService.CATEGORY_TYPE_NO_CATEGORY) {
                        totalPointsEarned += pointsEarned.doubleValue();
                        literalTotalPointsEarned = (new BigDecimal(pointsEarned.doubleValue()))
                                .add(literalTotalPointsEarned);
                        assignmentsTaken.add(go.getId());
                    } else if (gradebook.getCategory_type() == GradebookService.CATEGORY_TYPE_ONLY_CATEGORY
                            && go != null) {
                        totalPointsEarned += pointsEarned.doubleValue();
                        literalTotalPointsEarned = (new BigDecimal(pointsEarned.doubleValue()))
                                .add(literalTotalPointsEarned);
                        assignmentsTaken.add(go.getId());
                    } else if (gradebook.getCategory_type() == GradebookService.CATEGORY_TYPE_WEIGHTED_CATEGORY
                            && go != null && categories != null) {
                        for (int i = 0; i < categories.size(); i++) {
                            Category cate = (Category) categories.get(i);
                            if (cate != null && !cate.isRemoved() && go.getCategory() != null
                                    && cate.getId().equals(go.getCategory().getId())) {
                                assignmentsTaken.add(go.getId());
                                literalTotalPointsEarned = (new BigDecimal(pointsEarned.doubleValue()))
                                        .add(literalTotalPointsEarned);
                                if (cateScoreMap.get(cate.getId()) != null) {
                                    cateScoreMap.put(cate.getId(),
                                            new Double(((Double) cateScoreMap.get(cate.getId())).doubleValue()
                                                    + pointsEarned.doubleValue()));
                                } else {
                                    cateScoreMap.put(cate.getId(), new Double(pointsEarned));
                                }
                                break;
                            }
                        }
                    }
                }

            }
        }

        if (gradebook.getCategory_type() == GradebookService.CATEGORY_TYPE_WEIGHTED_CATEGORY
                && categories != null) {
            Iterator assgnsIter = countedAssigns.iterator();
            while (assgnsIter.hasNext()) {
                Assignment asgn = (Assignment) assgnsIter.next();
                if (assignmentsTaken.contains(asgn.getId())) {
                    for (int i = 0; i < categories.size(); i++) {
                        Category cate = (Category) categories.get(i);
                        if (cate != null && !cate.isRemoved() && asgn.getCategory() != null
                                && cate.getId().equals(asgn.getCategory().getId()) && !asgn.isExtraCredit()) {

                            if (cateTotalScoreMap.get(cate.getId()) == null) {
                                cateTotalScoreMap.put(cate.getId(), asgn.getPointsPossible());
                            } else {
                                cateTotalScoreMap.put(cate.getId(),
                                        new Double(((Double) cateTotalScoreMap.get(cate.getId())).doubleValue()
                                                + asgn.getPointsPossible().doubleValue()));
                            }

                        }
                    }
                }
            }
        }

        if (assignmentsTaken.isEmpty())
            totalPointsEarned = -1;

        if (gradebook.getCategory_type() == GradebookService.CATEGORY_TYPE_WEIGHTED_CATEGORY) {
            for (int i = 0; i < categories.size(); i++) {
                Category cate = (Category) categories.get(i);
                if (cate != null && !cate.isRemoved() && cateScoreMap.get(cate.getId()) != null
                        && cateTotalScoreMap.get(cate.getId()) != null) {
                    totalPointsEarned += ((Double) cateScoreMap.get(cate.getId())).doubleValue()
                            * cate.getWeight().doubleValue()
                            / ((Double) cateTotalScoreMap.get(cate.getId())).doubleValue();
                }
            }
        }

        if (log.isDebugEnabled())
            log.debug(
                    "getTotalPointsEarnedInternal for studentId=" + studentId + " returning " + totalPointsEarned);
        List returnList = new ArrayList();
        returnList.add(new Double(totalPointsEarned));
        returnList.add(
                new Double((new BigDecimal(literalTotalPointsEarned.doubleValue(), GradebookService.MATH_CONTEXT))
                        .doubleValue()));
        return returnList;
    }

    @Override
    public double getTotalPointsInternal(final Gradebook gradebook, final List categories, final String studentId,
            List<AssignmentGradeRecord> studentGradeRecs, List<Assignment> countedAssigns, boolean literalTotal) {
        int gbGradeType = gradebook.getGrade_type();
        if (gbGradeType != GradebookService.GRADE_TYPE_POINTS
                && gbGradeType != GradebookService.GRADE_TYPE_PERCENTAGE) {
            if (log.isInfoEnabled())
                log.error("Wrong grade type in GradebookCalculationImpl.getTotalPointsInternal");
            return -1;
        }

        if (studentGradeRecs == null || countedAssigns == null) {
            if (log.isDebugEnabled())
                log.debug("Returning 0 from getTotalPointsInternal "
                        + "since studentGradeRecs or countedAssigns was null");
            return 0;
        }

        double totalPointsPossible = 0;

        HashSet<Assignment> countedSet = new HashSet<Assignment>(countedAssigns);

        // we need to filter this list to identify only "counted" grade recs
        List<AssignmentGradeRecord> countedGradeRecs = new ArrayList<AssignmentGradeRecord>();
        for (AssignmentGradeRecord gradeRec : studentGradeRecs) {
            Assignment assign = gradeRec.getAssignment();
            boolean extraCredit = assign.isExtraCredit();
            if (gradebook.getCategory_type() != GradebookService.CATEGORY_TYPE_NO_CATEGORY
                    && assign.getCategory() != null && assign.getCategory().isExtraCredit())
                extraCredit = true;

            if (assign.isCounted() && !assign.getUngraded() && !assign.isRemoved() && countedSet.contains(assign)
                    && assign.getPointsPossible() != null && assign.getPointsPossible() > 0
                    && !gradeRec.getDroppedFromGrade() && !extraCredit) {
                countedGradeRecs.add(gradeRec);
            }
        }

        Set assignmentsTaken = new HashSet();
        Set categoryTaken = new HashSet();
        for (AssignmentGradeRecord gradeRec : countedGradeRecs) {
            if (gradeRec.getPointsEarned() != null && !gradeRec.getPointsEarned().equals("")) {
                Double pointsEarned = new Double(gradeRec.getPointsEarned());
                Assignment go = gradeRec.getAssignment();
                if (pointsEarned != null) {
                    if (gradebook.getCategory_type() == GradebookService.CATEGORY_TYPE_NO_CATEGORY) {
                        assignmentsTaken.add(go.getId());
                    } else if ((gradebook.getCategory_type() == GradebookService.CATEGORY_TYPE_ONLY_CATEGORY
                            || gradebook.getCategory_type() == GradebookService.CATEGORY_TYPE_WEIGHTED_CATEGORY)
                            && go != null && categories != null) {
                        //                      assignmentsTaken.add(go.getId());
                        //                  }
                        //                  else if(gradebook.getCategory_type() == GradebookService.CATEGORY_TYPE_WEIGHTED_CATEGORY && go != null && categories != null)
                        //                  {
                        for (int i = 0; i < categories.size(); i++) {
                            Category cate = (Category) categories.get(i);
                            if (cate != null && !cate.isRemoved() && go.getCategory() != null
                                    && cate.getId().equals(go.getCategory().getId())
                                    && ((cate.isExtraCredit() != null && !cate.isExtraCredit())
                                            || cate.isExtraCredit() == null)) {
                                assignmentsTaken.add(go.getId());
                                categoryTaken.add(cate.getId());
                                break;
                            }
                        }
                    }
                }
            }
        }

        if (!assignmentsTaken.isEmpty()) {
            if (!literalTotal && gradebook.getCategory_type() == GradebookService.CATEGORY_TYPE_WEIGHTED_CATEGORY) {
                for (int i = 0; i < categories.size(); i++) {
                    Category cate = (Category) categories.get(i);
                    if (cate != null && !cate.isRemoved() && categoryTaken.contains(cate.getId())) {
                        totalPointsPossible += cate.getWeight().doubleValue();
                    }
                }
                return totalPointsPossible;
            }
            Iterator assignmentIter = countedAssigns.iterator();
            while (assignmentIter.hasNext()) {
                Assignment asn = (Assignment) assignmentIter.next();
                if (asn != null) {
                    Double pointsPossible = asn.getPointsPossible();

                    if (gradebook.getCategory_type() == GradebookService.CATEGORY_TYPE_NO_CATEGORY
                            && assignmentsTaken.contains(asn.getId())) {
                        totalPointsPossible += pointsPossible.doubleValue();
                    } else if (gradebook.getCategory_type() == GradebookService.CATEGORY_TYPE_ONLY_CATEGORY
                            && assignmentsTaken.contains(asn.getId())) {
                        totalPointsPossible += pointsPossible.doubleValue();
                    } else if (literalTotal
                            && gradebook.getCategory_type() == GradebookService.CATEGORY_TYPE_WEIGHTED_CATEGORY
                            && assignmentsTaken.contains(asn.getId())) {
                        totalPointsPossible += pointsPossible.doubleValue();
                    }
                }
            }
        } else
            totalPointsPossible = -1;

        return totalPointsPossible;
    }

    @Override
    public void applyDropScores(Collection<AssignmentGradeRecord> gradeRecords) {
        super.applyDropScores(gradeRecords);
    }
}