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