mirror of
https://github.com/Team4388/RidgeScout.git
synced 2026-06-09 08:38:03 -06:00
Compare commits
1 Commits
v3.1
...
test-branch
| Author | SHA1 | Date | |
|---|---|---|---|
| b41ed2667c |
@@ -24,6 +24,7 @@ public abstract class FieldType {
|
||||
public static final int numberType = 251;
|
||||
public static final int checkboxType = 250;
|
||||
public static final int fieldposType = 249;
|
||||
public static final int toggleType = 248;
|
||||
|
||||
public enum inputTypes {
|
||||
SLIDER,
|
||||
@@ -32,7 +33,8 @@ public abstract class FieldType {
|
||||
TALLY,
|
||||
NUMBER,
|
||||
CHECKBOX,
|
||||
FIELDPOS
|
||||
FIELDPOS,
|
||||
TOGGLE;
|
||||
}
|
||||
public String UUID;
|
||||
public String name;
|
||||
@@ -89,8 +91,6 @@ public abstract class FieldType {
|
||||
public abstract void setViewValue(Object value);
|
||||
public abstract RawDataType getViewValue();
|
||||
|
||||
|
||||
|
||||
public abstract void add_individual_view(LinearLayout parent, RawDataType data);
|
||||
public abstract void add_compiled_view(LinearLayout parent, RawDataType[] data);
|
||||
public abstract void add_history_view(LinearLayout parent, RawDataType[] data);
|
||||
|
||||
@@ -65,6 +65,7 @@ public class TallyType extends FieldType {
|
||||
|
||||
public TallyCounterView tally = null;
|
||||
|
||||
|
||||
public View createView(Context context, Function<RawDataType, Integer> onUpdate){
|
||||
tally = new TallyCounterView(context);
|
||||
tally.setOnCountChangedListener(n -> onUpdate.apply(getViewValue()));
|
||||
|
||||
@@ -0,0 +1,368 @@
|
||||
package com.ridgebotics.ridgescout.types.input;
|
||||
|
||||
import static com.ridgebotics.ridgescout.utility.Colors.chart_background;
|
||||
import static com.ridgebotics.ridgescout.utility.Colors.chart_text;
|
||||
import static com.ridgebotics.ridgescout.utility.Colors.dropdown_value_text_1;
|
||||
import static com.ridgebotics.ridgescout.utility.Colors.dropdown_value_text_2;
|
||||
import static com.ridgebotics.ridgescout.utility.Colors.tally_data;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TableRow;
|
||||
import android.widget.TextView;
|
||||
|
||||
import 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.IntType;
|
||||
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||
import com.ridgebotics.ridgescout.ui.data.DataProcessing;
|
||||
import com.ridgebotics.ridgescout.ui.views.CandlestickHeader;
|
||||
import com.ridgebotics.ridgescout.ui.views.CandlestickView;
|
||||
import com.ridgebotics.ridgescout.ui.views.TallyCounterView;
|
||||
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ToggleType extends FieldType {
|
||||
public int get_byte_id() {return toggleType;}
|
||||
public inputTypes getInputType(){return inputTypes.TOGGLE;}
|
||||
public RawDataType.valueTypes getValueType(){return RawDataType.valueTypes.NUM;}
|
||||
public Object get_fallback_value(){return 0;}
|
||||
public ToggleType(){}
|
||||
public String get_type_name(){return "Toggle";}
|
||||
public ToggleType(String UUID, String name, String description, int default_value){
|
||||
super(UUID, name, description);
|
||||
this.default_value = default_value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void encodeData(ByteBuilder bb) throws ByteBuilder.buildingException {
|
||||
bb.addInt((int) default_value);
|
||||
}
|
||||
public void decodeData(ArrayList<BuiltByteParser.parsedObject> objects) {
|
||||
default_value = objects.get(0).get();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public TallyCounterView tally = null;
|
||||
|
||||
|
||||
public View createView(Context context, Function<RawDataType, Integer> onUpdate){
|
||||
tally = new TallyCounterView(context);
|
||||
tally.setOnCountChangedListener(n -> onUpdate.apply(getViewValue()));
|
||||
|
||||
setViewValue(default_value);
|
||||
|
||||
return tally;
|
||||
|
||||
}
|
||||
|
||||
public void setViewValue(Object value) {
|
||||
if(tally == null) return;
|
||||
if(IntType.isNull((int)value)){
|
||||
nullify();
|
||||
return;
|
||||
}
|
||||
|
||||
isBlank = false;
|
||||
tally.setVisibility(View.VISIBLE);
|
||||
tally.setValue((int) value);
|
||||
}
|
||||
public void nullify(){
|
||||
isBlank = true;
|
||||
tally.setVisibility(View.GONE);
|
||||
}
|
||||
public RawDataType getViewValue(){
|
||||
if(tally == null) return null;
|
||||
if(tally.getVisibility() == View.GONE) return IntType.newNull(name);
|
||||
return new IntType(name, tally.getValue());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void add_individual_view(LinearLayout parent, RawDataType 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(RawDataType[] 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(RawDataType[] 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, RawDataType[] 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(tally_data);
|
||||
dataSet.setValueTextColor(dropdown_value_text_1);
|
||||
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(dropdown_value_text_2);
|
||||
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(dropdown_value_text_2);
|
||||
|
||||
chart.getXAxis().setTextColor(chart_text);
|
||||
chart.getAxisLeft().setTextColor(chart_text);
|
||||
chart.getAxisRight().setTextColor(chart_text);
|
||||
|
||||
Legend legend = chart.getLegend();
|
||||
legend.setTextColor(chart_text);
|
||||
|
||||
parent.addView(chart);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void add_history_view(LinearLayout parent, RawDataType[] 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(chart_background);
|
||||
|
||||
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(tally_data);
|
||||
dataSet.setValueTextColor(dropdown_value_text_1);
|
||||
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(dropdown_value_text_2);
|
||||
|
||||
chart.getXAxis().setTextColor(chart_text);
|
||||
chart.getAxisLeft().setTextColor(chart_text);
|
||||
chart.getAxisRight().setTextColor(chart_text);
|
||||
|
||||
Legend legend = chart.getLegend();
|
||||
legend.setTextColor(chart_text);
|
||||
|
||||
|
||||
chart.getAxisLeft().setAxisMinimum(min);
|
||||
chart.getAxisLeft().setAxisMaximum(max);
|
||||
|
||||
chart.getAxisRight().setAxisMinimum(min);
|
||||
chart.getAxisRight().setAxisMaximum(max);
|
||||
|
||||
|
||||
parent.addView(chart);
|
||||
}
|
||||
|
||||
public void addDataToTable(TableLayout parent, Map<Integer, List<RawDataType>> data){
|
||||
int[] tmp_abs_bounds = DataProcessing.getNumberBounds(data);
|
||||
int absmin = tmp_abs_bounds[0];
|
||||
int absmax = tmp_abs_bounds[1];
|
||||
|
||||
//(int[]) teamData.get(i).get())[0];
|
||||
// AlertManager.alert("Results","Min: " + min + " Max: " + max);
|
||||
|
||||
parent.removeAllViews();
|
||||
|
||||
List<CandlestickView> views = new ArrayList<>();
|
||||
|
||||
for(Integer teamNum : data.keySet()){
|
||||
CandlestickView candlestickView = new CandlestickView(parent.getContext());
|
||||
candlestickView.fromTeamData(data.get(teamNum), teamNum, absmin, absmax);
|
||||
views.add(candlestickView);
|
||||
}
|
||||
|
||||
|
||||
TableRow row = new TableRow(parent.getContext());
|
||||
|
||||
// Make candlestick chart fill full width
|
||||
parent.setColumnStretchable(1, true);
|
||||
|
||||
// Fill in top left cell
|
||||
row.addView(new View(parent.getContext()));
|
||||
|
||||
CandlestickHeader header = new CandlestickHeader(parent.getContext());
|
||||
header.setScale(absmin, absmax);
|
||||
row.addView(header);
|
||||
|
||||
parent.addView(row);
|
||||
|
||||
// parent.addView(new );
|
||||
|
||||
try {
|
||||
Collections.sort(views, (a, b) -> (int) ((b.average - a.average) * 50.f));
|
||||
}catch (Exception e){}
|
||||
|
||||
for(int i = 0; i < views.size(); i++){
|
||||
row = new TableRow(parent.getContext());
|
||||
CandlestickView view = views.get(i);
|
||||
|
||||
TextView teamNum = new TextView(parent.getContext());
|
||||
TableRow.LayoutParams params = new TableRow.LayoutParams();
|
||||
params.gravity = Gravity.CENTER;
|
||||
teamNum.setLayoutParams(params);
|
||||
teamNum.setPadding(10,10,10,10);
|
||||
teamNum.setTextAppearance(com.google.android.material.R.style.TextAppearance_MaterialComponents_Headline6);
|
||||
teamNum.setText(String.valueOf(view.teamNum));
|
||||
|
||||
|
||||
row.addView(teamNum);
|
||||
row.addView(view);
|
||||
|
||||
parent.addView(row);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString(RawDataType data){
|
||||
return String.valueOf((int) data.get());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ 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;
|
||||
import com.ridgebotics.ridgescout.types.input.ToggleType;
|
||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
@@ -29,7 +30,8 @@ public class FieldEditorHelper {
|
||||
paramNumber,
|
||||
paramString,
|
||||
paramStringArray,
|
||||
paramNumberArray
|
||||
paramNumberArray,
|
||||
paramBoolean
|
||||
}
|
||||
|
||||
public static class parameterType {
|
||||
@@ -64,6 +66,15 @@ public class FieldEditorHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public static class paramBoolean extends parameterType{
|
||||
public boolean val;
|
||||
public paramBoolean(String name, boolean val){
|
||||
this.name = name + " (Boolean)";
|
||||
this.val = val;
|
||||
this.id = parameterTypeEnum.paramBoolean;
|
||||
}
|
||||
}
|
||||
|
||||
// public static class paramNumberArray extends parameterType{
|
||||
// public int[] val;
|
||||
// public paramNumberArray(String name, int[] val){
|
||||
@@ -113,6 +124,12 @@ public class FieldEditorHelper {
|
||||
new paramNumber("Default Y", 0)
|
||||
};
|
||||
|
||||
public static final parameterType[] defaultToggleParam = new parameterType[]{
|
||||
new paramString("Name", "New Toggle"),
|
||||
new paramString("Description", ""),
|
||||
new paramBoolean("Default true or false",true)
|
||||
};
|
||||
|
||||
|
||||
private static parameterType[] getSliderParams(SliderType s){
|
||||
return new parameterType[]{
|
||||
@@ -173,6 +190,13 @@ public class FieldEditorHelper {
|
||||
new paramNumber("Default Y", ((int[]) s.default_value)[1])
|
||||
};
|
||||
}
|
||||
private static parameterType[] getToggleParams(ToggleType s){
|
||||
return new parameterType[]{
|
||||
new paramString("Name", s.name),
|
||||
new paramString("Description", s.description),
|
||||
new paramBoolean("Default true or false", (boolean) s.default_value)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -224,6 +248,12 @@ public class FieldEditorHelper {
|
||||
};
|
||||
}
|
||||
|
||||
public static void setToggleParam(ToggleType s, parameterType[] types){
|
||||
s.name = ((paramString) types[0]).val;
|
||||
s.description = ((paramString) types[1]).val;
|
||||
s.default_value = ((paramBoolean) types[2]).val;
|
||||
}
|
||||
|
||||
|
||||
private static void setInputParameter(FieldType t, parameterType[] types){
|
||||
switch (t.getInputType()){
|
||||
@@ -248,6 +278,9 @@ public class FieldEditorHelper {
|
||||
case FIELDPOS:
|
||||
setFieldPosParam((FieldposType) t, types);
|
||||
break;
|
||||
case TOGGLE:
|
||||
setToggleParam((ToggleType) t, types);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,6 +302,8 @@ public class FieldEditorHelper {
|
||||
return getCheckboxParam((CheckboxType) t);
|
||||
case FIELDPOS:
|
||||
return getFieldPosParam((FieldposType) t);
|
||||
case TOGGLE:
|
||||
return getToggleParams((ToggleType) t);
|
||||
}
|
||||
return new parameterType[]{};
|
||||
}
|
||||
@@ -305,6 +340,16 @@ public class FieldEditorHelper {
|
||||
));
|
||||
return text;
|
||||
}
|
||||
private static View createBooleanEdit(Context c, boolean value){
|
||||
EditText text = new EditText(c);
|
||||
text.setText(value);
|
||||
text.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
private static View createEdit(Context c, parameterType t){
|
||||
switch (t.id){
|
||||
@@ -384,6 +429,11 @@ public class FieldEditorHelper {
|
||||
fieldposType.UUID = UUID.randomUUID().toString();
|
||||
setFieldPosParam(fieldposType, defaultFieldPosParam);
|
||||
return fieldposType;
|
||||
case 7:
|
||||
ToggleType toggleType = new ToggleType();
|
||||
toggleType.UUID = UUID.randomUUID().toString();
|
||||
setToggleParam(toggleType, defaultToggleParam);
|
||||
return toggleType;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user