From 9d8ad3b3ba9aff715d80ea88858f2ce5ec941dbf Mon Sep 17 00:00:00 2001 From: David Whitlock Date: Sun, 27 Mar 2022 19:58:04 -0700 Subject: [PATCH 1/4] Generate CSV for assignment scores in a grade book. --- .../canvas/CanvasGradesCSVGenerator.java | 24 +++++++++++++---- .../canvas/CanvasGradesCSVGeneratorTest.java | 27 +++++++++++++++++++ 2 files changed, 46 insertions(+), 5 deletions(-) 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 958020e61..231a8833c 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,6 +2,7 @@ import com.opencsv.CSVWriter; import edu.pdx.cs410J.grader.Assignment; +import edu.pdx.cs410J.grader.Grade; import edu.pdx.cs410J.grader.GradeBook; import edu.pdx.cs410J.grader.Student; @@ -49,11 +50,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) { 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 b98ace2f5..133efb726 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); From 1880fd7e5e1a85e4e1ef05b7ca16f18be161e386 Mon Sep 17 00:00:00 2001 From: David Whitlock Date: Sun, 27 Mar 2022 20:08:49 -0700 Subject: [PATCH 2/4] Increment the minor version of the grader library for generating Canvas CSV. --- grader/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grader/pom.xml b/grader/pom.xml index 626709db5..88014d0ba 100644 --- a/grader/pom.xml +++ b/grader/pom.xml @@ -8,7 +8,7 @@ io.github.davidwhitlock.cs410J grader grader - 2022.4.2 + 2022.4.4 jar http://www.cs.pdx.edu/~whitlock From ab3511588e5428d234dad4e0e84b888ddcbf8766 Mon Sep 17 00:00:00 2001 From: David Whitlock Date: Sun, 27 Mar 2022 20:37:53 -0700 Subject: [PATCH 3/4] Added support for exporting Canvas CSV to GraderTools --- .../edu/pdx/cs410J/grader/GraderTools.java | 4 + .../canvas/CanvasGradesCSVGenerator.java | 15 ++-- .../canvas/GradesFromCanvasExporter.java | 75 +++++++++++++++++++ 3 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 grader/src/main/java/edu/pdx/cs410J/grader/canvas/GradesFromCanvasExporter.java 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 ee063121d..81a9ec9cb 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.poa.ui.PlanOfAttackGrader; import org.slf4j.LoggerFactory; @@ -55,6 +56,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 231a8833c..177b6150d 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 @@ -6,6 +6,7 @@ import edu.pdx.cs410J.grader.GradeBook; import edu.pdx.cs410J.grader.Student; +import java.io.IOException; import java.io.Writer; import java.util.ArrayList; import java.util.List; @@ -18,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) { 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..352385ddc --- /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; +import edu.pdx.cs410J.grader.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); + } +} From 84df3e4588f8513276025e967cb0625cf415a5d3 Mon Sep 17 00:00:00 2001 From: David Whitlock Date: Sun, 15 May 2022 21:07:39 -0700 Subject: [PATCH 4/4] Fix some problems introduced by the code merged from the 2022.1.0-SNAPSHOT branch. --- .../pdx/cs410J/grader/canvas/CanvasGradesCSVGenerator.java | 7 +++---- .../pdx/cs410J/grader/canvas/GradesFromCanvasExporter.java | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) 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 4264fc019..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,6 +2,7 @@ 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; @@ -20,7 +21,7 @@ public CanvasGradesCSVGenerator(Writer writer) { public void generate(GradeBook book) throws IOException { try ( - CSVWriter csv = new CSVWriter(writer); + CSVWriter csv = new CSVWriter(writer) ) { writeHeaderRow(book, csv); writePossiblePointsRow(book, csv); @@ -90,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 index 352385ddc..538201534 100644 --- a/grader/src/main/java/edu/pdx/cs410J/grader/canvas/GradesFromCanvasExporter.java +++ b/grader/src/main/java/edu/pdx/cs410J/grader/canvas/GradesFromCanvasExporter.java @@ -1,8 +1,8 @@ package edu.pdx.cs410J.grader.canvas; import edu.pdx.cs410J.ParserException; -import edu.pdx.cs410J.grader.GradeBook; -import edu.pdx.cs410J.grader.XmlGradeBookParser; +import edu.pdx.cs410J.grader.gradebook.GradeBook; +import edu.pdx.cs410J.grader.gradebook.XmlGradeBookParser; import java.io.File; import java.io.FileWriter;