diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..56608d2 --- /dev/null +++ b/.classpath @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b7b64f0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.class +target/* +*/target +target +target/ diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..b0872d2 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +codingcompetition2019 \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..2545dc7 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..8fc1775 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + 1570335134007 + + + + \ No newline at end of file diff --git a/.project b/.project new file mode 100644 index 0000000..b4cd1c3 --- /dev/null +++ b/.project @@ -0,0 +1,23 @@ + + + codingcompetition2019 + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..839d647 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,5 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.apt.core.prefs b/.settings/org.eclipse.jdt.apt.core.prefs new file mode 100644 index 0000000..d4313d4 --- /dev/null +++ b/.settings/org.eclipse.jdt.apt.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.apt.aptEnabled=false diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..ac8e750 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.processAnnotations=disabled +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/feedback.txt b/feedback.txt index 8234592..8b0c98b 100644 --- a/feedback.txt +++ b/feedback.txt @@ -1,9 +1,16 @@ -Your team (name of each individual participating): -How many JUnits were you able to get to pass? +Your team (name of each individual participating): Mudit Gupta and Ryan Thomas Lynch +How many JUnits were you able to get to pass? 10/10 Document and describe any enhancements included to help the judges properly grade your submission. - Step 1: - Step 2: - + Added Javadocs + We wanted to make our code as understandable as possible, so the addition of javadocs makes + each function very simple to understand. + Following CheckStyle-6.2.2 + To ensure cleanliness and readability in our code, we decided to follow the guidelines + established by CheckStyle-6.2.2. + Attempting to be time efficient with iterations over functions based on disaster category + The code will only perform evaluations for entries of the correct category. Once an entry + is found in the wrong category, the function will stop processing the list given that the + data is sorted by category. Feedback for the coding competition? Things you would like to see in future events? \ No newline at end of file diff --git a/src/main/java/codingcompetition2019/CodingCompCSVUtil.java b/src/main/java/codingcompetition2019/CodingCompCSVUtil.java index 74f3074..9d7f136 100644 --- a/src/main/java/codingcompetition2019/CodingCompCSVUtil.java +++ b/src/main/java/codingcompetition2019/CodingCompCSVUtil.java @@ -1,58 +1,221 @@ package codingcompetition2019; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +/** + * This class holds methods that interpret natural disaster records + * @author Mudit Gupta and Ryan Thomas Lynch + * @version 1.0 + */ public class CodingCompCSVUtil { + + /** + * Interprets CSV file as a list of list of strings - only returns records for a specified country + * @param fileName the file path relative to the location of program execution + * @param countryName the country we want records from + * @return a list of list of strings representing each entry in the CSV related to the country + * @throws IOException thrown when fileName is invalid + */ public List> readCSVFileByCountry(String fileName, String countryName) throws IOException { - // TODO implement this method - return null; + File file = new File(fileName); + FileReader fr = new FileReader(file); + BufferedReader br = new BufferedReader(fr); + String entry; + List> interpretedFile = new ArrayList>(); + while ((entry = br.readLine()) != null) { + List interpretedLine = Arrays.asList(entry.split("\\s*,\\s*")); + if (interpretedLine.get(0).equals(countryName)) { + interpretedFile.add(interpretedLine); + } + } + return interpretedFile; } - + + /** + * Interprets CSV file as a list of list of strings including column headers + * @param fileName the file path relative to the location of program execution + * @return a list of list of strings representing each entry in the CSV + * @throws IOException thrown when fileName is invalid + */ public List> readCSVFileWithHeaders(String fileName) throws IOException { - // TODO implement this method - return null; + File file = new File(fileName); + FileReader fr = new FileReader(file); + BufferedReader br = new BufferedReader(fr); + String entry; + List> interpretedFile = new ArrayList(); + while ((entry = br.readLine()) != null) { + List interpretedLine = Arrays.asList(entry.split("\\s*,\\s*")); + interpretedFile.add(interpretedLine); + } + return interpretedFile; } - + + /** + * Interprets CSV file as a list of list of strings excluding column headers + * @param fileName the file path relative to the location of program execution + * @return a list of list of strings representing each disaster entry in the CSV + * @throws IOException thrown when fileName is invalid + */ public List> readCSVFileWithoutHeaders(String fileName) throws IOException { - // TODO implement this method - return null; + List> interpretedFile = readCSVFileWithHeaders(fileName); + interpretedFile.remove(0); + return interpretedFile; } - + + /** + * Finds the most impactful year for a given set of natural disaster records + * @param records a list of lists of strings representing natural disaster data interpreted from a CSV file + * @return a DisasterDescription for the disasters in the most impactful year + */ public DisasterDescription getMostImpactfulYear(List> records) { - // TODO implement this method - return null; + //checks formatting style of records - if sorted by category, use category method + if (records.get(0).get(0).equals("All natural disasters")) { + return getMostImpactfulYearByCategory("All natural disasters", records); + } + int highestNumDisasters = Integer.parseInt(records.get(0).get(3)); + int yearOf_highestNumDisasters = Integer.parseInt(records.get(0).get(2)); + for (int i = 1; i < records.size(); i++) { + int numDisasters = Integer.parseInt(records.get(i).get(3)); + if(numDisasters > highestNumDisasters) { + highestNumDisasters = numDisasters; + yearOf_highestNumDisasters = Integer.parseInt(records.get(i).get(2)); + } + } + return new DisasterDescription(highestNumDisasters, yearOf_highestNumDisasters); } + /** + * Finds the most impactful year for a given set of natural disasters of a certain category + * @param category the desired category + * @param records a list of lists of strings representing natural disaster data interpreted from a CSV file + * @return a DisasterDescription for the disasters of a certain category in the most impactful year + */ public DisasterDescription getMostImpactfulYearByCategory(String category, List> records) { - // TODO implement this method - return null; + boolean foundCategory = false; + int i = 0; + while (!foundCategory && i < records.size()) { + if(records.get(i++).get(0).equals(category)) { + foundCategory = true; + i--; + } + } + List currentEntry = records.get(i++); + int highestNumDistasters = Integer.parseInt(currentEntry.get(3)); + int yearOf_highestNumDistasters = Integer.parseInt(currentEntry.get(2)); + while((currentEntry = records.get(i++)).get(0).equals(category) && i < records.size()) { + int numDisasters = Integer.parseInt(currentEntry.get(3)); + if (numDisasters > highestNumDistasters) { + highestNumDistasters = numDisasters; + yearOf_highestNumDistasters = Integer.parseInt(currentEntry.get(2)); + } + } + return new DisasterDescription(category, highestNumDistasters, yearOf_highestNumDistasters); } + /** + * Finds the most impactful disaster for a given set of natural disasters in a certain year + * @param year the desired year + * @param records a list of lists of strings representing natural disaster data interpreted from a CSV file + * @return a DisasterDescription for the most impactful disaster category in a given year + */ public DisasterDescription getMostImpactfulDisasterByYear(String year, List> records) { - // TODO implement this method - return null; + int mostImpactsByDisaster = Integer.parseInt(records.get(0).get(3)); + String categoryOf_mostImpactfulDisaster = records.get(0).get(0); + for (int i = 1; i < records.size(); i++) { + List line = records.get(i); + if (line.get(2).equals(year) && !(line.get(0).equals("All natural disasters"))) { + int numDisasters = Integer.parseInt(line.get(3)); + if (numDisasters > mostImpactsByDisaster) { + categoryOf_mostImpactfulDisaster = line.get(0); + mostImpactsByDisaster = numDisasters; + } + } + } + return new DisasterDescription(categoryOf_mostImpactfulDisaster, mostImpactsByDisaster, Integer.parseInt(year)); } + /** + * counts the number of incidents of a certain category within a set of disaster records + * @param category the desired category to measure + * @param records a list of lists of strings representing natural disaster data interpreted from a CSV file + * @return a DisasterDescription for the number of incidents of a certain disaster category + */ public DisasterDescription getTotalReportedIncidentsByCategory(String category, List> records) { - // TODO implement this method - return null; + boolean foundCategory = false; + int i = 0; + while (!foundCategory && i < records.size()) { + if(records.get(i++).get(0).equals(category)) { + foundCategory = true; + i--; + } + } + List currentEntry = records.get(i++); + int totalReportedIncidents = Integer.parseInt(currentEntry.get(3)); + while((currentEntry = records.get(i++)).get(0).equals(category) && i < records.size()) { + int numDisasters = Integer.parseInt(currentEntry.get(3)); + totalReportedIncidents += numDisasters; + } + return new DisasterDescription(category,totalReportedIncidents); } - + /** * This method will return the count if the number of incident falls within the provided range. * To simplify the problem, we assume: * + A value of -1 is provided if the max range is NOT applicable. * + A min value can be provided, without providing a max value (which then has to be -1 like indicated above). - * + If a max value is provided, then a max value is also needed. + * + If a max value is provided, then a MIN value is also needed. + * @param records a list of lists of strings representing natural disaster data interpreted from a CSV file + * @param min the minimum number of incidents to count a year (see above for specifications) + * @param max the maximum number of incidents to count a year (see above for specifications) + * @return the number of incidents that fall in the given range */ public int countImpactfulYearsWithReportedIncidentsWithinRange(List> records, int min, int max) { - // TODO implement this method - return -1; + int count = 0; + if (min == -1) { + for (List entry : records) { + count++; + } + } + else { + for (List entry : records) { + int numIncidents = Integer.parseInt(entry.get(3)); + if (min <= numIncidents && (max == -1 ? true : numIncidents <= max)) { + count++; + } + } + } + return count; } - + + + /** + * counts the number of incidents in a set of natural disaster records + * used as a helper method for firstRecordsHaveMoreReportedIndicents + * @param records a list of lists of strings representing natural disaster data interpreted from a CSV file + * @return the number of incidents in the records + */ + private int countIncidents(List> records) { + int count = 0; + for (List entry : records) { + int numDisasters = Integer.parseInt(entry.get(3)); + count += numDisasters; + } + return count; + } + + /** + * Returns true if the first parameter has strictly more total reported incidents than the second. + * @param records1 The first list to check. Returns true if it has strictly more incidents. + * @param records2 The second list to check. Returns true if it has strictly fewer incidents. + * @return True if the first list is strictly larger than the second in terms of total reported incidents. + */ public boolean firstRecordsHaveMoreReportedIndicents(List> records1, List> records2) { - // TODO implement this method - return false; + return countIncidents(records1) > countIncidents(records2); } } diff --git a/src/main/java/codingcompetition2019/DisasterDescription.java b/src/main/java/codingcompetition2019/DisasterDescription.java index 662626b..f51345f 100644 --- a/src/main/java/codingcompetition2019/DisasterDescription.java +++ b/src/main/java/codingcompetition2019/DisasterDescription.java @@ -1,5 +1,75 @@ package codingcompetition2019; +/** + * This class represents a description for a natural disaster + * @author Mudit Gupta and Ryan Thomas Lynch + * @version 1.0 + */ public class DisasterDescription { - // TODO finish this class + + + private String category; + private int reportedIncidents; + private int year; + + /** + * Initializes a description of some summary of disasters in a + * given year and category with the number of incidents reported. + * @param category The category of incidents in this summary. + * @param reportedIncidents The number of incidents in the category and year. + * @param year The year to which this summary applies. + */ + public DisasterDescription(String category, int reportedIncidents, int year) { + this.category = category; + this.reportedIncidents = reportedIncidents; + this.year = year; + } + + /** + * Initializes a description of some summary of disasters in a + * given category with the number of incidents reported with either an unknown + * year or no proper year (sets year to -1). + * @param category The category of incidents in this summary. + * @param reportedIncidents The number of incidents in the category. + */ + public DisasterDescription(String category, int reportedIncidents) { + this(category, reportedIncidents, -1); + } + + /** + * Initializes a description of some summary of disasters in a + * given year with the number of incidents reported with either an unknown + * category or no proper category (sets category to null). + * @param reportedIncidents The number of incidents in the category. + * @param year The year of the incidents in this summary. + */ + public DisasterDescription(int reportedIncidents, int year) { + this(null, reportedIncidents, year); + } + + /** + * Returns the category. + * @return the category. + */ + public String getCategory() { + return category; + } + + /** + * Returns the number of reported incidents in this summary. + * @return the number of reported incidents in this summary. + */ + public int getReportedIncidentsNum() { + return reportedIncidents; + } + + /** + * Returns the year as a String if it exists (is not -1). If the year is -1, + * returns "NoYr". + * @return the year as a String if it exists (is not -1). If the year is -1, + * returns "NoYr". + */ + public String getYear() { + return year == -1 ? "NoYr" : String.valueOf(year); + } } diff --git a/target/classes/codingcompetition2019/CodingCompCSVUtil.class b/target/classes/codingcompetition2019/CodingCompCSVUtil.class new file mode 100644 index 0000000..4346fec Binary files /dev/null and b/target/classes/codingcompetition2019/CodingCompCSVUtil.class differ