From 3084224af9dae717e6ac8f0ecc51c6087fed1375 Mon Sep 17 00:00:00 2001 From: Astatin3 <77305074+Astatin3@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:42:43 -0600 Subject: [PATCH] Start work on search menu, other random stuff --- README.md | 2 + .../SettingsVersionStack/sv1.java | 13 ++ .../scoutingData/ScoutingVersion.java | 120 +++++++++++-- .../scoutingapp2025/ui/data/searchView.java | 158 ++++++++++++++++++ .../ui/scouting/scoutingFragment.java | 12 +- .../ui/settings/settingsFragment.java | 15 ++ .../scoutingapp2025/utility/fileEditor.java | 33 ++++ app/src/main/res/layout/fragment_data.xml | 15 +- app/src/main/res/layout/fragment_settings.xml | 37 +++- app/src/main/res/values/strings.xml | 2 +- 10 files changed, 382 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index d9f7e14..08c68d2 100644 --- a/README.md +++ b/README.md @@ -15,4 +15,6 @@ Also TODO: Also Also TODO: - Make practice mode - Make server software to allow for easy sync over wifi +- AI overview of scouting data for a team??? +- Bluetooth data sync - Test the scouting app \ No newline at end of file diff --git a/app/src/main/java/com/astatin3/scoutingapp2025/SettingsVersionStack/sv1.java b/app/src/main/java/com/astatin3/scoutingapp2025/SettingsVersionStack/sv1.java index a9846db..470c051 100644 --- a/app/src/main/java/com/astatin3/scoutingapp2025/SettingsVersionStack/sv1.java +++ b/app/src/main/java/com/astatin3/scoutingapp2025/SettingsVersionStack/sv1.java @@ -22,6 +22,7 @@ public class sv1 extends sv0 { writeTag("selected_event_code", "unset"); // writeTag("practice_mode", "false"); writeTag("wifi_mode", "false"); + writeTag("team_num", "4388"); writeTag("match_num", "0"); writeTag("alliance_pos", "red-1"); @@ -48,4 +49,16 @@ public class sv1 extends sv0 { public void set_alliance_pos(String pos){ writeTag("alliance_pos", pos); } + + public int get_team_num(){return Integer.parseInt(readTag("team_num"));} + public void set_team_num(String str){ + + if(str.isEmpty()) { + set_team_num(0); + return; + } + + set_team_num(Integer.parseInt(str)); + } + public void set_team_num(int num){writeTag("team_num", String.valueOf(num));} } diff --git a/app/src/main/java/com/astatin3/scoutingapp2025/scoutingData/ScoutingVersion.java b/app/src/main/java/com/astatin3/scoutingapp2025/scoutingData/ScoutingVersion.java index 372abe7..45fefb8 100644 --- a/app/src/main/java/com/astatin3/scoutingapp2025/scoutingData/ScoutingVersion.java +++ b/app/src/main/java/com/astatin3/scoutingapp2025/scoutingData/ScoutingVersion.java @@ -4,8 +4,13 @@ import android.app.slice.Slice; import android.content.Context; import android.text.Editable; import android.text.TextWatcher; +import android.view.Gravity; import android.view.View; +import android.view.ViewGroup; import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -21,14 +26,18 @@ import com.skydoves.powerspinner.PowerSpinnerView; import com.skydoves.powerspinner.SpinnerGravity; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.function.Function; -public class ScoutingVersion { +public class +ScoutingVersion { public static final int slider_type_id = 255; public static final int dropdownType = 254; public static final int notesType = 253; + + public enum inputTypes { // USERNAME, SLIDER, @@ -41,6 +50,25 @@ public class ScoutingVersion { STRING } + + + + + + + + + + + + + + + + + + + public abstract class inputType { public String name; public Object default_value; @@ -58,17 +86,15 @@ public class ScoutingVersion { public void setViewValue(dataType type){setViewValue(type.get());} public abstract void setViewValue(Object value); public abstract dataType getViewValue(); + public abstract void add_individual_view(LinearLayout parent, dataType data); } -// public class usernameType extends inputType { -// public String defaultValue; -// public inputTypes getInputType(){return inputTypes.USERNAME;} -// public valueTypes getValueType(){return valueTypes.STRING;} -// public usernameType(String name, String defaultValue){ -// super(name); -// this.defaultValue = defaultValue; -// } -// } + + + + + + public class sliderType extends inputType { // public int defaultValue; @@ -128,10 +154,32 @@ public class ScoutingVersion { if(slider == null) return null; return new intType(name, min + (int) (slider.getValue() * (max-min))); } + public void add_individual_view(LinearLayout parent, dataType data){ + Slider slider = new Slider(parent.getContext()); + + float slider_position = (float) ((int) data.get()-min) / (max-min); + float step_size = (float) 1/max; + int round_position = Math.round(slider_position / step_size); + slider.setValue(round_position*step_size); + + slider.setStepSize((float) 1 / max); + slider.setEnabled(false); + parent.addView(slider); + } } + + + + + + + + + + public class dropdownType extends inputType { public String[] text_options; public int get_byte_id() {return dropdownType;} @@ -209,8 +257,30 @@ public class ScoutingVersion { if(dropdown == null) return null; return new intType(name, dropdown.getSelectedIndex()); } + public void add_individual_view(LinearLayout parent, dataType data){ + TextView tv = new TextView(parent.getContext()); + tv.setLayoutParams(new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + )); + tv.setPadding(20,20,20,20); + tv.setGravity(Gravity.CENTER_HORIZONTAL); + tv.setText(text_options[(int) data.get()]); + tv.setTextSize(18); + parent.addView(tv); + } } + + + + + + + + + + public class notesType extends inputType { public int get_byte_id() {return notesType;} public inputTypes getInputType(){return inputTypes.NOTES_INPUT;} @@ -257,9 +327,39 @@ public class ScoutingVersion { if(text == null) return null; return new stringType(name, text.getText().toString()); } + public void add_individual_view(LinearLayout parent, dataType data){ + TextView tv = new TextView(parent.getContext()); + tv.setLayoutParams(new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + )); + tv.setGravity(Gravity.CENTER_HORIZONTAL); + tv.setText((String) data.get()); + tv.setTextSize(18); + parent.addView(tv); + } } + + + + + + + + + + + + + + + + + + + public abstract class dataType { diff --git a/app/src/main/java/com/astatin3/scoutingapp2025/ui/data/searchView.java b/app/src/main/java/com/astatin3/scoutingapp2025/ui/data/searchView.java index 94dde6c..3901f8f 100644 --- a/app/src/main/java/com/astatin3/scoutingapp2025/ui/data/searchView.java +++ b/app/src/main/java/com/astatin3/scoutingapp2025/ui/data/searchView.java @@ -2,12 +2,27 @@ package com.astatin3.scoutingapp2025.ui.data; import android.content.Context; import android.util.AttributeSet; +import android.view.Gravity; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TableLayout; +import android.widget.TableRow; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.constraintlayout.widget.ConstraintLayout; import com.astatin3.scoutingapp2025.databinding.FragmentDataBinding; +import com.astatin3.scoutingapp2025.scoutingData.ScoutingDataWriter; +import com.astatin3.scoutingapp2025.scoutingData.ScoutingVersion; +import com.astatin3.scoutingapp2025.scoutingData.fields; import com.astatin3.scoutingapp2025.types.frcEvent; +import com.astatin3.scoutingapp2025.types.frcTeam; +import com.astatin3.scoutingapp2025.utility.fileEditor; + +import java.util.ArrayList; +import java.util.Arrays; public class searchView extends ConstraintLayout { public searchView(@NonNull Context context) { @@ -18,9 +33,152 @@ public class searchView extends ConstraintLayout { } FragmentDataBinding binding; + String evcode; + frcEvent event; + + ScoutingVersion.inputType[][] match_values; + ScoutingVersion.transferType[][] match_transferValues; + ScoutingVersion.inputType[][] pit_values; + ScoutingVersion.transferType[][] pit_transferValues; public void init(FragmentDataBinding binding, frcEvent event){ this.binding = binding; + this.evcode = event.eventCode; + this.event = event; + + + match_values = fields.load(fields.matchFieldsFilename); + match_transferValues = fields.sv.get_transfer_values(match_values); + pit_values = fields.load(fields.pitsFieldsFilename); + pit_transferValues = fields.sv.get_transfer_values(pit_values); + + + binding.searchArea.removeAllViews(); + + TableLayout table = new TableLayout(getContext()); + table.setStretchAllColumns(true); + binding.searchArea.addView(table); + +// binding.searchTable.addView(table); + + int[] teams = new int[event.teams.size()]; + + for(int i = 0 ; i < event.teams.size(); i++){ + teams[i] = event.teams.get(i).teamNumber; + } + + Arrays.sort(teams); + + for(int i = 0; i < event.teams.size(); i++){ + frcTeam team = null; + for(int a = 0 ; a < event.teams.size(); a++){ + if(event.teams.get(a).teamNumber == teams[i]){ + team = event.teams.get(a); + break; + } + } + + TableRow tr = new TableRow(getContext()); + TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, + FrameLayout.LayoutParams.WRAP_CONTENT + ); + rowParams.setMargins(20,20,20,20); + tr.setLayoutParams(rowParams); + tr.setPadding(20,20,20,20); + table.addView(tr); + + tr.setBackgroundColor(0x1000ff00); + + TextView tv = new TextView(getContext()); + tv.setText(String.valueOf(team.teamNumber)); + tv.setTextSize(20); + tr.addView(tv); + + tv = new TextView(getContext()); + tv.setText(team.teamName); + tv.setTextSize(16); + tr.addView(tv); + + frcTeam finalTeam = team; + tr.setOnClickListener(v -> { + loadTeam(finalTeam); + }); + } + } + + public void loadTeam(frcTeam team){ + binding.searchArea.removeAllViews(); + + LinearLayout ll = new LinearLayout(getContext()); + ll.setLayoutParams(new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + )); + ll.setOrientation(LinearLayout.VERTICAL); + binding.searchArea.addView(ll); + + TextView tv = new TextView(getContext()); + tv.setLayoutParams(new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + )); + tv.setGravity(Gravity.CENTER_HORIZONTAL); + tv.setText(team.teamName); + tv.setTextSize(28); + ll.addView(tv); + + tv = new TextView(getContext()); + tv.setLayoutParams(new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + )); + tv.setGravity(Gravity.CENTER_HORIZONTAL); + tv.setText(team.getDescription()); + tv.setTextSize(16); + ll.addView(tv); + + String[] files = fileEditor.getMatchesByTeamNum(team.teamNumber); + + for(int i = 0; i < files.length; i++){ + String[] split = files[i].split("-"); + int match_num = Integer.parseInt(split[1]); + + ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[i], match_values, match_transferValues); + + tv = new TextView(getContext()); + tv.setLayoutParams(new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + )); + tv.setPadding(0,20,0,5); + tv.setGravity(Gravity.CENTER_HORIZONTAL); + tv.setText("Match " + (match_num) + " by " + psda.username); + tv.setTextSize(30); + ll.addView(tv); + + for(int a = 0 ; a < psda.data.array.length; a++){ + tv = new TextView(getContext()); + tv.setLayoutParams(new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + )); + tv.setGravity(Gravity.CENTER_HORIZONTAL); + tv.setText(psda.data.array[a].name); + tv.setTextSize(25); + ll.addView(tv); + + + match_values[match_values.length-1][a].add_individual_view(ll, psda.data.array[a]); + } + } + + System.out.println(ll.getChildCount()); + +// ScoutingDataWriter.ParsedScoutingDataResult[] scoutingData; + } + + public void display_uncompiled_data(){ } } diff --git a/app/src/main/java/com/astatin3/scoutingapp2025/ui/scouting/scoutingFragment.java b/app/src/main/java/com/astatin3/scoutingapp2025/ui/scouting/scoutingFragment.java index e9bc589..af747eb 100644 --- a/app/src/main/java/com/astatin3/scoutingapp2025/ui/scouting/scoutingFragment.java +++ b/app/src/main/java/com/astatin3/scoutingapp2025/ui/scouting/scoutingFragment.java @@ -32,19 +32,21 @@ public class scoutingFragment extends Fragment { binding.matchScoutingView.setVisibility(View.GONE); binding.pitScoutingView.setVisibility(View.GONE); + String evcode = latestSettings.settings.get_evcode(); - frcEvent event = frcEvent.decode(fileEditor.readFile(evcode + ".eventdata")); - - if(event.matches.isEmpty()) - binding.matchScoutingButton.setVisibility(View.GONE); - if(evcode.equals("unset")){ binding.noEventError.setVisibility(View.VISIBLE); binding.buttons.setVisibility(View.GONE); is_main_page = false; + return root; } + frcEvent event = frcEvent.decode(fileEditor.readFile(evcode + ".eventdata")); + + if(event.matches.isEmpty()) + binding.matchScoutingButton.setVisibility(View.GONE); + binding.matchScoutingButton.setOnClickListener(v -> { binding.buttons.setVisibility(View.GONE); binding.matchScoutingView.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/com/astatin3/scoutingapp2025/ui/settings/settingsFragment.java b/app/src/main/java/com/astatin3/scoutingapp2025/ui/settings/settingsFragment.java index f5ac525..426c035 100644 --- a/app/src/main/java/com/astatin3/scoutingapp2025/ui/settings/settingsFragment.java +++ b/app/src/main/java/com/astatin3/scoutingapp2025/ui/settings/settingsFragment.java @@ -167,6 +167,20 @@ public class settingsFragment extends Fragment { + EditText team_num = binding.teamNumber; + team_num.setText(String.valueOf(latestSettings.settings.get_team_num())); + team_num.addTextChangedListener(new TextWatcher() { + + public void afterTextChanged(Editable s) { + latestSettings.settings.set_team_num(team_num.getText().toString()); + } + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + public void onTextChanged(CharSequence s, int start, int before, int count) {} + }); + + + + CheckBox wifi_mode = binding.wifiMode; @@ -201,6 +215,7 @@ public class settingsFragment extends Fragment { // practice_mode.setChecked(latestSettings.settings.get_practice_mode()); wifi_mode.setChecked(latestSettings.settings.get_wifi_mode()); alliance_pos_spinnerView.selectItemByIndex(0); + team_num.setText(String.valueOf(latestSettings.settings.get_team_num())); }); alert.setNegativeButton("Cancel", null); diff --git a/app/src/main/java/com/astatin3/scoutingapp2025/utility/fileEditor.java b/app/src/main/java/com/astatin3/scoutingapp2025/utility/fileEditor.java index 36348b3..e86fbc6 100644 --- a/app/src/main/java/com/astatin3/scoutingapp2025/utility/fileEditor.java +++ b/app/src/main/java/com/astatin3/scoutingapp2025/utility/fileEditor.java @@ -18,7 +18,9 @@ import java.nio.BufferOverflowException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.zip.DataFormatException; import java.util.zip.Deflater; import java.util.zip.Inflater; @@ -217,6 +219,37 @@ public final class fileEditor { } + public static String[] getMatchesByTeamNum(int teamNum){ + File f = new File(baseDir); + File[] files = f.listFiles(); + + ArrayList outFiles = new ArrayList<>(); + + if(files == null){return new String[0];} + + for (File file : files) { + if(!file.isDirectory() && file.getName().endsWith(teamNum+".matchscoutdata")) { + outFiles.add(file.getName()); + } + } + + String[] filenames = outFiles.toArray(new String[0]); + + Arrays.sort(filenames, new Comparator() { + @Override + public int compare(String o1, String o2) { + return Integer.valueOf(o1.split("-")[1]).compareTo(Integer.valueOf(o2.split("-")[1])); + } + }); + + + return filenames; + } + + + + + public static boolean setTeams(Context context, String key, ArrayList teams){ return true; } diff --git a/app/src/main/res/layout/fragment_data.xml b/app/src/main/res/layout/fragment_data.xml index 939a720..0a17de9 100644 --- a/app/src/main/res/layout/fragment_data.xml +++ b/app/src/main/res/layout/fragment_data.xml @@ -109,10 +109,17 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> - - - - + + + + + + + + diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index 3cc6c80..653953a 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -44,14 +44,11 @@ android:id="@+id/textView2" android:layout_width="66dp" android:layout_height="24dp" - android:layout_marginStart="172dp" android:layout_marginTop="16dp" - android:layout_marginEnd="173dp" android:text="Name" android:textAlignment="center" android:textSize="16sp" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> @@ -140,17 +137,47 @@ app:spinner_popup_background="@color/black_2" app:spinner_popup_elevation="14dp" /> + + + + + app:layout_constraintTop_toBottomOf="@+id/team_number" />