diff --git a/grader/src/main/java/edu/pdx/cs410J/grader/GraderTools.java b/grader/src/main/java/edu/pdx/cs410J/grader/GraderTools.java index 62d190dc9..80e02f6d9 100644 --- a/grader/src/main/java/edu/pdx/cs410J/grader/GraderTools.java +++ b/grader/src/main/java/edu/pdx/cs410J/grader/GraderTools.java @@ -3,6 +3,7 @@ import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import com.google.common.annotations.VisibleForTesting; +import edu.pdx.cs410J.grader.canvas.GradesFromCanvasExporter; import edu.pdx.cs410J.grader.canvas.GradesFromCanvasImporter; import edu.pdx.cs410J.grader.gradebook.ui.GradeBookGUI; import edu.pdx.cs410J.grader.poa.ui.PlanOfAttackGrader; @@ -56,6 +57,9 @@ private static Class getToolClass(String tool) { case "importFromCanvas" : return GradesFromCanvasImporter.class; + case "exportToCanvasCsv" : + return GradesFromCanvasExporter.class; + case "importFromProjectReports" : return ProjectGradesImporter.class; diff --git a/grader/src/main/java/edu/pdx/cs410J/grader/canvas/CanvasGradesCSVGenerator.java b/grader/src/main/java/edu/pdx/cs410J/grader/canvas/CanvasGradesCSVGenerator.java index a0b3fb0c6..daba226d7 100644 --- a/grader/src/main/java/edu/pdx/cs410J/grader/canvas/CanvasGradesCSVGenerator.java +++ b/grader/src/main/java/edu/pdx/cs410J/grader/canvas/CanvasGradesCSVGenerator.java @@ -2,9 +2,11 @@ import com.opencsv.CSVWriter; import edu.pdx.cs410J.grader.gradebook.Assignment; +import edu.pdx.cs410J.grader.gradebook.Grade; import edu.pdx.cs410J.grader.gradebook.GradeBook; import edu.pdx.cs410J.grader.gradebook.Student; +import java.io.IOException; import java.io.Writer; import java.util.ArrayList; import java.util.List; @@ -17,11 +19,15 @@ public CanvasGradesCSVGenerator(Writer writer) { this.writer = writer; } - public void generate(GradeBook book) { - CSVWriter csv = new CSVWriter(writer); - writeHeaderRow(book, csv); - writePossiblePointsRow(book, csv); - writeStudentRows(book, csv); + public void generate(GradeBook book) throws IOException { + try ( + CSVWriter csv = new CSVWriter(writer) + ) { + writeHeaderRow(book, csv); + writePossiblePointsRow(book, csv); + writeStudentRows(book, csv); + csv.flush(); + } } private void writePossiblePointsRow(GradeBook book, CSVWriter csv) { @@ -49,11 +55,24 @@ private void writeStudentRow(GradeBook book, Student student, CSVWriter csv) { } private String[] getStudentLine(GradeBook book, Student student) { - return new String[] { - getStudentName(student), - student.getCanvasId(), - book.getSectionName(student.getEnrolledSection()) - }; + List line = new ArrayList<>(); + line.add(getStudentName(student)); + line.add(student.getCanvasId()); + line.add(book.getSectionName(student.getEnrolledSection())); + + addCellsForEachAssignment(book, line, assignment -> getGrade(student, assignment)); + + return line.toArray(new String[0]); + } + + private String getGrade(Student student, Assignment assignment) { + Grade grade = student.getGrade(assignment); + if (grade == null) { + return null; + + } else { + return String.valueOf(grade.getScore()); + } } private String getStudentName(Student student) { @@ -72,9 +91,7 @@ private void writeHeaderRow(GradeBook book, CSVWriter csv) { } private void addCellsForEachAssignment(GradeBook book, List line, Function function) { - book.getAssignmentNames().stream().map(book::getAssignment).forEach(assignment -> { - line.add(function.apply(assignment)); - }); + book.getAssignmentNames().stream().map(book::getAssignment).forEach(assignment -> line.add(function.apply(assignment))); } private String getAssignmentHeaderCell(Assignment assignment) { diff --git a/grader/src/main/java/edu/pdx/cs410J/grader/canvas/GradesFromCanvasExporter.java b/grader/src/main/java/edu/pdx/cs410J/grader/canvas/GradesFromCanvasExporter.java new file mode 100644 index 000000000..538201534 --- /dev/null +++ b/grader/src/main/java/edu/pdx/cs410J/grader/canvas/GradesFromCanvasExporter.java @@ -0,0 +1,75 @@ +package edu.pdx.cs410J.grader.canvas; + +import edu.pdx.cs410J.ParserException; +import edu.pdx.cs410J.grader.gradebook.GradeBook; +import edu.pdx.cs410J.grader.gradebook.XmlGradeBookParser; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintStream; + +public class GradesFromCanvasExporter { + + public static void exportGradesToCanvasCsv(FileWriter canvasCsv, GradeBook gradebook) throws IOException { + CanvasGradesCSVGenerator generator = new CanvasGradesCSVGenerator(canvasCsv); + generator.generate(gradebook); + } + + public static void main(String[] args) throws IOException, ParserException { + String canvasCsvFileName = null; + String gradeBookFileName = null; + + for (String arg : args) { + if (canvasCsvFileName == null) { + canvasCsvFileName = arg; + + } else if (gradeBookFileName == null) { + gradeBookFileName = arg; + + } else { + usage("Extraneous command line argument: " + arg); + } + } + + if (canvasCsvFileName == null) { + usage("Missing Canvas CSV file name"); + return; + } + + if (gradeBookFileName == null) { + usage("Missing grade book file name"); + } + + GradeBook gradebook = parseGradeBook(gradeBookFileName); + + FileWriter writer = new FileWriter(canvasCsvFileName); + + exportGradesToCanvasCsv(writer, gradebook); + } + + private static GradeBook parseGradeBook(String gradeBookFileName) throws IOException, ParserException { + File gradeBookFile = new File(gradeBookFileName); + if (!gradeBookFile.exists()) { + usage("Grade Book file \"" + gradeBookFile + "\" does not exist"); + } + + XmlGradeBookParser parser = new XmlGradeBookParser(gradeBookFile); + return parser.parse(); + } + + private static void usage(String message) { + PrintStream err = System.err; + + err.println("+++ " + message); + err.println(); + err.println("usage: java GradesFromCanvasImporter canvasGradesCsvFileName gradeBookFileName"); + err.println(" canvasGradesCsvFileName Name of the CSV grades file exported from Canvas"); + err.println(" gradeBookFileName Gradebook file"); + err.println(); + err.println("Imports grades from Canvas into a gradebook"); + err.println(); + + System.exit(1); + } +} diff --git a/grader/src/test/java/edu/pdx/cs410J/grader/canvas/CanvasGradesCSVGeneratorTest.java b/grader/src/test/java/edu/pdx/cs410J/grader/canvas/CanvasGradesCSVGeneratorTest.java index 22eab5b25..9a77c5f4e 100644 --- a/grader/src/test/java/edu/pdx/cs410J/grader/canvas/CanvasGradesCSVGeneratorTest.java +++ b/grader/src/test/java/edu/pdx/cs410J/grader/canvas/CanvasGradesCSVGeneratorTest.java @@ -87,6 +87,33 @@ void canvasCSVHasAssignment() throws IOException { assertThat(canvasAssignment.getId(), equalTo(canvasId)); } + @Test + void canvasCSVHasAssignmentGrade() throws IOException { + GradeBook book = new GradeBook("Test"); + Student student = new Student("id") + .setFirstName("First Name") + .setLastName("Last Name") + .setCanvasId("Canvas Id"); + book.addStudent(student); + + String assignmentName = "Assignment Name"; + Assignment assignment = new Assignment(assignmentName, 4.0).setCanvasId(1234); + book.addAssignment(assignment); + double score = 3.5; + student.setGrade(assignment, score); + + CanvasGradesCSVParser parser = convertToCSVAndBack(book); + List students = parser.getGrades().getStudents(); + assertThat(students, hasSize(1)); + + List assignments = parser.getAssignments(); + assertThat(assignments, hasSize(1)); + + GradesFromCanvas.CanvasAssignment canvasAssignment = assignments.get(0); + GradesFromCanvas.CanvasStudent canvasStudent = students.get(0); + assertThat(canvasStudent.getScore(canvasAssignment), equalTo(score)); + } + private CanvasGradesCSVParser convertToCSVAndBack(GradeBook book) throws IOException { StringWriter sw = new StringWriter(); CanvasGradesCSVGenerator generator = new CanvasGradesCSVGenerator(sw);