diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5c19f15
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+/target/
+/.idea
+.classpath
+.project
+/.settings
\ No newline at end of file
diff --git a/codingcompetition2019.iml b/codingcompetition2019.iml
new file mode 100644
index 0000000..54ddd53
--- /dev/null
+++ b/codingcompetition2019.iml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/feedback.txt b/feedback.txt
index 8234592..ec30eba 100644
--- a/feedback.txt
+++ b/feedback.txt
@@ -1,9 +1,12 @@
-Your team (name of each individual participating):
-How many JUnits were you able to get to pass?
+Your team (name of each individual participating): Ishan Baniya
+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:
+ Step 1: Added meaningful description for each methods in CodingCompCSVUtil.java file for other developers to understand the code easily.
+ Step 2: Added a GUI that allows users to view the most impactful disaster by year and category.
-Feedback for the coding competition? Things you would like to see in future events?
\ No newline at end of file
+Feedback for the coding competition? Things you would like to see in future events?
+# It would have been better to have comments/example on the methods so it would be easier to know what to do for the implementation.
+
+
diff --git a/src/main/java/codingcompetition2019/CodingCompCSVUtil.java b/src/main/java/codingcompetition2019/CodingCompCSVUtil.java
index 74f3074..27ef7c6 100644
--- a/src/main/java/codingcompetition2019/CodingCompCSVUtil.java
+++ b/src/main/java/codingcompetition2019/CodingCompCSVUtil.java
@@ -1,58 +1,263 @@
package codingcompetition2019;
+import java.io.File;
import java.io.IOException;
-import java.util.List;
+import java.util.*;
public class CodingCompCSVUtil {
- public List> readCSVFileByCountry(String fileName, String countryName) throws IOException {
- // TODO implement this method
- return null;
- }
-
- public List> readCSVFileWithHeaders(String fileName) throws IOException {
- // TODO implement this method
- return null;
- }
-
- public List> readCSVFileWithoutHeaders(String fileName) throws IOException {
- // TODO implement this method
- return null;
- }
-
- public DisasterDescription getMostImpactfulYear(List> records) {
- // TODO implement this method
- return null;
- }
-
- public DisasterDescription getMostImpactfulYearByCategory(String category, List> records) {
- // TODO implement this method
- return null;
- }
-
- public DisasterDescription getMostImpactfulDisasterByYear(String year, List> records) {
- // TODO implement this method
- return null;
- }
-
- public DisasterDescription getTotalReportedIncidentsByCategory(String category, List> records) {
- // TODO implement this method
- return null;
- }
-
- /**
- * 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.
- */
- public int countImpactfulYearsWithReportedIncidentsWithinRange(List> records, int min, int max) {
- // TODO implement this method
- return -1;
- }
-
- public boolean firstRecordsHaveMoreReportedIndicents(List> records1, List> records2) {
- // TODO implement this method
- return false;
- }
+
+ /**
+ * This method reads the CSV file and returns the data about the specified country
+ * Each row has a data about the disaster for the a year separated by comma.
+ * Store the data separated by comma in a list if the name of the country matches.
+ * Store all the list with the matching country name in a list and return it.
+ *
+ * @param fileName filePath of the CSV file with data
+ * @param countryName name of the country to filter the records by
+ * @return Data about the disaster for that country
+ * @throws IOException error on reading the file
+ */
+ public List> readCSVFileByCountry(String fileName, String countryName) throws IOException {
+ List> countries = readCSVFileWithoutHeaders(fileName);
+
+ // Filter the csv values by country
+ List> countryEntries = new ArrayList>();
+ for (List entry : countries) {
+ // Check if the name of the country matches
+ if (entry.get(0).trim().toLowerCase().equals(countryName.trim().toLowerCase())) {
+ countryEntries.add(entry);
+ }
+ }
+ return countryEntries;
+ }
+
+ /**
+ * This method reads the CSV file including the header.
+ * Each line of the CSV has data about the disaster separated by comma. Store it in a list.
+ * Add that list to a master list and return the master list.
+ *
+ * @param fileName filePath of the CSV file with data
+ * @return list with a list of data related to the disaster
+ * @throws IOException error on reading the file
+ */
+ public List> readCSVFileWithHeaders(String fileName) throws IOException {
+ // Get all entries without the header
+ File inputFile = new File(fileName);
+
+ List> csvEntriesWithHeader = new ArrayList>();
+
+ if (inputFile.exists()) {
+ try {
+ Scanner input = new Scanner(inputFile);
+ // Read each line an add it to the list
+ while (input.hasNext()) {
+ String currentLine = input.nextLine();
+ // Split the line by comma and store it as array
+ List values = Arrays.asList(currentLine.split(","));
+ csvEntriesWithHeader.add(values);
+ }
+
+ input.close();
+ } catch (IOException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ // Other unexpected error occurred
+ ex.printStackTrace();
+ return null;
+ }
+ }
+
+ return csvEntriesWithHeader;
+ }
+
+ /**
+ * This method reads the CSV file without the header.
+ * Each line of the CSV has data about the disaster separated by comma. Store it in a list
+ * Add that list to a master list and return the master list.
+ *
+ * @param fileName filePath of the CSV file with data
+ * @return list with a list of data related to the disaster
+ * @throws IOException error on reading the file
+ */
+ public List> readCSVFileWithoutHeaders(String fileName) throws IOException {
+ // Get all records with the header
+ List> allCSVEntries = readCSVFileWithHeaders(fileName);
+
+ //Remove the first entry of header
+ allCSVEntries.remove(0);
+
+ return allCSVEntries;
+ }
+
+ /**
+ * This method iterates through the records list and checks the number of reported incidents for each record
+ * It finds the year with the most number of reported incidents
+ *
+ * @param records list of data related to a disaster event
+ * @return info about the most impactful Disaster based on year
+ */
+ public DisasterDescription getMostImpactfulYear(List> records) {
+
+ // See if there is at least one record
+ if (records.size() > 0) {
+
+ //Assume the first entry is the most impactful
+ int year = Integer.parseInt(records.get(0).get(2));
+ int maxImpact = Integer.parseInt(records.get(0).get(3));
+ String entity = records.get(0).get(0);
+
+ //Iterate through each entry and get the find the most impact
+ for (List entry : records) {
+ int currentImpact = Integer.parseInt(entry.get(3));
+ if (currentImpact > maxImpact) {
+ maxImpact = currentImpact;
+ year = Integer.parseInt(entry.get(2));
+ entity = entry.get(0);
+ }
+ }
+
+ DisasterDescription disaster = new DisasterDescription();
+ disaster.setYear(year);
+ disaster.setReportedIncidentsNum(maxImpact);
+ disaster.setCategory(entity);
+
+ return disaster;
+ }
+
+ return new DisasterDescription();
+ }
+
+ /**
+ * This method filters the records by the given category.
+ * It calls getMostImpactfulYear() method to find the most impactful year after filtering the list.
+ * Then returns the info about the most impactful disaster for that given category.
+ *
+ * @param category Category of disaster
+ * @param records List of data about the disaster
+ * @return Info about the most impactful disaster for the given category
+ */
+ public DisasterDescription getMostImpactfulYearByCategory(String category, List> records) {
+
+ //Filter the list by category
+ List> recordByCategory = new LinkedList>();
+ for (List record : records) {
+ // Check if the category matches
+ if (record.get(0).toLowerCase().trim().equals(category.toLowerCase().trim())) {
+ recordByCategory.add(record);
+ }
+ }
+
+ return getMostImpactfulYear(recordByCategory);
+ }
+
+ /**
+ * This method filters the list by the given year.
+ * It calls getMostImpactfulYear() method to find the most impactful year after filtering the list.
+ * Then it returns info about the most impactful disaster for that given year.
+ *
+ * @param year Filter the record based on this year
+ * @param records List of data about the disaster
+ * @return Info about the most impactful disaster for the given year
+ */
+ public DisasterDescription getMostImpactfulDisasterByYear(String year, List> records) {
+
+ // Filter the record by year
+ List> recordsByYear = new LinkedList>();
+ for (List record : records) {
+ if (record.get(2).trim().toLowerCase().equals(year.trim().toLowerCase())) {
+ // Ignore for all natural disasters
+ if (!record.get(0).trim().toLowerCase().equals("all natural disasters")) {
+ recordsByYear.add(record);
+ }
+ }
+ }
+
+ return getMostImpactfulYear(recordsByYear);
+ }
+
+ /**
+ * This method iterates through the list of records
+ * For each record, if the category matches, it retrieves the number of reported incidents
+ * Then it calculates the total number of reported incidents for that category.
+ *
+ * @param category Disaster category to filter the records
+ * @param records List of data about disaster
+ * @return Total number of reported incidents for the given category
+ */
+ public DisasterDescription getTotalReportedIncidentsByCategory(String category, List> records) {
+
+ int totalIncidents = 0;
+ for (List record : records) {
+ // Check if the category matches
+ if (record.get(0).toLowerCase().trim().equals(category.toLowerCase().trim())) {
+ totalIncidents += Integer.parseInt(record.get(3));
+ }
+ }
+
+ DisasterDescription disaster = new DisasterDescription();
+ disaster.setCategory(category);
+ disaster.setReportedIncidentsNum(totalIncidents);
+
+ return disaster;
+ }
+
+
+ /**
+ * 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.
+ */
+ public int countImpactfulYearsWithReportedIncidentsWithinRange(List> records, int min, int max) {
+ boolean hasMaximumRange = max != -1;
+ int count = 0;
+
+ for (List record : records) {
+ int reportedIncident = Integer.parseInt(record.get(3));
+
+ if (hasMaximumRange) {
+ if (reportedIncident >= min && reportedIncident <= max) {
+ count++;
+ }
+ } else { // No maximum range
+ if (reportedIncident >= min) {
+ count++;
+ }
+ }
+ }
+
+ return count;
+ }
+
+ /**
+ * This method checks if the first list has more reported incidents than the second list.
+ * It calls getTotalReportedIncidents() to get the total number of reported incidents for both records
+ * It compares the total number of reported incidents for both records.
+ *
+ * @param records1 List of data about disaster
+ * @param records2 List of data about disaster
+ * @return Boolean value indicating record1 has more reported incidents than record2
+ */
+ public boolean firstRecordsHaveMoreReportedIndicents(List> records1, List> records2) {
+ return getTotalReportedIncidents(records1) > getTotalReportedIncidents(records2);
+ }
+
+ /**
+ * This method iterates through the records
+ * For each record, it retrieves the number of reported incident.
+ * It calculates the total reported incidents for that given data.
+ *
+ * @param records List of data about the disaster
+ * @return int total reported incidents
+ */
+ private int getTotalReportedIncidents(List> records) {
+ int total = 0;
+ for (List entry : records) {
+ total += Integer.parseInt(entry.get(3));
+ }
+ return total;
+ }
+
+
}
diff --git a/src/main/java/codingcompetition2019/DisasterDescription.java b/src/main/java/codingcompetition2019/DisasterDescription.java
index 662626b..226d12e 100644
--- a/src/main/java/codingcompetition2019/DisasterDescription.java
+++ b/src/main/java/codingcompetition2019/DisasterDescription.java
@@ -1,5 +1,58 @@
package codingcompetition2019;
+/**
+ * This class holds basic information about a given disaster
+ * It has the year the disaster occurred
+ * It has the total number of reported incidents for that given disaster
+ * It has the category of the disaster
+ * It has the country the description occurred
+ */
public class DisasterDescription {
- // TODO finish this class
+
+ private String category;
+ private String country;
+ private int reportedIncidentsNum;
+ private int year;
+
+ /**
+ * No-arg constructor
+ */
+ public DisasterDescription() {
+
+ }
+
+
+ // Accessors for data field
+ public String getCategory() {
+ return category;
+ }
+
+ public int getReportedIncidentsNum() {
+ return reportedIncidentsNum;
+ }
+
+ public String getYear() {
+ return year + "";
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ // Mutator for data field
+ public void setCategory(String category) {
+ this.category = category;
+ }
+
+ public void setReportedIncidentsNum(int reportedIncidentsNum) {
+ this.reportedIncidentsNum = reportedIncidentsNum;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
}
diff --git a/src/main/java/codingcompetition2019/NatualDisasterViewer.java b/src/main/java/codingcompetition2019/NatualDisasterViewer.java
new file mode 100644
index 0000000..99b3342
--- /dev/null
+++ b/src/main/java/codingcompetition2019/NatualDisasterViewer.java
@@ -0,0 +1,9 @@
+package codingcompetition2019;
+
+import codingcompetition2019.gui.WelcomeScreen;
+
+public class NatualDisasterViewer {
+ public static void main(String[] args){
+ (new WelcomeScreen()).setVisible(true);
+ }
+}
diff --git a/src/main/java/codingcompetition2019/gui/AllNaturalDisasters.java b/src/main/java/codingcompetition2019/gui/AllNaturalDisasters.java
new file mode 100644
index 0000000..0f4bf54
--- /dev/null
+++ b/src/main/java/codingcompetition2019/gui/AllNaturalDisasters.java
@@ -0,0 +1,156 @@
+package codingcompetition2019.gui;
+
+import codingcompetition2019.CodingCompCSVUtil;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.*;
+import java.util.List;
+
+public class AllNaturalDisasters extends JFrame {
+
+ private String naturalDisasterByTypeFile = "src/main/resources/natural-disasters-by-type.csv";
+ private CodingCompCSVUtil util;
+ private List> records;
+ private ArrayList disasters;
+ private ArrayList years;
+
+ private JLabel lblImpactedYear;
+ private JLabel lblTotalIncidents;
+ private JLabel lblDisasterName;
+ private JLabel lblReportedIncidentsByYear;
+
+ public AllNaturalDisasters(){
+ super("All Natural Disasters");
+ util = new CodingCompCSVUtil();
+ try{
+ records = util.readCSVFileWithoutHeaders(naturalDisasterByTypeFile);
+ getDisasterCategoriesAndYear();
+ }
+ catch (Exception ex) {
+
+ }
+
+ createGUIComponents();
+
+ setSize(400, 400);
+ setLocationRelativeTo(null);
+ setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+ }
+
+ private void getDisasterCategoriesAndYear(){
+ Set categories = new HashSet();
+ Set yearList = new TreeSet();
+
+ for(List record : records){
+ String category = record.get(0).trim();
+ String year = record.get(2).trim();
+ if (!categories.contains(category))
+ categories.add(category);
+
+ if (!yearList.contains(year))
+ yearList.add(year);
+ }
+ disasters = new ArrayList();
+ years = new ArrayList();
+
+ disasters.addAll(categories);
+ years.addAll(yearList);
+ }
+
+ private void createGUIComponents(){
+ Container pane = this.getContentPane();
+ pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
+
+ pane.add(Box.createVerticalGlue());
+ pane.add(getSelectionMenuByCategory());
+ pane.add(Box.createVerticalStrut(20));
+ pane.add(getDisasterInfoPanelByCategory());
+ pane.add(Box.createVerticalStrut(40));
+ pane.add(getSelectionMenuByYear());
+ pane.add(Box.createVerticalStrut(20));
+ pane.add(getDisasterInfoPanelByYear());
+ }
+
+ private JPanel getDisasterInfoPanelByCategory(){
+ JPanel disasterInfo = new JPanel();
+ disasterInfo.setBorder(BorderFactory.createTitledBorder("Disaster Info By Category"));
+ disasterInfo.setLayout(new GridLayout(2, 2));
+
+ disasterInfo.add(new JLabel("Most impacted year: "));
+ lblImpactedYear = new JLabel(util.getMostImpactfulYearByCategory(disasters.get(0), records).getYear() + "");
+ disasterInfo.add(lblImpactedYear);
+ disasterInfo.add(new JLabel("Total reported incidents: "));
+ lblTotalIncidents = new JLabel(util.getTotalReportedIncidentsByCategory(disasters.get(0), records).getReportedIncidentsNum() + "");
+ disasterInfo.add(lblTotalIncidents);
+
+
+ return disasterInfo;
+ }
+
+ private JPanel getSelectionMenuByCategory(){
+ JPanel selection = new JPanel();
+ selection.setLayout(new GridLayout(1, 2));
+ selection.setBorder(new EmptyBorder(10,10,10,10));
+ selection.add(new JLabel("Select Disaster Type"));
+
+ final JComboBox cbDisaster = new JComboBox(disasters.toArray());
+ selection.add(cbDisaster);
+ cbDisaster.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ updateCategoryInfo((String)cbDisaster.getSelectedItem());
+ }
+ });
+
+ return selection;
+ }
+
+ private JPanel getSelectionMenuByYear(){
+ JPanel selection = new JPanel();
+ selection.setLayout(new GridLayout(1, 2));
+ selection.setBorder(new EmptyBorder(10,10,10,10));
+ selection.add(new JLabel("Select Year"));
+
+ final JComboBox cbYear = new JComboBox(years.toArray());
+ selection.add(cbYear);
+ cbYear.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ updateYearInfo((String)cbYear.getSelectedItem());
+ }
+ });
+
+ return selection;
+ }
+
+ private JPanel getDisasterInfoPanelByYear(){
+ JPanel disasterInfo = new JPanel();
+ disasterInfo.setBorder(BorderFactory.createTitledBorder("Disaster Info By Year"));
+ disasterInfo.setLayout(new GridLayout(2, 2));
+
+ disasterInfo.add(new JLabel("Most impactful disaster: "));
+ lblDisasterName = new JLabel(util.getMostImpactfulDisasterByYear(years.get(0), records).getYear() + "");
+ disasterInfo.add(lblDisasterName);
+
+ disasterInfo.add(new JLabel("Total reported incidents: "));
+ lblReportedIncidentsByYear = new JLabel(util.getTotalReportedIncidentsByCategory(disasters.get(0), records).getReportedIncidentsNum() + "");
+ disasterInfo.add(lblReportedIncidentsByYear);
+
+
+ return disasterInfo;
+ }
+
+ private void updateCategoryInfo(String category){
+ lblTotalIncidents.setText(util.getTotalReportedIncidentsByCategory(category, records).getReportedIncidentsNum() + "");
+ lblImpactedYear.setText(util.getMostImpactfulYearByCategory(category, records).getYear() + "");
+ }
+
+ private void updateYearInfo(String year){
+ lblDisasterName.setText(util.getMostImpactfulDisasterByYear(year, records).getCategory() + "");
+ lblReportedIncidentsByYear.setText(util.getMostImpactfulDisasterByYear(year, records).getReportedIncidentsNum() + "");
+ }
+
+
+}
diff --git a/src/main/java/codingcompetition2019/gui/WelcomeScreen.java b/src/main/java/codingcompetition2019/gui/WelcomeScreen.java
new file mode 100644
index 0000000..64459d3
--- /dev/null
+++ b/src/main/java/codingcompetition2019/gui/WelcomeScreen.java
@@ -0,0 +1,58 @@
+package codingcompetition2019.gui;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class WelcomeScreen extends JFrame {
+
+ private JComboBox cbData;
+
+ public WelcomeScreen() {
+ super("Natural Disaster Info");
+ createGUIComponents();
+ setSize(400, 300);
+ setLocationRelativeTo(null);
+ setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+ }
+
+ private void createGUIComponents() {
+ JPanel dataTypePanel = new JPanel();
+ dataTypePanel.setLayout(new GridLayout(1, 2));
+ dataTypePanel.setBorder(new EmptyBorder(20, 20, 20, 20));
+ dataTypePanel.add(new JLabel("Select Data Type"));
+
+ String[] data = {"Natural Disasters by Type"};
+ cbData = new JComboBox(data);
+ dataTypePanel.add(cbData);
+
+ JButton btnGetData = new JButton("View Data");
+ btnGetData.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ switch(cbData.getSelectedIndex()){
+ case 0:
+ (new AllNaturalDisasters()).setVisible(true); break;
+// case 1:
+// (new Earthquake()).setVisible(true); break;
+// case 3:
+// (new Volcano()).setVisible(true); break;
+ }
+ }
+ });
+
+ Container pane = this.getContentPane();
+ pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
+
+ pane.add(Box.createVerticalStrut(25));
+ pane.add(new JLabel("Natural Disaster Info"));
+ pane.add(Box.createVerticalStrut(50));
+ pane.add(dataTypePanel);
+ pane.add(Box.createVerticalStrut(50));
+ pane.add(btnGetData);
+ pane.add(Box.createVerticalStrut(25));
+ }
+
+
+}