Add more types of fields, F-droid fixes

This commit is contained in:
Astatin3
2024-09-28 12:43:19 -06:00
parent d607f95a8a
commit 60d56473f5
21 changed files with 1205 additions and 76 deletions
@@ -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;
}
}
@@ -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());
@@ -3,7 +3,8 @@ package com.ridgebotics.ridgescout.types.data;
public abstract class dataType {
public enum valueTypes {
NUM,
STRING
NUMARR,
STRING,
}
private Object value;
@@ -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());
// }
}
@@ -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<BuiltByteParser.parsedObject> 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<dataType, Integer> 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<PieEntry> 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<Entry> 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);
}
}
@@ -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<BuiltByteParser.parsedObject> 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<dataType, Integer> 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<Entry> generateNormalDistribution(float mean, float stdDev, int count, int scale) {
List<Entry> 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<Entry> 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);
}
}
@@ -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;
@@ -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<BuiltByteParser.parsedObject> 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<dataType, Integer> 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<Entry> generateNormalDistribution(float mean, float stdDev, int count, int scale) {
List<Entry> 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<Integer> 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<Entry> 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<Entry> 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<Entry> 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);
}
}
@@ -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[]{};
}
@@ -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;
}
@@ -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
};
}
}
@@ -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<Integer[]> 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);
}
}
@@ -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);
@@ -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);
@@ -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) {}
@@ -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;
}
// }
}
}
@@ -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;
}
// }
}
}
@@ -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: