From 400be5d5557170cd8d2daa86072550365a7ae3d1 Mon Sep 17 00:00:00 2001 From: spencerng Date: Mon, 4 Feb 2019 23:47:47 -0500 Subject: [PATCH] Add dynamic stat generation methods --- ...sfirst_frc_team25_scouting_client_main.xml | 29 ---- build.gradle | 4 +- .../team25/scouting/client/ui/Controller.java | 40 ++++-- .../frc/team25/scouting/data/Alliance.java | 24 ---- .../team25/scouting/data/AllianceReport.java | 28 ++++ .../team25/scouting/data/BlueAlliance.java | 11 +- .../frc/team25/scouting/data/EventReport.java | 57 ++------ .../scouting/data/PicklistGenerator.java | 20 ++- .../{Sorters.java => SortersFilters.java} | 40 +++++- .../frc/team25/scouting/data/Statistics.java | 98 ++++++------- .../scouting/data/StringProcessing.java | 37 +++++ .../frc/team25/scouting/data/TeamReport.java | 129 +++++++----------- .../scouting/data/models/RankingTree.java | 6 +- .../scouting/data/models/ScoutEntry.java | 6 +- 14 files changed, 269 insertions(+), 260 deletions(-) delete mode 100644 .idea/artifacts/org_usfirst_frc_team25_scouting_client_main.xml delete mode 100644 src/main/java/org/usfirst/frc/team25/scouting/data/Alliance.java create mode 100644 src/main/java/org/usfirst/frc/team25/scouting/data/AllianceReport.java rename src/main/java/org/usfirst/frc/team25/scouting/data/{Sorters.java => SortersFilters.java} (69%) create mode 100644 src/main/java/org/usfirst/frc/team25/scouting/data/StringProcessing.java diff --git a/.idea/artifacts/org_usfirst_frc_team25_scouting_client_main.xml b/.idea/artifacts/org_usfirst_frc_team25_scouting_client_main.xml deleted file mode 100644 index 09ae655..0000000 --- a/.idea/artifacts/org_usfirst_frc_team25_scouting_client_main.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - $PROJECT_DIR$/out/artifacts/org_usfirst_frc_team25_scouting_client_main - - - - - - - - - - - - - \ No newline at end of file diff --git a/build.gradle b/build.gradle index a13995c..e860f76 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ apply plugin: 'application' apply plugin: 'javafx-gradle-plugin' group 'org.usfirst.frc.team25.scouting' -version '1.0-SNAPSHOT' +version '3.0' sourceCompatibility = 1.8 @@ -26,7 +26,7 @@ repositories { //create a single Jar with all dependencies task createJar(type: Jar) { manifest { - attributes 'Implementation-Title': 'Gradle Jar File Example', + attributes 'Implementation-Title': 'Raider Robotix Scouting', 'Implementation-Version': version, 'Main-Class': 'org.usfirst.frc.team25.scouting.client.ui.Main' } diff --git a/src/main/java/org/usfirst/frc/team25/scouting/client/ui/Controller.java b/src/main/java/org/usfirst/frc/team25/scouting/client/ui/Controller.java index f47309a..3cd0f73 100644 --- a/src/main/java/org/usfirst/frc/team25/scouting/client/ui/Controller.java +++ b/src/main/java/org/usfirst/frc/team25/scouting/client/ui/Controller.java @@ -31,7 +31,7 @@ public class Controller { private ArrayList jsonFileList; private String eventName; - private File currentDataDirectory; + private File currentDataDirectory, teamNameList; public void initialize() { @@ -85,12 +85,6 @@ public void initialize() { retrieveEventReport(); - File teamNameList = FileManager.getTeamNameList(currentDataDirectory); - - if (teamNameList != null) { - eventReport.setTeamNameList(teamNameList); - } - if (backupJson.isSelected()) { FileManager.createBackup(jsonFileList, currentDataDirectory); status += "\nBackup JSON files created"; @@ -165,12 +159,16 @@ public void initialize() { int teamNum; try { teamNum = Integer.parseInt(analysisTeamOne.getText()); + if (!eventReport.isTeamPlaying(teamNum)) { + addStatus("Invalid team number for event " + eventName + ". Please try again."); + } else { + addStatus(eventReport.getTeamReport(teamNum).getQuickStatus()); + } } catch (NumberFormatException e) { addStatus("Invalid or missing team number. Please try again."); - return; } - addStatus(eventReport.getTeamReport(teamNum).getQuickStatus()); + } else { int teamOne, teamTwo, teamThree; @@ -178,17 +176,25 @@ public void initialize() { teamOne = Integer.parseInt(analysisTeamOne.getText()); teamTwo = Integer.parseInt(analysisTeamTwo.getText()); teamThree = Integer.parseInt(analysisTeamThree.getText()); + if (!eventReport.isTeamPlaying(teamOne) || !eventReport.isTeamPlaying(teamTwo) || !eventReport.isTeamPlaying(teamThree)) { + addStatus("Invalid team number(s) for event " + eventName + ". Please try again."); + } else { + addStatus(eventReport.getAllianceReport(teamOne, teamTwo, teamThree).getQuickAllianceReport()); + } } catch (NumberFormatException e) { addStatus("Invalid or missing team number(s). Please try again."); - return; + } - addStatus(eventReport.getAllianceReport(teamOne, teamTwo, teamThree).getQuickAllianceReport()); } }); } + /** + * Retrieves JSON data files from the selected data directory and converts them into an EventReport for data + * processing + */ private void retrieveEventReport() { this.jsonFileList = FileManager.getDataFiles(currentDataDirectory); @@ -203,10 +209,22 @@ private void retrieveEventReport() { ArrayList scoutEntries = FileManager.deserializeData(jsonFileList); + this.teamNameList = FileManager.getTeamNameList(currentDataDirectory); this.eventReport = new EventReport(scoutEntries, eventName, currentDataDirectory); + + if (teamNameList != null) { + eventReport.setTeamNameList(teamNameList); + } + + eventReport.processTeamReports(); } + /** + * Adds a status display to the user-facing text box, with a separator between statuses + * + * @param message Text to display to the user + */ private void addStatus(String message) { statusTextBox.setText(message + "\n====================\n" + statusTextBox.getText()); } diff --git a/src/main/java/org/usfirst/frc/team25/scouting/data/Alliance.java b/src/main/java/org/usfirst/frc/team25/scouting/data/Alliance.java deleted file mode 100644 index 27fd3f3..0000000 --- a/src/main/java/org/usfirst/frc/team25/scouting/data/Alliance.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.usfirst.frc.team25.scouting.data; - -/** - * Class for alliance-based calculations and stats - * Not used during the 2018 season - */ -public class Alliance { - - //Probability variables declared here, such as # of baseline crosses or alliance score - - public Alliance(TeamReport teamOne, TeamReport teamTwo, TeamReport teamThree) { - - } - - - public void calculateStats() { - //Calculate declared variables here - } - - public String getQuickAllianceReport() { - //TODO write this - return ""; - } -} diff --git a/src/main/java/org/usfirst/frc/team25/scouting/data/AllianceReport.java b/src/main/java/org/usfirst/frc/team25/scouting/data/AllianceReport.java new file mode 100644 index 0000000..48549f4 --- /dev/null +++ b/src/main/java/org/usfirst/frc/team25/scouting/data/AllianceReport.java @@ -0,0 +1,28 @@ +package org.usfirst.frc.team25.scouting.data; + +/** + * Class for alliance-based calculations and stats + * Not used during the 2018 season + */ +public class AllianceReport { + + private TeamReport[] teamReports; + + //Add more here + private double expectedScore, expectedAutoPoints, expectedClimbPoints, expectedTeleOpPoints, expectedBonusRp; + + public AllianceReport(TeamReport teamOne, TeamReport teamTwo, TeamReport teamThree) { + + this.teamReports = new TeamReport[]{teamOne, teamTwo, teamThree}; + } + + + public void calculateStats() { + //Calculate declared variables here + } + + public String getQuickAllianceReport() { + //TODO write this + return ""; + } +} diff --git a/src/main/java/org/usfirst/frc/team25/scouting/data/BlueAlliance.java b/src/main/java/org/usfirst/frc/team25/scouting/data/BlueAlliance.java index ee9704c..49ce9d4 100644 --- a/src/main/java/org/usfirst/frc/team25/scouting/data/BlueAlliance.java +++ b/src/main/java/org/usfirst/frc/team25/scouting/data/BlueAlliance.java @@ -16,7 +16,7 @@ /** - * Class of static methods used to interface with online data from The Blue Alliance + * Class of static methods used to interface with online data from The Blue AllianceReport * * @author sng */ @@ -28,7 +28,6 @@ public static void initializeApi(Class c) throws IOException { String apiKey = IOUtils.toString(c.getClassLoader().getResourceAsStream("apikey/secret.txt"), "utf-8"); - System.out.println("API key: " + apiKey); TBA = new TBA(apiKey); } @@ -98,7 +97,7 @@ public static boolean exportSimpleTeamList(String eventCode, String fileName) th StringBuilder teamList = new StringBuilder(); ArrayList teams; try { - teams = Sorters.sortByTeamNum(new ArrayList<>(Arrays.asList(TBA.eventRequest.getTeams(eventCode)))); + teams = SortersFilters.sortByTeamNum(new ArrayList<>(Arrays.asList(TBA.eventRequest.getTeams(eventCode)))); } catch (IOException e) { e.printStackTrace(); return false; @@ -131,7 +130,7 @@ private static boolean exportTeamList(String eventCode, String fileName) throws try { for (Team team : - Sorters.sortByTeamNum(new ArrayList<>(Arrays.asList(TBA.eventRequest.getTeams(eventCode))))) { + SortersFilters.sortByTeamNum(new ArrayList<>(Arrays.asList(TBA.eventRequest.getTeams(eventCode))))) { teamList.append(team.getTeamNumber()).append(",").append(team.getNickname()).append(",\n"); } } catch (IOException e) { @@ -159,7 +158,7 @@ private static boolean exportMatchList(String eventCode, String fileName) throws StringBuilder matchList = new StringBuilder(); try { for (Match match : - Sorters.sortByMatchNum(Sorters.filterQualification(new ArrayList<>(Arrays.asList(TBA.eventRequest.getMatches(eventCode)))))) { + SortersFilters.sortByMatchNum(SortersFilters.filterQualification(new ArrayList<>(Arrays.asList(TBA.eventRequest.getMatches(eventCode)))))) { matchList.append(match.getMatchNumber()).append(","); for (int i = 0; i < 2; i++) //iterate through two alliances @@ -209,7 +208,7 @@ public static void downloadTeamEvents(File outputFolder, int year, int teamNum) public static boolean downloadEventMatchData(String eventCode, File outputDirectory) throws IOException { ArrayList matches = - Sorters.sortByMatchNum(Sorters.filterQualification(new ArrayList<>(Arrays.asList(TBA.eventRequest.getMatches(eventCode))))); + SortersFilters.sortByMatchNum(SortersFilters.filterQualification(new ArrayList<>(Arrays.asList(TBA.eventRequest.getMatches(eventCode))))); if (matches.size() == 0) { return false; diff --git a/src/main/java/org/usfirst/frc/team25/scouting/data/EventReport.java b/src/main/java/org/usfirst/frc/team25/scouting/data/EventReport.java index 90b58c9..d801831 100644 --- a/src/main/java/org/usfirst/frc/team25/scouting/data/EventReport.java +++ b/src/main/java/org/usfirst/frc/team25/scouting/data/EventReport.java @@ -30,13 +30,12 @@ public class EventReport { private HashMap teamReports; private String inaccuracyList; private File teamNameList; - private HashMap pickPoints; public EventReport(ArrayList entries, String event, File directory) { teamReports = new HashMap<>(); inaccuracyList = ""; - scoutEntries = entries; + this.scoutEntries = entries; this.event = event; this.directory = directory; @@ -53,6 +52,7 @@ public EventReport(ArrayList entries, String event, File directory) teamReports.get(teamNum).addEntry(entry); } + } public void fixInaccuraciesTBA() { @@ -122,9 +122,9 @@ public void fixInaccuraciesTBA() { "Climbing"); } - if (actualAutoRun != entry.getAuto().isReachHabLine()) { + if (actualAutoRun != entry.getAutonomous().isReachHabLine()) { inaccuracies += "auto run, "; - entry.getAuto().setReachHabLine(actualAutoRun); + entry.getAutonomous().setReachHabLine(actualAutoRun); } @@ -167,17 +167,13 @@ public void processTeamReports() { TeamReport report = teamReports.get(key); if (teamNameList != null) { + report.autoGetTeamName(teamNameList); } - report.calculateStats(); - - - teamReports.put(key, report); + report.findFrequentComments(); } - - } /** @@ -191,7 +187,8 @@ public boolean generateRawSpreadsheet(File outputDirectory) { for (ScoutEntry entry : scoutEntries) { - Object[] dataObjects = {entry.getPreMatch(), entry.getAuto(), entry.getTeleOp(), entry.getPostMatch()}; + Object[] dataObjects = {entry.getPreMatch(), entry.getAutonomous(), entry.getTeleOp(), + entry.getPostMatch()}; for (Object dataObject : dataObjects) { @@ -268,47 +265,19 @@ private String generateSpreadsheetHeader() { if (i == 1 || i == 2) { header.append(shortNames[i] + " - "); } - header.append(convertCamelToSentenceCase(metric.getName()) + ","); + header.append(StringProcessing.convertCamelToSentenceCase(metric.getName()) + ","); } } for (String key : scoutEntries.get(0).getPostMatch().getRobotQuickCommentSelections().keySet()) { - header.append(removeCommas(key)).append(","); + header.append(StringProcessing.removeCommasBreaks(key)).append(","); } return header.toString(); } - /** - * @param camelCaseString A string in lower camelCase - * @return The string in sentence case, with space separations. E.g., "numRocketHatches" becomes "Num rocket - * hatches" - */ - public static String convertCamelToSentenceCase(String camelCaseString) { - //TODO write this - return camelCaseString; - } - - /** - * Helper method to prevent manual comments with commas - * from changing CSV format - * - * @param s String to be processed - * @return String without commas - */ - private String removeCommas(String s) { - StringBuilder newString = new StringBuilder(); - for (int i = 0; i < s.length(); i++) { - if (s.charAt(i) != ',') { - newString.append(s.charAt(i)); - } else { - newString.append("; "); - } - } - return newString.toString(); - } /** * Serializes the ArrayList of all ScoutEntrys into a JSON file @@ -329,7 +298,7 @@ public boolean generateCombineJson(File outputDirectory) { } public void setTeamNameList(File list) { - teamNameList = list; + this.teamNameList = list; } @@ -378,8 +347,8 @@ public TeamReport getTeamReport(int teamNum) { return teamReports.get(teamNum); } - public Alliance getAllianceReport(int teamOne, int teamTwo, int teamThree) { - return new Alliance(teamReports.get(teamOne), teamReports.get(teamTwo), teamReports.get(teamThree)); + public AllianceReport getAllianceReport(int teamOne, int teamTwo, int teamThree) { + return new AllianceReport(teamReports.get(teamOne), teamReports.get(teamTwo), teamReports.get(teamThree)); } } diff --git a/src/main/java/org/usfirst/frc/team25/scouting/data/PicklistGenerator.java b/src/main/java/org/usfirst/frc/team25/scouting/data/PicklistGenerator.java index cb509a3..86c9c5a 100644 --- a/src/main/java/org/usfirst/frc/team25/scouting/data/PicklistGenerator.java +++ b/src/main/java/org/usfirst/frc/team25/scouting/data/PicklistGenerator.java @@ -487,7 +487,7 @@ public void generateComparePointList() { * @return Formatted list, with tree levels not clamped down */ private String hashMapToStringList(HashMap teamPointsMap) { - teamPointsMap = Sorters.sortByComparator(teamPointsMap, false); + teamPointsMap = SortersFilters.sortByComparator(teamPointsMap, false); StringBuilder result = new StringBuilder(); int rank = 1; for (Map.Entry entry : teamPointsMap.entrySet()) { @@ -529,4 +529,22 @@ public void generatePickPointList() { } + /** + * Generates a list based on a calculated ability to be a good first pick robot + * Calculated ability derived from collected metrics (e.g. climbs, cargo, hatches) + * TODO write this + */ + public void generateCalculatedFirstPicklist() { + + } + + /** + * Generates a list based on a calculated ability to be a good first pick robot + * Calculated ability derived from collected metrics (e.g. climbs, cargo, hatches) + * TODO write this + */ + public void generateCalculatedSecondPicklist() { + + } + } diff --git a/src/main/java/org/usfirst/frc/team25/scouting/data/Sorters.java b/src/main/java/org/usfirst/frc/team25/scouting/data/SortersFilters.java similarity index 69% rename from src/main/java/org/usfirst/frc/team25/scouting/data/Sorters.java rename to src/main/java/org/usfirst/frc/team25/scouting/data/SortersFilters.java index 43e24da..8704fa2 100644 --- a/src/main/java/org/usfirst/frc/team25/scouting/data/Sorters.java +++ b/src/main/java/org/usfirst/frc/team25/scouting/data/SortersFilters.java @@ -4,7 +4,9 @@ import com.thebluealliance.api.v3.models.SimpleMatch; import com.thebluealliance.api.v3.models.SimpleTeam; import com.thebluealliance.api.v3.models.Team; +import org.usfirst.frc.team25.scouting.data.models.ScoutEntry; +import java.lang.reflect.Method; import java.util.*; /** @@ -12,7 +14,7 @@ * * @author sng */ -public class Sorters { +public class SortersFilters { /** * Method implementing a Comparator to sort Matches @@ -86,4 +88,40 @@ public static HashMap sortByComparator(HashMap filterDataObject(ArrayList scoutEntries, Class objectClass) { + ArrayList filteredList = new ArrayList<>(); + + Method correctGetter = null; + + for (Method m : ScoutEntry.class.getMethods()) { + + if (m.getName().substring(3).toLowerCase().equals(objectClass.getSimpleName().toLowerCase()) && m.getParameterTypes().length == 0) { + correctGetter = m; + break; + } + } + + + try { + if (correctGetter != null) { + + for (ScoutEntry entry : scoutEntries) { + filteredList.add(correctGetter.invoke(entry)); + + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + + return filteredList; + + } } diff --git a/src/main/java/org/usfirst/frc/team25/scouting/data/Statistics.java b/src/main/java/org/usfirst/frc/team25/scouting/data/Statistics.java index 1bb95c6..2183fc0 100644 --- a/src/main/java/org/usfirst/frc/team25/scouting/data/Statistics.java +++ b/src/main/java/org/usfirst/frc/team25/scouting/data/Statistics.java @@ -1,5 +1,6 @@ package org.usfirst.frc.team25.scouting.data; +import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; @@ -13,7 +14,7 @@ public static double percentAtLeastOne(double p1, double p2, double p3) { return 100 - percentNone(p1, p2, p3); } - private static double percentNone(double p1, double p2, double p3) { + public static double percentNone(double p1, double p2, double p3) { return 100 * (1 - p1) * (1 - p2) * (1 - p3); } @@ -21,7 +22,7 @@ public static double percentAtLeastTwo(double p1, double p2, double p3) { return 100 - percentNone(p1, p2, p3) - percentExactlyOne(p1, p2, p3); } - private static double percentExactlyOne(double p1, double p2, double p3) { + public static double percentExactlyOne(double p1, double p2, double p3) { return 100 * (p1 * (1 - p2) * (1 - p3) + p2 * (1 - p1) * (1 - p3) + p3 * (1 - p1) * (1 - p3)); } @@ -40,13 +41,6 @@ public static double round(double value, int places) { return bd.doubleValue(); } - public static ArrayList toDoubleArrayList(ArrayList arr) { - ArrayList toReturn = new ArrayList<>(); - for (int i : arr) { - toReturn.add((double) i); - } - return toReturn; - } /** * Calculates the uncorrected standard deviation of an event @@ -54,14 +48,22 @@ public static ArrayList toDoubleArrayList(ArrayList arr) { * @param dataset Array with data points * @return Uncorrected standard deviation */ - - public static double popStandardDeviation(ArrayList dataset) { - double average = average(dataset); + public static double standardDeviation(ArrayList dataset, String metricName) { + double average = average(dataset, metricName); double sumSquareDev = 0; - for (double i : dataset) { - sumSquareDev += Math.pow(i - average, 2); + + try { + Method correctMethod = getCorrectMethod((Class) dataset.get(0).getClass(), metricName); + if (correctMethod != null) { + for (Object dataObject : dataset) { + sumSquareDev += Math.pow((double) correctMethod.invoke(dataObject) - average, 2); + } + } + } catch (Exception e) { + e.printStackTrace(); } - return Math.sqrt(sumSquareDev / dataset.size()); + + return Math.sqrt(sumSquareDev / (dataset.size() - 1)); } /** @@ -70,61 +72,49 @@ public static double popStandardDeviation(ArrayList dataset) { * @param dataset Array of numbers * @return Average of entries in array, 0 if dataset.size() is 0 */ - private static double average(ArrayList dataset) { + public static double average(ArrayList dataset, String metricName) { if (dataset.size() == 0) { return 0; } - return sum(dataset) / dataset.size(); + return sum(dataset, metricName) / dataset.size(); } - - - - /* Calculates the success rate of an event in all matches - - @param success Array with number of successes - * @param total Array with number of attempts - * @return Success percentage of event - */ - /*public static double successPercentage(int[] success, int[] total){ - return (((double)sum(success))/sum(total))*100; - } - - /** Calculates the corrected standard deviation of an event - * - * @param dataset Array with data points - * @return Corrected standard deviation (length-1) - */ - /*public static double standardDeviation(int[] dataset){ - double average = average(dataset); - double sumSquareDev = 0; - for(int i : dataset) - sumSquareDev+= Math.pow(i-average, 2); - return Math.sqrt(sumSquareDev/(dataset.length-1)); - } - - public static double standardDeviation(double[] dataset){ - double average = average(dataset); - double sumSquareDev = 0; - for(double i : dataset) - sumSquareDev+= Math.pow(i-average, 2); - return Math.sqrt(sumSquareDev/(dataset.length-1)); - }*/ - /** * Calculates the sum of an array of numbers * * @param dataset Array of numbers to be summed * @return Sum of the elements in dataset */ - private static double sum(ArrayList dataset) { + public static double sum(ArrayList dataset, String metricName) { double sum = 0; - for (double i : dataset) { - sum += i; + + try { + Method correctMethod = getCorrectMethod(dataset.get(0).getClass(), metricName); + if (correctMethod != null) { + for (Object dataObject : dataset) { + sum += 1.0 * (Integer) correctMethod.invoke(dataObject); + } + } + } catch (Exception e) { + e.printStackTrace(); } + return sum; } + private static Method getCorrectMethod(Class dataObjectClass, String metricName) { + Method correctGetter = null; + + for (Method m : dataObjectClass.getMethods()) { + if (m.getName().substring(3).toLowerCase().equals(metricName.toLowerCase()) && m.getParameterTypes().length == 0) { + correctGetter = m; + break; + } + } + + return correctGetter; + } + } diff --git a/src/main/java/org/usfirst/frc/team25/scouting/data/StringProcessing.java b/src/main/java/org/usfirst/frc/team25/scouting/data/StringProcessing.java new file mode 100644 index 0000000..3926748 --- /dev/null +++ b/src/main/java/org/usfirst/frc/team25/scouting/data/StringProcessing.java @@ -0,0 +1,37 @@ +package org.usfirst.frc.team25.scouting.data; + +public class StringProcessing { + + /** + * Helper method to prevent manual comments with commas or line breaks + * from changing CSV format + * + * @param s String to be processed + * @return String without commas + */ + public static String removeCommasBreaks(String s) { + StringBuilder newString = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) != ',' && s.charAt(i) != '\n') { + newString.append(s.charAt(i)); + } else { + newString.append("; "); + } + } + return newString.toString(); + } + + + /** + * @param camelCaseString A string in lower camelCase + * @return The string in sentence case, with space separations. E.g., "numRocketHatches" becomes "Num rocket + * hatches" + */ + public static String convertCamelToSentenceCase(String camelCaseString) { + //TODO write this + + return camelCaseString; + } + + +} diff --git a/src/main/java/org/usfirst/frc/team25/scouting/data/TeamReport.java b/src/main/java/org/usfirst/frc/team25/scouting/data/TeamReport.java index 155bb78..aeda0b9 100644 --- a/src/main/java/org/usfirst/frc/team25/scouting/data/TeamReport.java +++ b/src/main/java/org/usfirst/frc/team25/scouting/data/TeamReport.java @@ -1,5 +1,6 @@ package org.usfirst.frc.team25.scouting.data; +import org.usfirst.frc.team25.scouting.data.models.Autonomous; import org.usfirst.frc.team25.scouting.data.models.ScoutEntry; import java.io.File; @@ -14,22 +15,44 @@ */ public class TeamReport { - final String autoGearPegLoc = ""; - final transient String frequentPilotCommentStr = ""; - final ArrayList teleOpCubes = new ArrayList<>(); private final transient ArrayList entries; - private final int teamNum; //transient because it's the key of the HashMap in EventReport - private final ArrayList totalSwitchCubes = new ArrayList<>(); - private final ArrayList totalScaleCubes = new ArrayList<>(); - private final ArrayList totalCubes = new ArrayList<>(); - private final ArrayList totalDroppedCubes = new ArrayList<>(); - private final ArrayList firstCubeTimes = new ArrayList<>(); - private String teamName; - private transient String frequentRobotCommentStr = ""; + private final int teamNum; + private String teamName, frequentRobotCommentStr, allComments; public TeamReport(int teamNum) { this.teamNum = teamNum; entries = new ArrayList<>(); + + } + + /** + * Generates an easily-readable report with relevant stats on an team's capability + * + * @return A formatted string with relevant aggregate team stats + */ + public String getQuickStatus() { + //TODO write this + String statusString = "Team " + getTeamNum(); + + if (!getTeamName().isEmpty()) { + statusString += " - " + getTeamName(); + } + + statusString += "\n\nAutonomous:\n"; + + + ArrayList autoList = SortersFilters.filterDataObject(entries, Autonomous.class); + + statusString += "Avg. cargo ship cargo: " + Statistics.round(Statistics.average(autoList, "cargoShipCargo"), 2); + + statusString += "\n\nTele-Op:\n"; + + statusString += "\n\nEndgame:\n"; + + statusString += "\n\nOverall:\n"; + + + return statusString; } public String getTeamName() { @@ -46,23 +69,19 @@ public void autoGetTeamName(File dataLocation) { String[] values = data.split(",\n"); for (String value : values) { + if (value.split(",")[0].equals(Integer.toString(teamNum))) { teamName = value.split(",")[1]; - return; //Terminates the method + return; } } } - public void calculateStats() { - - calculateTotals(); - - //Calculate percentages, averages, standard deviations here + public void findFrequentComments() { HashMap commentFrequencies = new HashMap<>(); - for (String key : entries.get(0).getPostMatch().getRobotQuickCommentSelections().keySet()) { commentFrequencies.put(key, 0); for (ScoutEntry entry : entries) { @@ -75,95 +94,41 @@ public void calculateStats() { ArrayList frequentRobotComment = new ArrayList<>(); for (String key : commentFrequencies.keySet()) { + + // Feel free to change this ratio if (commentFrequencies.get(key) >= entries.size() / 4.0) { frequentRobotComment.add(key); } } - - boolean doNotPick = frequentRobotComment.contains("Do not pick (explain)"); - boolean isActive = frequentRobotComment.contains("Active gear mech."); - boolean hasIntake = frequentRobotComment.contains("Fuel intake"); - //Instance variables below should not be serialized but may be accessed by EventReports for analysis - boolean hasPickup = frequentRobotComment.contains("Gear pickup"); - - frequentRobotComment.remove("Do not pick (explain)"); - frequentRobotComment.remove("Active gear mech."); - frequentRobotComment.remove("Fuel intake"); - frequentRobotComment.remove("Gear pickup"); - - commentFrequencies = new HashMap<>(); - - for (String comment : frequentRobotComment) { - frequentRobotCommentStr += removeCommas(comment) + ';'; + frequentRobotCommentStr += StringProcessing.removeCommasBreaks(comment) + ';'; } - computeRankingMetrics(); - - String allComments = ""; + allComments = ""; for (ScoutEntry entry : entries) { if (!entry.getPostMatch().getRobotComment().equals("")) { allComments += entry.getPostMatch().getRobotComment() + "; "; } - /*if(!autoGearPegLoc.contains(entry.getAuto().getGearPeg())) - autoGearPegLoc+=entry.getAuto().getGearPeg()+"; ";*/ - } - - - } - - private void calculateTotals() { - - //Calculate total variables declared above - //i.e. total cubes delivered in teleop - } - private String removeCommas(String s) { - StringBuilder newString = new StringBuilder(); - for (int i = 0; i < s.length(); i++) { - if (s.charAt(i) != ',') { - newString.append(s.charAt(i)); - } else { - newString.append("; "); - } } - return newString.toString(); - } - private void computeRankingMetrics() { - double autoAbility = 0; - double teleOpAbility = 0; - double driveTeamAbility = 0; - double robotQualities = 0; - double firstPickAbility = 0; - double secondPickAbility = 0; - } - public int getTeamNum() { - return teamNum; } public void addEntry(ScoutEntry entry) { - entry.getPostMatch().setRobotComment(removeCommasAndBreaks(entry.getPostMatch().getRobotComment())); + entry.getPostMatch().setRobotComment(StringProcessing.removeCommasBreaks(entry.getPostMatch().getRobotComment())); entries.add(entry); } - private String removeCommasAndBreaks(String s) { - StringBuilder newString = new StringBuilder(); - for (int i = 0; i < s.length(); i++) { - if (s.charAt(i) != ',' && s.charAt(i) != '\n') { - newString.append(s.charAt(i)); - } else { - newString.append("; "); - } - } - return newString.toString(); + public ArrayList getEntries() { + return this.entries; } - public String getQuickStatus() { - return ""; + + public int getTeamNum() { + return teamNum; } diff --git a/src/main/java/org/usfirst/frc/team25/scouting/data/models/RankingTree.java b/src/main/java/org/usfirst/frc/team25/scouting/data/models/RankingTree.java index 6d1fda1..4438c34 100644 --- a/src/main/java/org/usfirst/frc/team25/scouting/data/models/RankingTree.java +++ b/src/main/java/org/usfirst/frc/team25/scouting/data/models/RankingTree.java @@ -1,6 +1,6 @@ package org.usfirst.frc.team25.scouting.data.models; -import org.usfirst.frc.team25.scouting.data.Sorters; +import org.usfirst.frc.team25.scouting.data.SortersFilters; import java.util.ArrayList; import java.util.HashMap; @@ -154,7 +154,7 @@ public void addNodeBelow(int newNodeNum, int oldNode) throws Exception { * a node on each line, followed by a comma and its level */ public String toString() { - ranks = Sorters.sortByComparator(ranks, false); + ranks = SortersFilters.sortByComparator(ranks, false); StringBuilder result = new StringBuilder(); for (Map.Entry entry : ranks.entrySet()) { try { @@ -174,7 +174,7 @@ public String toString() { */ public ArrayList toArrayList() { ArrayList result = new ArrayList<>(); - ranks = Sorters.sortByComparator(ranks, false); + ranks = SortersFilters.sortByComparator(ranks, false); for (Map.Entry entry : ranks.entrySet()) { try { result.add(entry.getKey()); diff --git a/src/main/java/org/usfirst/frc/team25/scouting/data/models/ScoutEntry.java b/src/main/java/org/usfirst/frc/team25/scouting/data/models/ScoutEntry.java index 5b7ab7f..2281ae1 100644 --- a/src/main/java/org/usfirst/frc/team25/scouting/data/models/ScoutEntry.java +++ b/src/main/java/org/usfirst/frc/team25/scouting/data/models/ScoutEntry.java @@ -6,7 +6,7 @@ public class ScoutEntry implements Serializable { private PreMatch preMatch; - private Autonomous auto; + private Autonomous autonomous; private TeleOp teleOp; private PostMatch postMatch; private transient int sandstormPoints, teleOpPoints, climbPoints, calculatedPointContribution, autoHatches, @@ -21,8 +21,8 @@ public PreMatch getPreMatch() { return preMatch; } - public Autonomous getAuto() { - return auto; + public Autonomous getAutonomous() { + return autonomous; } public TeleOp getTeleOp() {