001package edu.pdx.cs.joy.grader; 002 003import com.google.common.annotations.VisibleForTesting; 004import edu.pdx.cs.joy.ParserException; 005import edu.pdx.cs.joy.grader.gradebook.GradeBook; 006import edu.pdx.cs.joy.grader.gradebook.Student; 007import edu.pdx.cs.joy.grader.gradebook.XmlGradeBookParser; 008 009import java.io.File; 010import java.io.IOException; 011import java.util.ArrayList; 012import java.util.List; 013import java.util.function.Supplier; 014import java.util.stream.Stream; 015 016import static java.util.stream.Collectors.toCollection; 017 018public class GenerateStudentInitialsFile { 019 020 public static List<String> generateInitials(Stream<Student> students) { 021 return students 022 .map(StudentInitials::new) 023 .sorted() 024 .map(StudentInitials::getInitials) 025 .collect(toCollection(ArrayList::new)); 026 } 027 028 @VisibleForTesting 029 static class StudentInitials implements Comparable<StudentInitials> { 030 private final Student student; 031 int uniqueCharsOfFirstname = 1; 032 int uniqueCharsOfLastname = 1; 033 034 public StudentInitials(Student student) { 035 this.student = student; 036 } 037 038 public String getInitials() { 039 return getFirstNameInitials() + getLastNameInitials(); 040 } 041 042 private String getLastNameInitials() { 043 return getNameInitials(student::getLastName, uniqueCharsOfLastname); 044 } 045 046 private static String getNameInitials(Supplier<String> nameAccessor, int uniqueChars) { 047 return uppercaseFirstLetter(nameAccessor.get().substring(0, uniqueChars)); 048 } 049 050 private static String uppercaseFirstLetter(String substring) { 051 if (substring.isEmpty()) { 052 return ""; 053 } 054 055 StringBuilder sb = new StringBuilder(); 056 sb.append(Character.toUpperCase(substring.charAt(0))); 057 if (substring.length() > 1) { 058 sb.append(substring.substring(1).toLowerCase()); 059 } 060 return sb.toString(); 061 } 062 063 private String getFirstNameInitials() { 064 return getNameInitials(student::getFirstName, uniqueCharsOfFirstname); 065 } 066 067 @Override 068 public int compareTo(StudentInitials other) { 069 int lastInitialsComparison = this.getLastNameInitials().compareToIgnoreCase(other.getLastNameInitials()); 070 if (lastInitialsComparison != 0) { 071 return lastInitialsComparison; 072 } 073 int firstInitialsComparison = this.getFirstNameInitials().compareToIgnoreCase(other.getFirstNameInitials()); 074 if (firstInitialsComparison != 0) { 075 return firstInitialsComparison; 076 } 077 078 if (this.uniqueCharsOfLastname > this.uniqueCharsOfFirstname) { 079 this.incrementUniqueCharsOfFirstName(); 080 other.incrementUniqueCharsOfFirstName(); 081 082 } else { 083 this.incrementUniqueCharsOfLastName(); 084 other.incrementUniqueCharsOfLastName(); 085 } 086 return this.compareTo(other); 087 } 088 089 @VisibleForTesting 090 void incrementUniqueCharsOfLastName() { 091 if (this.uniqueCharsOfLastname < student.getLastName().length()) { 092 this.uniqueCharsOfLastname++; 093 } 094 } 095 096 @VisibleForTesting 097 void incrementUniqueCharsOfFirstName() { 098 if (this.uniqueCharsOfFirstname < student.getFirstName().length()) { 099 this.uniqueCharsOfFirstname++; 100 } 101 } 102 } 103 104 public static void main(String[] args) { 105 if (args.length < 1) { 106 usage("Usage: GenerateStudentInitialsFile gradeBookFile"); 107 } 108 109 String gradeBookFileName = args[0]; 110 GradeBook book = loadGradeBookFromFile(gradeBookFileName); 111 List<String> initials = generateInitials(book.studentsStream()); 112 113 System.out.println(""" 114 Replace your initials in this file with the word "HERE" to demonstrate that you can push to this repository. 115 116 """); 117 for (int i = 0; i < initials.size(); i++) { 118 String initial = initials.get(i); 119 System.out.format("%2d. %s%n", (i + 1), initial); 120 } 121 } 122 123 private static GradeBook loadGradeBookFromFile(String gradeBookFileName) { 124 File gradeBookFile = getExistingGradeBookFile(gradeBookFileName); 125 return parseGradeBookFile(gradeBookFile); 126 } 127 128 private static GradeBook parseGradeBookFile(File file) { 129 try { 130 return new XmlGradeBookParser(file).parse(); 131 132 } catch (ParserException | IOException e) { 133 usage("While parsing " + file + ": " + e); 134 return null; 135 } 136 } 137 138 private static File getExistingGradeBookFile(String gradeBookFileName) { 139 File file = new File(gradeBookFileName); 140 if (!file.exists()) { 141 usage("Grade book file does not exist: " + gradeBookFileName); 142 } 143 return file; 144 } 145 146 private static void usage(String message) { 147 System.err.println(message); 148 System.exit(1); 149 } 150}