From ca33f5c98a4d8b9522bb3ed0bb04f5eda67ba787 Mon Sep 17 00:00:00 2001 From: isabelle926 Date: Tue, 28 May 2024 10:37:22 -0700 Subject: [PATCH] fix bugs --- .../mvc/statsData/Categorical.java | 43 ++-- .../mvc/statsData/CategoricalRequest.java | 25 +++ .../mvc/statsData/CategoricalVars.java | 29 --- .../mvc/statsData/StatsApiController.java | 72 +++---- .../mvc/statsData/TwoCategorical.java | 200 ++++++++---------- 5 files changed, 158 insertions(+), 211 deletions(-) create mode 100644 src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/CategoricalRequest.java diff --git a/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/Categorical.java b/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/Categorical.java index 1fe9c81..a777a32 100644 --- a/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/Categorical.java +++ b/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/Categorical.java @@ -6,13 +6,9 @@ import jakarta.persistence.*; import java.util.Map; +import java.util.ArrayList; import java.util.HashMap; import java.util.stream.Collectors; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartUtils; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.data.category.DefaultCategoryDataset; import java.io.File; import java.io.IOException; @@ -25,8 +21,19 @@ public class Categorical extends StatsFunctions { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; - - private List variableNames; //if size == 2, first val = explanatory, second = response + private int size; + private ArrayList data; + + // Custom setters if needed, otherwise Lombok will generate them + public void setSize(int size) { + this.size = size; + } + + public void setData(ArrayList data) { + this.data = data; + } + + private ArrayList variableNames; //if size == 2, first val = explanatory, second = response private Map items = new HashMap<>(); // Name, Frequency @@ -39,26 +46,4 @@ public Map calculateRelativeFrequency() { e -> e.getValue() / total )); } - - // Method to generate a bar chart - public void generateBarChart(String chartTitle, String categoryAxisLabel, String valueAxisLabel, String filePath) throws IOException { - DefaultCategoryDataset dataset = new DefaultCategoryDataset(); - - items.forEach((key, value) -> { - dataset.addValue(value, "Frequency", key); - }); - - JFreeChart barChart = ChartFactory.createBarChart( - chartTitle, - categoryAxisLabel, - valueAxisLabel, - dataset, - PlotOrientation.VERTICAL, - true, true, false); - - int width = 640; /* Width of the image */ - int height = 480; /* Height of the image */ - File barChartFile = new File(filePath); - ChartUtils.saveChartAsJPEG(barChartFile, barChart, width, height); - } } diff --git a/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/CategoricalRequest.java b/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/CategoricalRequest.java new file mode 100644 index 0000000..bd6e8ab --- /dev/null +++ b/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/CategoricalRequest.java @@ -0,0 +1,25 @@ +package com.nighthawk.spring_portfolio.mvc.statsData; + +import java.util.ArrayList; + +public class CategoricalRequest { + private int size; + private ArrayList data; + + // Getters and Setters + public int getSize() { + return size; + } + + public void setSize(int size) { + this.size = size; + } + + public ArrayList getData() { + return data; + } + + public void setData(ArrayList data) { + this.data = data; + } +} diff --git a/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/CategoricalVars.java b/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/CategoricalVars.java index c1762cb..73c214c 100644 --- a/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/CategoricalVars.java +++ b/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/CategoricalVars.java @@ -5,11 +5,6 @@ import lombok.NoArgsConstructor; import jakarta.persistence.*; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartUtils; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.data.category.DefaultCategoryDataset; import java.io.File; import java.io.IOException; @@ -47,30 +42,6 @@ public double[][] calculateRelativeFrequencies() { return relativeFrequencies; } - // Method to generate a bar chart for the two-way table - public void generateBarChart(String chartTitle, String categoryAxisLabel, String valueAxisLabel, String filePath) throws IOException { - DefaultCategoryDataset dataset = new DefaultCategoryDataset(); - - for (int i = 0; i < frequencies.length; i++) { - for (int j = 0; j < frequencies[i].length; j++) { - dataset.addValue(frequencies[i][j], explanatoryName + " " + i, responseName + " " + j); - } - } - - JFreeChart barChart = ChartFactory.createBarChart( - chartTitle, - categoryAxisLabel, - valueAxisLabel, - dataset, - PlotOrientation.VERTICAL, - true, true, false); - - int width = 640; /* Width of the image */ - int height = 480; /* Height of the image */ - File barChartFile = new File(filePath); - ChartUtils.saveChartAsJPEG(barChartFile, barChart, width, height); - } - // Override toString method to handle the array printing properly @Override public String toString() { diff --git a/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/StatsApiController.java b/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/StatsApiController.java index 7c491fa..7e8021d 100644 --- a/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/StatsApiController.java +++ b/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/StatsApiController.java @@ -1,22 +1,18 @@ package com.nighthawk.spring_portfolio.mvc.statsData; -import org.hibernate.Hibernate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import jakarta.transaction.Transactional; - import java.util.ArrayList; import java.util.List; import java.util.Optional; -@RestController // annotation to simplify the creation of RESTful web services -@RequestMapping("/api/stats") // all requests in file begin with this URI +@RestController +@RequestMapping("/api/stats") public class StatsApiController { - // Autowired enables Control to connect URI request and POJO Object to easily for Database CRUD operations @Autowired private QuantitativeJpaRepository qRepository; @Autowired @@ -28,46 +24,42 @@ public class StatsApiController { @Autowired private TwoCategoricalJpaRepository twoCategoricalRepository; - /* GET List of all of any type of data - * @GetMapping annotation is used for mapping HTTP GET requests onto specific handler methods. - */ - @GetMapping("/twoQuantitative") @Transactional public ResponseEntity> getTwoQuantitatives() { List twoQuantitatives = twoQRepository.findAll(); twoQuantitatives.forEach(quantitative -> Hibernate.initialize(quantitative.getLsrl())); return new ResponseEntity<>(twoQuantitatives, HttpStatus.OK); - } + } @GetMapping("/quantitative") public ResponseEntity> getQuantitatives() { List quantitative = qRepository.findAll(); return new ResponseEntity<>(quantitative, HttpStatus.OK); - } + } @PostMapping("/newQuantitative") public ResponseEntity newQuantitative(@RequestBody QuantitativeRequest quantitativeRequest) { List data = quantitativeRequest.getData(); - String name = quantitativeRequest.getName(); + String name = quantitativeRequest.getName(); Quantitative quantitative = new Quantitative(data, name); - + qRepository.save(quantitative); return new ResponseEntity<>(quantitative, HttpStatus.OK); } @PostMapping("/newTwoQuantitative") - public ResponseEntity newCode(@RequestBody TwoQuantitativeRequest twoQuantitativeRequest) { + public ResponseEntity newTwoQuantitative(@RequestBody TwoQuantitativeRequest twoQuantitativeRequest) { List explanatory = twoQuantitativeRequest.getExplanatory(); List response = twoQuantitativeRequest.getResponse(); - String explanatoryName = twoQuantitativeRequest.getExplanatoryName(); - String responseName = twoQuantitativeRequest.getResponseName(); + String explanatoryName = twoQuantitativeRequest.getExplanatoryName(); + String responseName = twoQuantitativeRequest.getResponseName(); Quantitative quantitative1 = new Quantitative(explanatory, explanatoryName); Quantitative quantitative2 = new Quantitative(response, responseName); - + qRepository.save(quantitative1); qRepository.save(quantitative2); @@ -81,33 +73,28 @@ public ResponseEntity newCode(@RequestBody TwoQuantitativeReque twoQRepository.save(twoQuantitative); return new ResponseEntity<>(twoQuantitative, HttpStatus.OK); - } + } - /* GET Specific of any type of data - * @GetMapping annotation is used for mapping HTTP GET requests onto specific handler methods. - */ - @GetMapping("/getQuantitative{id}") + @GetMapping("/getQuantitative/{id}") public ResponseEntity getQuantitative(@PathVariable long id) { Optional optional = qRepository.findById(id); - if (optional.isPresent()) { // Good ID - Quantitative quantitative = optional.get(); // value from findByID - return new ResponseEntity<>(quantitative, HttpStatus.OK); // OK HTTP response: status code, headers, and body + if (optional.isPresent()) { + Quantitative quantitative = optional.get(); + return new ResponseEntity<>(quantitative, HttpStatus.OK); } - // Bad ID - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } - @GetMapping("/getTwoQuantitative{id}") + @GetMapping("/getTwoQuantitative/{id}") @Transactional public ResponseEntity getTwoQuantitative(@PathVariable long id) { Optional optional = twoQRepository.findById(id); - if (optional.isPresent()) { // Good ID - TwoQuantitative twoQuantitative = optional.get(); // value from findByID + if (optional.isPresent()) { + TwoQuantitative twoQuantitative = optional.get(); Hibernate.initialize(twoQuantitative.getLsrl()); - return new ResponseEntity<>(twoQuantitative, HttpStatus.OK); // OK HTTP response: status code, headers, and body + return new ResponseEntity<>(twoQuantitative, HttpStatus.OK); } - // Bad ID - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } @GetMapping("/categorical") @@ -119,7 +106,7 @@ public ResponseEntity> getCategoricals() { @PostMapping("/newCategorical") public ResponseEntity newCategorical(@RequestBody CategoricalRequest categoricalRequest) { int size = categoricalRequest.getSize(); - ArrayList data = categoricalRequest.getData(); + ArrayList data = categoricalRequest.getData(); Categorical categorical = new Categorical(); categorical.setSize(size); @@ -130,15 +117,14 @@ public ResponseEntity newCategorical(@RequestBody CategoricalReques return new ResponseEntity<>(categorical, HttpStatus.OK); } - @GetMapping("/getCategorical{id}") + @GetMapping("/getCategorical/{id}") public ResponseEntity getCategorical(@PathVariable long id) { Optional optional = cRepository.findById(id); - if (optional.isPresent()) { // Good ID - Categorical categorical = optional.get(); // value from findByID - return new ResponseEntity<>(categorical, HttpStatus.OK); // OK HTTP response: status code, headers, and body + if (optional.isPresent()) { + Categorical categorical = optional.get(); + return new ResponseEntity<>(categorical, HttpStatus.OK); } - // Bad ID - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } @GetMapping("/categoricalVars") @@ -163,7 +149,7 @@ public ResponseEntity newCategoricalVars(@RequestBody Categoric return new ResponseEntity<>(categoricalVars, HttpStatus.OK); } - @GetMapping("/getCategoricalVars{id}") + @GetMapping("/getCategoricalVars/{id}") public ResponseEntity getCategoricalVars(@PathVariable long id) { Optional optional = cVarsRepository.findById(id); if (optional.isPresent()) { @@ -197,7 +183,7 @@ public ResponseEntity newTwoCategorical(@RequestBody TwoCategori return new ResponseEntity<>(twoCategorical, HttpStatus.OK); } - @GetMapping("/getTwoCategorical{id}") + @GetMapping("/getTwoCategorical/{id}") public ResponseEntity getTwoCategorical(@PathVariable long id) { Optional optional = twoCategoricalRepository.findById(id); if (optional.isPresent()) { diff --git a/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/TwoCategorical.java b/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/TwoCategorical.java index d50a6a0..f56b95b 100644 --- a/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/TwoCategorical.java +++ b/src/main/java/com/nighthawk/spring_portfolio/mvc/statsData/TwoCategorical.java @@ -5,166 +5,146 @@ import lombok.NoArgsConstructor; import jakarta.persistence.*; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartUtils; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.data.category.DefaultCategoryDataset; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; +import java.util.List; @Data @AllArgsConstructor @NoArgsConstructor -@Entity // Annotation to simplify creating an entity, which is a lightweight persistence domain object. Typically, an entity represents a table in a relational database, and each entity instance corresponds to a row in that table. -public class TwoCategorical extends StatsFunctions { +@Entity +public class TwoCategorical { + @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; - private String explanatoryName; - private String responseName; + private String explanatory; + private String response; + private int freq; + private double relFreq; + + // Constructor to initialize the object with data + public TwoCategorical(String explanatory, String response, int freq, double relFreq) { + this.explanatory = explanatory; + this.response = response; + this.freq = freq; + this.relFreq = relFreq; + } - @Lob - private double[][] frequencies; + // Getters and Setters + public String getExplanatory() { + return explanatory; + } - public TwoCategorical(String explanatoryName, String responseName, double[][] frequencies) { - this.explanatoryName = explanatoryName; - this.responseName = responseName; - this.frequencies = frequencies; + public void setExplanatory(String explanatory) { + this.explanatory = explanatory; } - // Method to calculate relative frequencies for the two-way table - public double[][] calculateRelativeFrequencies() { - double total = Arrays.stream(frequencies) - .flatMapToDouble(Arrays::stream) - .sum(); - double[][] relativeFrequencies = new double[frequencies.length][frequencies[0].length]; - for (int i = 0; i < frequencies.length; i++) { - for (int j = 0; j < frequencies[i].length; j++) { - relativeFrequencies[i][j] = frequencies[i][j] / total; - } - } - return relativeFrequencies; + public String getResponse() { + return response; } - // Method to generate a bar chart for the two-way table - public void generateBarChart(String chartTitle, String categoryAxisLabel, String valueAxisLabel, String filePath) throws IOException { - DefaultCategoryDataset dataset = new DefaultCategoryDataset(); + public void setResponse(String response) { + this.response = response; + } - for (int i = 0; i < frequencies.length; i++) { - for (int j = 0; j < frequencies[i].length; j++) { - dataset.addValue(frequencies[i][j], explanatoryName + " " + i, responseName + " " + j); - } - } + public int getFreq() { + return freq; + } - JFreeChart barChart = ChartFactory.createBarChart( - chartTitle, - categoryAxisLabel, - valueAxisLabel, - dataset, - PlotOrientation.VERTICAL, - true, true, false); + public void setFreq(int freq) { + this.freq = freq; + } - int width = 640; /* Width of the image */ - int height = 480; /* Height of the image */ - File barChartFile = new File(filePath); - ChartUtils.saveChartAsJPEG(barChartFile, barChart, width, height); + public double getRelFreq() { + return relFreq; } - // Method to flatten the frequencies array into a single list of doubles - private double[] flattenFrequencies() { - return Arrays.stream(frequencies).flatMapToDouble(Arrays::stream).toArray(); + public void setRelFreq(double relFreq) { + this.relFreq = relFreq; } // Method to calculate mean - public double calculateMean() { - double[] flatFrequencies = flattenFrequencies(); - return Arrays.stream(flatFrequencies).average().orElse(0.0); + public static double calculateMean(List data) { + double sum = 0.0; + for (double num : data) { + sum += num; + } + return sum / data.size(); } // Method to calculate standard deviation - public double calculateSD() { - double[] flatFrequencies = flattenFrequencies(); - double mean = calculateMean(); - return Math.sqrt(Arrays.stream(flatFrequencies).map(f -> Math.pow(f - mean, 2)).average().orElse(0.0)); + public static double calculateSD(List data) { + double mean = calculateMean(data); + double sum = 0.0; + for (double num : data) { + sum += Math.pow(num - mean, 2); + } + return Math.sqrt(sum / data.size()); } // Method to calculate median - public double getMedian() { - double[] flatFrequencies = flattenFrequencies(); - Arrays.sort(flatFrequencies); - int middle = flatFrequencies.length / 2; - if (flatFrequencies.length % 2 == 0) { - return (flatFrequencies[middle - 1] + flatFrequencies[middle]) / 2.0; + public static double getMedian(List data) { + data.sort(Double::compareTo); + int middle = data.size() / 2; + if (data.size() % 2 == 0) { + return (data.get(middle - 1) + data.get(middle)) / 2.0; } else { - return flatFrequencies[middle]; + return data.get(middle); } } // Method to get minimum value - public double getMinimum() { - return Arrays.stream(flatFrequencies()).min().orElse(0.0); + public static double getMinimum(List data) { + return data.stream().min(Double::compare).orElse(Double.NaN); } // Method to get maximum value - public double getMaximum() { - return Arrays.stream(flatFrequencies()).max().orElse(0.0); + public static double getMaximum(List data) { + return data.stream().max(Double::compare).orElse(Double.NaN); } - // Method to calculate quartile one - public double getQuartileOne() { - double[] flatFrequencies = flattenFrequencies(); - Arrays.sort(flatFrequencies); - return flatFrequencies[flatFrequencies.length / 4]; - } - - // Method to calculate quartile three - public double getQuartileThree() { - double[] flatFrequencies = flattenFrequencies(); - Arrays.sort(flatFrequencies); - return flatFrequencies[(flatFrequencies.length * 3) / 4]; + // Method to calculate correlation + public static double calculateCorrelation(List data1, List data2) { + double mean1 = calculateMean(data1); + double mean2 = calculateMean(data2); + double sumXY = 0.0, sumX2 = 0.0, sumY2 = 0.0; + for (int i = 0; i < data1.size(); i++) { + double x = data1.get(i) - mean1; + double y = data2.get(i) - mean2; + sumXY += x * y; + sumX2 += x * x; + sumY2 += y * y; + } + return sumXY / Math.sqrt(sumX2 * sumY2); } - // Override toString method to handle the array printing properly - @Override - public String toString() { - return "TwoCategorical{" + - "id=" + id + - ", explanatoryName='" + explanatoryName + '\'' + - ", responseName='" + responseName + '\'' + - ", frequencies=" + Arrays.deepToString(frequencies) + - '}'; + // Method to calculate standard error + public static double calculateStandardError(List data) { + return calculateSD(data) / Math.sqrt(data.size()); } + // Method to print data public void printData() { - System.out.println("Data: " + Arrays.deepToString(frequencies) + - "\nExplanatory Name: " + explanatoryName + - "\nResponse Name: " + responseName + - "\nMean: " + calculateMean() + - "\nStandard Deviation: " + calculateSD() + - "\nMin: " + getMinimum() + - "\nMax: " + getMaximum() + - "\nMedian: " + getMedian() + - "\nQ1: " + getQuartileOne() + - "\nQ3: " + getQuartileThree()); + System.out.println("Explanatory: " + this.explanatory + + ", Response: " + this.response + + ", Frequency: " + this.freq + + ", Relative Frequency: " + this.relFreq); } + // Static method to initialize a sample TwoCategorical object public static TwoCategorical init() { - double[][] frequencies = { - {10.0, 20.0, 30.0}, - {15.0, 25.0, 35.0} - }; + String explanatory = "Explanatory Variable"; + String response = "Response Variable"; + int freq = 50; + double relFreq = 0.5; - TwoCategorical twoCat = new TwoCategorical("Explanatory", "Response", frequencies); - twoCat.printData(); + TwoCategorical twoCategorical = new TwoCategorical(explanatory, response, freq, relFreq); + twoCategorical.printData(); - return twoCat; + return twoCategorical; } public static void main(String[] args) { - TwoCategorical twoCat = init(); + TwoCategorical twoCategorical = init(); } }