001package edu.pdx.cs.joy.grader.canvas; 002 003import edu.pdx.cs.joy.grader.gradebook.Assignment; 004import edu.pdx.cs.joy.grader.gradebook.GradeBook; 005import edu.pdx.cs.joy.grader.gradebook.Student; 006 007import java.util.*; 008import java.util.stream.Collectors; 009 010public class GradesFromCanvas { 011 private final List<CanvasStudent> students = new ArrayList<>(); 012 013 public static CanvasStudentBuilder newStudent() { 014 return new CanvasStudentBuilder(); 015 } 016 017 public void addStudent(CanvasStudent student) { 018 this.students.add(student); 019 } 020 021 public Optional<Student> findStudentInGradebookForCanvasStudent(CanvasStudent canvasStudent, GradeBook book) { 022 return book.studentsStream().filter((Student student) -> { 023 if (haveSameCanvasId(canvasStudent, student)) { 024 return true; 025 026 } else if (studentIdIsSameAsLoginId(canvasStudent, student)) { 027 noteStudent(canvasStudent, student, book); 028 return true; 029 030 } else if (haveSameFirstAndLastNameIgnoringCase(canvasStudent, student)) { 031 noteStudent(canvasStudent, student, book); 032 return true; 033 034 } else if (haveSameNickAndLastNameIgnoringCase(canvasStudent, student)) { 035 noteStudent(canvasStudent, student, book); 036 return true; 037 038 } else { 039 return false; 040 } 041 }).findAny(); 042 } 043 044 private void noteStudent(CanvasStudent canvasStudent, Student student, GradeBook book) { 045 student.setCanvasId(canvasStudent.getCanvasId()); 046 book.setSectionName(student.getEnrolledSection(), canvasStudent.getSection()); 047 } 048 049 private boolean studentIdIsSameAsLoginId(CanvasStudent d2lStudent, Student student) { 050 return d2lStudent.getLoginId().equals(student.getId()); 051 } 052 053 private boolean haveSameFirstAndLastNameIgnoringCase(CanvasStudent d2lStudent, Student student) { 054 return d2lStudent.getFirstName().equalsIgnoreCase(student.getFirstName()) && 055 d2lStudent.getLastName().equalsIgnoreCase(student.getLastName()); 056 } 057 058 private boolean haveSameNickAndLastNameIgnoringCase(CanvasStudent d2lStudent, Student student) { 059 return d2lStudent.getFirstName().equalsIgnoreCase(student.getNickName()) && 060 d2lStudent.getLastName().equalsIgnoreCase(student.getLastName()); 061 } 062 063 private boolean haveSameCanvasId(CanvasStudent canvasStudent, Student student) { 064 return canvasStudent.getCanvasId().equals(student.getCanvasId()); 065 } 066 067 public List<CanvasStudent> getStudents() { 068 return this.students; 069 } 070 071 public Optional<Assignment> findAssignmentInGradebookForCanvasQuiz(CanvasAssignment canvasAssignment, GradeBook gradebook) { 072 String canvasQuizName = canvasAssignment.getName(); 073 Optional<Assignment> maybeAssignment; 074 075 Assignment assignment = gradebook.getAssignment(canvasQuizName); 076 if (assignment != null) { 077 maybeAssignment = noteMatchedAssignment(assignment, canvasAssignment); 078 079 } else { 080 maybeAssignment = findAssignmentInGradebookLike(canvasAssignment, gradebook); 081 } 082 083 return maybeAssignment; 084 } 085 086 private Optional<Assignment> noteMatchedAssignment(Assignment assignment, CanvasAssignment canvasAssignment) { 087 assignment.setCanvasId(canvasAssignment.getId()); 088 return Optional.of(assignment); 089 } 090 091 private Optional<Assignment> findAssignmentInGradebookLike(CanvasAssignment canvasAssignment, GradeBook gradebook) { 092 List<Assignment> assignments = new ArrayList<>(); 093 String canvasQuizName = canvasAssignment.getName(); 094 for (String assignmentName : gradebook.getAssignmentNames()) { 095 Assignment assignment = gradebook.getAssignment(assignmentName); 096 if (canvasQuizName.startsWith(assignmentName)) { 097 assignments.add(assignment); 098 099 } else if (canvasQuizName.contains(assignment.getDescription())) { 100 assignments.add(assignment); 101 } 102 } 103 104 if (assignments.isEmpty()) { 105 return Optional.empty(); 106 107 } else if (assignments.size() == 1) { 108 return noteMatchedAssignment(assignments.get(0), canvasAssignment); 109 110 } else { 111 String message = "Multiple assignments match \"" + canvasQuizName + "\": " + 112 assignments.stream().map(Assignment::getName).collect(Collectors.joining(", ")); 113 throw new IllegalStateException(message); 114 } 115 } 116 117 static class CanvasStudent { 118 private final String firstName; 119 private final String lastName; 120 private final String loginId; 121 private final String canvasId; 122 private final String section; 123 private final Map<CanvasAssignment, Double> scores = new HashMap<>(); 124 125 public CanvasStudent(String firstName, String lastName, String loginId, String canvasId, String section) { 126 this.firstName = firstName; 127 this.lastName = lastName; 128 this.loginId = loginId; 129 this.canvasId = canvasId; 130 this.section = section; 131 } 132 133 public String getLoginId() { 134 return loginId; 135 } 136 137 public String getFirstName() { 138 return firstName; 139 } 140 141 public String getLastName() { 142 return lastName; 143 } 144 145 public String getCanvasId() { 146 return this.canvasId; 147 } 148 149 public void setScore(CanvasAssignment assignment, Double score) { 150 this.scores.put(assignment, score); 151 } 152 153 public Double getScore(CanvasAssignment assignment) { 154 return this.scores.get(assignment); 155 } 156 157 public Iterable<CanvasAssignment> getAssignments() { 158 return this.scores.keySet(); 159 } 160 161 public String getSection() { 162 return section; 163 } 164 165 @Override 166 public String toString() { 167 return "Canvas student \"" + getFirstName() + " " + getLastName() + "\" with id " + getLoginId(); 168 } 169 } 170 171 static class CanvasStudentBuilder { 172 private String firstName; 173 private String lastName; 174 private String loginId; 175 private String canvasId; 176 private String section; 177 178 private CanvasStudentBuilder() { 179 180 } 181 182 public CanvasStudentBuilder setFirstName(String firstName) { 183 this.firstName = firstName; 184 return this; 185 } 186 187 public CanvasStudentBuilder setLastName(String lastName) { 188 this.lastName = lastName; 189 return this; 190 } 191 192 public CanvasStudentBuilder setLoginId(String loginId) { 193 this.loginId = loginId; 194 return this; 195 } 196 197 public CanvasStudentBuilder setCanvasId(String canvasId) { 198 this.canvasId = canvasId; 199 return this; 200 } 201 202 public CanvasStudentBuilder setSection(String section) { 203 this.section = section; 204 return this; 205 } 206 207 public CanvasStudent create() { 208 if (firstName == null) { 209 throw new IllegalStateException("Missing first name"); 210 } 211 212 if (lastName == null) { 213 throw new IllegalStateException("Missing last name"); 214 } 215 216 if (loginId == null) { 217 throw new IllegalStateException("Missing login Id"); 218 } 219 220 if (canvasId == null) { 221 throw new IllegalStateException("Missing canvas Id"); 222 } 223 224 if (section == null) { 225 throw new IllegalStateException("Missing section"); 226 } 227 228 return new CanvasStudent(firstName, lastName, loginId, canvasId, section); 229 } 230 } 231 232 public static class CanvasAssignment { 233 private final String name; 234 private final int id; 235 private double pointsPossible; 236 237 public CanvasAssignment(String name, int id) { 238 this.name = name; 239 this.id = id; 240 } 241 242 public String getName() { 243 return name; 244 } 245 246 public int getId() { 247 return id; 248 } 249 250 public double getPointsPossible() { 251 return pointsPossible; 252 } 253 254 void setPossiblePoints(double possiblePoints) { 255 this.pointsPossible = possiblePoints; 256 } 257 } 258}