/*==========================================================================*\ | $Id: DownloadScoresDialog.java,v 1.2 2010/10/19 18:37:37 aallowat Exp $ |*-------------------------------------------------------------------------*| | Copyright (C) 2006-2010 Virginia Tech | | This file is part of Web-CAT. | | Web-CAT is free software; you can redistribute it and/or modify | it under the terms of the GNU Affero General Public License as published | by the Free Software Foundation; either version 3 of the License, or | (at your option) any later version. | | Web-CAT is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | GNU General Public License for more details. | | You should have received a copy of the GNU Affero General Public License | along with Web-CAT; if not, see <http://www.gnu.org/licenses/>. \*==========================================================================*/ package org.webcat.grader; import java.io.ByteArrayOutputStream; import java.io.File; import org.apache.log4j.Logger; import org.webcat.core.Course; import org.webcat.core.CourseOffering; import org.webcat.core.DeliverFile; import org.webcat.core.Semester; import org.webcat.core.User; import org.webcat.core.WCComponent; import org.webcat.ui.util.ComponentIDGenerator; import com.Ostermiller.util.ExcelCSVPrinter; import com.webobjects.appserver.WOActionResults; import com.webobjects.appserver.WOContext; import com.webobjects.appserver.WOResponse; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSData; import com.webobjects.foundation.NSMutableArray; import com.webobjects.foundation.NSTimestamp; //------------------------------------------------------------------------- /** * Allow the user to download grades for an assignment in spreadsheet form * as a CSV file. * * @author Tony Allevato * @author Last changed by $Author: aallowat $ * @version $Revision: 1.2 $, $Date: 2010/10/19 18:37:37 $ */ public class DownloadScoresDialog extends WCComponent { //~ Constructors .......................................................... // ---------------------------------------------------------- public DownloadScoresDialog(WOContext context) { super(context); } //~ KVC attributes (must be public) ....................................... public boolean useBlackboardFormat; public boolean useMoodleFormat = true; public boolean useFullFormat; public boolean omitStaff = true; public NSArray<AssignmentOffering> assignmentOfferings; public NSArray<CourseOffering> courseOfferings; public Assignment assignment; public Course course; public Semester semester; public ComponentIDGenerator idFor; //~ Methods ............................................................... // ---------------------------------------------------------- @Override public void appendToResponse(WOResponse response, WOContext context) { idFor = new ComponentIDGenerator(this); AssignmentOffering ao = assignmentOfferings.objectAtIndex(0); // Assume these are the same for all assignment offerings (which they // should be, unless we redesign the navigation). assignment = ao.assignment(); course = ao.courseOffering().course(); semester = ao.courseOffering().semester(); super.appendToResponse(response, context); } // ---------------------------------------------------------- public String courseTitleString() { CourseOffering offering = courseOfferings.objectAtIndex(0); if (courseOfferings.count() > 1) { return offering.course().toString() + " (All)"; } else { return offering.toString(); } } // ---------------------------------------------------------- /** * Downloads the scores in the appropriate file format. * * @return the CSV content as a DeliverFile component */ public WOActionResults downloadScores() { collectSubmissionsToExport(); byte[] rawData; if (useFullFormat) { rawData = exportAsWebCATCSV(); } else { rawData = exportAsBlackboardCSV(useMoodleFormat); } String filename; if (assignmentOfferings.count() == 1) { filename = assignmentOfferings.objectAtIndex(0).courseOffering() .crnSubdirName() + "-"; } else { filename = course.deptNumber() + "-"; } filename += assignment.subdirName() + ".csv"; DeliverFile csvFile = pageWithName(DeliverFile.class); csvFile.setFileData(new NSData(rawData)); csvFile.setFileName(new File(filename)); csvFile.setContentType("application/octet-stream"); csvFile.setStartDownload(true); return csvFile; } // ---------------------------------------------------------- private void collectSubmissionsToExport() { NSMutableArray<UserSubmissionPair> submissions = new NSMutableArray<UserSubmissionPair>(); for (AssignmentOffering ao : assignmentOfferings) { NSArray<User> students = omitStaff ? ao.courseOffering().studentsWithoutStaff() : ao.courseOffering().studentsAndStaff(); submissions.addObjectsFromArray(Submission.submissionsForGrading( localContext(), ao, false, students, null)); } submissionsToExport = submissions; } // ---------------------------------------------------------- private void print(ExcelCSVPrinter out, String field) { if (field == null) { out.print(""); } else { out.print(field); } } // ---------------------------------------------------------- private void print(ExcelCSVPrinter out, Number field) { if (field == null) { out.print(""); } else { out.print(field.toString()); } } // ---------------------------------------------------------- public byte[] exportAsWebCATCSV() { ByteArrayOutputStream outBytes = new ByteArrayOutputStream(4096); ExcelCSVPrinter out = new ExcelCSVPrinter(outBytes); // Basic header information out.print("Course"); out.print(""); out.println(course.deptNumber()); out.print("Semester"); out.print(""); out.println(semester.name()); out.print("Assignment"); out.print(""); out.println(assignment.name()); out.print("Generated on"); out.print(""); out.println(wcSession().timeFormatter().format(new NSTimestamp())); out.println(""); // Column titles out.print("ID No."); out.print("User"); out.print("Last Name"); out.print("First Name"); out.print("Sub No."); out.print("Time"); out.print("Correctness"); out.print("Style"); out.print("Design"); out.print("Penalty/Bonus"); out.println("Total"); for (UserSubmissionPair pair : submissionsToExport) { if (pair.userHasSubmission()) { User student = pair.user(); Submission submission = pair.submission(); print(out, student.universityIDNo()); print(out, student.userName()); print(out, student.lastName()); print(out, student.firstName()); log.debug("submission found = " + submission.submitNumber()); print(out, submission.submitNumberRaw()); print(out, submission.submitTime().toString()); SubmissionResult result = pair.submission().result(); print(out, result.correctnessScoreRaw()); print(out, result.toolScoreRaw()); print(out, result.taScoreRaw()); print(out, Double.toString( result.earlyBonus() - result.latePenalty())); out.println(Double.toString(result.finalScore())); } } return outBytes.toByteArray(); } // ---------------------------------------------------------- public byte[] exportAsBlackboardCSV(boolean targetMoodle) { ByteArrayOutputStream outBytes = new ByteArrayOutputStream(4096); ExcelCSVPrinter out = new ExcelCSVPrinter(outBytes); // Basic header information if (targetMoodle) { out.print("username"); out.println(assignment.name()); } else { out.print("PID"); String name = assignment.name(); if (name.startsWith("Lab")) { name += " (Lab)"; } out.println(name); } for (UserSubmissionPair pair : submissionsToExport) { if (pair.userHasSubmission()) { print(out, pair.user().userName()); out.println(Double.toString( pair.submission().result().finalScore())); } } if (!targetMoodle) { out.print("Points Possible"); out.println(assignment .submissionProfile().availablePointsRaw().toString()); } return outBytes.toByteArray(); } //~ Static/instance variables ............................................. private NSArray<UserSubmissionPair> submissionsToExport; private static final Logger log = Logger.getLogger(DownloadScoresDialog.class); }