diff --git a/src/main/java/org/grahamkirby/race_timing/common/CompletionStatus.java b/src/main/java/org/grahamkirby/race_timing/common/CompletionStatus.java index 1ec8568..b882956 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/CompletionStatus.java +++ b/src/main/java/org/grahamkirby/race_timing/common/CompletionStatus.java @@ -2,7 +2,18 @@ public enum CompletionStatus { - COMPLETED, // Completed race or series. - DNS, // Did Not Start: runner appears in entry but no finish(es) recorded. - DNF // Did Not Finish: did not complete all legs or sufficient component races. + /** + * Completed race or series. + */ + COMPLETED, + + /** + * Did Not Start: runner appears in entry but no finish(es) recorded. + */ + DNS, + + /** + * Did Not Finish: did not complete all legs or sufficient component races. + */ + DNF } diff --git a/src/main/java/org/grahamkirby/race_timing/common/Normalisation.java b/src/main/java/org/grahamkirby/race_timing/common/Normalisation.java index e840be7..9a2cd2a 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/Normalisation.java +++ b/src/main/java/org/grahamkirby/race_timing/common/Normalisation.java @@ -5,6 +5,7 @@ import java.util.Map; import java.util.Set; +@SuppressWarnings("StringTemplateMigration") public class Normalisation { private static final int SECONDS_PER_HOUR = 3600; @@ -20,11 +21,11 @@ public Normalisation(final Race race) { this.race = race; } - public String getFirstName(final String name) { + static String getFirstName(final String name) { return name.split(" ")[0]; } - public String getLastName(final String name) { + static String getLastName(final String name) { return Arrays.stream(name.split(" ")).toList().getLast(); } @@ -106,35 +107,35 @@ private String lookupInStopWords(final String word) { // Try case insensitive match. return race.capitalisation_stop_words.stream(). - filter(w -> w.equalsIgnoreCase(word)). - findFirst(). - orElse(null); + filter(w -> w.equalsIgnoreCase(word)). + findFirst(). + orElse(null); } - private boolean isTitleCase(final String input) { + @SuppressWarnings("TypeMayBeWeakened") + private static boolean isTitleCase(final String input) { return !Character.isLowerCase(input.charAt(0)) && - input.chars().boxed().skip(1).noneMatch(Character::isUpperCase); + input.chars().boxed().skip(1).noneMatch(Character::isUpperCase); } private static String replaceAllMapEntries(final String s, final Map normalisation_map) { String result = s; - for (final String key : normalisation_map.keySet()) { + for (final Map.Entry entry : normalisation_map.entrySet()) { - final String value = normalisation_map.get(key); - result = result.replaceAll("(?i)" + key, value); + final String value = entry.getValue(); + result = result.replaceAll(STR."(?i)\{entry.getKey()}", value); } return result; } - public static Duration parseTime(String element) { + public static Duration parseTime(final String element) { try { return parseTime(element, ":"); - } - catch (Exception _) { + } catch (final RuntimeException _) { return parseTime(element, "\\."); } } @@ -142,28 +143,27 @@ public static Duration parseTime(String element) { private static Duration parseTime(String element, final String separator) { element = element.strip(); - if (element.startsWith(separator)) element = "0" + element; - if (element.endsWith(separator)) element = element + "0"; + if (element.startsWith(separator)) element = STR."0\{element}"; + if (element.endsWith(separator)) element = STR."\{element}0"; try { final String[] parts = element.split(separator); - final String time_as_ISO = STR."PT\{hours(parts)}\{minutes(parts)}\{seconds(parts)}"; - return Duration.parse(time_as_ISO); - } - catch (Exception _) { - throw new RuntimeException("illegal time: " + element); + return Duration.parse(STR."PT\{hours(parts)}\{minutes(parts)}\{seconds(parts)}"); + + } catch (final RuntimeException _) { + throw new RuntimeException(STR."illegal time: \{element}"); } } public static String format(final Duration duration) { - final long s = duration.getSeconds(); + final long seconds = duration.getSeconds(); final int n = duration.getNano(); - String result = String.format("0%d:%02d:%02d", s / SECONDS_PER_HOUR, (s % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE, (s % SECONDS_PER_MINUTE)); + String result = String.format("0%d:%02d:%02d", seconds / SECONDS_PER_HOUR, (seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE, (seconds % SECONDS_PER_MINUTE)); if (n > 0) { - double fractional_seconds = n / NANOSECONDS_PER_SECOND; + final double fractional_seconds = n / NANOSECONDS_PER_SECOND; result += String.format("%1$,.3f", fractional_seconds).substring(1); while (result.endsWith("0")) result = result.substring(0, result.length() - 1); } @@ -171,11 +171,13 @@ public static String format(final Duration duration) { } private static String hours(final String[] parts) { - return parts.length > 2 ? parts[0] + "H" : ""; + return parts.length > 2 ? STR."\{parts[0]}H" : ""; } + private static String minutes(final String[] parts) { return (parts.length > 2 ? parts[1] : parts[0]) + "M"; } + private static String seconds(final String[] parts) { return (parts.length > 2 ? parts[2] : parts[1]) + "S"; } diff --git a/src/main/java/org/grahamkirby/race_timing/common/Race.java b/src/main/java/org/grahamkirby/race_timing/common/Race.java index 971785b..b7fcc49 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/Race.java +++ b/src/main/java/org/grahamkirby/race_timing/common/Race.java @@ -103,10 +103,10 @@ public abstract class Race { public static final int UNKNOWN_LEG_NUMBER = 0; protected static final int UNKNOWN_RACE_POSITION = 0; - private static final String DEFAULT_ENTRY_MAP_PATH = "/src/main/resources/configuration/default_entry_map" + SUFFIX_CSV; - private static final String DEFAULT_NORMALISED_HTML_ENTITIES_PATH = "/src/main/resources/configuration/html_entities" + SUFFIX_CSV; - private static final String DEFAULT_NORMALISED_CLUB_NAMES_PATH = "/src/main/resources/configuration/club_names" + SUFFIX_CSV; - private static final String DEFAULT_CAPITALISATION_STOP_WORDS_PATH = "/src/main/resources/configuration/capitalisation_stop_words" + SUFFIX_CSV; + private static final String DEFAULT_ENTRY_MAP_PATH = STR."/src/main/resources/configuration/default_entry_map\{SUFFIX_CSV}"; + private static final String DEFAULT_NORMALISED_HTML_ENTITIES_PATH = STR."/src/main/resources/configuration/html_entities\{SUFFIX_CSV}"; + private static final String DEFAULT_NORMALISED_CLUB_NAMES_PATH = STR."/src/main/resources/configuration/club_names\{SUFFIX_CSV}"; + private static final String DEFAULT_CAPITALISATION_STOP_WORDS_PATH = STR."/src/main/resources/configuration/capitalisation_stop_words\{SUFFIX_CSV}"; ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -116,7 +116,7 @@ public abstract class Race { protected List overall_results; public RacePrizes prizes; - protected StringBuilder notes; + private StringBuilder notes; protected RaceInput input; protected RaceOutputCSV output_CSV; @@ -125,10 +125,10 @@ public abstract class Race { public RaceOutputPDF output_PDF; public Normalisation normalisation; - public Map normalised_html_entities; - public Set capitalisation_stop_words; + Map normalised_html_entities; + Set capitalisation_stop_words; + Map normalised_club_names; public Set non_title_case_words; - public Map normalised_club_names; private Map entry_map; public String entry_column_map_string; @@ -138,7 +138,7 @@ public abstract class Race { ////////////////////////////////////////////////////////////////////////////////////////////////// - public Race(final Path config_file_path) throws IOException { + protected Race(final Path config_file_path) throws IOException { this.config_file_path = config_file_path; properties = loadProperties(config_file_path); @@ -149,7 +149,7 @@ public Race(final Path config_file_path) throws IOException { ////////////////////////////////////////////////////////////////////////////////////////////////// public abstract void calculateResults(); - public abstract boolean allowEqualPositions(); + public abstract boolean areEqualPositionsAllowed(); protected abstract RaceInput getInput(); protected abstract RaceOutputCSV getOutputCSV(); @@ -162,7 +162,7 @@ public Race(final Path config_file_path) throws IOException { protected abstract void outputResults() throws IOException; protected abstract List> getComparators(); protected abstract List> getDNFComparators(); - protected abstract boolean entryCategoryIsEligibleForPrizeCategoryByGender(EntryCategory entry_category, PrizeCategory prize_category); + protected abstract boolean isEntryCategoryEligibleForPrizeCategoryByGender(EntryCategory entry_category, PrizeCategory prize_category); protected abstract EntryCategory getEntryCategory(RaceResult result); ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -217,15 +217,15 @@ public Path getPath(final String path) { getPathRelativeToRaceConfigFile(path); } - public final boolean entryCategoryIsEligibleForPrizeCategory(final EntryCategory entry_category, final PrizeCategory prize_category) { + final boolean isEntryCategoryEligibleForPrizeCategory(final EntryCategory entry_category, final PrizeCategory prize_category) { - return entryCategoryIsEligibleForPrizeCategoryByGender(entry_category, prize_category) && entryCategoryIsEligibleForPrizeCategoryByAge(entry_category, prize_category); + return isEntryCategoryEligibleForPrizeCategoryByGender(entry_category, prize_category) && isEntryCategoryEligibleForPrizeCategoryByAge(entry_category, prize_category); } - public boolean entryCategoryIsEligibleInSomePrizeCategory(final EntryCategory entry_category, final List prize_categories) { + private boolean isEntryCategoryEligibleInSomePrizeCategory(final EntryCategory entry_category, final Collection prize_categories) { return prize_categories.stream(). - map(category -> entryCategoryIsEligibleForPrizeCategory(entry_category, category)). + map(category -> isEntryCategoryEligibleForPrizeCategory(entry_category, category)). reduce(Boolean::logicalOr). orElseThrow(); } @@ -242,16 +242,16 @@ public List getOverallResults() { return overall_results; } - public List getOverallResults(final List prize_categories) { + public List getOverallResults(final Collection prize_categories) { - final Predicate prize_category_filter = result -> entryCategoryIsEligibleInSomePrizeCategory(getEntryCategory(result), prize_categories); + final Predicate prize_category_filter = result -> isEntryCategoryEligibleInSomePrizeCategory(getEntryCategory(result), prize_categories); return getOverallResults(prize_category_filter); } - public List getOverallResults(final Predicate inclusion_filter) { + public List getOverallResults(final Predicate inclusion_filter) { - final List results = getOverallResults().stream().filter(inclusion_filter).toList(); - setPositionStrings(results, allowEqualPositions()); + final List results = overall_results.stream().filter(inclusion_filter).toList(); + setPositionStrings(results, areEqualPositionsAllowed()); return results; } @@ -274,7 +274,7 @@ public EntryCategory lookupEntryCategory(final String short_name) { return entry_categories.stream(). filter(category -> category.getShortName().equals(short_name)). findFirst(). - orElseThrow(() -> new RuntimeException("Category not found: " + short_name)); + orElseThrow(() -> new RuntimeException(STR."Category not found: \{short_name}")); } public String mapCategory(final String category) { @@ -285,34 +285,34 @@ public String mapCategory(final String category) { public static Path getTestResourcesRootPath(final String individual_test_resource_root) { - return getPathRelativeToProjectRoot("/src/test/resources/" + individual_test_resource_root); + return getPathRelativeToProjectRoot(STR."/src/test/resources/\{individual_test_resource_root}"); } ////////////////////////////////////////////////////////////////////////////////////////////////// - protected int compareCompletion(final RaceResult r1, final RaceResult r2) { + protected static int compareCompletion(final RaceResult r1, final RaceResult r2) { return Boolean.compare(r1.getCompletionStatus() != CompletionStatus.COMPLETED, r2.getCompletionStatus() != CompletionStatus.COMPLETED); } - protected int comparePerformance(final RaceResult r1, final RaceResult r2) { + protected static int comparePerformance(final RaceResult r1, final RaceResult r2) { return r1.comparePerformanceTo(r2); } - protected int compareRunnerFirstName(final RaceResult r1, final RaceResult r2) { + protected static int compareRunnerFirstName(final RaceResult r1, final RaceResult r2) { - return normalisation.getFirstName(r1.getIndividualRunnerName()).compareTo(normalisation.getFirstName(r2.getIndividualRunnerName())); + return Normalisation.getFirstName(r1.getIndividualRunnerName()).compareTo(Normalisation.getFirstName(r2.getIndividualRunnerName())); } - protected int compareRunnerLastName(final RaceResult r1, final RaceResult r2) { + protected static int compareRunnerLastName(final RaceResult r1, final RaceResult r2) { - return normalisation.getLastName(r1.getIndividualRunnerName()).compareTo(normalisation.getLastName(r2.getIndividualRunnerName())); + return Normalisation.getLastName(r1.getIndividualRunnerName()).compareTo(Normalisation.getLastName(r2.getIndividualRunnerName())); } ////////////////////////////////////////////////////////////////////////////////////////////////// - protected void setPositionStrings(final List results, final boolean allow_equal_positions) { + protected static void setPositionStrings(final List results, final boolean allow_equal_positions) { // Sets position strings for dead heats, if allowed by the allow_equal_positions flag. // E.g. if results 3 and 4 have the same time, both will be set to "3=". @@ -337,22 +337,21 @@ protected void setPositionStrings(final List results, fina } else setPositionStringByPosition(results, result_index); } - } - else + } else for (int result_index = 0; result_index < results.size(); result_index++) setPositionStringByPosition(results, result_index); } - private void recordEqualPositions(List results, int start_index, int end_index) { + private static void recordEqualPositions(final List results, final int start_index, final int end_index) { final int equal_position = start_index + 1; // Record the same position for all the results with equal times. for (int i = start_index; i <= end_index; i++) - results.get(i).position_string = equal_position + "="; + results.get(i).position_string = STR."\{equal_position}="; } - private int getHighestIndexWithSamePerformance(final List results, final int start_index) { + private static int getHighestIndexWithSamePerformance(final List results, final int start_index) { final RaceResult first_result_considered = results.get(start_index); int highest_index_with_same_result = start_index; @@ -367,7 +366,7 @@ private int getHighestIndexWithSamePerformance(final List return highest_index_with_same_result; } - private void setPositionStringByPosition(final List results, final int result_index) { + private static void setPositionStringByPosition(final List results, final int result_index) { results.get(result_index).position_string = String.valueOf(result_index + 1); } @@ -405,7 +404,7 @@ private void configureNormalisation() throws IOException { private void configureImportCategoryMap() throws IOException { - entry_map = loadImportCategoryMap(KEY_ENTRY_MAP_PATH, DEFAULT_ENTRY_MAP_PATH); + entry_map = loadImportCategoryMap(); } private void configureCategories() throws IOException { @@ -414,7 +413,8 @@ private void configureCategories() throws IOException { prize_category_groups = getPrizeCategoryGroups(getPath(getProperty(KEY_CATEGORIES_PRIZE_PATH))); } - private Properties loadProperties(final Path config_file_path) throws IOException { + @SuppressWarnings("OverlyBroadThrowsClause") + private static Properties loadProperties(final Path config_file_path) throws IOException { try (final FileInputStream stream = new FileInputStream(config_file_path.toString())) { @@ -446,7 +446,7 @@ protected void sortDNFResults() { overall_results.sort(dnfOnly(combineComparators(getDNFComparators()))); } - protected Comparator combineComparators(final List> comparators) { + protected static Comparator combineComparators(final Collection> comparators) { return comparators. stream(). @@ -454,14 +454,14 @@ protected Comparator combineComparators(final List 0); } - private Comparator dnfOnly(final Comparator comparator) { + private static Comparator dnfOnly(final Comparator comparator) { return (r1, r2) -> r1.getCompletionStatus() != CompletionStatus.DNF || r2.getCompletionStatus() != CompletionStatus.DNF ? 0 : comparator.compare(r1, r2); } - private List getPrizeCategoryGroups(final Path prize_categories_path) throws IOException { + private static List getPrizeCategoryGroups(final Path prize_categories_path) throws IOException { - List groups = new ArrayList<>(); + final List groups = new ArrayList<>(); Files.readAllLines(prize_categories_path).stream(). filter(line -> !line.startsWith(COMMENT_SYMBOL)). @@ -475,13 +475,13 @@ private List getPrizeCategoryGroups(final Path prize_categor return groups; } - private void addGroupIfAbsent(final List groups, final String group_name) { + private static void addGroupIfAbsent(final Collection groups, final String group_name) { if (getGroupWithName(groups, group_name) == null) groups.add(new PrizeCategoryGroup(group_name, new ArrayList<>())); } - private PrizeCategoryGroup getGroupWithName(final List groups, final String group_name) { + private static PrizeCategoryGroup getGroupWithName(final Collection groups, final String group_name) { return groups.stream(). filter(group -> group.group_title().equals(group_name)). @@ -489,11 +489,11 @@ private PrizeCategoryGroup getGroupWithName(final List group orElse(null); } - private boolean entryCategoryIsEligibleForPrizeCategoryByAge(final EntryCategory entry_category, final PrizeCategory prize_category) { + private static boolean isEntryCategoryEligibleForPrizeCategoryByAge(final EntryCategory entry_category, final PrizeCategory prize_category) { if (entry_category == null) return true; return entry_category.getMinimumAge() >= prize_category.getMinimumAge() && - entry_category.getMaximumAge() <= prize_category.getMaximumAge(); + entry_category.getMaximumAge() <= prize_category.getMaximumAge(); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -508,31 +508,34 @@ private Path getPathRelativeToRaceConfigFile(final String path) { return config_file_path.getParent().resolve(path); } - private Map loadImportCategoryMap(final String path_key, final String default_path) throws IOException { + private Map loadImportCategoryMap() throws IOException { final Map map = new HashMap<>(); - final Path category_map_path = getPath(getProperty(path_key, default_path)); + final Path category_map_path = getPath(getProperty(KEY_ENTRY_MAP_PATH, DEFAULT_ENTRY_MAP_PATH)); Files.readAllLines(category_map_path).stream(). filter(line -> !line.startsWith(COMMENT_SYMBOL)). - forEachOrdered(line -> { + forEachOrdered(line -> processLine(line, map)); - if (entry_column_map_string == null) + return map; + } - // First non-comment line contains column mapping. - entry_column_map_string = line; + @SuppressWarnings("BoundedWildcard") + private void processLine(final String line, final Map category_map) { - else { - // Subsequent non-comment lines contain category mappings. - final String[] parts = line.split(","); - map.put(parts[0], parts[1]); - } - }); + if (entry_column_map_string == null) - return map; + // First non-comment line contains column mapping. + entry_column_map_string = line; + + else { + // Subsequent non-comment lines contain category mappings. + final String[] parts = line.split(","); + category_map.put(parts[0], parts[1]); + } } - protected Map loadNormalisationMap(final String path_key, final String default_path, final boolean key_case_sensitive) throws IOException { + private Map loadNormalisationMap(final String path_key, final String default_path, final boolean key_case_sensitive) throws IOException { final Map map = key_case_sensitive ? new HashMap<>() : new TreeMap<>(String.CASE_INSENSITIVE_ORDER); @@ -541,7 +544,8 @@ protected Map loadNormalisationMap(final String path_key, final return map; } - private void loadMap(final Path path, final Map map) throws IOException { + @SuppressWarnings("BoundedWildcard") + private static void loadMap(final Path path, final Map map) throws IOException { Files.readAllLines(path).forEach(line -> { diff --git a/src/main/java/org/grahamkirby/race_timing/common/RaceInput.java b/src/main/java/org/grahamkirby/race_timing/common/RaceInput.java index 3088781..aa4c77f 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/RaceInput.java +++ b/src/main/java/org/grahamkirby/race_timing/common/RaceInput.java @@ -21,7 +21,7 @@ public abstract class RaceInput { protected final Race race; protected String entries_path, raw_results_path, results_path, categories_entry_path, categories_prize_path; - public RaceInput(Race race) { + protected RaceInput(final Race race) { this.race = race; } } diff --git a/src/main/java/org/grahamkirby/race_timing/common/RacePrizes.java b/src/main/java/org/grahamkirby/race_timing/common/RacePrizes.java index daaaa55..9b0946b 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/RacePrizes.java +++ b/src/main/java/org/grahamkirby/race_timing/common/RacePrizes.java @@ -39,19 +39,19 @@ public void allocatePrizes() { setPrizeWinners(category); } - protected boolean prizeWinner(final RaceResult result, final PrizeCategory category) { + protected boolean isPrizeWinner(final RaceResult result, final PrizeCategory category) { - return !alreadyWonPrize(result) && - result.getCompletionStatus() == CompletionStatus.COMPLETED && - race.entryCategoryIsEligibleForPrizeCategory(result.getCategory(), category); + return !hasAlreadyWonPrize(result) && + result.getCompletionStatus() == CompletionStatus.COMPLETED && + race.isEntryCategoryEligibleForPrizeCategory(result.getCategory(), category); } - protected boolean alreadyWonPrize(RaceResult result) { + private static boolean hasAlreadyWonPrize(final RaceResult result) { return result.category_of_prize_awarded != null; } - protected void setPrizeWinner(final RaceResult result, final PrizeCategory category) { + protected static void setPrizeWinner(final RaceResult result, final PrizeCategory category) { result.category_of_prize_awarded = category; } @@ -63,39 +63,39 @@ public List getPrizeWinners(final PrizeCategory category) { filter(result -> result.category_of_prize_awarded.equals(category)). toList(); - race.setPositionStrings(prize_results, race.allowEqualPositions()); + Race.setPositionStrings(prize_results, race.areEqualPositionsAllowed()); return prize_results; } - public void setPrizeWinners(final PrizeCategory category) { + private void setPrizeWinners(final PrizeCategory category) { final AtomicInteger position = new AtomicInteger(1); race.getOverallResults().stream(). filter(_ -> position.get() <= category.numberOfPrizes()). - filter(result -> prizeWinner(result, category)). + filter(result -> isPrizeWinner(result, category)). forEachOrdered(result -> { setPrizeWinner(result, category); position.getAndIncrement(); }); } - public boolean prizesInThisOrLaterCategory(final PrizeCategory category) { + public boolean arePrizesInThisOrLaterCategory(final PrizeCategory category) { for (final PrizeCategory category2 : race.getPrizeCategories().reversed()) { if (!race.prizes.getPrizeWinners(category2).isEmpty()) return true; - if (category.equals(category2) && !prizesInOtherCategorySameAge(category)) return false; + if (category.equals(category2) && !arePrizesInOtherCategorySameAge(category)) return false; } return false; } - public boolean prizesInOtherCategorySameAge(final PrizeCategory category) { + private boolean arePrizesInOtherCategorySameAge(final PrizeCategory category) { return race.getPrizeCategories().stream(). - filter(c -> !c.equals(category)). - filter(c -> c.getMinimumAge() == category.getMinimumAge()). - anyMatch(c -> !race.prizes.getPrizeWinners(c).isEmpty()); + filter(cat -> !cat.equals(category)). + filter(cat -> cat.getMinimumAge() == category.getMinimumAge()). + anyMatch(cat -> !race.prizes.getPrizeWinners(cat).isEmpty()); } } diff --git a/src/main/java/org/grahamkirby/race_timing/common/RaceResult.java b/src/main/java/org/grahamkirby/race_timing/common/RaceResult.java index 7249a88..a6db196 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/RaceResult.java +++ b/src/main/java/org/grahamkirby/race_timing/common/RaceResult.java @@ -23,9 +23,9 @@ public abstract class RaceResult { public final Race race; public String position_string; - public PrizeCategory category_of_prize_awarded; + PrizeCategory category_of_prize_awarded; - protected RaceResult(Race race) { + protected RaceResult(final Race race) { this.race = race; } diff --git a/src/main/java/org/grahamkirby/race_timing/common/RawResult.java b/src/main/java/org/grahamkirby/race_timing/common/RawResult.java index 194c592..81c1461 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/RawResult.java +++ b/src/main/java/org/grahamkirby/race_timing/common/RawResult.java @@ -23,8 +23,8 @@ public class RawResult { - int bib_number; - String comment = ""; + private int bib_number; + private String comment = ""; public Duration recorded_finish_time; public RawResult(final String file_line) { diff --git a/src/main/java/org/grahamkirby/race_timing/common/Runner.java b/src/main/java/org/grahamkirby/race_timing/common/Runner.java index 30a48e2..16591cd 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/Runner.java +++ b/src/main/java/org/grahamkirby/race_timing/common/Runner.java @@ -33,11 +33,11 @@ public Runner(final String name, final String club, final EntryCategory category } @Override - public boolean equals(final Object other) { + public boolean equals(final Object obj) { - return other instanceof Runner other_runner && - name.equals(other_runner.name) && - club.equals(other_runner.club); + return obj instanceof final Runner other_runner && + name.equals(other_runner.name) && + club.equals(other_runner.club); } @Override @@ -47,6 +47,6 @@ public int hashCode() { @Override public String toString() { - return name + ", " + club; + return STR."\{name}, \{club}"; } } diff --git a/src/main/java/org/grahamkirby/race_timing/common/Team.java b/src/main/java/org/grahamkirby/race_timing/common/Team.java index 377af59..837ce51 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/Team.java +++ b/src/main/java/org/grahamkirby/race_timing/common/Team.java @@ -4,4 +4,5 @@ import java.util.List; -public record Team(String name, EntryCategory category, List runner_names) {} +public record Team(String name, EntryCategory category, List runner_names) { +} diff --git a/src/main/java/org/grahamkirby/race_timing/common/categories/Category.java b/src/main/java/org/grahamkirby/race_timing/common/categories/Category.java index 73f19ae..b608fa4 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/categories/Category.java +++ b/src/main/java/org/grahamkirby/race_timing/common/categories/Category.java @@ -16,6 +16,8 @@ */ package org.grahamkirby.race_timing.common.categories; +import java.util.Objects; + /** * Parent class for entry category and prize category, * each including a gender and age range. @@ -35,7 +37,7 @@ public abstract class Category { private final int minimum_age; private final int maximum_age; - public Category(final String long_name, final String short_name, final String gender, final int minimum_age, final int maximum_age) { + protected Category(final String long_name, final String short_name, final String gender, final int minimum_age, final int maximum_age) { this.long_name = long_name; this.short_name = short_name; @@ -64,7 +66,13 @@ public int getMaximumAge() { return maximum_age; } - public boolean equals(final Object o) { - return o instanceof Category other && gender.equals(other.gender) && minimum_age == other.minimum_age && maximum_age == other.maximum_age; + @Override + public boolean equals(final Object obj) { + return obj instanceof final Category other && gender.equals(other.gender) && minimum_age == other.minimum_age && maximum_age == other.maximum_age; + } + + @Override + public int hashCode() { + return Objects.hash(gender, minimum_age, maximum_age); } } diff --git a/src/main/java/org/grahamkirby/race_timing/common/categories/EntryCategory.java b/src/main/java/org/grahamkirby/race_timing/common/categories/EntryCategory.java index 9ade480..22ea045 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/categories/EntryCategory.java +++ b/src/main/java/org/grahamkirby/race_timing/common/categories/EntryCategory.java @@ -19,13 +19,14 @@ /** * Category specific to a particular entry. */ -public class EntryCategory extends Category { +public final class EntryCategory extends Category { - public EntryCategory(final String long_name, final String short_name, final String gender, final int minimum_age, final int maximum_age) { + private EntryCategory(final String long_name, final String short_name, final String gender, final int minimum_age, final int maximum_age) { super(long_name, short_name, gender, minimum_age, maximum_age); } + @SuppressWarnings("DuplicatedCode") public static EntryCategory makeEntryCategory(final String line) { final String[] parts = line.split(","); diff --git a/src/main/java/org/grahamkirby/race_timing/common/categories/PrizeCategory.java b/src/main/java/org/grahamkirby/race_timing/common/categories/PrizeCategory.java index 23fb36f..0f5de6c 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/categories/PrizeCategory.java +++ b/src/main/java/org/grahamkirby/race_timing/common/categories/PrizeCategory.java @@ -22,18 +22,19 @@ * may be eligible for a prize category e.g. an open prize category * may include multiple age categories. */ -public class PrizeCategory extends Category { +public final class PrizeCategory extends Category { public static final int PRIZE_CATEGORY_GROUP_NAME_INDEX = 6; private final int number_of_prizes; - public PrizeCategory(final String long_name, final String short_name, final String gender, final int minimum_age, final int maximum_age, final int number_of_prizes) { + private PrizeCategory(final String long_name, final String short_name, final String gender, final int minimum_age, final int maximum_age, final int number_of_prizes) { super(long_name, short_name, gender, minimum_age, maximum_age); this.number_of_prizes = number_of_prizes; } + @SuppressWarnings("DuplicatedCode") public static PrizeCategory makePrizeCategory(final String line) { final String[] parts = line.split(","); diff --git a/src/main/java/org/grahamkirby/race_timing/common/categories/PrizeCategoryGroup.java b/src/main/java/org/grahamkirby/race_timing/common/categories/PrizeCategoryGroup.java index f2d9c74..7dc6951 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/categories/PrizeCategoryGroup.java +++ b/src/main/java/org/grahamkirby/race_timing/common/categories/PrizeCategoryGroup.java @@ -2,4 +2,5 @@ import java.util.List; -public record PrizeCategoryGroup(String group_title, List categories){} +public record PrizeCategoryGroup(String group_title, List categories) { +} diff --git a/src/main/java/org/grahamkirby/race_timing/common/output/CreditLink.java b/src/main/java/org/grahamkirby/race_timing/common/output/CreditLink.java index fe254c8..5252c67 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/output/CreditLink.java +++ b/src/main/java/org/grahamkirby/race_timing/common/output/CreditLink.java @@ -2,5 +2,5 @@ public enum CreditLink { - INCLUDE_CREDIT_LINK, DONT_INCLUDE_CREDIT_LINK + INCLUDE_CREDIT_LINK, DO_NOT_INCLUDE_CREDIT_LINK } diff --git a/src/main/java/org/grahamkirby/race_timing/common/output/RaceOutput.java b/src/main/java/org/grahamkirby/race_timing/common/output/RaceOutput.java index d4f678c..a02a48c 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/output/RaceOutput.java +++ b/src/main/java/org/grahamkirby/race_timing/common/output/RaceOutput.java @@ -26,12 +26,13 @@ import java.io.OutputStreamWriter; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Collection; import java.util.List; import java.util.function.Function; import static org.grahamkirby.race_timing.common.Race.*; -public abstract class RaceOutput { +abstract class RaceOutput { protected static final String DNF_STRING = "DNF"; @@ -40,9 +41,9 @@ public abstract class RaceOutput { protected String year; protected String race_name_for_results; protected String race_name_for_filenames; - protected String overall_results_filename; - protected String prizes_filename; - protected String notes_filename; + private String overall_results_filename; + String prizes_filename; + String notes_filename; protected Path output_directory_path; ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -58,7 +59,7 @@ public abstract class RaceOutput { ////////////////////////////////////////////////////////////////////////////////////////////////// - public RaceOutput(final Race race) { + RaceOutput(final Race race) { this.race = race; configure(); @@ -71,7 +72,7 @@ public void printResults() throws IOException { try (final OutputStreamWriter writer = new OutputStreamWriter(stream)) { writer.append(getResultsHeader()); - printResults(writer, getOverallResultPrinter(writer), CreditLink.DONT_INCLUDE_CREDIT_LINK); + printResults(writer, getOverallResultPrinter(writer), CreditLink.DO_NOT_INCLUDE_CREDIT_LINK); } } @@ -102,8 +103,8 @@ private void readProperties() { protected void constructFilePaths() { - overall_results_filename = race_name_for_filenames + "_overall_" + year; - prizes_filename = race_name_for_filenames + "_prizes_" + year; + overall_results_filename = STR."\{race_name_for_filenames}_overall_\{year}"; + prizes_filename = STR."\{race_name_for_filenames}_prizes_\{year}"; notes_filename = "processing_notes"; output_directory_path = race.getPath("../output"); @@ -111,7 +112,7 @@ protected void constructFilePaths() { ////////////////////////////////////////////////////////////////////////////////////////////////// - protected void printResults(final OutputStreamWriter writer, ResultPrinter printer, final CreditLink credit_link_option) throws IOException { + protected void printResults(final OutputStreamWriter writer, final ResultPrinter printer, final CreditLink credit_link_option) throws IOException { for (int i = 0; i < race.prize_category_groups.size(); i++) { @@ -122,22 +123,22 @@ protected void printResults(final OutputStreamWriter writer, ResultPrinter print final boolean only_one_group = race.prize_category_groups.size() == 1; final boolean last_group = i == race.prize_category_groups.size() - 1; - final String sub_heading = only_one_group ? "" : "\n" + makeSubHeading(group_title); + final String sub_heading = only_one_group ? "" : LINE_SEPARATOR + makeSubHeading(group_title); - printResults(writer, printer, prize_categories, sub_heading, (credit_link_option == CreditLink.INCLUDE_CREDIT_LINK && last_group) ? CreditLink.INCLUDE_CREDIT_LINK : CreditLink.DONT_INCLUDE_CREDIT_LINK); + printResults(writer, printer, prize_categories, sub_heading, (credit_link_option == CreditLink.INCLUDE_CREDIT_LINK && last_group) ? CreditLink.INCLUDE_CREDIT_LINK : CreditLink.DO_NOT_INCLUDE_CREDIT_LINK); } } - protected void printResults(final OutputStreamWriter writer, ResultPrinter printer, final List categories, final String sub_heading, final CreditLink include_credit_link) throws IOException { + void printResults(final OutputStreamWriter writer, final ResultPrinter printer, final Collection categories, final String sub_heading, final CreditLink credit_link_option) throws IOException { writer.append(sub_heading); final List results = race.getOverallResults(categories); - printer.print(results, include_credit_link); + printer.print(results, credit_link_option); } - protected String makeSubHeading(String s) { + protected String makeSubHeading(final String s) { return s; } @@ -148,32 +149,31 @@ protected void printPrizes(final OutputStreamWriter writer) throws IOException { writer.append(getPrizesSectionHeader()); printPrizes(category -> { - try { - printPrizes(writer, category); - - } catch (IOException e) { - throw new RuntimeException(e); - } + printPrizes(writer, category); return null; }); } - protected void printPrizes(final Function prize_printer) { + void printPrizes(final Function prize_printer) { race.prize_category_groups.stream(). flatMap(group -> group.categories().stream()). - filter(race.prizes::prizesInThisOrLaterCategory). + filter(race.prizes::arePrizesInThisOrLaterCategory). forEachOrdered(prize_printer::apply); } - private void printPrizes(final OutputStreamWriter writer, final PrizeCategory category) throws IOException { + private void printPrizes(final OutputStreamWriter writer, final PrizeCategory category) { - writer.append(getPrizesCategoryHeader(category)); + try { + writer.append(getPrizesCategoryHeader(category)); - final List category_prize_winners = race.prizes.getPrizeWinners(category); + final List category_prize_winners = race.prizes.getPrizeWinners(category); + getPrizeResultPrinter(writer).print(category_prize_winners, CreditLink.DO_NOT_INCLUDE_CREDIT_LINK); - getPrizeResultPrinter(writer).print(category_prize_winners, CreditLink.DONT_INCLUDE_CREDIT_LINK); + writer.append(getPrizesCategoryFooter()); - writer.append(getPrizesCategoryFooter()); + } catch (final IOException e) { + throw new RuntimeException(e); + } } } diff --git a/src/main/java/org/grahamkirby/race_timing/common/output/RaceOutputCSV.java b/src/main/java/org/grahamkirby/race_timing/common/output/RaceOutputCSV.java index 92b42f0..00d17cc 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/output/RaceOutputCSV.java +++ b/src/main/java/org/grahamkirby/race_timing/common/output/RaceOutputCSV.java @@ -21,23 +21,27 @@ import java.io.IOException; import java.io.OutputStreamWriter; -import java.util.List; +import java.util.Collection; + +import static org.grahamkirby.race_timing.common.Race.SUFFIX_CSV; public abstract class RaceOutputCSV extends RaceOutput { - public RaceOutputCSV(final Race race) { + protected RaceOutputCSV(final Race race) { super(race); } - protected String getResultsHeader() { return ""; } + protected String getResultsHeader() { + return ""; + } - protected void printResults(final OutputStreamWriter writer, ResultPrinter printer, final List categories, final String sub_heading, final CreditLink credit_link_option) throws IOException { + protected void printResults(final OutputStreamWriter writer, final ResultPrinter printer, final Collection categories, final String sub_heading, final CreditLink credit_link_option) throws IOException { super.printResults(writer, printer, categories, "", credit_link_option); } @Override public String getFileSuffix() { - return ".csv"; + return SUFFIX_CSV; } @Override @@ -55,7 +59,7 @@ public String getPrizesCategoryFooter() { return ""; } - protected static String encode(String s) { + protected static String encode(final String s) { return s.contains(",") ? STR."\"\{s}\"" : s; } } diff --git a/src/main/java/org/grahamkirby/race_timing/common/output/RaceOutputPDF.java b/src/main/java/org/grahamkirby/race_timing/common/output/RaceOutputPDF.java index b5fbd23..de4650c 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/output/RaceOutputPDF.java +++ b/src/main/java/org/grahamkirby/race_timing/common/output/RaceOutputPDF.java @@ -41,7 +41,7 @@ public abstract class RaceOutputPDF extends RaceOutput { private static final String PRIZE_FONT_ITALIC_NAME = StandardFonts.HELVETICA_OBLIQUE; private static final int PRIZE_FONT_SIZE = 24; - public RaceOutputPDF(final Race race) { + protected RaceOutputPDF(final Race race) { super(race); } @@ -66,7 +66,9 @@ protected String getPrizesSectionHeader() { } @Override - protected String getResultsHeader() { return ""; } + protected String getResultsHeader() { + return ""; + } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -75,69 +77,55 @@ private void printPrizes(final Document document) throws IOException { document.add(getPrizesSectionHeaderPDF()); printPrizes(category -> { - try { - printPrizes(document, category); - return null; - - } catch (IOException e) { - throw new RuntimeException(e); - } + printPrizes(document, category); + return null; }); } - private void printPrizes(final Document document, final PrizeCategory category) throws IOException { + private void printPrizes(final Document document, final PrizeCategory category) { - document.add(getPrizesCategoryHeaderPDF(category)); + try { + document.add(getPrizesCategoryHeaderPDF(category)); - final List category_prize_winners = race.prizes.getPrizeWinners(category); + final List category_prize_winners = race.prizes.getPrizeWinners(category); - new PrizeResultPrinter(race, document).print(category_prize_winners, CreditLink.DONT_INCLUDE_CREDIT_LINK); + new PrizeResultPrinter(race, document).print(category_prize_winners, CreditLink.DO_NOT_INCLUDE_CREDIT_LINK); + + } catch (final IOException e) { + throw new RuntimeException(e); + } } private Paragraph getPrizesSectionHeaderPDF() throws IOException { return new Paragraph(). - setFont(getFont(PRIZE_FONT_NAME)). - setFontSize(PRIZE_FONT_SIZE). - add(STR."\{race_name_for_results} \{year} Category Prizes"); + setFont(getFont(PRIZE_FONT_NAME)). + setFontSize(PRIZE_FONT_SIZE). + add(STR."\{race_name_for_results} \{year} Category Prizes"); } - private Paragraph getPrizesCategoryHeaderPDF(final PrizeCategory category) throws IOException { + private static Paragraph getPrizesCategoryHeaderPDF(final PrizeCategory category) throws IOException { return new Paragraph(STR."Category: \{category.getLongName()}"). - setFont(getFont(PRIZE_FONT_BOLD_NAME)). - setUnderline(). - setPaddingTop(PRIZE_FONT_SIZE); - } - - // Needs to be static to allow access from inner classes of subclasses of this class. - protected static void printPrizePDF(final Document document, final String position_string, final String name, final String detail1, final String detail2) throws IOException { - - final PdfFont font = getFont(PRIZE_FONT_NAME); - final PdfFont bold_font = getFont(PRIZE_FONT_BOLD_NAME); - - final Paragraph paragraph = new Paragraph().setFont(font).setMarginBottom(0); - - paragraph.add(new Text(STR."\{position_string}: ").setFont(font)); - paragraph.add(new Text(name).setFont(bold_font)); - paragraph.add(new Text(STR." (\{detail1}) \{detail2}").setFont(font)); - - document.add(paragraph); + setFont(getFont(PRIZE_FONT_BOLD_NAME)). + setUnderline(). + setPaddingTop(PRIZE_FONT_SIZE); } - protected static PdfFont getFont(final String font_name) throws IOException { + private static PdfFont getFont(final String font_name) throws IOException { return PdfFontFactory.createFont(font_name); } ////////////////////////////////////////////////////////////////////////////////////////////////// - public record PrizeWinnerDetails(String position_string, String name, String detail1, String detail2) {} + public record PrizeWinnerDetails(String position_string, String name, String detail1, String detail2) { + } - private static class PrizeResultPrinter extends ResultPrinter { + private static final class PrizeResultPrinter extends ResultPrinter { private final Document document; - public PrizeResultPrinter(final Race race, final Document document) { + private PrizeResultPrinter(final Race race, final Document document) { super(race, null); this.document = document; } @@ -162,6 +150,20 @@ public void printNoResults() throws IOException { document.add(new Paragraph("No results").setFont(getFont(PRIZE_FONT_ITALIC_NAME))); } + + private static void printPrizePDF(final Document document, final String position_string, final String name, final String detail1, final String detail2) throws IOException { + + final PdfFont font = getFont(PRIZE_FONT_NAME); + final PdfFont bold_font = getFont(PRIZE_FONT_BOLD_NAME); + + final Paragraph paragraph = new Paragraph().setFont(font).setMarginBottom(0); + + paragraph.add(new Text(STR."\{position_string}: ").setFont(font)); + paragraph.add(new Text(name).setFont(bold_font)); + paragraph.add(new Text(STR." (\{detail1}) \{detail2}").setFont(font)); + + document.add(paragraph); + } } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -170,17 +172,25 @@ public void printNoResults() throws IOException { // Not implemented since PDF created using PDF document writer rather than output stream. @Override - protected ResultPrinter getOverallResultPrinter(OutputStreamWriter writer) { throw new UnsupportedOperationException(); } + protected ResultPrinter getOverallResultPrinter(final OutputStreamWriter writer) { + throw new UnsupportedOperationException(); + } // Not implemented since PDF created using PDF document writer rather than output stream. @Override - protected ResultPrinter getPrizeResultPrinter(OutputStreamWriter writer) { throw new UnsupportedOperationException(); } + protected ResultPrinter getPrizeResultPrinter(final OutputStreamWriter writer) { + throw new UnsupportedOperationException(); + } // Not implemented since we use a specialised version creating a PDF paragraph. @Override - public String getPrizesCategoryHeader(PrizeCategory category) { throw new UnsupportedOperationException(); } + public String getPrizesCategoryHeader(final PrizeCategory category) { + throw new UnsupportedOperationException(); + } // Not implemented since we use a specialised version creating a PDF paragraph. @Override - public String getPrizesCategoryFooter() { throw new UnsupportedOperationException(); } + public String getPrizesCategoryFooter() { + throw new UnsupportedOperationException(); + } } diff --git a/src/main/java/org/grahamkirby/race_timing/common/output/RaceOutputText.java b/src/main/java/org/grahamkirby/race_timing/common/output/RaceOutputText.java index 181d215..57fd4ae 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/output/RaceOutputText.java +++ b/src/main/java/org/grahamkirby/race_timing/common/output/RaceOutputText.java @@ -24,9 +24,11 @@ import java.io.OutputStreamWriter; import java.nio.file.Files; +import static org.grahamkirby.race_timing.common.Race.LINE_SEPARATOR; + public abstract class RaceOutputText extends RaceOutput { - public RaceOutputText(final Race race) { + protected RaceOutputText(final Race race) { super(race); } @@ -45,36 +47,37 @@ protected String getPrizesSectionHeader() { } @Override - protected String getResultsHeader() { return ""; } + protected String getResultsHeader() { + return ""; + } @Override protected String getPrizesCategoryHeader(final PrizeCategory category) { final String header = STR."Category: \{category.getLongName()}"; return STR.""" -\{header} -\{"-".repeat(header.length())} + \{header} + \{"-".repeat(header.length())} -"""; + """; } @Override protected String getPrizesCategoryFooter() { - return "\n\n"; + return LINE_SEPARATOR + LINE_SEPARATOR; } public void printNotes() throws IOException { race.non_title_case_words.stream(). - sorted(). - reduce((s1, s2) -> STR."\{s1}, \{s2}"). - ifPresent(s -> race.getNotes().append("Converted to title case: ").append(s)); + sorted(). + reduce((s1, s2) -> STR."\{s1}, \{s2}"). + ifPresent(s -> race.getNotes().append("Converted to title case: ").append(s)); final OutputStream stream = Files.newOutputStream(output_directory_path.resolve(notes_filename + getFileSuffix())); try (final OutputStreamWriter writer = new OutputStreamWriter(stream)) { - String string = race.getNotes().toString(); - writer.append(string); + writer.append(race.getNotes().toString()); } } @@ -82,5 +85,7 @@ public void printNotes() throws IOException { // Full results not printed to text file. @Override - protected ResultPrinter getOverallResultPrinter(OutputStreamWriter writer) { throw new UnsupportedOperationException(); } + protected ResultPrinter getOverallResultPrinter(final OutputStreamWriter writer) { + throw new UnsupportedOperationException(); + } } diff --git a/src/main/java/org/grahamkirby/race_timing/common/output/ResultPrinterCSV.java b/src/main/java/org/grahamkirby/race_timing/common/output/ResultPrinterCSV.java index 0d687ba..16d5a4e 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/output/ResultPrinterCSV.java +++ b/src/main/java/org/grahamkirby/race_timing/common/output/ResultPrinterCSV.java @@ -5,9 +5,10 @@ import java.io.IOException; import java.io.OutputStreamWriter; +@SuppressWarnings("NoopMethodInAbstractClass") public abstract class ResultPrinterCSV extends ResultPrinter { - public ResultPrinterCSV(final Race race, final OutputStreamWriter writer) { + protected ResultPrinterCSV(final Race race, final OutputStreamWriter writer) { super(race, writer); } @@ -16,7 +17,7 @@ public void printResultsHeader() throws IOException { } @Override - public void printResultsFooter(final CreditLink include_credit_link) { + public void printResultsFooter(final CreditLink credit_link_option) { } @Override diff --git a/src/main/java/org/grahamkirby/race_timing/common/output/ResultPrinterText.java b/src/main/java/org/grahamkirby/race_timing/common/output/ResultPrinterText.java index 554c774..21b7714 100644 --- a/src/main/java/org/grahamkirby/race_timing/common/output/ResultPrinterText.java +++ b/src/main/java/org/grahamkirby/race_timing/common/output/ResultPrinterText.java @@ -5,9 +5,10 @@ import java.io.IOException; import java.io.OutputStreamWriter; +@SuppressWarnings("NoopMethodInAbstractClass") public abstract class ResultPrinterText extends ResultPrinter { - public ResultPrinterText(final Race race, final OutputStreamWriter writer) { + protected ResultPrinterText(final Race race, final OutputStreamWriter writer) { super(race, writer); } diff --git a/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRace.java b/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRace.java index 903a964..0f30aeb 100644 --- a/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRace.java +++ b/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRace.java @@ -32,6 +32,7 @@ import java.util.Comparator; import java.util.List; +@SuppressWarnings("VariableNotUsedInsideIf") public class IndividualRace extends SingleRace { private String median_time_string; @@ -97,8 +98,8 @@ public Duration getMedianTime() { final IndividualRaceResult median_result2 = (IndividualRaceResult) results.get(results.size() / 2 + 1); return median_result1.finish_time.plus(median_result2.finish_time).dividedBy(2); - } - else { + + } else { final IndividualRaceResult median_result = (IndividualRaceResult) results.get(results.size() / 2); return median_result.finish_time; } @@ -159,15 +160,6 @@ protected RaceOutputPDF getOutputPDF() { return new IndividualRaceOutputPDF(this); } -// @Override - protected void initialiseResults() { - - entries.stream(). - map(entry -> (IndividualRaceEntry) entry). - map(entry -> new IndividualRaceResult(this, entry)). - forEachOrdered(overall_results::add); - } - @Override protected void outputResults() throws IOException { @@ -181,17 +173,17 @@ protected void outputResults() throws IOException { @Override public List> getComparators() { - return List.of(this::compareCompletion, this::comparePerformance, this::compareRecordedPosition); + return List.of(Race::compareCompletion, Race::comparePerformance, this::compareRecordedPosition); } @Override public List> getDNFComparators() { - return List.of(this::compareRunnerLastName, this::compareRunnerFirstName); + return List.of(Race::compareRunnerLastName, Race::compareRunnerFirstName); } @Override - protected boolean entryCategoryIsEligibleForPrizeCategoryByGender(final EntryCategory entry_category, final PrizeCategory prize_category) { + protected boolean isEntryCategoryEligibleForPrizeCategoryByGender(final EntryCategory entry_category, final PrizeCategory prize_category) { return entry_category == null || entry_category.getGender().equals(prize_category.getGender()); } @@ -203,21 +195,29 @@ protected EntryCategory getEntryCategory(final RaceResult result) { } @Override - protected void fillDNF(final String dnf_string) { + protected void fillDNF(final String individual_dnf_string) { try { - final int bib_number = Integer.parseInt(dnf_string); + final int bib_number = Integer.parseInt(individual_dnf_string); final IndividualRaceResult result = getResultWithBibNumber(bib_number); result.completion_status = CompletionStatus.DNF; - } - catch (Exception e) { + + } catch (final NumberFormatException e) { throw new RuntimeException("illegal DNF string: ", e); } } ////////////////////////////////////////////////////////////////////////////////////////////////// + private void initialiseResults() { + + entries.stream(). + map(entry -> (IndividualRaceEntry) entry). + map(entry -> new IndividualRaceResult(this, entry)). + forEachOrdered(overall_results::add); + } + private void fillFinishTimes() { raw_results.forEach(raw_result -> { @@ -237,7 +237,7 @@ private IndividualRaceResult getResultWithBibNumber(final int bib_number) { map(result -> ((IndividualRaceResult) result)). filter(result -> result.entry.bib_number == bib_number). findFirst(). - orElseThrow(() -> new RuntimeException("unregistered bib number: " + bib_number)); + orElseThrow(() -> new RuntimeException(STR."unregistered bib number: \{bib_number}")); } private IndividualRaceEntry getEntryWithBibNumber(final int bib_number) { @@ -246,7 +246,7 @@ private IndividualRaceEntry getEntryWithBibNumber(final int bib_number) { map(entry -> ((IndividualRaceEntry) entry)). filter(entry -> entry.bib_number == bib_number). findFirst(). - orElseThrow(() -> new RuntimeException("unregistered bib number: " + bib_number)); + orElseThrow(() -> new RuntimeException(STR."unregistered bib number: \{bib_number}")); } private int getRecordedPosition(final int bib_number) { diff --git a/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceEntry.java b/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceEntry.java index ec219cd..08a1885 100644 --- a/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceEntry.java +++ b/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceEntry.java @@ -23,6 +23,7 @@ import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; public class IndividualRaceEntry extends RaceEntry { @@ -37,16 +38,15 @@ public class IndividualRaceEntry extends RaceEntry { public final Runner runner; + @SuppressWarnings({"SequencedCollectionMethodCanBeUsed", "OverlyBroadCatchBlock", "IfCanBeAssertion"}) public IndividualRaceEntry(final List elements, final Race race) { final List mapped_elements = mapElements(elements, race.entry_column_map_string); if (mapped_elements.size() != EXPECTED_NUMBER_OF_ENTRY_ELEMENTS) - //noinspection SequencedCollectionMethodCanBeUsed - throw new RuntimeException("illegal composition for runner: " + mapped_elements.get(BIB_NUMBER_INDEX)); + throw new RuntimeException(STR."illegal composition for runner: \{mapped_elements.get(BIB_NUMBER_INDEX)}"); try { - //noinspection SequencedCollectionMethodCanBeUsed bib_number = Integer.parseInt(mapped_elements.get(BIB_NUMBER_INDEX)); final String name = race.normalisation.cleanRunnerName(mapped_elements.get(NAME_INDEX)); @@ -56,13 +56,13 @@ public IndividualRaceEntry(final List elements, final Race race) { final EntryCategory category = category_name.isEmpty() ? null : race.lookupEntryCategory(category_name); runner = new Runner(name, club, category); - } - catch (RuntimeException e) { - throw new RuntimeException("illegal category for runner: " + bib_number); + + } catch (final RuntimeException _) { + throw new RuntimeException(STR."illegal category for runner: \{bib_number}"); } } - private List mapElements(final List elements, final String entry_column_map_string) { + private static List mapElements(final List elements, final String entry_column_map_string) { // Expected format of map string: "1,3-2,4,5", // meaning elements 2 and 3 should be swapped and concatenated with a space to give compound element. @@ -81,13 +81,18 @@ private static String getMappedElement(final List elements, final String @Override public String toString() { - return runner.name + ", " + runner.club; + return STR."\{runner.name}, \{runner.club}"; } @Override - public boolean equals(Object other) { - return other instanceof IndividualRaceEntry other_entry && + public boolean equals(final Object obj) { + return obj instanceof final IndividualRaceEntry other_entry && runner.name.equals(other_entry.runner.name) && runner.club.equals(other_entry.runner.club); } + + @Override + public int hashCode() { + return Objects.hash(runner.name, runner.club); + } } diff --git a/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceInput.java b/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceInput.java index c0a5585..0183805 100644 --- a/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceInput.java +++ b/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceInput.java @@ -26,7 +26,7 @@ public class IndividualRaceInput extends SingleRaceInput { - public IndividualRaceInput(final Race race) { + IndividualRaceInput(final Race race) { super(race); } diff --git a/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceOutputCSV.java b/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceOutputCSV.java index 117709c..43404a8 100644 --- a/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceOutputCSV.java +++ b/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceOutputCSV.java @@ -27,12 +27,13 @@ import java.io.OutputStreamWriter; import static org.grahamkirby.race_timing.common.Normalisation.format; +import static org.grahamkirby.race_timing.common.Race.LINE_SEPARATOR; public class IndividualRaceOutputCSV extends RaceOutputCSV { - private static final String OVERALL_RESULTS_HEADER = "Pos,No,Runner,Club,Category,Time\n"; + private static final String OVERALL_RESULTS_HEADER = STR."Pos,No,Runner,Club,Category,Time\{LINE_SEPARATOR}"; - public IndividualRaceOutputCSV(final Race race) { + IndividualRaceOutputCSV(final Race race) { super(race); } @@ -48,13 +49,15 @@ protected ResultPrinter getOverallResultPrinter(final OutputStreamWriter writer) // Prize results not printed to CSV file. @Override - protected ResultPrinter getPrizeResultPrinter(final OutputStreamWriter writer) { throw new UnsupportedOperationException(); } + protected ResultPrinter getPrizeResultPrinter(final OutputStreamWriter writer) { + throw new UnsupportedOperationException(); + } ////////////////////////////////////////////////////////////////////////////////////////////////// - private static class OverallResultPrinter extends ResultPrinterCSV { + private static final class OverallResultPrinter extends ResultPrinterCSV { - public OverallResultPrinter(final Race race, final OutputStreamWriter writer) { + private OverallResultPrinter(final Race race, final OutputStreamWriter writer) { super(race, writer); } @@ -64,7 +67,7 @@ public void printResult(final RaceResult r) throws IOException { final IndividualRaceResult result = (IndividualRaceResult) r; writer.append(STR."\{result.shouldDisplayPosition() ? result.position_string : ""},\{result.entry.bib_number},\{encode(result.entry.runner.name)},"). - append(STR."\{encode(result.entry.runner.club)},\{result.entry.runner.category.getShortName()},\{result.getCompletionStatus() == CompletionStatus.COMPLETED ? format(result.duration()) : "DNF"}\n"); + append(STR."\{encode(result.entry.runner.club)},\{result.entry.runner.category.getShortName()},\{result.getCompletionStatus() == CompletionStatus.COMPLETED ? format(result.duration()) : "DNF"}\n"); } } } diff --git a/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceOutputHTML.java b/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceOutputHTML.java index 921fac4..d3cd4cf 100644 --- a/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceOutputHTML.java +++ b/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceOutputHTML.java @@ -30,10 +30,11 @@ import java.nio.file.Files; import static org.grahamkirby.race_timing.common.Normalisation.format; +import static org.grahamkirby.race_timing.common.Race.LINE_SEPARATOR; -public class IndividualRaceOutputHTML extends RaceOutputHTML { +class IndividualRaceOutputHTML extends RaceOutputHTML { - public IndividualRaceOutputHTML(final IndividualRace race) { + IndividualRaceOutputHTML(final IndividualRace race) { super(race); } @@ -44,9 +45,9 @@ public void printCombined() throws IOException { try (final OutputStreamWriter writer = new OutputStreamWriter(stream)) { - writer.append("

Results

\n"); + writer.append("

Results

").append(LINE_SEPARATOR); printPrizes(writer); - writer.append("

Overall

\n"); + writer.append("

Overall

").append(LINE_SEPARATOR); printResults(writer, getOverallResultPrinter(writer), CreditLink.INCLUDE_CREDIT_LINK); } } @@ -63,9 +64,9 @@ protected ResultPrinter getPrizeResultPrinter(final OutputStreamWriter writer) { ////////////////////////////////////////////////////////////////////////////////////////////////// - private static class OverallResultPrinter extends ResultPrinterHTML { + private static final class OverallResultPrinter extends ResultPrinterHTML { - public OverallResultPrinter(final Race race, final OutputStreamWriter writer) { + private OverallResultPrinter(final Race race, final OutputStreamWriter writer) { super(race, writer); } @@ -91,7 +92,7 @@ public void printResultsHeader() throws IOException { @Override public void printResult(final RaceResult r) throws IOException { - final IndividualRaceResult result = ((IndividualRaceResult)r); + final IndividualRaceResult result = ((IndividualRaceResult) r); writer.append(STR.""" @@ -106,28 +107,28 @@ public void printResult(final RaceResult r) throws IOException { } } - private static class PrizeResultPrinter extends ResultPrinterHTML { + private static final class PrizeResultPrinter extends ResultPrinterHTML { - public PrizeResultPrinter(final Race race, final OutputStreamWriter writer) { + private PrizeResultPrinter(final Race race, final OutputStreamWriter writer) { super(race, writer); } @Override public void printResultsHeader() throws IOException { - writer.append("
    \n"); + writer.append("
      ").append(LINE_SEPARATOR); } @Override public void printResultsFooter(final CreditLink credit_link_option) throws IOException { - writer.append("
    \n\n"); + writer.append("
").append(LINE_SEPARATOR).append(LINE_SEPARATOR); } @Override public void printResult(final RaceResult r) throws IOException { - final IndividualRaceResult result = ((IndividualRaceResult)r); + final IndividualRaceResult result = ((IndividualRaceResult) r); writer.append(STR."
  • \{result.position_string} \{race.normalisation.htmlEncode(result.entry.runner.name)} (\{result.entry.runner.club}) \{format(result.duration())}
  • \n"); } diff --git a/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceOutputPDF.java b/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceOutputPDF.java index ec2e909..92b853c 100644 --- a/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceOutputPDF.java +++ b/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceOutputPDF.java @@ -23,7 +23,7 @@ public class IndividualRaceOutputPDF extends RaceOutputPDF { - public IndividualRaceOutputPDF(final IndividualRace results) { + IndividualRaceOutputPDF(final IndividualRace results) { super(results); } diff --git a/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceOutputText.java b/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceOutputText.java index e3c2532..6bc144d 100644 --- a/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceOutputText.java +++ b/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceOutputText.java @@ -27,9 +27,9 @@ import static org.grahamkirby.race_timing.common.Normalisation.format; -public class IndividualRaceOutputText extends RaceOutputText { +class IndividualRaceOutputText extends RaceOutputText { - public IndividualRaceOutputText(final IndividualRace race) { + IndividualRaceOutputText(final IndividualRace race) { super(race); } @@ -39,9 +39,9 @@ protected ResultPrinter getPrizeResultPrinter(final OutputStreamWriter writer) { ////////////////////////////////////////////////////////////////////////////////////////////////// - private static class PrizeResultPrinter extends ResultPrinterText { + private static final class PrizeResultPrinter extends ResultPrinterText { - public PrizeResultPrinter(final Race race, final OutputStreamWriter writer) { + private PrizeResultPrinter(final Race race, final OutputStreamWriter writer) { super(race, writer); } diff --git a/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceResult.java b/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceResult.java index 89cb2f7..adb44cf 100644 --- a/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceResult.java +++ b/src/main/java/org/grahamkirby/race_timing/individual_race/IndividualRaceResult.java @@ -46,7 +46,7 @@ public IndividualRaceResult(final IndividualRace race, final IndividualRaceEntry ////////////////////////////////////////////////////////////////////////////////////////////////// @Override - public CompletionStatus getCompletionStatus () { + public CompletionStatus getCompletionStatus() { return completion_status; } diff --git a/src/main/java/org/grahamkirby/race_timing/relay_race/LegResult.java b/src/main/java/org/grahamkirby/race_timing/relay_race/LegResult.java index 425254e..b9fccfd 100644 --- a/src/main/java/org/grahamkirby/race_timing/relay_race/LegResult.java +++ b/src/main/java/org/grahamkirby/race_timing/relay_race/LegResult.java @@ -34,12 +34,13 @@ public class LegResult extends RaceResult { Duration start_time; // Relative to start of leg 1. Duration finish_time; // Relative to start of leg 1. - public LegResult(final RelayRaceEntry entry, final Race race) { + LegResult(final RelayRaceEntry entry, final Race race) { super(race); + this.entry = entry; - this.completion_status = CompletionStatus.DNF; - this.in_mass_start = false; + completion_status = CompletionStatus.DNF; + in_mass_start = false; } public Duration duration() { @@ -77,6 +78,6 @@ public boolean shouldDisplayPosition() { @Override public boolean shouldBeDisplayedInResults() { - return getCompletionStatus() == CompletionStatus.COMPLETED; + return completion_status == CompletionStatus.COMPLETED; } } diff --git a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRace.java b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRace.java index 59df7bf..b767755 100644 --- a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRace.java +++ b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRace.java @@ -17,6 +17,7 @@ package org.grahamkirby.race_timing.relay_race; import org.grahamkirby.race_timing.common.CompletionStatus; +import org.grahamkirby.race_timing.common.Race; import org.grahamkirby.race_timing.common.RaceInput; import org.grahamkirby.race_timing.common.RaceResult; import org.grahamkirby.race_timing.common.categories.EntryCategory; @@ -39,24 +40,19 @@ public class RelayRace extends SingleRace { - public int getNumberOfLegs() { + int getNumberOfLegs() { return number_of_legs; } - public void setNumber_of_legs(int number_of_legs) { - this.number_of_legs = number_of_legs; - } - - public Set getPairedLegs() { + Set getPairedLegs() { return paired_legs; } - public void setPaired_legs(Set paired_legs) { - this.paired_legs = paired_legs; + private record IndividualLegStart(int bib_number, int leg_number, Duration start_time) { } - private record IndividualLegStart(int bib_number, int leg_number, Duration start_time) {} - private record ResultWithLegIndex(RelayRaceResult result, int leg_index) {} + private record ResultWithLegIndex(RelayRaceResult result, int leg_index) { + } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -82,7 +78,7 @@ public RelayRace(final Path config_file_path) throws IOException { super(config_file_path); } - public static void main(String[] args) throws IOException { + public static void main(final String[] args) throws IOException { // Path to configuration file should be first argument. @@ -140,7 +136,7 @@ protected void configureInputData() throws IOException { super.configureInputData(); - ((RelayRaceInput)input).loadTimeAnnotations(raw_results); + ((RelayRaceInput) input).loadTimeAnnotations(raw_results); } @Override @@ -177,12 +173,6 @@ protected void configureHelpers() { prizes = new RelayRacePrizes(this); } -// @Override - protected void initialiseResults() { - - entries.forEach(entry -> overall_results.add(new RelayRaceResult((RelayRaceEntry) entry, this))); - } - @Override protected void outputResults() throws IOException { @@ -203,24 +193,23 @@ protected List> getComparators() { // DNF results are sorted in increasing order of bib number. // Where two teams have the same overall time, the order in which their last leg runner_names were recorded is preserved. - return List.of(this::compareCompletion, this::comparePerformance, this::compareLastLegPosition); + return List.of(Race::compareCompletion, Race::comparePerformance, this::compareLastLegPosition); } @Override protected List> getDNFComparators() { - return List.of(this::compareBibNumber); + return List.of(RelayRace::compareBibNumber); } @Override - protected boolean entryCategoryIsEligibleForPrizeCategoryByGender(final EntryCategory entry_category, final PrizeCategory prize_category) { + protected boolean isEntryCategoryEligibleForPrizeCategoryByGender(final EntryCategory entry_category, final PrizeCategory prize_category) { if (entry_category.getGender().equals(prize_category.getGender())) return true; return gender_eligibility_map.keySet().stream(). filter(entry_gender -> entry_category.getGender().equals(entry_gender)). - filter(entry_gender -> prize_category.getGender().equals(gender_eligibility_map.get(entry_gender))). - count() > 0; + anyMatch(entry_gender -> prize_category.getGender().equals(gender_eligibility_map.get(entry_gender))); } @Override @@ -229,29 +218,34 @@ protected EntryCategory getEntryCategory(final RaceResult result) { } @Override - protected void fillDNF(final String dnf_string) { + protected void fillDNF(final String individual_dnf_string) { try { - final ResultWithLegIndex result_with_leg = getResultWithLegIndex(dnf_string); + final ResultWithLegIndex result_with_leg = getResultWithLegIndex(individual_dnf_string); final LegResult result = result_with_leg.result.leg_results.get(result_with_leg.leg_index); result.completion_status = CompletionStatus.DNF; - } - catch (Exception e) { + + } catch (final RuntimeException _) { throw new RuntimeException("illegal DNF time"); } } ////////////////////////////////////////////////////////////////////////////////////////////////// + private void initialiseResults() { + + entries.forEach(entry -> overall_results.add(new RelayRaceResult((RelayRaceEntry) entry, this))); + } + private List> getLegResultComparators(final int leg_number) { return leg_number == 1 ? - List.of(this::compareCompletion, this::comparePerformance, this::compareRecordedLegPosition): - List.of(this::compareCompletion, this::comparePerformance, this::compareRunnerLastName, this::compareRunnerFirstName); + List.of(Race::compareCompletion, Race::comparePerformance, this::compareRecordedLegPosition) : + List.of(Race::compareCompletion, Race::comparePerformance, Race::compareRunnerLastName, Race::compareRunnerFirstName); } - private int compareBibNumber(final RaceResult r1, final RaceResult r2) { + private static int compareBibNumber(final RaceResult r1, final RaceResult r2) { return Integer.compare(((RelayRaceResult) r1).entry.bib_number, ((RelayRaceResult) r2).entry.bib_number); } @@ -273,7 +267,7 @@ private int compareRecordedLegPosition(final RaceResult r1, final RaceResult r2) ////////////////////////////////////////////////////////////////////////////////////////////////// - protected List getLegResults(final int leg_number) { + List getLegResults(final int leg_number) { final List results = getOverallResults().stream(). map(result -> (RelayRaceResult) result). @@ -287,7 +281,7 @@ protected List getLegResults(final int leg_number) { return results; } - protected String getMassStartAnnotation(final LegResult leg_result, final int leg_number) { + String getMassStartAnnotation(final LegResult leg_result, final int leg_number) { // Adds e.g. "(M3)" after names of runner_names that started in leg 3 mass start. return leg_result.in_mass_start ? STR." (M\{getNextMassStartLeg(leg_number)})" : ""; @@ -297,11 +291,11 @@ private int getNextMassStartLeg(final int leg_number) { return leg_number + (int) mass_start_legs.subList(leg_number - 1, number_of_legs).stream(). - filter(b -> !b). - count(); + filter(is_mass_start -> !is_mass_start). + count(); } - protected Duration sumDurationsUpToLeg(final List leg_results, final int leg_number) { + static Duration sumDurationsUpToLeg(final List leg_results, final int leg_number) { return leg_results.subList(0, leg_number).stream(). map(LegResult::duration). @@ -316,7 +310,9 @@ private int getRecordedLegPosition(final int bib_number, final int leg_number) { final AtomicInteger legs_completed = new AtomicInteger(0); final int position = (int) raw_results.stream(). - peek(result -> { if (result.getBibNumber() == bib_number) legs_completed.incrementAndGet(); }). + peek(result -> { + if (result.getBibNumber() == bib_number) legs_completed.incrementAndGet(); + }). takeWhile(result -> result.getBibNumber() != bib_number || legs_completed.get() < leg_number). count() + 1; @@ -374,13 +370,14 @@ private void setMassStartTime(final String time_as_string, final int leg_index) final Duration mass_start_time = parseTime(time_as_string); final Duration previous_mass_start_time = leg_index > 0 ? start_times_for_mass_starts.get(leg_index - 1) : null; - checkMassStartTimesOrder(previous_mass_start_time, mass_start_time); + verifyMassStartTimesOrder(previous_mass_start_time, mass_start_time); start_times_for_mass_starts.add(mass_start_time); mass_start_legs.add(!mass_start_time.equals(Duration.ZERO)); } - private void checkMassStartTimesOrder(final Duration previous_mass_start_time, final Duration current_mass_start_time) { + @SuppressWarnings({"TypeMayBeWeakened", "IfCanBeAssertion"}) + private static void verifyMassStartTimesOrder(final Duration previous_mass_start_time, final Duration current_mass_start_time) { if (previous_mass_start_time != null && !previous_mass_start_time.equals(Duration.ZERO) && @@ -410,7 +407,7 @@ private void configureGenderEligibilityMap() throws IOException { filter(line -> !line.startsWith(COMMENT_SYMBOL)). forEachOrdered(line -> { final String[] elements = line.split(","); - gender_eligibility_map.put(elements[0],elements[1]); + gender_eligibility_map.put(elements[0], elements[1]); }); } @@ -435,11 +432,11 @@ private void configureIndividualLegStarts() { individual_leg_starts = individual_leg_starts_string == null ? new ArrayList<>() : Arrays.stream(individual_leg_starts_string.split(",")). - map(this::getIndividualLegStart). + map(RelayRace::getIndividualLegStart). toList(); } - private IndividualLegStart getIndividualLegStart(final String individual_leg_starts_string) { + private static IndividualLegStart getIndividualLegStart(final String individual_leg_starts_string) { final String[] split = individual_leg_starts_string.split("/"); @@ -466,7 +463,7 @@ private void recordLegResults() { private void recordLegResult(final RelayRaceRawResult raw_result) { final int team_index = findIndexOfTeamWithBibNumber(raw_result.getBibNumber()); - final RelayRaceResult result = (RelayRaceResult)overall_results.get(team_index); + final RelayRaceResult result = (RelayRaceResult) overall_results.get(team_index); final int leg_index = findIndexOfNextUnfilledLegResult(result.leg_results); final LegResult leg_result = result.leg_results.get(leg_index); @@ -483,12 +480,12 @@ private void recordLegResult(final RelayRaceRawResult raw_result) { private void sortLegResults() { - overall_results.forEach(this::sortLegResults); + overall_results.forEach(RelayRace::sortLegResults); } - private void sortLegResults(final RaceResult result) { + private static void sortLegResults(final RaceResult result) { - final List leg_results = ((RelayRaceResult)result).leg_results; + final List leg_results = ((RelayRaceResult) result).leg_results; // Sort by explicitly recorded leg number. leg_results.sort(Comparator.comparingInt(o -> o.leg_number)); @@ -506,7 +503,7 @@ private ResultWithLegIndex getResultWithLegIndex(final String bib_and_leg) { final int bib_number = Integer.parseInt(elements[0]); final int leg_number = Integer.parseInt(elements[1]); - final RelayRaceResult result = (RelayRaceResult)overall_results.get(findIndexOfTeamWithBibNumber(bib_number)); + final RelayRaceResult result = (RelayRaceResult) overall_results.get(findIndexOfTeamWithBibNumber(bib_number)); return new ResultWithLegIndex(result, leg_number - 1); } @@ -519,10 +516,10 @@ private void fillStartTimes() { private void fillLegResultDetails(final RaceResult result) { for (int leg_index = 0; leg_index < number_of_legs; leg_index++) - fillLegResultDetails(((RelayRaceResult)result).leg_results, leg_index); + fillLegResultDetails(((RelayRaceResult) result).leg_results, leg_index); } - private void fillLegResultDetails(final List leg_results, final int leg_index) { + private void fillLegResultDetails(final List leg_results, final int leg_index) { final LegResult leg_result = leg_results.get(leg_index); @@ -546,7 +543,7 @@ private Duration getIndividualStartTime(final LegResult leg_result, final int le orElse(null); } - private Duration getLegStartTime(final Duration individual_start_time, final Duration mass_start_time, final Duration previous_team_member_finish_time, final int leg_index) { + private static Duration getLegStartTime(final Duration individual_start_time, final Duration mass_start_time, final Duration previous_team_member_finish_time, final int leg_index) { // Individual leg time recorded for this runner. if (individual_start_time != null) return individual_start_time; @@ -562,6 +559,7 @@ private Duration getLegStartTime(final Duration individual_start_time, final Dur return !mass_start_time.equals(Duration.ZERO) && mass_start_time.compareTo(previous_team_member_finish_time) < 0 ? mass_start_time : previous_team_member_finish_time; } + @SuppressWarnings("TypeMayBeWeakened") private boolean isInMassStart(final Duration individual_start_time, final Duration mass_start_time, final Duration previous_runner_finish_time, final int leg_index) { // Not in mass start if there is an individually recorded time, or it's the first leg. @@ -574,17 +572,20 @@ private boolean isInMassStart(final Duration individual_start_time, final Durati return !mass_start_time.equals(Duration.ZERO) && mass_start_time.compareTo(previous_runner_finish_time) < 0; } - private int findIndexOfNextUnfilledLegResult(final List leg_results) { + @SuppressWarnings({"TypeMayBeWeakened", "IfCanBeAssertion"}) + private static int findIndexOfNextUnfilledLegResult(final List leg_results) { final int index = (int) leg_results.stream(). takeWhile(result -> result.finish_time != null). count(); - if (index == leg_results.size()) throw new RuntimeException("surplus result recorded for team: " + leg_results.getFirst().entry.bib_number); + if (index == leg_results.size()) + throw new RuntimeException(STR."surplus result recorded for team: \{leg_results.getFirst().entry.bib_number}"); return index; } + @SuppressWarnings({"IfCanBeAssertion"}) private int findIndexOfTeamWithBibNumber(final int bib_number) { final int index = (int) overall_results.stream(). @@ -592,7 +593,7 @@ private int findIndexOfTeamWithBibNumber(final int bib_number) { takeWhile(result -> result.entry.bib_number != bib_number). count(); - if (index == overall_results.size()) throw new RuntimeException("unregistered team: " + bib_number); + if (index == overall_results.size()) throw new RuntimeException(STR."unregistered team: \{bib_number}"); return index; } @@ -601,27 +602,27 @@ private void addPaperRecordingComments() { for (int i = 0; i < raw_results.size(); i++) { - final boolean last_electronically_recorded_result = i == ((RelayRaceInput)input).getNumberOfRawResults() - 1; + final boolean last_electronically_recorded_result = i == ((RelayRaceInput) input).getNumberOfRawResults() - 1; - if (last_electronically_recorded_result && ((RelayRaceInput)input).getNumberOfRawResults() < raw_results.size()) + if (last_electronically_recorded_result && ((RelayRaceInput) input).getNumberOfRawResults() < raw_results.size()) raw_results.get(i).appendComment("Remaining times from paper recording sheet only."); } } private void printDetailedResults() throws IOException { - ((RelayRaceOutputCSV)output_CSV).printDetailedResults(); - ((RelayRaceOutputHTML)output_HTML).printDetailedResults(CreditLink.INCLUDE_CREDIT_LINK); + ((RelayRaceOutputCSV) output_CSV).printDetailedResults(); + ((RelayRaceOutputHTML) output_HTML).printDetailedResults(); } private void printLegResults() throws IOException { - ((RelayRaceOutputCSV)output_CSV).printLegResults(); - ((RelayRaceOutputHTML)output_HTML).printLegResults(); + ((RelayRaceOutputCSV) output_CSV).printLegResults(); + ((RelayRaceOutputHTML) output_HTML).printLegResults(); } private void printCollatedTimes() throws IOException { - ((RelayRaceOutputText)output_text).printCollatedResults(); + ((RelayRaceOutputText) output_text).printCollatedResults(); } } diff --git a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceEntry.java b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceEntry.java index 49519f3..99f68e5 100644 --- a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceEntry.java +++ b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceEntry.java @@ -22,6 +22,7 @@ import org.grahamkirby.race_timing.common.categories.EntryCategory; import java.util.List; +import java.util.Objects; public class RelayRaceEntry extends RaceEntry { @@ -32,15 +33,14 @@ public class RelayRaceEntry extends RaceEntry { public Team team; - public RelayRaceEntry(final List elements, final Race race) { + @SuppressWarnings("SequencedCollectionMethodCanBeUsed") + RelayRaceEntry(final List elements, final Race race) { // Expected format: "1", "Team 1", "Women Senior", "John Smith", "Hailey Dickson & Alix Crawford", "Rhys Müllar & Paige Thompson", "Amé MacDonald" if (elements.size() != FIRST_RUNNER_NAME_INDEX + ((RelayRace) race).getNumberOfLegs()) - //noinspection SequencedCollectionMethodCanBeUsed - throw new RuntimeException("illegal composition for team: " + elements.get(BIB_NUMBER_INDEX)); + throw new RuntimeException(STR."illegal composition for team: \{elements.get(BIB_NUMBER_INDEX)}"); - //noinspection SequencedCollectionMethodCanBeUsed bib_number = Integer.parseInt(elements.get(BIB_NUMBER_INDEX)); try { final String name = elements.get(TEAM_NAME_INDEX); @@ -49,9 +49,9 @@ public RelayRaceEntry(final List elements, final Race race) { final List runners = elements.subList(FIRST_RUNNER_NAME_INDEX, elements.size()).stream().map(s -> race.normalisation.cleanRunnerName(s)).toList(); team = new Team(name, category, runners); - } - catch (RuntimeException e) { - throw new RuntimeException("illegal category for team: " + bib_number); + + } catch (final RuntimeException _) { + throw new RuntimeException(STR."illegal category for team: \{bib_number}"); } } @@ -61,8 +61,13 @@ public String toString() { } @Override - public boolean equals(Object other) { - return other instanceof RelayRaceEntry other_entry && - team.name().equals(other_entry.team.name()); + public boolean equals(final Object obj) { + return obj instanceof final RelayRaceEntry other_entry && + team.name().equals(other_entry.team.name()); + } + + @Override + public int hashCode() { + return Objects.hashCode(team.name()); } } diff --git a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceInput.java b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceInput.java index f2de13f..2d157b7 100644 --- a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceInput.java +++ b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceInput.java @@ -35,7 +35,7 @@ public class RelayRaceInput extends SingleRaceInput { private String paper_results_path, annotations_path; private int number_of_raw_results; - public RelayRaceInput(final Race race) { + RelayRaceInput(final Race race) { super(race); } @@ -71,11 +71,11 @@ protected RawResult loadRawResult(final String line) { return new RelayRaceRawResult(line); } - protected int getNumberOfRawResults() { + int getNumberOfRawResults() { return number_of_raw_results; } - protected void loadTimeAnnotations(final List raw_results) throws IOException { + void loadTimeAnnotations(final List raw_results) throws IOException { if (annotations_path != null) { @@ -93,7 +93,7 @@ protected void loadTimeAnnotations(final List raw_results) throws IOE } } - private static void updateResult(final List raw_results, final String[] elements) { + private static void updateResult(final List raw_results, final String[] elements) { final int position = Integer.parseInt(elements[1]); final RawResult raw_result = raw_results.get(position - 1); diff --git a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceMissingData.java b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceMissingData.java index 1254ad6..4fef2e9 100644 --- a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceMissingData.java +++ b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceMissingData.java @@ -25,10 +25,14 @@ import static org.grahamkirby.race_timing.common.Race.UNKNOWN_BIB_NUMBER; -public class RelayRaceMissingData { +class RelayRaceMissingData { - private record TeamSummaryAtPosition(int team_number, int finishes_before, int finishes_after, Duration previous_finish, Duration next_finish) { } - private record ContiguousSequence(int start_index, int end_index) {} + private record TeamSummaryAtPosition(int team_number, int finishes_before, int finishes_after, + Duration previous_finish, Duration next_finish) { + } + + private record ContiguousSequence(int start_index, int end_index) { + } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -38,13 +42,13 @@ private record ContiguousSequence(int start_index, int end_index) {} private final RelayRace race; - public RelayRaceMissingData(RelayRace race) { + RelayRaceMissingData(final RelayRace race) { this.race = race; } ////////////////////////////////////////////////////////////////////////////////////////////////// - protected void interpolateMissingTimes() { + void interpolateMissingTimes() { final int index_of_first_result_with_recorded_time = getIndexOfFirstResultWithRecordedTime(); @@ -54,12 +58,12 @@ protected void interpolateMissingTimes() { setTimesForResultsAfterFirstRecordedTime(index_of_first_result_with_recorded_time); } - protected void guessMissingBibNumbers() { + void guessMissingBibNumbers() { // Missing bib numbers are only guessed if a full set of finish times has been recorded, // i.e. all runner_names have finished. - if (timesAreRecordedForAllRunners()) + if (areTimesRecordedForAllRunners()) guessMissingBibNumbersWithAllTimesRecorded(); else recordCommentsForNonGuessedResults(); @@ -67,7 +71,7 @@ protected void guessMissingBibNumbers() { ////////////////////////////////////////////////////////////////////////////////////////////////// - private boolean timesAreRecordedForAllRunners() { + private boolean areTimesRecordedForAllRunners() { return race.getRawResults().size() == race.entries.size() * race.getNumberOfLegs(); } @@ -75,7 +79,8 @@ private boolean timesAreRecordedForAllRunners() { private int getIndexOfFirstResultWithRecordedTime() { int raw_result_index = 0; - while (raw_result_index < race.getRawResults().size() && race.getRawResults().get(raw_result_index).getRecordedFinishTime() == null) raw_result_index++; + while (raw_result_index < race.getRawResults().size() && race.getRawResults().get(raw_result_index).getRecordedFinishTime() == null) + raw_result_index++; return raw_result_index; } @@ -118,7 +123,11 @@ private ContiguousSequence getNextContiguousSequenceWithMissingTimes(final int s private void interpolateTimesForContiguousSequence(final ContiguousSequence sequence) { - if (!isLastResult(sequence.end_index)) { + // For results after the last recorded time, use the last recorded time. + if (isLastResult(sequence.end_index)) { + setTimesForResultsAfterLastRecordedTime(sequence.start_index); + + } else { final Duration start_time = race.getRawResults().get(sequence.start_index - 1).getRecordedFinishTime(); final Duration end_time = race.getRawResults().get(sequence.end_index + 1).getRecordedFinishTime(); @@ -128,10 +137,6 @@ private void interpolateTimesForContiguousSequence(final ContiguousSequence sequ interpolateTimes(sequence, time_step); } - - else - // For results after the last recorded time, use the last recorded time. - setTimesForResultsAfterLastRecordedTime(sequence.start_index); } private boolean isLastResult(final int end_index) { @@ -148,13 +153,13 @@ private void interpolateTimes(final ContiguousSequence sequence, final Duration final Duration rounded_interpolated_finish_time = roundToIntegerSeconds(interpolated_finish_time); final RawResult interpolated_result = race.getRawResults().get(sequence.start_index + i); - + interpolated_result.setRecordedFinishTime(rounded_interpolated_finish_time); interpolated_result.appendComment("Time not recorded. Time interpolated."); } } - private Duration roundToIntegerSeconds(final Duration duration) { + private static Duration roundToIntegerSeconds(final Duration duration) { long seconds = duration.getSeconds(); if (duration.getNano() > HALF_A_SECOND_IN_NANOSECONDS) seconds++; @@ -168,7 +173,7 @@ private void setTimesForResultsAfterLastRecordedTime(final int missing_times_sta for (int i = missing_times_start_index; i < race.getRawResults().size(); i++) { final RawResult missing_result = race.getRawResults().get(i); - + missing_result.setRecordedFinishTime(last_recorded_time); missing_result.appendComment("Time not recorded. No basis for interpolation so set to last recorded time."); } @@ -230,7 +235,7 @@ private List summarise(final int position) { } private TeamSummaryAtPosition summarise(final int position, final int bib_number) { - + final int finishes_before = getNumberOfTeamFinishesBetween(0, position - 1, bib_number); final int finishes_after = getNumberOfTeamFinishesBetween(position, race.getRawResults().size(), bib_number); @@ -278,8 +283,8 @@ private Duration getFinishTimeIfBibNumberMatches(final int bib_number, final int return (result_bib_number == bib_number) ? result.getRecordedFinishTime() : null; } - - private void sort(final List summaries) { + + private static void sort(final List summaries) { summaries.sort(Comparator.comparing(o -> o.previous_finish)); summaries.sort(Comparator.comparing(o -> o.next_finish)); diff --git a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceOutputCSV.java b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceOutputCSV.java index 58b07cf..ad83c14 100644 --- a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceOutputCSV.java +++ b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceOutputCSV.java @@ -95,7 +95,7 @@ private void printDetailedResults(final OutputStreamWriter writer) throws IOExce for (final PrizeCategoryGroup group : race.prize_category_groups) { final List results = race.getOverallResults(group.categories()); - printer.print(results, CreditLink.DONT_INCLUDE_CREDIT_LINK); + printer.print(results, CreditLink.DO_NOT_INCLUDE_CREDIT_LINK); } } @@ -120,7 +120,7 @@ private void printLegResults(final OutputStreamWriter writer, final int leg) thr final List leg_results = ((RelayRace) race).getLegResults(leg); - new LegResultPrinter(race, writer, leg).print(leg_results, CreditLink.DONT_INCLUDE_CREDIT_LINK); + new LegResultPrinter(race, writer, leg).print(leg_results, CreditLink.DO_NOT_INCLUDE_CREDIT_LINK); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -194,7 +194,7 @@ public void printResult(final RaceResult r) throws IOException { final String leg_runner_names = leg_result.entry.team.runner_names().get(leg - 1); final String leg_mass_start_annotation = relay_race.getMassStartAnnotation(leg_result, leg); final String leg_time = completed ? format(leg_result.duration()) : DNF_STRING; - final String split_time = completed && all_previous_legs_completed ? format(relay_race.sumDurationsUpToLeg(result.leg_results, leg)) : DNF_STRING; + final String split_time = completed && all_previous_legs_completed ? format(RelayRace.sumDurationsUpToLeg(result.leg_results, leg)) : DNF_STRING; writer.append(STR."\{encode(leg_runner_names)}\{leg_mass_start_annotation},\{leg_time},\{split_time}"); diff --git a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceOutputHTML.java b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceOutputHTML.java index 22209a7..86892c1 100644 --- a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceOutputHTML.java +++ b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceOutputHTML.java @@ -31,12 +31,13 @@ import java.util.List; import static org.grahamkirby.race_timing.common.Normalisation.format; +import static org.grahamkirby.race_timing.common.Race.LINE_SEPARATOR; public class RelayRaceOutputHTML extends RaceOutputHTML { private String detailed_results_filename; - public RelayRaceOutputHTML(final RelayRace race) { + RelayRaceOutputHTML(final RelayRace race) { super(race); } @@ -50,21 +51,21 @@ public void printCombined() throws IOException { try (final OutputStreamWriter writer = new OutputStreamWriter(stream)) { - writer.append("

    Results

    \n"); + writer.append("

    Results

    ").append(LINE_SEPARATOR); printPrizes(writer); - writer.append("

    Overall

    \n"); - printResults(writer, getOverallResultPrinter(writer), CreditLink.DONT_INCLUDE_CREDIT_LINK); + writer.append("

    Overall

    ").append(LINE_SEPARATOR); + printResults(writer, getOverallResultPrinter(writer), CreditLink.DO_NOT_INCLUDE_CREDIT_LINK); - writer.append("

    Full Results

    \n"); - printDetailedResults(writer, CreditLink.DONT_INCLUDE_CREDIT_LINK); + writer.append("

    Full Results

    ").append(LINE_SEPARATOR); + printDetailedResults(writer, CreditLink.DO_NOT_INCLUDE_CREDIT_LINK); - writer.append("

    M3: mass start leg 3
    M4: mass start leg 4

    \n"); + writer.append("

    M3: mass start leg 3
    M4: mass start leg 4

    ").append(LINE_SEPARATOR); for (int leg_number = 1; leg_number <= ((RelayRace) race).getNumberOfLegs(); leg_number++) { - writer.append("

    \n

    Leg ").append(String.valueOf(leg_number)).append(" Results

    \n"); - printLegResults(writer, leg_number, (leg_number == ((RelayRace) race).getNumberOfLegs()) ? CreditLink.INCLUDE_CREDIT_LINK : CreditLink.DONT_INCLUDE_CREDIT_LINK); + writer.append(STR."

    \{LINE_SEPARATOR}

    Leg \{leg_number} Results

    \{LINE_SEPARATOR}"); + printLegResults(writer, leg_number, (leg_number == ((RelayRace) race).getNumberOfLegs()) ? CreditLink.INCLUDE_CREDIT_LINK : CreditLink.DO_NOT_INCLUDE_CREDIT_LINK); } } } @@ -73,7 +74,7 @@ public void printCombined() throws IOException { protected void constructFilePaths() { super.constructFilePaths(); - detailed_results_filename = race_name_for_filenames + "_detailed_" + year; + detailed_results_filename = STR."\{race_name_for_filenames}_detailed_\{year}"; } @Override @@ -88,23 +89,23 @@ protected ResultPrinter getPrizeResultPrinter(final OutputStreamWriter writer) { ////////////////////////////////////////////////////////////////////////////////////////////////// - public void printDetailedResults(final CreditLink credit_link_option) throws IOException { + void printDetailedResults() throws IOException { - final OutputStream stream = Files.newOutputStream(output_directory_path.resolve(detailed_results_filename + ".html")); + final OutputStream stream = Files.newOutputStream(output_directory_path.resolve(STR."\{detailed_results_filename}.html")); try (final OutputStreamWriter writer = new OutputStreamWriter(stream)) { - printDetailedResults(writer, credit_link_option); + printDetailedResults(writer, CreditLink.INCLUDE_CREDIT_LINK); } } - protected void printDetailedResults(final OutputStreamWriter writer, final CreditLink credit_link_option) throws IOException { + private void printDetailedResults(final OutputStreamWriter writer, final CreditLink credit_link_option) throws IOException { printResults(writer, new DetailedResultPrinter(race, writer), credit_link_option); } ////////////////////////////////////////////////////////////////////////////////////////////////// - protected void printLegResults() throws IOException { + void printLegResults() throws IOException { for (int leg = 1; leg <= ((RelayRace) race).getNumberOfLegs(); leg++) printLegResults(leg); @@ -128,9 +129,9 @@ private void printLegResults(final OutputStreamWriter writer, final int leg, fin ////////////////////////////////////////////////////////////////////////////////////////////////// - private static class OverallResultPrinter extends ResultPrinterHTML { + private static final class OverallResultPrinter extends ResultPrinterHTML { - public OverallResultPrinter(Race race, OutputStreamWriter writer) { + private OverallResultPrinter(final Race race, final OutputStreamWriter writer) { super(race, writer); } @@ -169,11 +170,11 @@ public void printResult(final RaceResult r) throws IOException { } } - private static class LegResultPrinter extends ResultPrinterHTML { + private static final class LegResultPrinter extends ResultPrinterHTML { final int leg; - public LegResultPrinter(final Race race, final OutputStreamWriter writer, final int leg) { + private LegResultPrinter(final Race race, final OutputStreamWriter writer, final int leg) { super(race, writer); this.leg = leg; @@ -210,9 +211,9 @@ public void printResult(final RaceResult r) throws IOException { } } - private static class DetailedResultPrinter extends ResultPrinterHTML { + private static final class DetailedResultPrinter extends ResultPrinterHTML { - public DetailedResultPrinter(Race race, OutputStreamWriter writer) { + private DetailedResultPrinter(final Race race, final OutputStreamWriter writer) { super(race, writer); } @@ -259,7 +260,7 @@ public void printResult(final RaceResult r) throws IOException { \{result.entry.team.category().getLongName()} """); - boolean any_previous_leg_dnf = false; + boolean all_previous_legs_completed = true; for (int leg = 1; leg <= relay_race.getNumberOfLegs(); leg++) { @@ -269,7 +270,7 @@ public void printResult(final RaceResult r) throws IOException { final String leg_runner_names = leg_result.entry.team.runner_names().get(leg - 1); final String leg_mass_start_annotation = relay_race.getMassStartAnnotation(leg_result, leg); final String leg_time = completed ? format(leg_result.duration()) : DNF_STRING; - final String split_time = completed && !any_previous_leg_dnf ? format(relay_race.sumDurationsUpToLeg(result.leg_results, leg)) : DNF_STRING; + final String split_time = completed && all_previous_legs_completed ? format(RelayRace.sumDurationsUpToLeg(result.leg_results, leg)) : DNF_STRING; writer.append(STR.""" \{race.normalisation.htmlEncode(leg_runner_names)}\{leg_mass_start_annotation} @@ -277,31 +278,31 @@ public void printResult(final RaceResult r) throws IOException { \{split_time} """); - if (!completed) any_previous_leg_dnf = true; + if (!completed) all_previous_legs_completed = false; } writer.append(""" - - """); + + """); } } - private static class PrizeResultPrinter extends ResultPrinterHTML { + private static final class PrizeResultPrinter extends ResultPrinterHTML { - public PrizeResultPrinter(Race race, OutputStreamWriter writer) { + private PrizeResultPrinter(final Race race, final OutputStreamWriter writer) { super(race, writer); } @Override public void printResultsHeader() throws IOException { - writer.append("
      \n"); + writer.append("
        ").append(LINE_SEPARATOR); } @Override public void printResultsFooter(final CreditLink credit_link_option) throws IOException { - writer.append("
      \n\n"); + writer.append("
    ").append(LINE_SEPARATOR).append(LINE_SEPARATOR); } @Override diff --git a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceOutputPDF.java b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceOutputPDF.java index 199cf87..ffdf8a0 100644 --- a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceOutputPDF.java +++ b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceOutputPDF.java @@ -21,9 +21,9 @@ import static org.grahamkirby.race_timing.common.Normalisation.format; -public class RelayRaceOutputPDF extends RaceOutputPDF { +class RelayRaceOutputPDF extends RaceOutputPDF { - public RelayRaceOutputPDF(final RelayRace results) { + RelayRaceOutputPDF(final RelayRace results) { super(results); } diff --git a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceOutputText.java b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceOutputText.java index 7bc6396..797a61c 100644 --- a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceOutputText.java +++ b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRaceOutputText.java @@ -42,7 +42,7 @@ public class RelayRaceOutputText extends RaceOutputText { private String collated_times_filename; - public RelayRaceOutputText(final RelayRace results) { + RelayRaceOutputText(final RelayRace results) { super(results); } @@ -56,7 +56,7 @@ protected void constructFilePaths() { collated_times_filename = "times_collated"; } - public void printCollatedResults() throws IOException { + void printCollatedResults() throws IOException { final OutputStream stream = Files.newOutputStream(output_directory_path.resolve(collated_times_filename + ".txt")); diff --git a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRacePrizes.java b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRacePrizes.java index 5ae6223..0c67c31 100644 --- a/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRacePrizes.java +++ b/src/main/java/org/grahamkirby/race_timing/relay_race/RelayRacePrizes.java @@ -63,7 +63,7 @@ private void allocateFirstPrizes(final List prize_categories) { for (final PrizeCategory category : prize_categories) for (final RaceResult result : race.getOverallResults()) - if (prizeWinner(result, category)) { + if (isPrizeWinner(result, category)) { setPrizeWinner(result, category); break; } @@ -83,7 +83,7 @@ private void allocateMinorPrizes(final PrizeCategory category) { if (position > category.numberOfPrizes()) return; - if (prizeWinner(result, category)) { + if (isPrizeWinner(result, category)) { setPrizeWinner(result, category); position++; } diff --git a/src/main/java/org/grahamkirby/race_timing/series_race/SeriesRace.java b/src/main/java/org/grahamkirby/race_timing/series_race/SeriesRace.java index 4edfae2..f414745 100644 --- a/src/main/java/org/grahamkirby/race_timing/series_race/SeriesRace.java +++ b/src/main/java/org/grahamkirby/race_timing/series_race/SeriesRace.java @@ -53,7 +53,7 @@ public void calculateResults() { } @Override - public boolean allowEqualPositions() { + public boolean areEqualPositionsAllowed() { // There can be dead heats in overall results, since these are determined by sum of results // from multiple races, rather than there being an ordering imposed at a single funnel. @@ -101,7 +101,7 @@ protected void readProperties() { } @Override - protected boolean entryCategoryIsEligibleForPrizeCategoryByGender(final EntryCategory entry_category, final PrizeCategory prize_category) { + protected boolean isEntryCategoryEligibleForPrizeCategoryByGender(final EntryCategory entry_category, final PrizeCategory prize_category) { return entry_category != null && entry_category.getGender().equals(prize_category.getGender()); } diff --git a/src/main/java/org/grahamkirby/race_timing/series_race/grand_prix/GrandPrixRace.java b/src/main/java/org/grahamkirby/race_timing/series_race/grand_prix/GrandPrixRace.java index 92da208..a9a1991 100644 --- a/src/main/java/org/grahamkirby/race_timing/series_race/grand_prix/GrandPrixRace.java +++ b/src/main/java/org/grahamkirby/race_timing/series_race/grand_prix/GrandPrixRace.java @@ -16,6 +16,7 @@ */ package org.grahamkirby.race_timing.series_race.grand_prix; +import org.grahamkirby.race_timing.common.Race; import org.grahamkirby.race_timing.common.RaceInput; import org.grahamkirby.race_timing.common.RaceResult; import org.grahamkirby.race_timing.common.Runner; @@ -107,7 +108,7 @@ protected RaceOutputPDF getOutputPDF() { @Override protected List> getComparators() { - return List.of(this::compareCompletion, this::comparePerformance, this::compareRunnerLastName, this::compareRunnerFirstName); + return List.of(Race::compareCompletion, Race::comparePerformance, Race::compareRunnerLastName, Race::compareRunnerFirstName); } @Override diff --git a/src/main/java/org/grahamkirby/race_timing/series_race/midweek/MidweekRace.java b/src/main/java/org/grahamkirby/race_timing/series_race/midweek/MidweekRace.java index e537b69..acc3bee 100644 --- a/src/main/java/org/grahamkirby/race_timing/series_race/midweek/MidweekRace.java +++ b/src/main/java/org/grahamkirby/race_timing/series_race/midweek/MidweekRace.java @@ -16,10 +16,7 @@ */ package org.grahamkirby.race_timing.series_race.midweek; -import org.grahamkirby.race_timing.common.CompletionStatus; -import org.grahamkirby.race_timing.common.RaceInput; -import org.grahamkirby.race_timing.common.RaceResult; -import org.grahamkirby.race_timing.common.Runner; +import org.grahamkirby.race_timing.common.*; import org.grahamkirby.race_timing.common.output.RaceOutputCSV; import org.grahamkirby.race_timing.common.output.RaceOutputHTML; import org.grahamkirby.race_timing.common.output.RaceOutputPDF; @@ -101,7 +98,7 @@ protected RaceOutputPDF getOutputPDF() { @Override protected List> getComparators() { - return List.of(this::compareCompletion, this::comparePerformance, this::compareRunnerLastName, this::compareRunnerFirstName); + return List.of(Race::compareCompletion, Race::comparePerformance, Race::compareRunnerLastName, Race::compareRunnerFirstName); } @Override diff --git a/src/main/java/org/grahamkirby/race_timing/series_race/tour/TourRace.java b/src/main/java/org/grahamkirby/race_timing/series_race/tour/TourRace.java index 444bbac..3270b8e 100644 --- a/src/main/java/org/grahamkirby/race_timing/series_race/tour/TourRace.java +++ b/src/main/java/org/grahamkirby/race_timing/series_race/tour/TourRace.java @@ -16,6 +16,7 @@ */ package org.grahamkirby.race_timing.series_race.tour; +import org.grahamkirby.race_timing.common.Race; import org.grahamkirby.race_timing.common.RaceInput; import org.grahamkirby.race_timing.common.RaceResult; import org.grahamkirby.race_timing.common.Runner; @@ -97,7 +98,7 @@ protected void printCombined() throws IOException { @Override protected List> getComparators() { - return List.of(this::compareCompletion, this::compareCompletionSoFar, this::comparePerformance, this::compareRunnerLastName, this::compareRunnerFirstName); + return List.of(Race::compareCompletion, this::compareCompletionSoFar, Race::comparePerformance, Race::compareRunnerLastName, Race::compareRunnerFirstName); } @Override diff --git a/src/main/java/org/grahamkirby/race_timing/series_race/tour/TourRaceOutputHTML.java b/src/main/java/org/grahamkirby/race_timing/series_race/tour/TourRaceOutputHTML.java index cd4bb87..107bc58 100644 --- a/src/main/java/org/grahamkirby/race_timing/series_race/tour/TourRaceOutputHTML.java +++ b/src/main/java/org/grahamkirby/race_timing/series_race/tour/TourRaceOutputHTML.java @@ -84,7 +84,7 @@ private void printIndividualRaceResults(final OutputStreamWriter writer, final I final List category_results = individual_race.getOverallResults(prize_categories); - new IndividualRaceResultPrinter(race, sub_heading, writer).print(category_results, CreditLink.DONT_INCLUDE_CREDIT_LINK); + new IndividualRaceResultPrinter(race, sub_heading, writer).print(category_results, CreditLink.DO_NOT_INCLUDE_CREDIT_LINK); } ////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/main/java/org/grahamkirby/race_timing/single_race/SingleRace.java b/src/main/java/org/grahamkirby/race_timing/single_race/SingleRace.java index a3baa6c..d6d82b8 100644 --- a/src/main/java/org/grahamkirby/race_timing/single_race/SingleRace.java +++ b/src/main/java/org/grahamkirby/race_timing/single_race/SingleRace.java @@ -38,7 +38,7 @@ public SingleRace(final Path config_file_path) throws IOException { ////////////////////////////////////////////////////////////////////////////////////////////////// @Override - public boolean allowEqualPositions() { + public boolean areEqualPositionsAllowed() { // No dead heats for overall results, since an ordering is imposed at the finish. return false; diff --git a/src/test/java/org/grahamkirby/race_timing/RaceTest.java b/src/test/java/org/grahamkirby/race_timing/RaceTest.java index 2322e8c..33dec1b 100644 --- a/src/test/java/org/grahamkirby/race_timing/RaceTest.java +++ b/src/test/java/org/grahamkirby/race_timing/RaceTest.java @@ -60,7 +60,7 @@ public abstract class RaceTest { private static boolean first_test = true; // Whether at least one test failed earlier in the run. - private static boolean some_previous_test_failed = false; + private static boolean no_previous_test_failed = true; // Whether the current test failed. private boolean failed_test = true; @@ -85,7 +85,7 @@ public void tearDown() throws IOException { if (DEBUG) { // Whether this is the first test in the run to have failed. - final boolean first_failed_test = failed_test && !some_previous_test_failed; + final boolean first_failed_test = failed_test && no_previous_test_failed; // Whether the retained output directory is present from a previous run (in which case it should be deleted). final boolean output_directory_retained_from_previous_run = first_test && Files.exists(retained_output_directory); @@ -100,9 +100,9 @@ public void tearDown() throws IOException { cleanUpDirectories(output_directory_retained_from_previous_run, output_directory_should_be_retained); first_test = false; - if (first_failed_test) some_previous_test_failed = true; - } - else + if (first_failed_test) no_previous_test_failed = false; + + } else deleteDirectory(test_directory); } @@ -120,7 +120,7 @@ private void cleanUpDirectories(final boolean output_directory_retained_from_pre ////////////////////////////////////////////////////////////////////////////////////////////////// - protected void configureTest(final String individual_test_resource_root) throws IOException { + private void configureTest(final String individual_test_resource_root) throws IOException { test_directory = DEBUG ? Paths.get(USER_TEST_DIRECTORY_PATH) : Files.createTempDirectory(null); @@ -128,7 +128,7 @@ protected void configureTest(final String individual_test_resource_root) throws configureDirectoryContents(resources_input_directory); } - protected void testExpectedException(final String configuration_name, final String expected_error_message) throws IOException { + void testExpectedException(final String configuration_name, final String expected_error_message) throws IOException { configureTest(configuration_name); @@ -137,11 +137,11 @@ protected void testExpectedException(final String configuration_name, final Stri () -> makeRace(config_file_path).processResults() ); - assertEquals(expected_error_message, exception.getMessage()); + assertEquals(expected_error_message, exception.getMessage(), "Unexpected exception message"); // Test has passed if this line is reached. failed_test = false; - } + } protected void testExpectedCompletion(final String configuration_name) throws IOException { @@ -182,19 +182,19 @@ private static void assertThatDirectoryContainsAllExpectedContent(final Path exp for (final String expected_file_name : getDirectoryEntries(expected)) { - if (!fileInExpectedDirectoryShouldBeIgnored(expected_file_name)) { + if (!shouldFileInExpectedDirectoryBeIgnored(expected_file_name)) { final Path path_expected = expected.resolve(expected_file_name); final Path path_actual = actual.resolve(expected_file_name); if (Files.isDirectory(path_expected)) { - assertTrue(Files.isDirectory(path_actual)); + assertTrue(Files.isDirectory(path_actual), "Expected directory missing"); assertThatDirectoryContainsAllExpectedContent(path_expected, path_actual); - } - else { - assertFalse(Files.isDirectory(path_actual)); - assertThatFilesHaveSameContentIgnoringWhitespace(path_expected, path_actual); + + } else { + assertFalse(Files.isDirectory(path_actual), "Unexpected directory"); + assertThatFilesHaveSameContent(path_expected, path_actual); } } } @@ -207,26 +207,16 @@ private static List getDirectoryEntries(final Path directory) throws IOE } } - private static void assertThatFilesHaveSameContentIgnoringWhitespace(final Path path1, final Path path2) throws IOException { - -// final String file_content1 = removeWhiteSpace(getFileContent(path1)); -// final String file_content2 = removeWhiteSpace(getFileContent(path2)); - final String file_content1 = (getFileContent(path1)); - final String file_content2 = (getFileContent(path2)); + private static void assertThatFilesHaveSameContent(final Path path1, final Path path2) { - if (!file_content1.equals(file_content2)) + if (!getFileContent(path1).equals(getFileContent(path2))) fail(STR."Files differ: \{path1}, \{path2}"); } private static String getFileContent(final Path path) { try { - if (!path.toString().endsWith(SUFFIX_PDF)) - return Files.readAllLines(path).stream(). - reduce(String::concat). - orElse(""); - - else { + if (path.toString().endsWith(SUFFIX_PDF)) { try (final PdfDocument document = new PdfDocument(new PdfReader(path.toString()))) { final StringBuilder text = new StringBuilder(); @@ -235,10 +225,10 @@ private static String getFileContent(final Path path) { return text.toString(); } - } - } - catch (final IOException e) { - fail("Expected output file not found: " + path); + } else return String.join("", Files.readAllLines(path)); + + } catch (final IOException e) { + fail(STR."Expected output file not found: \{path}"); throw new RuntimeException(e); } } @@ -247,15 +237,12 @@ private static List loadIgnoredFileNames() { try { return Files.readAllLines(Paths.get(IGNORED_FILE_NAMES_PATH)).stream().toList(); + } catch (final IOException e) { + throw new RuntimeException(e); } - catch (IOException e) {throw new RuntimeException(e);} } - private static String removeWhiteSpace(final String s) { - return s.replaceAll("\t", "").replaceAll("\n", "").replaceAll(" ", ""); - } - - private static boolean fileInExpectedDirectoryShouldBeIgnored(final String file_name) { + private static boolean shouldFileInExpectedDirectoryBeIgnored(final String file_name) { return ignored_file_names.contains(file_name); } @@ -264,14 +251,14 @@ private static void copyDirectory(final Path source_directory, final Path destin Files.walkFileTree(source_directory, new SimpleFileVisitor<>() { @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes ignore) throws IOException { + public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException { Files.copy(dir, destination_directory.resolve(source_directory.relativize(dir))); return CONTINUE; } @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes ignore) throws IOException { + public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException { Files.copy(file, destination_directory.resolve(source_directory.relativize(file))); return CONTINUE; @@ -284,17 +271,17 @@ private static void deleteDirectory(final Path directory) throws IOException { Files.walkFileTree(directory, new SimpleFileVisitor<>() { @Override - public FileVisitResult postVisitDirectory(final Path dir, final IOException ignore) throws IOException { + public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException { Files.delete(dir); - return FileVisitResult.CONTINUE; + return CONTINUE; } @Override - public FileVisitResult visitFile(final Path file, final BasicFileAttributes ignore) throws IOException { + public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException { Files.delete(file); - return FileVisitResult.CONTINUE; + return CONTINUE; } }); }