From 5447b648577cfd90633213fcb258fd4581596504 Mon Sep 17 00:00:00 2001 From: Michael Mikovsky <77305074+Astatin3@users.noreply.github.com> Date: Mon, 31 Mar 2025 11:58:45 -0600 Subject: [PATCH] Change header byte length, add data view by field type --- .../ridgebotics/ridgescout/types/file.java | 20 ++- .../ridgescout/types/input/checkboxType.java | 4 + .../ridgescout/types/input/dropdownType.java | 4 + .../ridgescout/types/input/fieldposType.java | 4 + .../ridgescout/types/input/inputType.java | 70 ++++----- .../ridgescout/types/input/numberType.java | 4 + .../ridgescout/types/input/sliderType.java | 4 + .../ridgescout/types/input/tallyType.java | 19 +++ .../ridgescout/types/input/textType.java | 4 + .../ridgescout/ui/FieldBorderedRow.java | 67 +++++++++ .../ridgescout/ui/TeamListOption.java | 4 +- .../ridgescout/ui/TeamSelectorFragment.java | 47 ------ .../ridgescout/ui/data/DataFragment.java | 114 ++++++++++++-- .../ridgescout/ui/data/FieldDataFragment.java | 94 ++++++++++++ .../ridgescout/ui/data/TeamsFragment.java | 8 +- .../ui/scouting/PitScoutingFragment.java | 6 + .../ui/scouting/PitSelectorFragment.java | 140 ++++++++++++++++++ .../ui/scouting/ScoutingFragment.java | 7 +- .../ui/settings/FieldsFragment.java | 6 +- .../ui/settings/settingsFragment.java | 4 +- .../ui/transfer/FileSelectorFragment.java | 15 +- .../ridgescout/utility/BuiltByteParser.java | 14 +- .../ridgescout/utility/ByteBuilder.java | 23 +-- .../ridgescout/utility/DataManager.java | 2 + .../ridgescout/utility/fileEditor.java | 5 +- .../ridgescout/utility/settingsManager.java | 5 + app/src/main/res/layout/fragment_data.xml | 36 +++-- .../res/layout/fragment_data_field_data.xml | 31 ++++ .../main/res/layout/fragment_pit_selector.xml | 20 +++ ...ields.xml => fragment_settings_fields.xml} | 0 .../main/res/layout/view_field_border_row.xml | 55 +++++++ app/src/main/res/layout/view_team_option.xml | 4 +- .../main/res/navigation/mobile_navigation.xml | 35 +++-- 33 files changed, 699 insertions(+), 176 deletions(-) create mode 100644 app/src/main/java/com/ridgebotics/ridgescout/ui/FieldBorderedRow.java create mode 100644 app/src/main/java/com/ridgebotics/ridgescout/ui/data/FieldDataFragment.java create mode 100644 app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/PitSelectorFragment.java create mode 100644 app/src/main/res/layout/fragment_data_field_data.xml create mode 100644 app/src/main/res/layout/fragment_pit_selector.xml rename app/src/main/res/layout/{fragment_data_fields.xml => fragment_settings_fields.xml} (100%) create mode 100644 app/src/main/res/layout/view_field_border_row.xml diff --git a/app/src/main/java/com/ridgebotics/ridgescout/types/file.java b/app/src/main/java/com/ridgebotics/ridgescout/types/file.java index cf94f01..a116def 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/types/file.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/file.java @@ -5,6 +5,7 @@ import com.ridgebotics.ridgescout.utility.BuiltByteParser; import com.ridgebotics.ridgescout.utility.ByteBuilder; import com.ridgebotics.ridgescout.utility.fileEditor; +import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.Objects; @@ -28,8 +29,15 @@ public class file { public byte[] encode(){ try { ByteBuilder bb = new ByteBuilder() - .addString(filename) - .addRaw(255, Objects.requireNonNull(fileEditor.readFile(filename))); + .addString(filename); + +// byte[] data = Objects.requireNonNull(fileEditor.readFile(filename)); + +// for(int i = 0; i < data.length / 65535; i++){ +// bb.addRaw(255, fileEditor.getByteBlock(data, i*65535, (i+1)*65535)); +// } + + bb.addRaw(255, Objects.requireNonNull(fileEditor.readFile(filename))); return bb.build(); @@ -46,6 +54,14 @@ public class file { file f = new file(); f.filename = (String) objects.get(0).get(); + +// ByteArrayOutputStream fileData = new ByteArrayOutputStream(); +// +// for(int i = 1; i < objects.size(); i++){ +// byte[] blockBytes = (byte[]) objects.get(i).get(); +// fileData.write(blockBytes, (i-1)*65535, blockBytes.length); +// } + f.data = (byte[]) objects.get(1).get(); return f; diff --git a/app/src/main/java/com/ridgebotics/ridgescout/types/input/checkboxType.java b/app/src/main/java/com/ridgebotics/ridgescout/types/input/checkboxType.java index f7e886d..4dac5c1 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/types/input/checkboxType.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/input/checkboxType.java @@ -220,6 +220,10 @@ public class checkboxType extends inputType { parent.addView(chart); } + public void addDataToTable(LinearLayout parent, List[] data){ + + } + public String toString(dataType data){ return (int) data.get() == 1 ? "true" : "false"; } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/types/input/dropdownType.java b/app/src/main/java/com/ridgebotics/ridgescout/types/input/dropdownType.java index 596f40c..15fe0d3 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/types/input/dropdownType.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/input/dropdownType.java @@ -246,6 +246,10 @@ public class dropdownType extends inputType { parent.addView(chart); } + public void addDataToTable(LinearLayout parent, List[] data){ + + } + public String toString(dataType data){ return text_options[(int) data.get()]; } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/types/input/fieldposType.java b/app/src/main/java/com/ridgebotics/ridgescout/types/input/fieldposType.java index f6d4293..61d2b06 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/types/input/fieldposType.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/input/fieldposType.java @@ -233,6 +233,10 @@ public class fieldposType extends inputType { parent.addView(chart); } + public void addDataToTable(LinearLayout parent, List[] data){ + + } + public String toString(dataType data){ int[] intarr = (int[]) data.get(); return "[" + intarr[0] + "," + intarr[1] + "]"; diff --git a/app/src/main/java/com/ridgebotics/ridgescout/types/input/inputType.java b/app/src/main/java/com/ridgebotics/ridgescout/types/input/inputType.java index 6e291e3..69b7269 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/types/input/inputType.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/input/inputType.java @@ -9,6 +9,7 @@ import com.ridgebotics.ridgescout.types.data.dataType; import com.ridgebotics.ridgescout.utility.BuiltByteParser; import com.ridgebotics.ridgescout.utility.ByteBuilder; +import java.util.List; import java.util.function.Function; public abstract class inputType { @@ -59,55 +60,34 @@ public abstract class inputType { -// private enum parameterTypeEnum { -// paramNumber, -// paramString, -// paramStringArray -// } -// -// public static class parameterType { -// public String name; -// public parameterTypeEnum id; -// } -// -// public static class paramNumber extends parameterType { -// public int val; -// public paramNumber(String name, int val){ -// this.name = name + " (Number)"; -// this.val = val; -// this.id = parameterTypeEnum.paramNumber; -// } -// } -// -// public static class paramString extends parameterType { -// public String val; -// public paramString(String name, String val){ -// this.name = name + " (String)"; -// this.val = val; -// this.id = parameterTypeEnum.paramString; -// } -// } -// -// public static class paramStringArray extends parameterType { -// public String[] val; -// public paramStringArray(String name, String[] val){ -// this.name = name + " (String array)"; -// this.val = val; -// this.id = parameterTypeEnum.paramStringArray; -// } -// } - -// public abstract parameterType[] getDefaultParameters(); - - public abstract void add_individual_view(LinearLayout parent, dataType data); - - public abstract void add_compiled_view(LinearLayout parent, dataType[] data); - - public abstract void add_history_view(LinearLayout parent, dataType[] data); + public abstract void addDataToTable(LinearLayout parent, List[] data); + + public abstract String toString(dataType data); + + + public int[] getNumberBounds(List[] data){ + int min = Integer.MAX_VALUE; + int max = Integer.MIN_VALUE; + + for(int teamNum = 0; teamNum < data.length; teamNum++){ + if(data[teamNum] == null) continue; + for(int i = 0; i < data[teamNum].size(); i++){ + dataType dataPoint = data[teamNum].get(i); + if(dataPoint == null || dataPoint.getValueType() != getValueType()) continue; + int num = (int) dataPoint.get(); + if(num > max) max = num; + if(num < min) min = num; + } + } + + return new int[]{min, max}; + } + + } \ No newline at end of file diff --git a/app/src/main/java/com/ridgebotics/ridgescout/types/input/numberType.java b/app/src/main/java/com/ridgebotics/ridgescout/types/input/numberType.java index 8949463..66e7fe1 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/types/input/numberType.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/input/numberType.java @@ -319,6 +319,10 @@ public class numberType extends inputType { parent.addView(chart); } + public void addDataToTable(LinearLayout parent, List[] data){ + + } + public String toString(dataType data){ return String.valueOf((int) data.get()); } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/types/input/sliderType.java b/app/src/main/java/com/ridgebotics/ridgescout/types/input/sliderType.java index bf9e527..aac2b0f 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/types/input/sliderType.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/input/sliderType.java @@ -305,6 +305,10 @@ public class sliderType extends inputType { parent.addView(chart); } + public void addDataToTable(LinearLayout parent, List[] data){ + + } + public String toString(dataType data){ return String.valueOf((int) data.get()); } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/types/input/tallyType.java b/app/src/main/java/com/ridgebotics/ridgescout/types/input/tallyType.java index ce7e42b..18cfa62 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/types/input/tallyType.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/input/tallyType.java @@ -13,6 +13,7 @@ import android.widget.TextView; import com.ridgebotics.ridgescout.types.data.dataType; import com.ridgebotics.ridgescout.types.data.intType; import com.ridgebotics.ridgescout.ui.scouting.TallyCounterView; +import com.ridgebotics.ridgescout.utility.AlertManager; import com.ridgebotics.ridgescout.utility.BuiltByteParser; import com.ridgebotics.ridgescout.utility.ByteBuilder; import com.github.mikephil.charting.charts.LineChart; @@ -299,6 +300,24 @@ public class tallyType extends inputType { parent.addView(chart); } + public void addDataToTable(LinearLayout parent, List[] data){ + int min = Integer.MAX_VALUE; + int max = Integer.MIN_VALUE; + + for(int teamNum = 0; teamNum < data.length; teamNum++){ + if(data[teamNum] == null) continue; + for(int i = 0; i < data[teamNum].size(); i++){ + dataType dataPoint = data[teamNum].get(i); + if(dataPoint == null || dataPoint.getValueType() != getValueType()) continue; + int num = (int) dataPoint.get(); + if(num > max) max = num; + if(num < min) min = num; + } + } + + AlertManager.error("Min: " + min + " Max: " + max); + } + public String toString(dataType data){ return String.valueOf((int) data.get()); } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/types/input/textType.java b/app/src/main/java/com/ridgebotics/ridgescout/types/input/textType.java index 3551f1d..6664d16 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/types/input/textType.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/input/textType.java @@ -231,6 +231,10 @@ public class textType extends inputType { } + public void addDataToTable(LinearLayout parent, List[] data){ + + } + public String toString(dataType data){ return String.valueOf(data.get()); } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/FieldBorderedRow.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/FieldBorderedRow.java new file mode 100644 index 0000000..479e675 --- /dev/null +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/FieldBorderedRow.java @@ -0,0 +1,67 @@ +package com.ridgebotics.ridgescout.ui; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TableRow; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.constraintlayout.widget.ConstraintLayout; + +import com.ridgebotics.ridgescout.R; +import com.ridgebotics.ridgescout.types.input.inputType; + +public class FieldBorderedRow extends TableRow { + public FieldBorderedRow(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + init(context); + } + + public FieldBorderedRow(Context context) { + super(context); + init(context); + } + private ConstraintLayout box; + private View coloredBackground; + + public void init(Context context) { + LayoutInflater.from(context).inflate(R.layout.view_field_border_row, this, true); + + + box = findViewById(R.id.field_option_box); + coloredBackground = findViewById(R.id.field_option_background); + } + + public void setColor(int color){ + Drawable drawable = box.getBackground(); + drawable.mutate(); + drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP); + + float[] hsv = new float[3]; + Color.colorToHSV(color,hsv); + + coloredBackground.setBackgroundColor( + Color.HSVToColor(127, new float[]{ + hsv[0], + Math.min(hsv[1], 0.75f), + Math.min(hsv[2], 0.5f) + }) + ); + } + + public void fromField(inputType field){ + ((TextView) findViewById(R.id.field_option_name)).setText(field.name); + ((TextView) findViewById(R.id.field_option_type)).setText(field.get_type_name()); + } + + @Override + public void addView(View v){ + box.addView(v); + } +} diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/TeamListOption.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/TeamListOption.java index e5a1d84..c34bb0a 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/TeamListOption.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/TeamListOption.java @@ -39,8 +39,8 @@ public class TeamListOption extends LinearLayout { public void init(Context context) { LayoutInflater.from(context).inflate(R.layout.view_team_option, this, true); - teamNumber = findViewById(R.id.team_option_number); - teamName = findViewById(R.id.team_option_name); + teamNumber = findViewById(R.id.field_option_type); + teamName = findViewById(R.id.field_option_name); teamLogo = findViewById(R.id.team_option_logo); diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/TeamSelectorFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/TeamSelectorFragment.java index 8515437..bb24f08 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/TeamSelectorFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/TeamSelectorFragment.java @@ -58,13 +58,6 @@ public class TeamSelectorFragment extends Fragment { } public void load_teams(){ -// binding.pitFileIndicator.setVisibility(View.GONE); -// binding.pitTeamName.setVisibility(View.GONE); -// binding.pitTeamDescription.setVisibility(View.GONE); -// -// clear_fields(); - - int[] teamNums = new int[event.teams.size()]; for(int i = 0 ; i < event.teams.size(); i++){ @@ -88,50 +81,10 @@ public class TeamSelectorFragment extends Fragment { } assert team != null; -// 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); - TeamListOption teamRow = new TeamListOption(getContext()); table.addView(teamRow); teamRow.fromTeam(team); - - if(pits_mode) { - String filename = evcode + "-" + team.teamNumber + ".pitscoutdata"; - - if (fileEditor.fileExist(filename)) { - final boolean[] rescout = {DataManager.rescout_list.contains(filename)}; - - teamRow.setColor(DataManager.rescout_list.contains(filename) ? 0x300000FF : 0x3000FF00); - - teamRow.setOnLongClickListener(v -> { - rescout[0] = !rescout[0]; - if(rescout[0]){ - DataManager.rescout_list.add(filename); - teamRow.setColor(0x300000FF); - DataManager.save_rescout_list(); - }else{ - DataManager.rescout_list.remove(filename); - teamRow.setColor(0x3000FF00); - DataManager.save_rescout_list(); - } - - - return true; - }); - } else { - teamRow.setColor(0x30FF0000); - teamRow.setOnLongClickListener(v -> true); - } - } - frcTeam finalTeam = team; teamRow.setOnClickListener(v -> { onSelect.onSelect(this, finalTeam); diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/DataFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/DataFragment.java index 609af03..00a7365 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/DataFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/DataFragment.java @@ -1,14 +1,23 @@ package com.ridgebotics.ridgescout.ui.data; +import static android.view.View.GONE; +import static android.view.View.TEXT_ALIGNMENT_VIEW_END; import static android.view.View.VISIBLE; import static androidx.navigation.fragment.FragmentKt.findNavController; +import static com.ridgebotics.ridgescout.utility.DataManager.evcode; +import static com.ridgebotics.ridgescout.utility.DataManager.event; +import static com.ridgebotics.ridgescout.utility.DataManager.match_latest_values; + import android.os.Bundle; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.TableRow; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -16,46 +25,119 @@ import androidx.fragment.app.Fragment; import com.ridgebotics.ridgescout.R; import com.ridgebotics.ridgescout.scoutingData.fields; +import com.ridgebotics.ridgescout.types.frcTeam; +import com.ridgebotics.ridgescout.ui.CustomSpinnerView; +import com.ridgebotics.ridgescout.ui.FieldBorderedRow; +import com.ridgebotics.ridgescout.ui.TeamListOption; import com.ridgebotics.ridgescout.ui.settings.FieldsFragment; +import com.ridgebotics.ridgescout.utility.AlertManager; +import com.ridgebotics.ridgescout.utility.DataManager; import com.ridgebotics.ridgescout.utility.settingsManager; import com.ridgebotics.ridgescout.databinding.FragmentDataBinding; import com.ridgebotics.ridgescout.ui.TeamSelectorFragment; import com.ridgebotics.ridgescout.utility.fileEditor; import com.ridgebotics.ridgescout.types.frcEvent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + public class DataFragment extends Fragment { private FragmentDataBinding binding; + private int option = 0; + - private boolean submenu = false; public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { binding = FragmentDataBinding.inflate(inflater, container, false); + binding.table.setStretchAllColumns(true); View root = binding.getRoot(); - String evcode = settingsManager.getEVCode(); - - if(evcode.equals("unset")){ + if(evcode == null || evcode.equals("unset") || event == null){ binding.noEventError.setVisibility(VISIBLE); - -// binding.teamsButton.setEnabled(false); - - + binding.dataTypeDropdown.setVisibility(GONE); return root; } -// frcEvent event = frcEvent.decode(fileEditor.readFile(evcode + ".eventdata")); + option = settingsManager.getDataMode(); - binding.teamsButton.setOnClickListener(v -> { - TeamSelectorFragment.setPits_mode(false); - TeamSelectorFragment.setOnSelect((self, team) -> { - TeamsFragment.setTeam(team); - findNavController(self).navigate(R.id.action_navigation_team_selector_to_navigation_data_teams); - }); - findNavController(this).navigate(R.id.action_navigation_data_to_navigation_team_selector); + binding.dataTypeDropdown.setTitle("Data type"); + binding.dataTypeDropdown.setOptions(List.of(new String[]{ + "By Team", "By Data Field" + }), option); + binding.dataTypeDropdown.setOnClickListener((item, index) -> { + option = index; + settingsManager.setDataMode(option); + reload_views(); }); + + reload_views(); + return root; } + + public void reload_views(){ + binding.table.removeViews(1, binding.table.getChildCount()-1); + + switch (option) { + case 0: + load_teams(); + break; + case 1: + load_fields(); + break; + } + + } + + public void load_teams(){ + DataManager.reload_event(); + int[] teamNums = new int[event.teams.size()]; + + for(int i = 0 ; i < event.teams.size(); i++){ + teamNums[i] = event.teams.get(i).teamNumber; + } + + Arrays.sort(teamNums); + + 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 == teamNums[i]){ + team = event.teams.get(a); + break; + } + } + assert team != null; + + TeamListOption teamRow = new TeamListOption(getContext()); + binding.table.addView(teamRow); + teamRow.fromTeam(team); + + frcTeam finalTeam = team; + teamRow.setOnClickListener(v -> { + TeamsFragment.setTeam(finalTeam); + findNavController(this).navigate(R.id.action_navigation_data_to_navigation_data_teams); + }); + } + } + public void load_fields(){ + DataManager.reload_match_fields(); + + for(int i = 0; i < match_latest_values.length; i++){ + FieldBorderedRow tr = new FieldBorderedRow(getContext()); + tr.fromField(match_latest_values[i]); + tr.setColor(i % 2 == 0 ? 0xff509050 : 0xff307030); + binding.table.addView(tr); + + final int fi = i; + tr.setOnClickListener(v -> { + FieldDataFragment.setFieldIndex(fi); + findNavController(this).navigate(R.id.action_navigation_data_to_navigation_data_field_data); + }); + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/FieldDataFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/FieldDataFragment.java new file mode 100644 index 0000000..ef90479 --- /dev/null +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/FieldDataFragment.java @@ -0,0 +1,94 @@ +package com.ridgebotics.ridgescout.ui.data; + + +import static android.view.View.GONE; +import static android.view.View.VISIBLE; +import static androidx.navigation.fragment.FragmentKt.findNavController; +import static com.ridgebotics.ridgescout.utility.DataManager.evcode; +import static com.ridgebotics.ridgescout.utility.DataManager.event; +import static com.ridgebotics.ridgescout.utility.DataManager.match_latest_values; +import static com.ridgebotics.ridgescout.utility.DataManager.match_transferValues; +import static com.ridgebotics.ridgescout.utility.DataManager.match_values; +import static com.ridgebotics.ridgescout.utility.DataManager.rescout_list; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.ridgebotics.ridgescout.R; +import com.ridgebotics.ridgescout.databinding.FragmentDataBinding; +import com.ridgebotics.ridgescout.databinding.FragmentDataFieldDataBinding; +import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter; +import com.ridgebotics.ridgescout.types.data.dataType; +import com.ridgebotics.ridgescout.types.frcTeam; +import com.ridgebotics.ridgescout.ui.FieldBorderedRow; +import com.ridgebotics.ridgescout.ui.TeamListOption; +import com.ridgebotics.ridgescout.utility.AlertManager; +import com.ridgebotics.ridgescout.utility.DataManager; +import com.ridgebotics.ridgescout.utility.fileEditor; +import com.ridgebotics.ridgescout.utility.settingsManager; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FieldDataFragment extends Fragment { + + private FragmentDataFieldDataBinding binding; + + private static int fieldIndex = -1; + public static void setFieldIndex(int index){ + fieldIndex = index; + } + + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + + binding = FragmentDataFieldDataBinding.inflate(inflater, container, false); + binding.table.setStretchAllColumns(true); + View root = binding.getRoot(); + + if (fieldIndex == -1) + return root; + + Thread t = new Thread(() -> { + + List[] data = new ArrayList[event.teams.size()]; + for (int teamIndex = 0; teamIndex < event.teams.size(); teamIndex++) { + + List filenames = new ArrayList<>(List.of(fileEditor.getMatchesByTeamNum(evcode, event.teams.get(teamIndex).teamNumber))); + filenames.removeAll(rescout_list); + + for (int i = 0; i < filenames.size(); i++) { + data[teamIndex] = new ArrayList<>(); + try { + ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(filenames.get(i), match_values, match_transferValues); + if (psda.data.array[fieldIndex] != null && psda.data.array[fieldIndex].get() != null) + data[teamIndex].add(psda.data.array[fieldIndex]); + } catch (Exception e) { + e.printStackTrace(); + AlertManager.addSimpleError("Failure to load file " + filenames.get(i)); + } + } + } + + System.out.println("Finished!"); + + + +// getActivity().runOnUiThread(() -> { + match_latest_values[fieldIndex].addDataToTable(binding.table, data); +// }); + }); + + t.start(); + + return root; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/TeamsFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/TeamsFragment.java index dec1313..d306d94 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/TeamsFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/TeamsFragment.java @@ -60,16 +60,14 @@ public class TeamsFragment extends Fragment { options.add("Compiled"); options.add("History"); - binding.dataTypeSpinner.setOptions(options, settingsManager.getDataMode()); + binding.dataTypeSpinner.setOptions(options, settingsManager.getTeamsDataMode()); binding.dataTypeSpinner.setOnClickListener((item, index) -> { - settingsManager.setDataMode(index); + settingsManager.setTeamsDataMode(index); loadTeam(index); }); -// binding.teamsMainElem. - - loadTeam(settingsManager.getDataMode()); + loadTeam(settingsManager.getTeamsDataMode()); return binding.getRoot(); } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/PitScoutingFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/PitScoutingFragment.java index e6ed6b0..90a764c 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/PitScoutingFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/PitScoutingFragment.java @@ -50,6 +50,12 @@ public class PitScoutingFragment extends Fragment { username = settingsManager.getUsername(); DataManager.reload_pit_fields(); + if(pit_latest_values == null) { + AlertManager.addSimpleError("Error loading pit fields!"); + return binding.getRoot(); + } + + loadTeam(); return binding.getRoot(); diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/PitSelectorFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/PitSelectorFragment.java new file mode 100644 index 0000000..80c0a86 --- /dev/null +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/PitSelectorFragment.java @@ -0,0 +1,140 @@ +package com.ridgebotics.ridgescout.ui.scouting; + +import static com.ridgebotics.ridgescout.utility.DataManager.evcode; +import static com.ridgebotics.ridgescout.utility.DataManager.event; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TableLayout; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.ridgebotics.ridgescout.databinding.FragmentTeamSelectorBinding; +import com.ridgebotics.ridgescout.types.frcTeam; +import com.ridgebotics.ridgescout.ui.TeamListOption; +import com.ridgebotics.ridgescout.utility.AlertManager; +import com.ridgebotics.ridgescout.utility.DataManager; +import com.ridgebotics.ridgescout.utility.fileEditor; + +import java.util.Arrays; + +public class PitSelectorFragment extends Fragment { + private FragmentTeamSelectorBinding binding; + + private static boolean pits_mode; + public static void setPits_mode(boolean mode){ + pits_mode = mode; + } + + private static onTeamSelected onSelect = new onTeamSelected() {@Override public void onSelect(PitSelectorFragment self, frcTeam team) {}}; + + public interface onTeamSelected { + void onSelect(PitSelectorFragment self, frcTeam team); + } + public static void setOnSelect(onTeamSelected tmponSelect){ + onSelect = tmponSelect; + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + binding = FragmentTeamSelectorBinding.inflate(inflater, container, false); + +// event = fileEditor.g + DataManager.reload_event(); + + if(evcode == null || evcode.equals("unset")){ + AlertManager.addSimpleError("You somehow have not loaded an event!"); + return binding.getRoot(); + } + + load_teams(); + + + return binding.getRoot(); + } + + public void load_teams(){ +// binding.pitFileIndicator.setVisibility(View.GONE); +// binding.pitTeamName.setVisibility(View.GONE); +// binding.pitTeamDescription.setVisibility(View.GONE); +// +// clear_fields(); + + + int[] teamNums = new int[event.teams.size()]; + + for(int i = 0 ; i < event.teams.size(); i++){ + teamNums[i] = event.teams.get(i).teamNumber; + } + + Arrays.sort(teamNums); + + TableLayout table = new TableLayout(getContext()); + table.setStretchAllColumns(true); + binding.teams.addView(table); + + + 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 == teamNums[i]){ + team = event.teams.get(a); + break; + } + } + assert team != null; + +// 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); + + TeamListOption teamRow = new TeamListOption(getContext()); + table.addView(teamRow); + teamRow.fromTeam(team); + + + String filename = evcode + "-" + team.teamNumber + ".pitscoutdata"; + + if (fileEditor.fileExist(filename)) { + final boolean[] rescout = {DataManager.rescout_list.contains(filename)}; + + teamRow.setColor(DataManager.rescout_list.contains(filename) ? 0x300000FF : 0x3000FF00); + + teamRow.setOnLongClickListener(v -> { + rescout[0] = !rescout[0]; + if(rescout[0]){ + DataManager.rescout_list.add(filename); + teamRow.setColor(0x300000FF); + DataManager.save_rescout_list(); + }else{ + DataManager.rescout_list.remove(filename); + teamRow.setColor(0x3000FF00); + DataManager.save_rescout_list(); + } + + + return true; + }); + } else { + teamRow.setColor(0x30FF0000); + teamRow.setOnLongClickListener(v -> true); + } + + + frcTeam finalTeam = team; + teamRow.setOnClickListener(v -> onSelect.onSelect(this, finalTeam)); + } + } + +} diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/ScoutingFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/ScoutingFragment.java index 7ada2ff..a75320d 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/ScoutingFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/ScoutingFragment.java @@ -104,12 +104,11 @@ public class ScoutingFragment extends Fragment { }); binding.pitScoutingButton.setOnClickListener(v -> { - TeamSelectorFragment.setPits_mode(true); - TeamSelectorFragment.setOnSelect((self, team) -> { + PitSelectorFragment.setOnSelect((self, team) -> { PitScoutingFragment.setTeam(team); - findNavController(self).navigate(R.id.action_navigation_team_selector_to_navigation_pit_scouting); + findNavController(self).navigate(R.id.action_navigation_scouting_pit_selector_to_navigation_pit_scouting); }); - findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_team_selector); + findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_scouting_pit_selector); }); binding.eventButton.setOnClickListener(v -> { diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/settings/FieldsFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/settings/FieldsFragment.java index f1b9eaf..22e1a09 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/settings/FieldsFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/settings/FieldsFragment.java @@ -22,7 +22,7 @@ import androidx.navigation.Navigation; import com.ridgebotics.ridgescout.MainActivity; import com.ridgebotics.ridgescout.R; -import com.ridgebotics.ridgescout.databinding.FragmentDataFieldsBinding; +import com.ridgebotics.ridgescout.databinding.FragmentSettingsFieldsBinding; import com.ridgebotics.ridgescout.scoutingData.fields; import com.ridgebotics.ridgescout.types.input.checkboxType; import com.ridgebotics.ridgescout.types.input.dropdownType; @@ -40,7 +40,7 @@ import java.util.Arrays; import java.util.List; public class FieldsFragment extends Fragment { - FragmentDataFieldsBinding binding; + FragmentSettingsFieldsBinding binding; private static String filename; public static void set_filename(String tmpfilename){ @@ -50,7 +50,7 @@ public class FieldsFragment extends Fragment { @SuppressLint("ClickableViewAccessibility") public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - binding = FragmentDataFieldsBinding.inflate(inflater, container, false); + binding = FragmentSettingsFieldsBinding.inflate(inflater, container, false); binding.valueEditScrollview.setOnTouchListener((v, event) -> true); diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/settings/settingsFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/settings/settingsFragment.java index 0588015..00eae73 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/settings/settingsFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/settings/settingsFragment.java @@ -313,14 +313,14 @@ public class settingsFragment extends Fragment { int value = getValue()+1; if(value >= max){ value = max; - getEditor().putInt(getKey(), max-1).apply(); + getEditor().putInt(getKey(), Math.max(0,max-1)).apply(); } tally.setValue(value); tally.setBounds(1, max); tally.setOnCountChangedListener(count -> { - getEditor().putInt(getKey(), count-1).apply(); + getEditor().putInt(getKey(), Math.max(0,count-1)).apply(); if(isReloadOnChange()) reloadSettings(); }); tally.setEnabled(enabled); diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/FileSelectorFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/FileSelectorFragment.java index 8e592b6..0ca98b2 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/FileSelectorFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/FileSelectorFragment.java @@ -189,7 +189,20 @@ public class FileSelectorFragment extends Fragment { for(int i = 0; i < filenames.size(); i++){ file f = new file(filenames.get(i)); - b.addRaw(file.typecode, f.encode()); + + if(!fileEditor.fileExist(f.filename)) { + AlertManager.addSimpleError("File " + f.filename + " Does not exist!"); + continue; + }; + + byte[] bytes = f.encode(); + + if(bytes == null || bytes.length == 0) { + AlertManager.addSimpleError("File " + f.filename + " Has no data!"); + continue; + }; + + b.addRaw(file.typecode, bytes); } return b.build(); diff --git a/app/src/main/java/com/ridgebotics/ridgescout/utility/BuiltByteParser.java b/app/src/main/java/com/ridgebotics/ridgescout/utility/BuiltByteParser.java index 78b3aaa..61c86c3 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/utility/BuiltByteParser.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/utility/BuiltByteParser.java @@ -1,5 +1,7 @@ package com.ridgebotics.ridgescout.utility; +import static com.ridgebotics.ridgescout.utility.fileEditor.lengthHeaderBytes; + import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; @@ -80,22 +82,22 @@ public class BuiltByteParser { this.bytes = bytes; } public ArrayList parse() throws byteParsingExeption { - if(bytes.length < 3){throw new byteParsingExeption("Invalid length");} + if(bytes.length < lengthHeaderBytes + 1){throw new byteParsingExeption("Invalid length");} int curIndex = 0; while(true){ // Log.i("t", String.valueOf(curIndex)); - final int length = fileEditor.fromBytes(fileEditor.getByteBlock(bytes, curIndex, curIndex+2), 2); - final int type = bytes[curIndex+2] & 0xFF; + final int length = fileEditor.fromBytes(fileEditor.getByteBlock(bytes, curIndex, curIndex+lengthHeaderBytes), lengthHeaderBytes); + final int type = bytes[curIndex+lengthHeaderBytes] & 0xFF; if(length == 0){ - curIndex += 3; + curIndex += lengthHeaderBytes; continue; } final byte[] block; try { - block = fileEditor.getByteBlock(bytes, curIndex + 3, curIndex + length + 3); + block = fileEditor.getByteBlock(bytes, curIndex + lengthHeaderBytes + 1, curIndex + length + lengthHeaderBytes + 1); } catch(Exception e){ throw new byteParsingExeption("Array out of bounds"); } @@ -158,7 +160,7 @@ public class BuiltByteParser { break; } - curIndex += length + 3; + curIndex += length + lengthHeaderBytes + 1; if(curIndex == bytes.length){ break; diff --git a/app/src/main/java/com/ridgebotics/ridgescout/utility/ByteBuilder.java b/app/src/main/java/com/ridgebotics/ridgescout/utility/ByteBuilder.java index 878c3b2..7843014 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/utility/ByteBuilder.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/utility/ByteBuilder.java @@ -1,5 +1,7 @@ package com.ridgebotics.ridgescout.utility; +import static com.ridgebotics.ridgescout.utility.fileEditor.lengthHeaderBytes; + import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -71,7 +73,7 @@ public class ByteBuilder { public ByteBuilder addInt(int num, int precision) throws buildingException { if(precision <= 0){throw new buildingException("Invalid precision: " + precision);} - if(precision > 65536){throw new buildingException("Precision too large (greter than 65536)");} + if(precision > Math.pow(lengthHeaderBytes,8)){throw new buildingException("Precision too large (greter than 16777216)");} if(precision < getLeastBytePrecision(num)){throw new buildingException("Precision too small");} if(num > Integer.MAX_VALUE){throw new buildingException("Integer overflow");} @@ -96,7 +98,7 @@ public class ByteBuilder { } public ByteBuilder addString(String str) throws buildingException { str = blankStrNull(str); - if(str.length() > 65536){throw new buildingException("String too long (greater than 65536)");} + if(str.length() > Math.pow(lengthHeaderBytes,8)){throw new buildingException("String too long (greater than 16777216)");} stringType stringType = new stringType(); // To get the length correctly, the string bytes need to be precalculated @@ -175,7 +177,7 @@ public class ByteBuilder { public ByteBuilder addLong(long num, int precision) throws buildingException { if(precision <= 0){throw new buildingException("Invalid precision: " + precision);} - if(precision > 65536){throw new buildingException("Precision too large (greter than 65536)");} + if(precision > Math.pow(lengthHeaderBytes,8)){throw new buildingException("Precision too large (greter than 16777216)");} if(precision < getLeastBytePrecision(num)){throw new buildingException("Precision too small");} if(num > Long.MAX_VALUE){throw new buildingException("Long overflow");} @@ -200,7 +202,7 @@ public class ByteBuilder { } public ByteBuilder addRaw(int type, byte[] bytes) throws buildingException { - if(bytes.length > 65536){throw new buildingException("Byte array length to long (greater than 65536)");} + if(bytes.length > 16777216){throw new buildingException("Byte array length to long (greater than 16777216)");} rawType rawType = new rawType(); rawType.type = type; @@ -213,7 +215,7 @@ public class ByteBuilder { public byte[] build() throws buildingException { if(bytesToBuild.size() == 0){throw new buildingException("Cannot build null data");} - int length = bytesToBuild.size() * 3; + int length = bytesToBuild.size() * (lengthHeaderBytes + 1); for(byteType bt : bytesToBuild){ length += bt.length(); } @@ -223,12 +225,13 @@ public class ByteBuilder { for(byteType bt : bytesToBuild){ - byte[] blockLength = fileEditor.toBytes(bt.length(), 2); + byte[] blockLength = fileEditor.toBytes(bt.length(), lengthHeaderBytes + 1); + + for(int i = 0; i < lengthHeaderBytes; i++) { + bytes[bytesFilled] = blockLength[i]; + bytesFilled += 1; + } - bytes[bytesFilled] = blockLength[0]; - bytesFilled += 1; - bytes[bytesFilled] = blockLength[1]; - bytesFilled += 1; bytes[bytesFilled] = bt.getType(); bytesFilled += 1; diff --git a/app/src/main/java/com/ridgebotics/ridgescout/utility/DataManager.java b/app/src/main/java/com/ridgebotics/ridgescout/utility/DataManager.java index 2aca2e3..4922f13 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/utility/DataManager.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/utility/DataManager.java @@ -14,6 +14,7 @@ public class DataManager { public static String evcode; public static frcEvent event; public static void reload_event(){ + if(event != null) return; evcode = getevcode(); if(evcode.equals("unset")) return; @@ -25,6 +26,7 @@ public class DataManager { settingsManager.setEVCode("unset"); evcode = "unset"; }else{ + AlertManager.toast("Reloaded event!"); reload_rescout_list(); } } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/utility/fileEditor.java b/app/src/main/java/com/ridgebotics/ridgescout/utility/fileEditor.java index 45ce812..c4e9646 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/utility/fileEditor.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/utility/fileEditor.java @@ -35,6 +35,7 @@ public final class fileEditor { public final static String baseDir = "/data/data/com.ridgebotics.ridgescout/"; public static final byte internalDataVersion = 0x01; public static final int maxCompressedBlockSize = 4096; + public static final int lengthHeaderBytes = 3; // private TimeZone localTimeZone = TimeZone.getDefault(); @@ -58,7 +59,7 @@ public final class fileEditor { public static byte[] toBytes(int num, int byteCount){ - if(num > (Math.pow(2,byteCount*8)-1)){ + if(num > (Math.pow(lengthHeaderBytes,byteCount*8)-1)){ throw new BufferOverflowException(); } byte[] bytes = new byte[byteCount]; @@ -69,7 +70,7 @@ public final class fileEditor { } public static byte[] toBytes(long num, int byteCount){ - if(num > (Math.pow(2,byteCount*8)-1)){ + if(num > (Math.pow(lengthHeaderBytes,byteCount*8)-1)){ throw new BufferOverflowException(); } byte[] bytes = new byte[byteCount]; diff --git a/app/src/main/java/com/ridgebotics/ridgescout/utility/settingsManager.java b/app/src/main/java/com/ridgebotics/ridgescout/utility/settingsManager.java index 193df9f..5b7f67b 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/utility/settingsManager.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/utility/settingsManager.java @@ -22,6 +22,7 @@ public class settingsManager { public static final String WifiModeKey = "wifi_mode"; public static final String DataModeKey = "data_view_mode"; + public static final String TeamsDataModeKey = "teams_data_view_mode"; public static final String BtUUIDKey = "bt_uuid"; public static final String FTPEnabled = "ftp_enabled"; public static final String FTPServer = "ftp_server"; @@ -42,6 +43,7 @@ public class settingsManager { hm.put(MatchNumKey, 0); hm.put(AllyPosKey, "red-1"); hm.put(DataModeKey, 0); + hm.put(TeamsDataModeKey, 0); hm.put(BtUUIDKey, UUID.randomUUID().toString()); hm.put(FTPEnabled, false); hm.put(FTPServer, "0.0.0.0"); @@ -67,6 +69,7 @@ public class settingsManager { getEditor() .putInt(MatchNumKey, (int) defaults.get( MatchNumKey )).apply(); getEditor() .putString(AllyPosKey, (String) defaults.get( AllyPosKey )).apply(); getEditor() .putInt(DataModeKey, (int) defaults.get( DataModeKey )).apply(); + getEditor() .putInt(TeamsDataModeKey, (int) defaults.get( TeamsDataModeKey )).apply(); getEditor() .putString(BtUUIDKey, (String) defaults.get( BtUUIDKey )).apply(); @@ -103,6 +106,8 @@ public class settingsManager { public static int getDataMode(){return prefs.getInt( DataModeKey, (int) defaults.get(DataModeKey));} public static void setDataMode(int num){ getEditor().putInt( DataModeKey,num).apply();} + public static int getTeamsDataMode(){return prefs.getInt( TeamsDataModeKey, (int) defaults.get(TeamsDataModeKey));} + public static void setTeamsDataMode(int num){ getEditor().putInt( TeamsDataModeKey,num).apply();} public static String getBtUUID(){return prefs.getString( BtUUIDKey, (String) defaults.get(BtUUIDKey));} public static void setBtUUID(String str){ getEditor().putString( BtUUIDKey,str).apply();} diff --git a/app/src/main/res/layout/fragment_data.xml b/app/src/main/res/layout/fragment_data.xml index 6128fe2..d9c43ee 100644 --- a/app/src/main/res/layout/fragment_data.xml +++ b/app/src/main/res/layout/fragment_data.xml @@ -17,25 +17,35 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> - -