org.sakaiproject.gradebookng.tool.panels.AssignmentStatisticsPanel.java Source code

Java tutorial

Introduction

Here is the source code for org.sakaiproject.gradebookng.tool.panels.AssignmentStatisticsPanel.java

Source

/**
 * Copyright (c) 2003-2017 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.gradebookng.tool.panels;

import java.awt.Color;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.StringResourceModel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberTickUnitSource;
import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.renderer.category.StandardBarPainter;
import org.jfree.data.category.DefaultCategoryDataset;
import org.sakaiproject.gradebookng.business.model.GbGradeInfo;
import org.sakaiproject.gradebookng.business.model.GbStudentGradeInfo;
import org.sakaiproject.gradebookng.business.util.FormatHelper;
import org.sakaiproject.gradebookng.tool.component.GbAjaxLink;
import org.sakaiproject.gradebookng.tool.component.JFreeChartImageWithToolTip;
import org.sakaiproject.service.gradebook.shared.Assignment;
import org.sakaiproject.service.gradebook.shared.GradingType;

public class AssignmentStatisticsPanel extends BasePanel {

    private static final long serialVersionUID = 1L;

    private final ModalWindow window;
    private final GradingType gradingType;

    public AssignmentStatisticsPanel(final String id, final IModel<Long> model, final ModalWindow window) {
        super(id, model);
        this.window = window;
        this.gradingType = GradingType.valueOf(this.businessService.getGradebook().getGrade_type());
    }

    @Override
    public void onInitialize() {
        super.onInitialize();

        final Long assignmentId = ((Model<Long>) getDefaultModel()).getObject();

        final Assignment assignment = this.businessService.getAssignment(assignmentId.longValue());

        AssignmentStatisticsPanel.this.window.setTitle(
                (new StringResourceModel("label.statistics.title", null, new Object[] { assignment.getName() })
                        .getString()));

        final List<GbStudentGradeInfo> gradeInfo = this.businessService.buildGradeMatrix(Arrays.asList(assignment));

        final List<Double> allGrades = new ArrayList<>();

        for (int i = 0; i < gradeInfo.size(); i++) {
            final GbStudentGradeInfo studentGradeInfo = gradeInfo.get(i);

            final Map<Long, GbGradeInfo> studentGrades = studentGradeInfo.getGrades();
            final GbGradeInfo grade = studentGrades.get(assignmentId);

            if (grade == null || grade.getGrade() == null) {
                // this is not the grade you are looking for
            } else {
                allGrades.add(Double.valueOf(grade.getGrade()));
            }
        }

        Collections.sort(allGrades);

        final DefaultCategoryDataset data = new DefaultCategoryDataset();

        final Map<String, Integer> counts = new TreeMap<>();
        Integer extraCredits = 0;

        // Start off with a 0-50% range
        counts.put(String.format("%d-%d", 0, 50), 0);

        final int range = 10;
        for (int start = 50; start < 100; start = start + range) {
            final String key = String.format("%d-%d", start, start + range);
            counts.put(key, 0);
        }

        for (final Double grade : allGrades) {
            if (isExtraCredit(grade, assignment)) {
                extraCredits = extraCredits + 1;
                continue;
            }

            final double percentage;
            if (GradingType.PERCENTAGE.equals(this.gradingType)) {
                percentage = grade;
            } else {
                percentage = grade / assignment.getPoints() * 100;
            }

            final int total = Double.valueOf(Math.ceil(percentage) / range).intValue();

            int start = total * range;

            if (start == 100) {
                start = start - range;
            }

            String key = String.format("%d-%d", start, start + range);

            if (start < 50) {
                key = String.format("%d-%d", 0, 50);
            }

            counts.put(key, counts.get(key) + 1);
        }

        for (final String label : counts.keySet()) {
            data.addValue(counts.get(label), "count", label);
        }
        if (extraCredits > 0) {
            data.addValue(extraCredits, "count", getString("label.statistics.chart.extracredit"));
        }

        final JFreeChart chart = ChartFactory.createBarChart(null, // the chart title
                getString("label.statistics.chart.xaxis"), // the label for the category axis
                getString("label.statistics.chart.yaxis"), // the label for the value axis
                data, // the dataset for the chart
                PlotOrientation.VERTICAL, // the plot orientation
                false, // show legend
                true, // show tooltips
                false); // show urls

        chart.setBorderVisible(false);

        chart.setAntiAlias(false);

        final CategoryPlot categoryPlot = chart.getCategoryPlot();
        final BarRenderer br = (BarRenderer) categoryPlot.getRenderer();

        br.setItemMargin(0);
        br.setMinimumBarLength(0.05);
        br.setMaximumBarWidth(0.1);
        br.setSeriesPaint(0, new Color(51, 122, 183));
        br.setBarPainter(new StandardBarPainter());
        br.setShadowPaint(new Color(220, 220, 220));
        BarRenderer.setDefaultShadowsVisible(true);

        br.setBaseToolTipGenerator(new StandardCategoryToolTipGenerator(getString("label.statistics.chart.tooltip"),
                NumberFormat.getInstance()));

        categoryPlot.setRenderer(br);

        // show only integers in the count axis
        categoryPlot.getRangeAxis().setStandardTickUnits(new NumberTickUnitSource(true));
        categoryPlot.setBackgroundPaint(Color.white);

        add(new JFreeChartImageWithToolTip("chart", Model.of(chart), "tooltip", 540, 300));

        add(new Label("graded", String.valueOf(allGrades.size())));

        if (allGrades.size() > 0) {
            add(new Label("average", constructAverageLabel(allGrades, assignment)));
            add(new Label("median", constructMedianLabel(allGrades, assignment)));
            add(new Label("lowest", constructLowestLabel(allGrades, assignment)));
            add(new Label("highest", constructHighestLabel(allGrades, assignment)));
            add(new Label("deviation", constructStandardDeviationLabel(allGrades)));
        } else {
            add(new Label("average", "-"));
            add(new Label("median", "-"));
            add(new Label("lowest", "-"));
            add(new Label("highest", "-"));
            add(new Label("deviation", "-"));
        }

        add(new GbAjaxLink("done") {
            private static final long serialVersionUID = 1L;

            @Override
            public void onClick(final AjaxRequestTarget target) {
                AssignmentStatisticsPanel.this.window.close(target);
            }
        });
    }

    private String constructAverageLabel(final List<Double> allGrades, final Assignment assignment) {
        final double average = calculateAverage(allGrades);
        final String averageFormatted = FormatHelper.formatDoubleToDecimal(Double.valueOf(average));

        if (GradingType.PERCENTAGE.equals(this.gradingType)) {
            return (new StringResourceModel("label.percentage.valued", null, new Object[] { averageFormatted }))
                    .getString();
        }

        final Double total = assignment.getPoints();
        final String percentage = FormatHelper.formatDoubleAsPercentage(100 * (average / total.doubleValue()));

        return (new StringResourceModel("label.statistics.averagevalue", null,
                new Object[] { averageFormatted, FormatHelper.formatGrade(String.valueOf(total)), percentage }))
                        .getString();
    }

    private String constructMedianLabel(final List<Double> allGrades, final Assignment assignment) {
        final double median = calculateMedian(allGrades);
        final String medianFormatted = FormatHelper.formatDoubleToDecimal(Double.valueOf(median));

        if (GradingType.PERCENTAGE.equals(this.gradingType)) {
            return (new StringResourceModel("label.percentage.valued", null, new Object[] { medianFormatted }))
                    .getString();
        }

        final Double total = assignment.getPoints();
        final String percentage = FormatHelper.formatDoubleAsPercentage(100 * (median / total.doubleValue()));

        return (new StringResourceModel("label.statistics.medianvalue", null,
                new Object[] { medianFormatted, FormatHelper.formatGrade(String.valueOf(total)), percentage }))
                        .getString();
    }

    private String constructLowestLabel(final List<Double> allGrades, final Assignment assignment) {
        final double lowest = Collections.min(allGrades);
        final String lowestFormatted = FormatHelper.formatDoubleToDecimal(Double.valueOf(lowest));

        if (GradingType.PERCENTAGE.equals(this.gradingType)) {
            return (new StringResourceModel("label.percentage.valued", null, new Object[] { lowestFormatted }))
                    .getString();
        }

        final Double total = assignment.getPoints();
        final String percentage = FormatHelper.formatDoubleAsPercentage(100 * (lowest / total.doubleValue()));

        return (new StringResourceModel("label.statistics.lowestvalue", null,
                new Object[] { lowestFormatted, FormatHelper.formatGrade(String.valueOf(total)), percentage }))
                        .getString();
    }

    private String constructHighestLabel(final List<Double> allGrades, final Assignment assignment) {
        final double highest = Collections.max(allGrades);
        final String highestFormatted = FormatHelper.formatDoubleToDecimal(Double.valueOf(highest));

        if (GradingType.PERCENTAGE.equals(this.gradingType)) {
            return (new StringResourceModel("label.percentage.valued", null, new Object[] { highestFormatted }))
                    .getString();
        }

        final Double total = assignment.getPoints();
        final String percentage = FormatHelper.formatDoubleAsPercentage(100 * (highest / total.doubleValue()));

        return new StringResourceModel("label.statistics.highestvalue", null,
                new Object[] { highestFormatted, FormatHelper.formatGrade(String.valueOf(total)), percentage })
                        .getString();
    }

    private String constructStandardDeviationLabel(final List<Double> allGrades) {
        final double deviation = calculateStandardDeviation(allGrades);

        return FormatHelper.formatDoubleToDecimal(Double.valueOf(deviation));
    }

    private double calculateAverage(final List<Double> allGrades) {
        double sum = 0;
        for (int i = 0; i < allGrades.size(); i++) {
            sum += allGrades.get(i);
        }
        return sum / allGrades.size();
    }

    private double calculateMedian(final List<Double> allGrades) {
        final int middle = allGrades.size() / 2;
        if (allGrades.size() % 2 == 1) {
            return allGrades.get(middle);
        } else {
            return (allGrades.get(middle - 1) + allGrades.get(middle)) / 2.0;
        }
    }

    private double calculateVariance(final List<Double> allGrades) {
        final double mean = calculateAverage(allGrades);
        double sum = 0;

        for (int i = 0; i < allGrades.size(); i++) {
            final double grade = allGrades.get(i);
            sum += (mean - grade) * (mean - grade);
        }

        return sum / allGrades.size();
    }

    private double calculateStandardDeviation(final List<Double> allGrades) {
        return Math.sqrt(calculateVariance(allGrades));
    }

    private boolean isExtraCredit(final Double grade, final Assignment assignment) {
        return (GradingType.PERCENTAGE.equals(this.gradingType) && grade > 100)
                || (GradingType.POINTS.equals(this.gradingType) && grade > assignment.getPoints());
    }
}