diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml index 1033d156..6e7d638b 100644 --- a/.idea/deploymentTargetSelector.xml +++ b/.idea/deploymentTargetSelector.xml @@ -16,6 +16,9 @@ + + \ No newline at end of file diff --git a/app/src/main/assets/input_data/Comments.csv b/app/src/main/assets/input_data/Comments.csv index 29160f30..9c4ef899 100644 --- a/app/src/main/assets/input_data/Comments.csv +++ b/app/src/main/assets/input_data/Comments.csv @@ -2,7 +2,7 @@ Id,isActive,Description 1,TRUE,Robot climbed noticeably faster than others 2,TRUE,Robot climbed noticeably slower than others 3,TRUE,Climb didn't count -4,TRUE,Evaded defense well +4,FALSE,Evaded defense well 5,TRUE,Ineffective defense 6,TRUE,Played really good defense 7,TRUE,Robot didn't contribute much (no auto - low scoring - no defense) diff --git a/app/src/main/java/com/team3663/scouting_app/activities/PostMatch.java b/app/src/main/java/com/team3663/scouting_app/activities/PostMatch.java index 9b252bb3..23e5d08a 100644 --- a/app/src/main/java/com/team3663/scouting_app/activities/PostMatch.java +++ b/app/src/main/java/com/team3663/scouting_app/activities/PostMatch.java @@ -3,6 +3,12 @@ import android.annotation.SuppressLint; import android.content.Intent; import android.os.Bundle; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AlertDialog; @@ -20,6 +26,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Objects; public class PostMatch extends AppCompatActivity { // ============================================================================================= @@ -30,6 +37,9 @@ public class PostMatch extends AppCompatActivity { //Creating an array list for the Comments ArrayList CommentList = new ArrayList<>(); ArrayList CommentArray = Globals.CommentList.getDescriptionList(); + ArrayList Accuracy = Globals.AccuracyTypeList.getDescriptionList(); + ArrayList ClimbLevel = Globals.ClimbLevelList.getDescriptionList(); + ArrayList ClimbPosition = Globals.ClimbPositionList.getDescriptionList(); @SuppressLint({"SetTextI18n", "MissingInflatedId"}) @Override @@ -45,8 +55,12 @@ protected void onCreate(Bundle in_savedInstanceState) { }); // Initialize activity components - initDidLeave(); initComments(); + initAccuracy(); + initClimbLevel(); + initClimbPosition(); + initStealFuel(); + initAffectedByDefense(); initReset(); initSubmit(); initStats(); @@ -134,20 +148,170 @@ private void initComments() { } // ============================================================================================= - // Function: initDidLeave - // Description: Initialize the Did Leave field + // Function: initAccuracy + // Description: Initialize the Accuracy field // Parameters: void // Output: void // ============================================================================================= - private void initDidLeave() { - // Default values - postMatchBinding.checkboxDidLeave.setChecked(true); + private void initAccuracy() { + ArrayAdapter adp_Accuracy = new ArrayAdapter<>(this, R.layout.cpr_spinner, Accuracy); + adp_Accuracy.setDropDownViewResource(R.layout.cpr_spinner_item); + postMatchBinding.spinnerAccuracy.setAdapter(adp_Accuracy); + + // Set starting selection + int start_Pos = 0; + for (int i = 0; i < Accuracy.size(); i++) { + if (Accuracy.get(i).equals(Globals.AccuracyTypeList.getAccuracyDescription(Globals.CurrentAccuracy))) { + start_Pos = i; + break; + } + } + postMatchBinding.spinnerAccuracy.setSelection(start_Pos); + + postMatchBinding.spinnerAccuracy.setOnItemSelectedListener( + new AdapterView.OnItemSelectedListener() { + + @Override + public void onItemSelected(AdapterView adapterView, View view, int i, long l) { + + int newAccuracy = Globals.AccuracyTypeList.getAccuracyValue(postMatchBinding.spinnerAccuracy.getSelectedItem().toString()); + + if (!Objects.equals(newAccuracy, Globals.CurrentAccuracy)) { + Globals.CurrentAccuracy = newAccuracy; + } + } + + @Override + public void onNothingSelected(AdapterView adapterView) { + Globals.CurrentAccuracy = Constants.PostMatch.ACCURACY_NOT_SELECTED; + } + }); + } + + // ============================================================================================= + // Function: initClimbLevel + // Description: Initialize the Climb Level field + // Parameters: void + // Output: void + // ============================================================================================= + private void initClimbLevel() { + ArrayAdapter adp_ClimbLevel = new ArrayAdapter<>(this, R.layout.cpr_spinner, ClimbLevel); + adp_ClimbLevel.setDropDownViewResource(R.layout.cpr_spinner_item); + postMatchBinding.spinnerClimbLevel.setAdapter(adp_ClimbLevel); + + // Set starting selection + int start_Pos = 0; + for (int i = 0; i < ClimbLevel.size(); i++) { + if (ClimbLevel.get(i).equals(Globals.ClimbLevelList.getClimbLevelDescription(Globals.CurrentClimbLevel))) { + start_Pos = i; + break; + } + } + postMatchBinding.spinnerClimbLevel.setSelection(start_Pos); + + postMatchBinding.spinnerClimbLevel.setOnItemSelectedListener( + new AdapterView.OnItemSelectedListener() { + + @Override + public void onItemSelected(AdapterView adapterView, View view, int i, long l) { + + String newClimbLevel = Globals.ClimbLevelList.getClimbLevelValue(postMatchBinding.spinnerClimbLevel.getSelectedItem().toString()); + + if (!Objects.equals(newClimbLevel, Globals.CurrentClimbLevel)) { + Globals.CurrentClimbLevel = newClimbLevel; + } + } + + @Override + public void onNothingSelected(AdapterView adapterView) { + Globals.CurrentClimbLevel = "-1"; + } + }); + } + + + // ============================================================================================= + // Function: initClimbPosition + // Description: Initialize the field + // Parameters: void + // Output: void + // ============================================================================================= + private void initClimbPosition() { + ArrayAdapter adp_ClimbPosition = new ArrayAdapter<>(this, R.layout.cpr_spinner, ClimbPosition); + adp_ClimbPosition.setDropDownViewResource(R.layout.cpr_spinner_item); + postMatchBinding.spinnerClimbPosition.setAdapter(adp_ClimbPosition); + + // Set starting selection + int start_Pos = 0; + for (int i = 0; i < ClimbPosition.size(); i++) { + if (ClimbPosition.get(i).equals(Globals.ClimbPositionList.getClimbPositionDescription(Globals.CurrentClimbPosition))) { + start_Pos = i; + break; + } + } + postMatchBinding.spinnerClimbPosition.setSelection(start_Pos); + + // Set up a listener to handle any changes to the dropdown + postMatchBinding.spinnerClimbPosition.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView adapterView, View view, int i, long l) { + + String newClimbPosition = Globals.ClimbPositionList.getClimbPositionValue(postMatchBinding.spinnerClimbPosition.getSelectedItem().toString()); + + if (!Objects.equals(newClimbPosition, Globals.CurrentClimbPosition)) { + Globals.CurrentClimbPosition = newClimbPosition; + } + } + + @Override + public void onNothingSelected(AdapterView adapterView) { + Globals.CurrentClimbPosition = "-1"; + } + }); + } + + // ============================================================================================= + // Function: initStealFuel + // Description: Initialize the Steal Fuel field + // Parameters: void + // Output: void + // ============================================================================================= + private void initStealFuel() { + RadioGroup stealFuelGroup = findViewById(R.id.radiogroup_StealFuel); + + stealFuelGroup.setOnCheckedChangeListener((group, checkedId) -> { + if (checkedId == View.NO_ID) { + Globals.stealFuelValue = "-1"; + } else if (checkedId == R.id.radiobutton_StealFuelYes) { + Globals.stealFuelValue = "yes"; + } else if (checkedId == R.id.radiobutton_StealFuelNo) { + Globals.stealFuelValue = "no"; + } + }); + } - // Since we are putting the checkbox on the RIGHT side of the text, the checkbox doesn't honor padding. - // So we need to use 7 spaces, but you can't when using a string resource (it ignores the trailing spaces) - // So add it in now. - String new_text = postMatchBinding.checkboxDidLeave.getText() + Globals.CheckBoxTextPadding; - postMatchBinding.checkboxDidLeave.setText(new_text); + // ============================================================================================= + // Function: initAffectedByDefense + // Description: Initialize the field + // Parameters: void + // Output: void + // ============================================================================================= + private void initAffectedByDefense() { + RadioGroup affectByDefenseGroup = findViewById(R.id.radiogroup_AffectedByDefense); + + affectByDefenseGroup.setOnCheckedChangeListener((group, checkedId) -> { + if (checkedId == View.NO_ID) { + Globals.affectedByDefenseValue = "-1"; + } else if (checkedId == R.id.radiobutton_NoDefense) { + Globals.affectedByDefenseValue = "none"; + } else if (checkedId == R.id.radiobutton_Low) { + Globals.affectedByDefenseValue = "low"; + } else if (checkedId == R.id.radiobutton_Medium) { + Globals.affectedByDefenseValue = "medium"; + } else if (checkedId == R.id.radiobutton_High) { + Globals.affectedByDefenseValue = "high"; + } + }); } // ============================================================================================= @@ -188,7 +352,6 @@ private void initSubmit() { startActivity(GoToPreMatch); } else { // Log all of the data from this page - Globals.EventLogger.LogData(Constants.Logger.LOGKEY_DID_LEAVE_START, String.valueOf(postMatchBinding.checkboxDidLeave.isChecked())); StringBuilder comment_sep_ID = new StringBuilder(); for (Integer comment_dropID : CommentList) { String comment = CommentArray.get(comment_dropID); @@ -197,6 +360,30 @@ private void initSubmit() { if (comment_sep_ID.length() > 0) comment_sep_ID = new StringBuilder(comment_sep_ID.substring(1)); Globals.EventLogger.LogData(Constants.Logger.LOGKEY_COMMENTS, comment_sep_ID.toString()); + // If any spinner data is left blank + if ((Constants.PostMatch.ACCURACY_NOT_SELECTED == Globals.CurrentAccuracy) || + Constants.PostMatch.CLIMB_LEVEL_NOT_SELECTED.equals(Globals.CurrentClimbLevel) || + Constants.PostMatch.CLIMB_POSITION_NOT_SELECTED.equals(Globals.CurrentClimbPosition)) { + + Toast.makeText(this, R.string.post_missing_data, Toast.LENGTH_SHORT).show(); + return; + } else { + // Log all the spinner data + Globals.EventLogger.LogData(Constants.Logger.LOGKEY_ACCURACY, String.valueOf(Globals.CurrentAccuracy)); + Globals.EventLogger.LogData(Constants.Logger.LOGKEY_CLIMB_LEVEL, String.valueOf(Globals.CurrentClimbLevel)); + Globals.EventLogger.LogData(Constants.Logger.LOGKEY_CLIMB_POSITION, String.valueOf(Globals.CurrentClimbPosition)); + } + + // If any radio button is left blank + if (Objects.equals(Globals.stealFuelValue, "-1") || Objects.equals(Globals.affectedByDefenseValue, "-1")) { + Toast.makeText(this, R.string.post_missing_data, Toast.LENGTH_SHORT).show(); + return; + } else { + // Log all the spinner data + Globals.EventLogger.LogData(Constants.Logger.LOGKEY_STEALFUEL,String.valueOf(Globals.stealFuelValue)); + Globals.EventLogger.LogData(Constants.Logger.LOGKEY_AFFECTED_BY_DEFENSE, String.valueOf(Globals.affectedByDefenseValue)); + } + Intent GoToSubmitData = new Intent(PostMatch.this, SubmitData.class); startActivity(GoToSubmitData); } @@ -211,6 +398,7 @@ private void initSubmit() { .startsWith(Constants.Achievements.EVENT_TYPE_FINAL)) Achievements.data_FinalType++; finish(); + }); } @@ -221,19 +409,9 @@ private void initSubmit() { // Output: void // ============================================================================================= private void initStats() { - StringBuilder statsCoral = new StringBuilder(); - StringBuilder statsAlgae = new StringBuilder(); - - for (int i = 4; i >0; --i) { - statsCoral.append("Placed L").append(i).append(": ").append(Achievements.data_match_CoralLevel[i]).append("\n"); - } - statsCoral.append("Dropped: ").append(Achievements.data_match_CoralDropped); - - statsAlgae.append("Net: ").append(Achievements.data_match_AlgaeInNet).append("\n") - .append("Processor: ").append(Achievements.data_match_AlgaeInProcessor); + String statsFuel = "Fuel: " + Achievements.data_match_FuelShot; - postMatchBinding.textStatsCoral.setText(statsCoral.toString()); - postMatchBinding.textStatsAlgae.setText(statsAlgae.toString()); + postMatchBinding.textStatsFuel.setText(statsFuel); //use achievement data } } \ No newline at end of file diff --git a/app/src/main/java/com/team3663/scouting_app/activities/SubmitData.java b/app/src/main/java/com/team3663/scouting_app/activities/SubmitData.java index 83d3fc2a..1bc625a0 100644 --- a/app/src/main/java/com/team3663/scouting_app/activities/SubmitData.java +++ b/app/src/main/java/com/team3663/scouting_app/activities/SubmitData.java @@ -390,6 +390,11 @@ private void initNext() { submitDataBinding.butNext.setOnClickListener(view -> { // Reset pre-Match settings for next time Globals.numStartingGamePiece = Constants.PreMatch.STARTING_GAME_PIECES; + Globals.CurrentAccuracy = Constants.PostMatch.ACCURACY_NOT_SELECTED; + Globals.CurrentClimbLevel = Constants.PostMatch.CLIMB_LEVEL_NOT_SELECTED; + Globals.CurrentClimbPosition = Constants.PostMatch.CLIMB_POSITION_NOT_SELECTED; + Globals.stealFuelValue = Constants.PostMatch.STEAL_FUEL_NOT_SELECTED; + Globals.affectedByDefenseValue = Constants.PostMatch.AFFECTED_BY_DEFENSE_NOT_SELECTED; Globals.isPractice = false; // Increases the team number so that it auto fills for the next match correctly diff --git a/app/src/main/java/com/team3663/scouting_app/config/Constants.java b/app/src/main/java/com/team3663/scouting_app/config/Constants.java index ab3f459d..ddeae6dc 100644 --- a/app/src/main/java/com/team3663/scouting_app/config/Constants.java +++ b/app/src/main/java/com/team3663/scouting_app/config/Constants.java @@ -9,7 +9,7 @@ public class Constants { public static class Logger { // Logger Keys - Data File is written in order of the FILE_HEADER array - public static final String[] LOGKEY_DATA_FILE_HEADER = new String[]{"Shadow", "Team", "TeamScouting", "Scouter", "DidPlay", "StartGamePiece", "DidLeaveStart", "Comments", "Achievements", "StartOffset", "Start"}; + public static final String[] LOGKEY_DATA_FILE_HEADER = new String[]{"Shadow", "Team", "TeamScouting", "Scouter", "DidPlay", "StartGamePiece", "DidLeaveStart", "Accuracy", "ClimbLevel", "ClimbPosition", "Comments", "Achievements", "StartOffset", "Start"}; public static final String LOGKEY_SHADOW_MODE = "Shadow"; public static final String LOGKEY_ACHIEVEMENT = "Achievements"; public static final String LOGKEY_MATCH_TYPE = "MatchType"; @@ -19,6 +19,11 @@ public static class Logger { public static final String LOGKEY_SCOUTER = "Scouter"; public static final String LOGKEY_DID_LEAVE_START = "DidLeaveStart"; public static final String LOGKEY_START_WITH_GAME_PIECE = "StartGamePiece"; + public static final String LOGKEY_ACCURACY = "Accuracy"; + public static final String LOGKEY_CLIMB_LEVEL = "ClimbLevel"; + public static final String LOGKEY_CLIMB_POSITION = "ClimbPosition"; + public static final String LOGKEY_STEALFUEL = "StealFuel"; + public static final String LOGKEY_AFFECTED_BY_DEFENSE = "AffectedByDefense"; public static final String LOGKEY_COMMENTS = "Comments"; public static final String LOGKEY_START_TIME_OFFSET = "StartOffset"; public static final String LOGKEY_START_TIME = "Start"; @@ -62,6 +67,14 @@ public static class Match { public static final int SEEKBAR_MAX = 60; } + public static class PostMatch { + public static final int ACCURACY_NOT_SELECTED = -1; + public static final String CLIMB_LEVEL_NOT_SELECTED = "-1"; + public static final String CLIMB_POSITION_NOT_SELECTED = "-1"; + public static final String STEAL_FUEL_NOT_SELECTED = "-1"; + public static final String AFFECTED_BY_DEFENSE_NOT_SELECTED = "-1"; + } + public static class Data { public static final String PRIVATE_BASE_DIR = "input_data"; public static final String PUBLIC_BASE_DIR = "CPR-Scouting"; diff --git a/app/src/main/java/com/team3663/scouting_app/config/Globals.java b/app/src/main/java/com/team3663/scouting_app/config/Globals.java index 6aa40d7b..1cf5a11b 100644 --- a/app/src/main/java/com/team3663/scouting_app/config/Globals.java +++ b/app/src/main/java/com/team3663/scouting_app/config/Globals.java @@ -5,6 +5,9 @@ import androidx.documentfile.provider.DocumentFile; +import com.team3663.scouting_app.data.Accuracy; +import com.team3663.scouting_app.data.ClimbLevel; +import com.team3663.scouting_app.data.ClimbPosition; import com.team3663.scouting_app.data.MatchTypes; import com.team3663.scouting_app.utility.Logger; import com.team3663.scouting_app.data.Colors; @@ -22,6 +25,12 @@ public class Globals { public static Competitions CompetitionList = new Competitions(); public static MatchTypes MatchTypeList = new MatchTypes(); public static Matches MatchList = new Matches(); + public static Accuracy AccuracyTypeList = new Accuracy(); + public static int CurrentAccuracy = Constants.PostMatch.ACCURACY_NOT_SELECTED; + public static ClimbLevel ClimbLevelList = new ClimbLevel(); + public static String CurrentClimbLevel = Constants.PostMatch.CLIMB_LEVEL_NOT_SELECTED; + public static ClimbPosition ClimbPositionList = new ClimbPosition(); + public static String CurrentClimbPosition = Constants.PostMatch.CLIMB_POSITION_NOT_SELECTED; public static Devices DeviceList = new Devices(); public static Events EventList = new Events(); public static Comments CommentList = new Comments(); @@ -55,6 +64,8 @@ public class Globals { public static boolean isPractice = false; public static int numStartingGamePiece = Constants.PreMatch.STARTING_GAME_PIECES; + public static String stealFuelValue = Constants.PostMatch.STEAL_FUEL_NOT_SELECTED; + public static String affectedByDefenseValue = Constants.PostMatch.AFFECTED_BY_DEFENSE_NOT_SELECTED; public static boolean isShadowMode = false; public static DocumentFile base_df = null; diff --git a/app/src/main/java/com/team3663/scouting_app/data/Accuracy.java b/app/src/main/java/com/team3663/scouting_app/data/Accuracy.java new file mode 100644 index 00000000..548385be --- /dev/null +++ b/app/src/main/java/com/team3663/scouting_app/data/Accuracy.java @@ -0,0 +1,84 @@ +package com.team3663.scouting_app.data; + +import com.team3663.scouting_app.config.Constants; + +import java.util.ArrayList; +import java.util.Objects; + +// ============================================================================================= +// Class: Accuracy +// Description: Defines a structure/class to hold the information for all Accuracy values +// ============================================================================================= + +public class Accuracy { + + private final ArrayList Accuracy_list; + + public Accuracy() { + Accuracy_list = new ArrayList<>(); + + // Add accuracy values into the list + addAccuracyRow(-1,""); + addClimbLevelRow("None", "None"); + addClimbLevelRow("L1", "L1"); + addClimbLevelRow("L2", "L2"); + addClimbLevelRow("L3", "L3"); + } + + // Add a row + public void addClimbLevelRow(String in_value, String in_description) { + climbLevel_list.add(new ClimbLevelRow(in_value, in_description)); + } + + // Return the size + public int size() { + return climbLevel_list.size(); + } + + public ArrayList getDescriptionList() { + ArrayList descriptions = new ArrayList<>(); + for (ClimbLevel.ClimbLevelRow clr : climbLevel_list) { + descriptions.add(clr.description); + } + return descriptions; + } + + public String getClimbLevelValue(String in_description) { + for (ClimbLevel.ClimbLevelRow clr : climbLevel_list) { + if (Objects.equals(clr.description, in_description)) { + return clr.value; + } + } + return ""; + } + + public String getClimbLevelDescription(String in_value) { + for (ClimbLevel.ClimbLevelRow clr : climbLevel_list) { + if (Objects.equals(clr.value, in_value)) { + return clr.description; + } + } + return ""; + } + + // Member Function: Empties out the list + public void clear() {climbLevel_list.clear();} + + // ============================================================================================= + // Class: ClimbPositionRow + // Description: Defines a structure/class to hold the information for each climb position + // ============================================================================================= + private static class ClimbLevelRow { + private final String value; + private final String description; + + public ClimbLevelRow(String in_value, String in_description) { + value = in_value; + description = in_description; + } + } +} diff --git a/app/src/main/java/com/team3663/scouting_app/data/ClimbPosition.java b/app/src/main/java/com/team3663/scouting_app/data/ClimbPosition.java new file mode 100644 index 00000000..e91b4c4f --- /dev/null +++ b/app/src/main/java/com/team3663/scouting_app/data/ClimbPosition.java @@ -0,0 +1,79 @@ +package com.team3663.scouting_app.data; + +import java.util.ArrayList; +import java.util.Objects; + +// ============================================================================================= +// Class: ClimbPosition +// Description: Defines a structure/class to hold the information for all robot Climb Position values +// ============================================================================================= + +public class ClimbPosition { + + private final ArrayList climbPosition_list; + + public ClimbPosition() { + climbPosition_list = new ArrayList<>(); + + // Add climb position values into the list + addClimbPositionRow("-1","