diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 870c88e..38cd282 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -16,12 +16,20 @@ android { namespace = "com.ridgebotics.ridgescout" compileSdk = 34 + dependenciesInfo { + // Disables dependency metadata when building APKs. + includeInApk = false + // Disables dependency metadata when building Android App Bundles. + includeInBundle = false + } + + defaultConfig { applicationId = "com.ridgebotics.ridgescout" minSdk = 24 targetSdk = 34 - versionCode = 3 - versionName = "0.3" + versionCode = 4 + versionName = "0.4" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a92caf9..0515d8a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,8 +15,8 @@ - - + + diff --git a/app/src/main/java/com/ridgebotics/ridgescout/scoutingData/ScoutingDataWriter.java b/app/src/main/java/com/ridgebotics/ridgescout/scoutingData/ScoutingDataWriter.java index 2365332..089ebd3 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/scoutingData/ScoutingDataWriter.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/scoutingData/ScoutingDataWriter.java @@ -3,6 +3,7 @@ package com.ridgebotics.ridgescout.scoutingData; import com.ridgebotics.ridgescout.scoutingData.transfer.transferType; import com.ridgebotics.ridgescout.types.ScoutingArray; import com.ridgebotics.ridgescout.types.data.dataType; +import com.ridgebotics.ridgescout.types.data.intArrType; import com.ridgebotics.ridgescout.types.data.stringType; import com.ridgebotics.ridgescout.types.input.inputType; import com.ridgebotics.ridgescout.types.data.intType; @@ -12,6 +13,7 @@ import com.ridgebotics.ridgescout.utility.BuiltByteParser; import com.ridgebotics.ridgescout.utility.ByteBuilder; import java.util.ArrayList; +import java.util.Arrays; public class ScoutingDataWriter { // private static final int int_type_id = 255; @@ -32,6 +34,9 @@ public class ScoutingDataWriter { bb.addString((String) data[i].forceGetValue()); System.out.println("Saved STR: " + data[i].getName() + ", ("+ data[i].get() +")"); break; + case NUMARR: + bb.addIntArray((int[]) data[i].forceGetValue()); + System.out.println("Saved INT Array: " + data[i].getName() + ", ("+ Arrays.toString((int[]) data[i].get()) +")"); } } byte[] bytes = bb.build(); @@ -73,6 +78,11 @@ public class ScoutingDataWriter { dataTypes[i].forceSetValue(objects.get(i+2).get()); System.out.println("Loaded STR: " + values[version][i].name + ", ("+ dataTypes[i].get() +")"); break; + case 3: // Int array + dataTypes[i] = intArrType.newNull(values[version][i].name); + dataTypes[i].forceSetValue(objects.get(i+2).get()); + System.out.println("Loaded intARR: " + values[version][i].name + ", ("+ Arrays.toString((int[])dataTypes[i].get()) +")"); + break; } } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/scoutingData/fields.java b/app/src/main/java/com/ridgebotics/ridgescout/scoutingData/fields.java index 257e3a4..2aedf5f 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/scoutingData/fields.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/scoutingData/fields.java @@ -1,7 +1,10 @@ package com.ridgebotics.ridgescout.scoutingData; +import com.ridgebotics.ridgescout.types.input.checkboxType; import com.ridgebotics.ridgescout.types.input.dropdownType; +import com.ridgebotics.ridgescout.types.input.fieldposType; import com.ridgebotics.ridgescout.types.input.inputType; +import com.ridgebotics.ridgescout.types.input.numberType; import com.ridgebotics.ridgescout.types.input.tallyType; import com.ridgebotics.ridgescout.types.input.textType; import com.ridgebotics.ridgescout.types.input.sliderType; @@ -20,6 +23,7 @@ public class fields { public static final inputType[][] default_match_fields = new inputType[][] { { + new fieldposType("Auto start pos", new int[]{0,0}), new tallyType("Auto Notes", 0), new sliderType("Auto Performance", 5, 0, 10), new textType("Auto Comments", ""), @@ -30,16 +34,13 @@ public class fields { new textType("Overall Driving Comments", ""), new sliderType("Score area (AMP <-> Speaker)", 5, 0, 10), new dropdownType("End Condition", new String[]{"Nothing", "Attempted Climb", "Successful Climbed", "Climbed with multiple robots", "Climbed with trap"}, 0), - new dropdownType("Robot Condition", new String[]{"Everything was working", "Something seemed to be broken", "Something was broken", "Missing robot (Joe Johnson)"}, 0), + new dropdownType("Robot Condition", new String[]{"Everything was working", "Something was maybe broken", "Something was broken", "Robot was disabled for part of the match", "Missing robot (Joe Johnson)"}, 0), new textType("Other Comments", "") } }; public static final inputType[][] default_pit_fields = new inputType[][] { { - new sliderType("How good is robot", 5, 0, 10), - new textType("notes", ""), - },{ new sliderType("How good is robot", 5, 0, 10), new sliderType("Test", 1, 0, 10), new textType("notes", ""), @@ -113,6 +114,15 @@ public class fields { case inputType.tallyType: t = new tallyType(); break; + case inputType.numberType: + t = new numberType(); + break; + case inputType.checkboxType: + t = new checkboxType(); + break; + case inputType.fieldposType: + t = new fieldposType(); + break; } t.decode((byte[]) obj.get()); diff --git a/app/src/main/java/com/ridgebotics/ridgescout/types/data/dataType.java b/app/src/main/java/com/ridgebotics/ridgescout/types/data/dataType.java index dd4c119..2de53e9 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/types/data/dataType.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/data/dataType.java @@ -3,7 +3,8 @@ package com.ridgebotics.ridgescout.types.data; public abstract class dataType { public enum valueTypes { NUM, - STRING + NUMARR, + STRING, } private Object value; diff --git a/app/src/main/java/com/ridgebotics/ridgescout/types/data/intArrType.java b/app/src/main/java/com/ridgebotics/ridgescout/types/data/intArrType.java new file mode 100644 index 0000000..16cf748 --- /dev/null +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/data/intArrType.java @@ -0,0 +1,54 @@ +package com.ridgebotics.ridgescout.types.data; + +public class intArrType extends dataType { + public static final int[] nullval = new int[]{255, 255}; +// public static final int unselectedval = 1; + + public valueTypes getValueType() { + return valueTypes.NUMARR; + } + +// public Object getNullValue(){ +// return nullval; +// } +// public Object getUnselectedValue(){ +// return unselectedval; +// } + + public Object get(){ + return (int[]) forceGetValue(); + } + + public void set(Object value){ + forceSetValue((int[]) value); + } + + public intArrType(String name, int[] value) { + super(name); + set(value); + } + + public static intArrType newNull(String name){ + return new intArrType(name, nullval); + } + +// public static intType newUnselected(String name){ +// final intType a = new intType(name, 0); +// a.forceSetValue(unselectedval); +// return a; +// } + + public static boolean isNull(int[] obj){ + return obj == nullval; + } + public boolean isNull() { + return isNull((int[]) forceGetValue()); + } + +// public static boolean isUnselected(int obj){ +// return obj == unselectedval; +// } +// public boolean isUnselected() { +// return isUnselected((int) forceGetValue()); +// } +} \ No newline at end of file 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 new file mode 100644 index 0000000..1bcf035 --- /dev/null +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/input/checkboxType.java @@ -0,0 +1,228 @@ +package com.ridgebotics.ridgescout.types.input; + +import android.content.Context; +import android.graphics.Color; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.constraintlayout.widget.ConstraintLayout; + +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.charts.PieChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.data.PieData; +import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.data.PieEntry; +import com.ridgebotics.ridgescout.types.data.dataType; +import com.ridgebotics.ridgescout.types.data.intType; +import com.ridgebotics.ridgescout.utility.BuiltByteParser; +import com.ridgebotics.ridgescout.utility.ByteBuilder; +import com.skydoves.powerspinner.IconSpinnerAdapter; +import com.skydoves.powerspinner.IconSpinnerItem; +import com.skydoves.powerspinner.OnSpinnerItemSelectedListener; +import com.skydoves.powerspinner.PowerSpinnerView; +import com.skydoves.powerspinner.SpinnerGravity; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +public class checkboxType extends inputType { + public int get_byte_id() {return checkboxType;} + public inputTypes getInputType(){return inputTypes.CHECKBOX;} + public dataType.valueTypes getValueType(){return dataType.valueTypes.NUM;} + public Object get_fallback_value(){return 0;} + public checkboxType(){}; + public String get_type_name(){return "Checkbox";} + public checkboxType(String name, int isChecked){ + super(name); + this.default_value = isChecked; + } + + + public byte[] encode() throws ByteBuilder.buildingException { + ByteBuilder bb = new ByteBuilder(); + bb.addString(name); + bb.addInt((int)default_value); + return bb.build(); + } + public void decode(byte[] bytes) throws BuiltByteParser.byteParsingExeption { + BuiltByteParser bbp = new BuiltByteParser(bytes); + ArrayList objects = bbp.parse(); + + name = (String) objects.get(0).get(); + default_value = objects.get(1).get(); + } + +// public PowerSpinnerView dropdown = null; + + public CheckBox checkBox = null; + + public View createView(Context context, Function onUpdate){ + checkBox = new CheckBox(context); + checkBox.setText(name); + checkBox.setTextSize(24); + setViewValue(default_value); + checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + onUpdate.apply(getViewValue()); + } + }); + + return checkBox; + + } + public void setViewValue(Object value) { + if(checkBox == null) return; + if(intType.isNull((int) value)){ + nullify(); + return; + } + + isBlank = false; + + checkBox.setVisibility(View.VISIBLE); + checkBox.setChecked((int) value == 1); + } + public void nullify(){ + isBlank = true; + checkBox.setVisibility(View.GONE); + } + public dataType getViewValue(){ + if(checkBox == null) return null; + if(checkBox.getVisibility() == View.GONE) return new intType(name, intType.nullval); + return new intType(name, checkBox.isChecked() ? 1 : 0); + } + + + + + + + public void add_individual_view(LinearLayout parent, dataType data){ + if(data.isNull()) return; + CheckBox cb = new CheckBox(parent.getContext()); + cb.setText(name); + cb.setChecked((int) data.get() == 1); + cb.setEnabled(false); + parent.addView(cb); + } + + + + public static int[] colors = {0x7f00ff00, 0x7f7f0000}; + + + public void add_compiled_view(LinearLayout parent, dataType[] data){ + PieChart chart = new PieChart(parent.getContext()); + FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ); + layout.height = 350; + chart.setLayoutParams(layout); + chart.setBackgroundColor(0xff252025); + parent.addView(chart); + + int numTrue = 0; + int numFalse = 0; + + for(int i = 0; i < data.length; i++) + if(!data[i].isNull()){ + if((int) data[i].get() == 1) + numTrue += 1; + else + numFalse += 1; + } + + + List entries = new ArrayList<>(); + + entries.add(new PieEntry((float) numTrue, "True")); + entries.add(new PieEntry((float) numFalse, "False")); + + PieDataSet pieDataSet = new PieDataSet(entries, name); + pieDataSet.setColors(colors); + PieData pieData = new PieData(pieDataSet); + chart.setDrawHoleEnabled(false); + chart.setData(pieData); + } + + + + + + + public void add_history_view(LinearLayout parent, dataType[] data){ + LineChart chart = new LineChart(parent.getContext()); + FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ); + layout.height = 350; + chart.setLayoutParams(layout); + chart.setBackgroundColor(0xff252025); + + LineData lineData = new LineData(); + + List entries = new ArrayList<>(); + for (int a = 0; a < data.length; a++) { + if(data[a].isNull()) continue; + + entries.add( + new Entry(a, + ((int) data[a].get()) + ) + ); + } + + LineDataSet dataSet = new LineDataSet(entries, "is checked"); + dataSet.setColor(Color.RED); + dataSet.setValueTextColor(Color.BLACK); + dataSet.setDrawCircles(false); + dataSet.setDrawValues(false); + dataSet.setValueTextColor(Color.RED); + lineData.addDataSet(dataSet); + + + + + chart.setData(lineData); + chart.invalidate(); + + chart.getDescription().setEnabled(false); + chart.setTouchEnabled(false); + chart.setDragEnabled(false); + chart.setScaleEnabled(false); + + + chart.getXAxis().setTextColor(Color.WHITE); + chart.getAxisLeft().setTextColor(Color.WHITE); + chart.getAxisRight().setTextColor(Color.WHITE); + + chart.getAxisLeft().setAxisMinimum(0.f); + chart.getAxisLeft().setAxisMaximum(1.f); + + chart.getAxisRight().setAxisMinimum(0.f); + chart.getAxisRight().setAxisMaximum(1.f); + + Legend legend = chart.getLegend(); + legend.setTextColor(Color.WHITE); + + chart.invalidate(); + parent.addView(chart); + } +} + 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 new file mode 100644 index 0000000..7cb635c --- /dev/null +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/input/fieldposType.java @@ -0,0 +1,230 @@ +package com.ridgebotics.ridgescout.types.input; + +import static android.text.InputType.TYPE_CLASS_NUMBER; + +import android.content.Context; +import android.graphics.Color; +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 com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; +import com.ridgebotics.ridgescout.R; +import com.ridgebotics.ridgescout.types.data.dataType; +import com.ridgebotics.ridgescout.types.data.intArrType; +import com.ridgebotics.ridgescout.types.data.intType; +import com.ridgebotics.ridgescout.ui.scouting.FieldPosView; +import com.ridgebotics.ridgescout.ui.scouting.MultiFieldPosView; +import com.ridgebotics.ridgescout.utility.BuiltByteParser; +import com.ridgebotics.ridgescout.utility.ByteBuilder; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +public class fieldposType extends inputType { + public int get_byte_id() {return fieldposType;} + public inputTypes getInputType(){return inputTypes.FIELDPOS;} + public dataType.valueTypes getValueType(){return dataType.valueTypes.NUM;} + public Object get_fallback_value(){return 0;} + public fieldposType(){} + public String get_type_name(){return "Field Pos";} + public fieldposType(String name, int[] default_value){ + super(name); + this.default_value = default_value; + } + + + + + + public byte[] encode() throws ByteBuilder.buildingException { + ByteBuilder bb = new ByteBuilder(); + bb.addString(name); + bb.addIntArray((int[]) default_value); + return bb.build(); + } + + public void decode(byte[] bytes) throws BuiltByteParser.byteParsingExeption { + BuiltByteParser bbp = new BuiltByteParser(bytes); + ArrayList objects = bbp.parse(); + + name = (String) objects.get(0).get(); + default_value = objects.get(1).get(); + System.out.println("Defalt value!!!!!" + default_value); + } + + + + + + public FieldPosView field = null; + + public View createView(Context context, Function onUpdate){ + field = new FieldPosView(context, pos -> { + onUpdate.apply(new intArrType(name, pos)); + }); + setViewValue(default_value); + return field; + + } + + public void setViewValue(Object value) { + if(field == null) return; + if(intArrType.isNull((int[]) value)){ + nullify(); + return; + } + + isBlank = false; + field.setVisibility(View.VISIBLE); + field.setPos((int[]) value); + } + public void nullify(){ + isBlank = true; + field.setVisibility(View.GONE); + } + public dataType getViewValue(){ + if(field == null) return null; + if(field.getVisibility() == View.GONE) return intArrType.newNull(name); + return new intArrType(name, field.getPos()); + } + + + + public void add_individual_view(LinearLayout parent, dataType data){ + if(data.isNull()) return; + + FieldPosView fp = new FieldPosView(parent.getContext()); + fp.setEnabled(false); + fp.setPos((int[]) data.get()); + + parent.addView(fp); + } + + + + + + + + + private static float calculateMean(int[] data) { + float sum = 0; + for (int value : data) { + sum += (float) value; + } + return sum / data.length; + } + + private static float calculateStandardDeviation(int[] data, float mean) { + float sum = 0; + for (int value : data) { + sum += (float) Math.pow((float) value - mean, 2); + } + return (float) Math.sqrt(sum / (data.length - 1)); + } + + private static List generateNormalDistribution(float mean, float stdDev, int count, int scale) { + List entries = new ArrayList<>(); + for (int i = 0; i < count; i++) { + float y = (float) ((1 / (stdDev * Math.sqrt(2 * Math.PI))) + * Math.exp(-0.5 * Math.pow(((float) i - mean) / stdDev, 2))); + entries.add(new Entry((float) i, y*scale)); // Scale y for visibility + } + return entries; + } + + private static int findMin(dataType[] data){ + int min = (int)data[0].get(); + for(int i = 1; i < data.length; i++) + if((int)data[i].get() < min) + min = (int)data[i].get(); + return min; + } + + private static int findMax(dataType[] data){ + int max = (int)data[0].get(); + for(int i = 1; i < data.length; i++) + if((int)data[i].get() > max) + max = (int)data[i].get(); + return max; + } + + public void add_compiled_view(LinearLayout parent, dataType[] data){ + MultiFieldPosView mfp = new MultiFieldPosView(parent.getContext()); + for(int i = 0; i < data.length; i++){ + if(data[i].isNull()) continue; + mfp.addPos((int[]) data[i].get()); + } + parent.addView(mfp); + } + + public void add_history_view(LinearLayout parent, dataType[] data){ + LineChart chart = new LineChart(parent.getContext()); + FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ); + layout.height = 350; + chart.setLayoutParams(layout); + chart.setBackgroundColor(0xff252025); + + int min = 0; + int max = 255; + + List entries = new ArrayList<>(); + for (int i = 0; i < data.length; i++){ + if(data[i] == null) continue; + if(data[i].isNull()) continue; + + entries.add(new Entry(i, 255-(float)((int[]) data[i].get())[1])); + } + + LineDataSet dataSet = new LineDataSet(entries, "Field position Y value"); + dataSet.setColor(Color.BLUE); + dataSet.setValueTextColor(Color.BLACK); + dataSet.setDrawCircles(false); + dataSet.setDrawValues(false); + + LineData lineData = new LineData(dataSet); + + chart.setData(lineData); + chart.invalidate(); + + chart.getDescription().setEnabled(false); + chart.setTouchEnabled(false); + chart.setDragEnabled(false); + chart.setScaleEnabled(false); + + dataSet.setValueTextColor(Color.RED); + + chart.getXAxis().setTextColor(Color.WHITE); + chart.getAxisLeft().setTextColor(Color.WHITE); + chart.getAxisRight().setTextColor(Color.WHITE); + + Legend legend = chart.getLegend(); + legend.setTextColor(Color.WHITE); + + + chart.getAxisLeft().setAxisMinimum(min); + chart.getAxisLeft().setAxisMaximum(max); + + chart.getAxisRight().setAxisMinimum(min); + chart.getAxisRight().setAxisMaximum(max); + + + parent.addView(chart); + } +} + 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 347d45f..71818f1 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 @@ -15,11 +15,18 @@ public abstract class inputType { public static final int dropdownType = 254; public static final int notesType = 253; public static final int tallyType = 252; + public static final int numberType = 251; + public static final int checkboxType = 250; + public static final int fieldposType = 249; + public enum inputTypes { SLIDER, DROPDOWN, NOTES_INPUT, - TALLY + TALLY, + NUMBER, + CHECKBOX, + FIELDPOS } public String name; public Object default_value; 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 new file mode 100644 index 0000000..dbff3a9 --- /dev/null +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/input/numberType.java @@ -0,0 +1,319 @@ +package com.ridgebotics.ridgescout.types.input; + +import static android.text.InputType.TYPE_CLASS_NUMBER; + +import android.content.Context; +import android.graphics.Color; +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 com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; +import com.ridgebotics.ridgescout.types.data.dataType; +import com.ridgebotics.ridgescout.types.data.intType; +import com.ridgebotics.ridgescout.utility.BuiltByteParser; +import com.ridgebotics.ridgescout.utility.ByteBuilder; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +public class numberType extends inputType { + public int get_byte_id() {return numberType;} + public inputTypes getInputType(){return inputTypes.NUMBER;} + public dataType.valueTypes getValueType(){return dataType.valueTypes.NUM;} + public Object get_fallback_value(){return 0;} + public numberType(){} + public String get_type_name(){return "Number";} + public numberType(String name, int default_value){ + super(name); + this.default_value = default_value; + } + + + + + + public byte[] encode() throws ByteBuilder.buildingException { + ByteBuilder bb = new ByteBuilder(); + bb.addString(name); + bb.addInt((int)default_value); + return bb.build(); + } + public void decode(byte[] bytes) throws BuiltByteParser.byteParsingExeption { + BuiltByteParser bbp = new BuiltByteParser(bytes); + ArrayList objects = bbp.parse(); + + name = (String) objects.get(0).get(); + default_value = objects.get(1).get(); + } + + + + + + public EditText num = null; + + public View createView(Context context, Function onUpdate){ + num = new EditText(context); + num.setInputType(TYPE_CLASS_NUMBER); + num.addTextChangedListener(new TextWatcher() { + public void afterTextChanged(Editable s) { + onUpdate.apply(getViewValue());} + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + public void onTextChanged(CharSequence s, int start, int before, int count) {} + }); + + setViewValue(default_value); + + return num; + + } + + public void setViewValue(Object value) { + if(num == null) return; + if(intType.isNull((int)value)){ + nullify(); + return; + } + + isBlank = false; + num.setVisibility(View.VISIBLE); + num.setText(String.valueOf(value)); + } + public void nullify(){ + isBlank = true; + num.setVisibility(View.GONE); + } + public dataType getViewValue(){ + if(num == null) return null; + if(num.getVisibility() == View.GONE) return intType.newNull(name); + return new intType(name, safeToInt(num.getText().toString())); + } + + + + private int safeToInt(String num){ + if(num.isEmpty()) + return intType.nullval; + try { + return Integer.parseInt(num); + }catch (NumberFormatException e){ + return intType.nullval; + } + } + + + + + public void add_individual_view(LinearLayout parent, dataType data){ + if(data.isNull()) return; + + 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.valueOf((int) data.get())); + tv.setTextSize(24); + parent.addView(tv); + } + + + + + + + + + private static float calculateMean(int[] data) { + float sum = 0; + for (int value : data) { + sum += (float) value; + } + return sum / data.length; + } + + private static float calculateStandardDeviation(int[] data, float mean) { + float sum = 0; + for (int value : data) { + sum += (float) Math.pow((float) value - mean, 2); + } + return (float) Math.sqrt(sum / (data.length - 1)); + } + + private static List generateNormalDistribution(float mean, float stdDev, int count, int scale) { + List entries = new ArrayList<>(); + for (int i = 0; i < count; i++) { + float y = (float) ((1 / (stdDev * Math.sqrt(2 * Math.PI))) + * Math.exp(-0.5 * Math.pow(((float) i - mean) / stdDev, 2))); + entries.add(new Entry((float) i, y*scale)); // Scale y for visibility + } + return entries; + } + + private static int findMin(dataType[] data){ + int min = (int)data[0].get(); + for(int i = 1; i < data.length; i++) + if((int)data[i].get() < min) + min = (int)data[i].get(); + return min; + } + + private static int findMax(dataType[] data){ + int max = (int)data[0].get(); + for(int i = 1; i < data.length; i++) + if((int)data[i].get() > max) + max = (int)data[i].get(); + return max; + } + + public void add_compiled_view(LinearLayout parent, dataType[] data){ + LineChart chart = new LineChart(parent.getContext()); + FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ); + layout.height = 350; + chart.setLayoutParams(layout); + chart.setBackgroundColor(0xff252025); + + int min = findMin(data); + int max = findMax(data); + + int[] values = new int[max-min+1]; + + for (int i = 0; i < data.length; i++) + if(data[i] != null && data[i].isNull()) + values[(int) data[i].get()-min]++; + + + ArrayList mean_temp = new ArrayList<>(); + for (int i = 0; i < data.length; i++) + if((int)data[i].get() != 0) + mean_temp.add((int) data[i].get()); + + int[] mean_vals = mean_temp.stream().mapToInt(Integer::intValue).toArray(); + + List entries = new ArrayList<>(); + for (int i = 0; i < values.length; i++) + entries.add(new Entry(i, values[i])); + + + LineDataSet dataSet = new LineDataSet(entries, name); + dataSet.setColor(Color.BLUE); + dataSet.setValueTextColor(Color.BLACK); + dataSet.setDrawCircles(false); + dataSet.setDrawValues(false); + + + + // Calculate mean and standard deviation + float mean = calculateMean(mean_vals); + float stdDev = calculateStandardDeviation(mean_vals, mean); + + // Generate normal distribution curve + List normalDistEntries = generateNormalDistribution(mean-min, stdDev, max-min+1, (max-min)/data.length); + + + LineDataSet normalDistSet = new LineDataSet(normalDistEntries, "Normal Distribution"); + normalDistSet.setColor(Color.RED); + normalDistSet.setDrawCircles(false); + normalDistSet.setDrawValues(false); + normalDistSet.setLineWidth(2f); + + LineData lineData = new LineData(dataSet, normalDistSet); + + chart.setData(lineData); + chart.invalidate(); + + chart.getDescription().setEnabled(false); + chart.setTouchEnabled(false); + chart.setDragEnabled(false); + chart.setScaleEnabled(false); + + dataSet.setValueTextColor(Color.RED); + + chart.getXAxis().setTextColor(Color.WHITE); + chart.getAxisLeft().setTextColor(Color.WHITE); + chart.getAxisRight().setTextColor(Color.WHITE); + + Legend legend = chart.getLegend(); + legend.setTextColor(Color.WHITE); + + parent.addView(chart); + } + + + + + public void add_history_view(LinearLayout parent, dataType[] data){ + LineChart chart = new LineChart(parent.getContext()); + FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ); + layout.height = 350; + chart.setLayoutParams(layout); + chart.setBackgroundColor(0xff252025); + + int min = findMin(data); + int max = findMax(data); + + List entries = new ArrayList<>(); + for (int i = 0; i < data.length; i++){ + if(data[i] == null) continue; + if(data[i].isNull()) continue; + + entries.add(new Entry(i, (float)(int) data[i].get())); + } + + + LineDataSet dataSet = new LineDataSet(entries, name); + dataSet.setColor(Color.BLUE); + dataSet.setValueTextColor(Color.BLACK); + dataSet.setDrawCircles(false); + dataSet.setDrawValues(false); + + LineData lineData = new LineData(dataSet); + + chart.setData(lineData); + chart.invalidate(); + + chart.getDescription().setEnabled(false); + chart.setTouchEnabled(false); + chart.setDragEnabled(false); + chart.setScaleEnabled(false); + + dataSet.setValueTextColor(Color.RED); + + chart.getXAxis().setTextColor(Color.WHITE); + chart.getAxisLeft().setTextColor(Color.WHITE); + chart.getAxisRight().setTextColor(Color.WHITE); + + Legend legend = chart.getLegend(); + legend.setTextColor(Color.WHITE); + + + chart.getAxisLeft().setAxisMinimum(min); + chart.getAxisLeft().setAxisMaximum(max); + + chart.getAxisRight().setAxisMinimum(min); + chart.getAxisRight().setAxisMaximum(max); + + + parent.addView(chart); + } +} + diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/FieldEditorHelper.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/FieldEditorHelper.java index ada42c5..2dea62d 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/FieldEditorHelper.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/FieldEditorHelper.java @@ -8,8 +8,11 @@ import android.widget.EditText; import android.widget.TableLayout; import android.widget.TextView; +import com.ridgebotics.ridgescout.types.input.checkboxType; import com.ridgebotics.ridgescout.types.input.dropdownType; +import com.ridgebotics.ridgescout.types.input.fieldposType; import com.ridgebotics.ridgescout.types.input.inputType; +import com.ridgebotics.ridgescout.types.input.numberType; import com.ridgebotics.ridgescout.types.input.sliderType; import com.ridgebotics.ridgescout.types.input.tallyType; import com.ridgebotics.ridgescout.types.input.textType; @@ -19,7 +22,8 @@ public class FieldEditorHelper { private enum parameterTypeEnum { paramNumber, paramString, - paramStringArray + paramStringArray, + paramNumberArray } public static class parameterType { @@ -54,6 +58,15 @@ public class FieldEditorHelper { } } +// public static class paramNumberArray extends parameterType{ +// public int[] val; +// public paramNumberArray(String name, int[] val){ +// this.name = name + " (Number array)"; +// this.val = val; +// this.id = parameterTypeEnum.paramNumberArray; +// } +// } + public static final parameterType[] defaultSliderParams = new parameterType[]{ new paramNumber("Min", 0), new paramNumber("Max", 10), @@ -69,6 +82,16 @@ public class FieldEditorHelper { public static final parameterType[] defaultTallyParams = new parameterType[]{ new paramNumber("Default Value", 0) }; + public static final parameterType[] defaultNumberParams = new parameterType[]{ + new paramNumber("Default Value", 0) + }; + public static final parameterType[] defaultCheckboxParam = new parameterType[]{ + new paramNumber("Default Value ( 1 or 0 )", 0) + }; + public static final parameterType[] defaultFieldPosParam = new parameterType[]{ + new paramNumber("Default X", 0), + new paramNumber("Default Y", 0) + }; private static parameterType[] getSliderParams(sliderType s){ @@ -98,6 +121,25 @@ public class FieldEditorHelper { }; } + private static parameterType[] getNumberParams(numberType s){ + return new parameterType[]{ + new paramNumber("Default Value", (int) s.default_value) + }; + } + + private static parameterType[] getCheckboxParam(checkboxType s){ + return new parameterType[]{ + new paramNumber("Default Value ( 1 or 0 )", (int) s.default_value) + }; + } + + private static parameterType[] getFieldPosParam(fieldposType s){ + return new parameterType[]{ + new paramNumber("Default X", ((int[]) s.default_value)[0]), + new paramNumber("Default Y", ((int[]) s.default_value)[1]) + }; + } + public static void setSliderParams(sliderType s, parameterType[] types){ @@ -119,6 +161,22 @@ public class FieldEditorHelper { s.default_value = ((paramNumber) types[0]).val; } + public static void setNumberParams(numberType s, parameterType[] types){ + s.default_value = ((paramNumber) types[0]).val; + } + + public static void setCheckboxParam(checkboxType s, parameterType[] types){ + s.default_value = ((paramNumber) types[0]).val; + } + + public static void setFieldPosParam(fieldposType s, parameterType[] types){ + s.default_value = new int[]{ + ((paramNumber) types[0]).val, + ((paramNumber) types[1]).val + }; + } + + private static void setInputParameter(inputType t, parameterType[] types){ switch (t.getInputType()){ case TALLY: @@ -133,6 +191,15 @@ public class FieldEditorHelper { case NOTES_INPUT: setTextParams((textType) t, types); break; + case NUMBER: + setNumberParams((numberType) t, types); + break; + case CHECKBOX: + setCheckboxParam((checkboxType) t, types); + break; + case FIELDPOS: + setFieldPosParam((fieldposType) t, types); + break; } } @@ -148,6 +215,12 @@ public class FieldEditorHelper { return getDropdownParams((dropdownType) t); case NOTES_INPUT: return getTextParams((textType) t); + case NUMBER: + return getNumberParams((numberType) t); + case CHECKBOX: + return getCheckboxParam((checkboxType) t); + case FIELDPOS: + return getFieldPosParam((fieldposType) t); } return new parameterType[]{}; } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/FieldsFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/FieldsFragment.java index 26a0544..6caaa9c 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/FieldsFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/FieldsFragment.java @@ -24,8 +24,11 @@ import androidx.navigation.Navigation; import com.ridgebotics.ridgescout.R; import com.ridgebotics.ridgescout.databinding.FragmentDataFieldsBinding; import com.ridgebotics.ridgescout.scoutingData.fields; +import com.ridgebotics.ridgescout.types.input.checkboxType; import com.ridgebotics.ridgescout.types.input.dropdownType; +import com.ridgebotics.ridgescout.types.input.fieldposType; import com.ridgebotics.ridgescout.types.input.inputType; +import com.ridgebotics.ridgescout.types.input.numberType; import com.ridgebotics.ridgescout.types.input.sliderType; import com.ridgebotics.ridgescout.types.input.tallyType; import com.ridgebotics.ridgescout.types.input.textType; @@ -381,6 +384,9 @@ public class FieldsFragment extends Fragment { iconSpinnerItems.add(new IconSpinnerItem("Text")); iconSpinnerItems.add(new IconSpinnerItem("Dropdown")); iconSpinnerItems.add(new IconSpinnerItem("Tally")); + iconSpinnerItems.add(new IconSpinnerItem("Number")); + iconSpinnerItems.add(new IconSpinnerItem("Checkbox")); + iconSpinnerItems.add(new IconSpinnerItem("Field Position")); IconSpinnerAdapter iconSpinnerAdapter = new IconSpinnerAdapter(dropdown); @@ -445,6 +451,24 @@ public class FieldsFragment extends Fragment { FieldEditorHelper.setTallyParams(tally, FieldEditorHelper.defaultTallyParams); addField_Part_4(tally); break; + case 4: + numberType num = new numberType(); + num.name = title; + FieldEditorHelper.setNumberParams(num, FieldEditorHelper.defaultNumberParams); + addField_Part_4(num); + break; + case 5: + checkboxType cb = new checkboxType(); + cb.name = title; + FieldEditorHelper.setCheckboxParam(cb, FieldEditorHelper.defaultCheckboxParam); + addField_Part_4(cb); + break; + case 6: + fieldposType fp = new fieldposType(); + fp.name = title; + FieldEditorHelper.setFieldPosParam(fp, FieldEditorHelper.defaultFieldPosParam); + addField_Part_4(fp); + break; } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/FieldPosView.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/FieldPosView.java new file mode 100644 index 0000000..4ddccb3 --- /dev/null +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/FieldPosView.java @@ -0,0 +1,115 @@ +package com.ridgebotics.ridgescout.ui.scouting; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import com.ridgebotics.ridgescout.R; + +public class FieldPosView extends FrameLayout { + private int x = -1; + private int y = -1; + private Paint paint; + private static final float POINT_RADIUS = 10f; + private ImageView imageView; + private boolean enabled = true; + + public interface onTapListener { + void onUpdate(int[] pos); + }; + + public FieldPosView(Context context) { + super(context); + init(context, pos -> {}); + } + + public FieldPosView(Context context, onTapListener tapListener) { + super(context); + init(context, tapListener); + } + + public FieldPosView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, pos -> {}); + } + + @SuppressLint("ClickableViewAccessibility") + private void init(Context context, onTapListener tl) { + // Initialize paint + paint = new Paint(); + paint.setColor(Color.RED); + paint.setStyle(Paint.Style.FILL); + + + // Create and add ImageView + imageView = new ImageView(context); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + LayoutParams.MATCH_PARENT, + LayoutParams.MATCH_PARENT + ); + imageView.setLayoutParams(params); + imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + imageView.setAdjustViewBounds(true); + addView(imageView); + + // Set touch listener + setOnTouchListener((v, event) -> { + if (enabled && event.getAction() == MotionEvent.ACTION_DOWN) { + x = (int) ((event.getX()/getWidth())*255); + y = (int) ((event.getY()/getHeight())*255); + tl.onUpdate(getPos()); + invalidate(); + return true; + } + return false; + }); + + setImageResource(R.drawable.field_2024); + + } + + public void setPos(int[] pos){ + if(pos.length == 0) return; + x = pos[0]; + y = pos[1]; + invalidate(); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (x >= 0 && y >= 0) { + canvas.drawCircle( + ((float) x /255)*getWidth(), + ((float) y /255)*getHeight(), + POINT_RADIUS, paint); + } + } + + public void setImageResource(int resId) { + imageView.setImageResource(resId); + } + + public void setImageDrawable(Drawable drawable) { + imageView.setImageDrawable(drawable); + } + + public void setImageBitmap(Bitmap bitmap) { + imageView.setImageBitmap(bitmap); + } + + public int[] getPos() { + return new int[]{ + x, + y + }; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/MultiFieldPosView.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/MultiFieldPosView.java new file mode 100644 index 0000000..bddde95 --- /dev/null +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/MultiFieldPosView.java @@ -0,0 +1,86 @@ +package com.ridgebotics.ridgescout.ui.scouting; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import com.ridgebotics.ridgescout.R; + +import java.util.ArrayList; +import java.util.List; + +public class MultiFieldPosView extends FrameLayout { + private Paint paint; + private static final float POINT_RADIUS = 10f; + private ImageView imageView; + private List points = new ArrayList<>(); + + public MultiFieldPosView(Context context) { + super(context); + init(context); + } + + public MultiFieldPosView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } + + @SuppressLint("ClickableViewAccessibility") + private void init(Context context) { + // Initialize paint + paint = new Paint(); + paint.setColor(Color.RED); + paint.setStyle(Paint.Style.FILL); + + + // Create and add ImageView + imageView = new ImageView(context); + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, + LayoutParams.MATCH_PARENT + ); + imageView.setLayoutParams(params); + imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + imageView.setAdjustViewBounds(true); + addView(imageView); + + setImageResource(R.drawable.field_2024); + + } + + public void addPos(int[] pos){ + if(pos.length != 2) return; + points.add(new Integer[]{ + pos[0], + pos[1] + }); + invalidate(); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + for(int i = 0; i < points.size(); i++){ + int x = points.get(i)[0]; + int y = points.get(i)[1]; + if (x >= 0 && y >= 0) { + canvas.drawCircle( + ((float) x / 255) * getWidth(), + ((float) y / 255) * getHeight(), + POINT_RADIUS, paint); + } + } + } + + public void setImageResource(int resId) { + imageView.setImageResource(resId); + } +} \ No newline at end of file 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 03150be..a24b02b 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 @@ -92,50 +92,6 @@ public class PitScoutingFragment extends Fragment { } -// public void init(frcEvent event){ -// -// evcode = event.eventCode; -// this.event = event; -// username = latestSettings.settings.get_username(); -// -//// binding.eventcode.setText(evcode); -// -// binding.pitBackButton.setOnClickListener(view -> { -// if(edited) save(); -// binding.pitTeamName.setVisibility(View.GONE); -// binding.pitTeamDescription.setVisibility(View.GONE); -// clear_fields(); -// load_teams(); -// }); -// -// values = fields.load(fields.pitsFieldsFilename); -// -// if(values == null || values.length == 0){ -// TextView tv = new TextView(getContext()); -// tv.setText("Failed to load fields.\nTry to either download or create pit scouting fields."); -// tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); -// binding.pitScoutArea.addView(tv); -// return; -// } -// -// latest_values = values[values.length-1]; -// transferValues = transferType.get_transfer_values(values); -// } -// -// public void clear_fields(){ -// int childCount = binding.pitScoutArea.getChildCount(); -// View[] views = new View[childCount]; -// -// for(int i = 0; i < childCount; i++){ -// views[i] = binding.pitScoutArea.getChildAt(i); -// } -// -// for(int i = 0; i < childCount; i++){ -// if(!views[i].isShown()) continue; -// binding.pitScoutArea.removeView(views[i]); -// } -// } - public void loadTeam(){ // clear_fields(); @@ -147,9 +103,6 @@ public class PitScoutingFragment extends Fragment { binding.pitTeamDescription.setText(team.getDescription()); binding.pitBarTeamNum.setText(String.valueOf(team.teamNumber)); -// binding.teamName.setText(team.teamName); -// binding.teamDescription.setText(team.getDescription()); - filename = evcode + "-" + team.teamNumber + ".pitscoutdata"; boolean new_file = !fileEditor.fileExist(filename); @@ -195,11 +148,7 @@ public class PitScoutingFragment extends Fragment { int fi = i; tv.setOnClickListener(p -> { -// boolean blank = !latest_values[fi].getViewValue().isNull(); - -// System.out.println(blank); - - asm.update(); + update_asm(); if(!pit_latest_values[fi].isBlank){ tv.setBackgroundColor(0xffff0000); diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/StatusFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/StatusFragment.java index 71ea7b3..ceb47b8 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/StatusFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/StatusFragment.java @@ -40,6 +40,7 @@ public class StatusFragment extends Fragment { } public static int color_found = 0x7f00ff00; public static int color_not_found = 0x7f7f0000; + private void addTableText(TableRow tr, String textStr){ TextView text = new TextView(getContext()); text.setTextSize(18); 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 11e332b..3c61074 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 @@ -19,6 +19,7 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import com.ridgebotics.ridgescout.databinding.FragmentSettingsBinding; +import com.ridgebotics.ridgescout.types.data.intType; import com.ridgebotics.ridgescout.utility.fileEditor; import com.ridgebotics.ridgescout.utility.settingsManager; @@ -41,6 +42,17 @@ public class settingsFragment extends Fragment { dropdown.setAdapter(adapter); } + private int safeToInt(String num){ + if(num.isEmpty()) + return 0; + try { + return Integer.parseInt(num); + }catch (NumberFormatException e){ + return 0; + } + } + + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -163,7 +175,7 @@ public class settingsFragment extends Fragment { team_num.addTextChangedListener(new TextWatcher() { public void afterTextChanged(Editable s) { - settingsManager.setTeamNum(Integer.parseInt(team_num.getText().toString())); + settingsManager.setTeamNum(safeToInt(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) {} diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/bluetooth/BluetoothReceiver.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/bluetooth/BluetoothReceiver.java index 68fc79a..c958849 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/bluetooth/BluetoothReceiver.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/bluetooth/BluetoothReceiver.java @@ -74,9 +74,9 @@ public class BluetoothReceiver { permissionsNeeded.add(Manifest.permission.BLUETOOTH_ADMIN); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - permissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION); - } +// if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { +// permissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION); +// } } } @@ -94,11 +94,11 @@ public class BluetoothReceiver { boolean hasBasicPermissions = ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_GRANTED; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - return hasBasicPermissions && ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; - } else { +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { +// return hasBasicPermissions && ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; +// } else { return hasBasicPermissions; - } +// } } } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/bluetooth/BluetoothSender.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/bluetooth/BluetoothSender.java index 3c2c7fc..eafc18d 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/bluetooth/BluetoothSender.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/bluetooth/BluetoothSender.java @@ -70,7 +70,7 @@ public class BluetoothSender { } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - permissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION); +// permissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION); } } } @@ -89,11 +89,11 @@ public class BluetoothSender { boolean hasBasicPermissions = ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_GRANTED; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - return hasBasicPermissions && ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; - } else { +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { +// return hasBasicPermissions && ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; +// } else { return hasBasicPermissions; - } +// } } } 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 1950fe7..9a7ef9f 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/utility/BuiltByteParser.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/utility/BuiltByteParser.java @@ -2,6 +2,7 @@ package com.ridgebotics.ridgescout.utility; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; public class BuiltByteParser { public static final Integer boolType = 0; @@ -121,6 +122,7 @@ public class BuiltByteParser { intArrayObject ia = new intArrayObject(); ia.arr = intArr; + System.out.println(Arrays.toString(intArr)); objects.add(ia); break; case 4: diff --git a/app/src/main/res/drawable/field_2024.png b/app/src/main/res/drawable/field_2024.png new file mode 100644 index 0000000..a2a7665 Binary files /dev/null and b/app/src/main/res/drawable/field_2024.png differ