1 Commits

Author SHA1 Message Date
Daniel Carta b41ed2667c Testing 9/18 2025-09-18 17:51:05 -06:00
51 changed files with 1079 additions and 1446 deletions
+2 -2
View File
@@ -28,9 +28,9 @@
- Statbotics intgration - Statbotics intgration
- Scout error estimation using OPR-like calculation - Scout error estimation using OPR-like calculation
- - Would most likely require Statbotics - - Would most likely require Statbotics
https://www.thebluealliance.com/avatars
### Screenshots ### Screenshots
|Match scouting interface|Field editor|Teams data viewer| |Match scouting interface|Field editor|Teams data viewer|
|-|-|-| |-|-|-|
|![Screenshot1](https://github.com/Team4388/ScoutingApp2025/blob/main/metadata/en-US/images/phoneScreenshots/1.png?raw=true)|![Screenshot2](https://github.com/Team4388/ScoutingApp2025/blob/main/metadata/en-US/images/phoneScreenshots/2.png?raw=true)|![Screenshot3](https://github.com/Team4388/ScoutingApp2025/blob/main/metadata/en-US/images/phoneScreenshots/3.png?raw=true)| |![Screenshot1](https://github.com/Team4388/ScoutingApp2025/blob/main/metadata/en-US/images/phoneScreenshots/1.png?raw=true)|![Screenshot2](https://github.com/Team4388/ScoutingApp2025/blob/main/metadata/en-US/images/phoneScreenshots/2.png?raw=true)|![Screenshot3](https://github.com/Team4388/ScoutingApp2025/blob/main/metadata/en-US/images/phoneScreenshots/3.png?raw=true)|
z
+6 -8
View File
@@ -57,21 +57,19 @@ dependencies {
implementation(libs.constraintlayout) implementation(libs.constraintlayout)
implementation(libs.lifecycle.livedata.ktx) implementation(libs.lifecycle.livedata.ktx)
implementation(libs.lifecycle.viewmodel.ktx) implementation(libs.lifecycle.viewmodel.ktx)
implementation(libs.navigation.fragment.v289) implementation("androidx.navigation:navigation-fragment:2.8.9")
implementation(libs.navigation.ui) implementation(libs.navigation.ui)
implementation(libs.preference) implementation(libs.preference)
// implementation(libs.asynclayoutinflator) // implementation(libs.support.annotations)
testImplementation(libs.junit) testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit) androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core) androidTestImplementation(libs.espresso.core)
var camerax_version = "1.4.2" var camerax_version = "1.3.2"
implementation("androidx.camera:camera-core:${camerax_version}") implementation("androidx.camera:camera-core:1.3.2")
implementation("androidx.camera:camera-camera2:${camerax_version}") implementation("androidx.camera:camera-camera2:1.3.2")
implementation("androidx.camera:camera-lifecycle:${camerax_version}") implementation("androidx.camera:camera-lifecycle:1.3.2")
implementation("androidx.camera:camera-view:${camerax_version}") implementation("androidx.camera:camera-view:${camerax_version}")
implementation("com.journeyapps:zxing-android-embedded:4.3.0") implementation("com.journeyapps:zxing-android-embedded:4.3.0")
@@ -1,4 +0,0 @@
package com.ridgebotics.ridgescout.types;
public class ColabArray {
}
@@ -9,13 +9,14 @@ import com.ridgebotics.ridgescout.utility.ByteBuilder;
import com.ridgebotics.ridgescout.utility.SettingsManager; import com.ridgebotics.ridgescout.utility.SettingsManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.IntStream; import java.util.stream.IntStream;
// Class to contain data for an entire event. // Class to contain data for an entire event.
// Easily encoded and decoded to binary format. // Easily encoded and decoded to binary format.
public class frcEvent { public class frcEvent {
public static final int typecode = 254;
public String eventCode; public String eventCode;
public String name; public String name;
public ArrayList<frcMatch> matches; public ArrayList<frcMatch> matches;
@@ -133,29 +134,29 @@ public class frcEvent {
return null; return null;
} }
// public
// Returns the soonest match that there will be all the possible upcoming data on other teams // Returns the soonest match that there will be all the possible upcoming data on other teams
public int getMostInformedBy(int ourTeamNum, int curMatch){ public void getReportMatches(int ourTeamNum){
frcMatch teamMatch = getNextTeamMatch(ourTeamNum, curMatch); frcMatch[] teamMatches = event.getTeamMatches(ourTeamNum);
int maxMatch = Integer.MIN_VALUE; for(int i = 0; i < teamMatches.length; i++){
int maxMatch = -1;
for(int a = 0; a < 6; a++){
int teamNum;
if(a < 3)
teamNum = teamMatches[i].redAlliance[a];
else
teamNum = teamMatches[i].blueAlliance[a-3];
for(int a = 0; a < 6; a++){ if(teamNum == ourTeamNum)
int teamNum; continue;
if(a < 3)
teamNum = teamMatch.redAlliance[a];
else
teamNum = teamMatch.blueAlliance[a-3];
if(teamNum == ourTeamNum) int matchNum = event.getMostRecentTeamMatch(teamNum, teamMatches[i].matchIndex);
continue; if(maxMatch < matchNum)
maxMatch = matchNum;
int matchNum = event.getMostRecentTeamMatch(teamNum, teamMatch.matchIndex); }
if(maxMatch < matchNum)
maxMatch = matchNum;
} }
return maxMatch;
} }
public frcTeam getTeamByNum(int teamNum){ public frcTeam getTeamByNum(int teamNum){
@@ -167,26 +168,6 @@ public class frcEvent {
return null; return null;
} }
public List<frcTeam> getTeamsSorted() {
int[] teamNums = new int[teams.size()];
for(int i = 0 ; i < teams.size(); i++){
teamNums[i] = teams.get(i).teamNumber;
}
Arrays.sort(teamNums);
List<frcTeam> list = new ArrayList<>();
for(int i = 0; i < teams.size(); i++){
frcTeam team = getTeamByNum(teamNums[i]);
assert team != null;
list.add(team);
}
return list;
}
public boolean getIsBlueAlliance(int teamNum, int matchNum){ public boolean getIsBlueAlliance(int teamNum, int matchNum){
return getIsBlueAlliance(teamNum, matches.get(matchNum)); return getIsBlueAlliance(teamNum, matches.get(matchNum));
@@ -24,6 +24,7 @@ public abstract class FieldType {
public static final int numberType = 251; public static final int numberType = 251;
public static final int checkboxType = 250; public static final int checkboxType = 250;
public static final int fieldposType = 249; public static final int fieldposType = 249;
public static final int toggleType = 248;
public enum inputTypes { public enum inputTypes {
SLIDER, SLIDER,
@@ -32,7 +33,8 @@ public abstract class FieldType {
TALLY, TALLY,
NUMBER, NUMBER,
CHECKBOX, CHECKBOX,
FIELDPOS FIELDPOS,
TOGGLE;
} }
public String UUID; public String UUID;
public String name; public String name;
@@ -89,8 +91,6 @@ public abstract class FieldType {
public abstract void setViewValue(Object value); public abstract void setViewValue(Object value);
public abstract RawDataType getViewValue(); public abstract RawDataType getViewValue();
public abstract void add_individual_view(LinearLayout parent, RawDataType data); public abstract void add_individual_view(LinearLayout parent, RawDataType data);
public abstract void add_compiled_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); public abstract void add_history_view(LinearLayout parent, RawDataType[] data);
@@ -65,6 +65,7 @@ public class TallyType extends FieldType {
public TallyCounterView tally = null; public TallyCounterView tally = null;
public View createView(Context context, Function<RawDataType, Integer> onUpdate){ public View createView(Context context, Function<RawDataType, Integer> onUpdate){
tally = new TallyCounterView(context); tally = new TallyCounterView(context);
tally.setOnCountChangedListener(n -> onUpdate.apply(getViewValue())); 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());
}
}
@@ -19,12 +19,9 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import com.ridgebotics.ridgescout.R;
import com.ridgebotics.ridgescout.types.frcTeam; import com.ridgebotics.ridgescout.types.frcTeam;
import com.ridgebotics.ridgescout.ui.views.FieldBorderedRow; import com.ridgebotics.ridgescout.ui.views.FieldBorderedRow;
import com.ridgebotics.ridgescout.ui.views.RecyclerList;
import com.ridgebotics.ridgescout.ui.views.TeamListOption; import com.ridgebotics.ridgescout.ui.views.TeamListOption;
import com.ridgebotics.ridgescout.utility.DataManager; import com.ridgebotics.ridgescout.utility.DataManager;
import com.ridgebotics.ridgescout.utility.SettingsManager; import com.ridgebotics.ridgescout.utility.SettingsManager;
@@ -47,7 +44,7 @@ public class DataFragment extends Fragment {
@Nullable Bundle savedInstanceState) { @Nullable Bundle savedInstanceState) {
binding = FragmentDataBinding.inflate(inflater, container, false); binding = FragmentDataBinding.inflate(inflater, container, false);
// binding.table.setStretchAllColumns(true); binding.table.setStretchAllColumns(true);
View root = binding.getRoot(); View root = binding.getRoot();
if(evcode == null || evcode.equals("unset") || event == null){ if(evcode == null || evcode.equals("unset") || event == null){
@@ -89,21 +86,35 @@ public class DataFragment extends Fragment {
public void load_teams(){ public void load_teams(){
RecyclerList<frcTeam> list = new RecyclerList<>(getContext()); int[] teamNums = new int[event.teams.size()];
binding.table.addView(list);
// list.setView
list for(int i = 0 ; i < event.teams.size(); i++){
.setup(R.layout.view_team_option, TeamListOption::new) teamNums[i] = event.teams.get(i).teamNumber;
.withLinearLayout() }
.withDivider()
.withItemClickListener((team, position) -> { Arrays.sort(teamNums);
TeamsFragment.setTeam(team);
for(int i = 0; i < event.teams.size(); i++){
frcTeam team = null;
for(int a = 0 ; a < event.teams.size(); a++){
if(event.teams.get(a).teamNumber == teamNums[i]){
team = event.teams.get(a);
break;
}
}
assert team != null;
TeamListOption teamRow = new TeamListOption(getContext());
binding.table.addView(teamRow);
teamRow.fromTeam(team);
frcTeam finalTeam = team;
teamRow.setOnClickListener(v -> {
TeamsFragment.setTeam(finalTeam);
((DataParentFragment) getParentFragment()).moveToFragment(new TeamsFragment()); ((DataParentFragment) getParentFragment()).moveToFragment(new TeamsFragment());
// findNavController(this).navigate(R.id.action_navigation_data_parent_to_navigation_data_teams);
}); });
}
list.setItems(event.getTeamsSorted());
} }
public void load_fields(){ public void load_fields(){
DataManager.reload_match_fields(); DataManager.reload_match_fields();
@@ -20,7 +20,6 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import com.google.android.material.divider.MaterialDivider; import com.google.android.material.divider.MaterialDivider;
import com.ridgebotics.ridgescout.ui.views.PitScoutingIndicator;
import com.ridgebotics.ridgescout.ui.views.ToggleTitleView; import com.ridgebotics.ridgescout.ui.views.ToggleTitleView;
import com.ridgebotics.ridgescout.utility.AlertManager; import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.SettingsManager; import com.ridgebotics.ridgescout.utility.SettingsManager;
@@ -77,6 +76,7 @@ public class PitScoutingFragment extends Fragment {
String fileUsernames = ""; String fileUsernames = "";
ToggleTitleView[] titles; ToggleTitleView[] titles;
AutoSaveManager asm = new AutoSaveManager(this::save, AUTO_SAVE_DELAY); AutoSaveManager asm = new AutoSaveManager(this::save, AUTO_SAVE_DELAY);
ArrayList<RawDataType> rawDataTypes; ArrayList<RawDataType> rawDataTypes;
@@ -99,7 +99,7 @@ public class PitScoutingFragment extends Fragment {
} }
public void set_indicator_color(int color){ public void set_indicator_color(int color){
binding.pitIndicator.setColor(color); binding.pitFileIndicator.setBackgroundColor(color);
} }
public void update_asm(){ public void update_asm(){
@@ -114,9 +114,10 @@ public class PitScoutingFragment extends Fragment {
public void loadTeam(){ public void loadTeam(){
// clear_fields(); // clear_fields();
binding.pitFileIndicator.setVisibility(View.VISIBLE);
binding.pitsTeamCard.setVisibility(View.VISIBLE); binding.pitsTeamCard.setVisibility(View.VISIBLE);
binding.pitIndicator.setTeamNum(team.teamNumber); binding.pitBarTeamNum.setText(String.valueOf(team.teamNumber));
binding.pitIndicator.setUsername(SettingsManager.getUsername()); binding.pitUsername.setText(SettingsManager.getUsername());
binding.pitsTeamCard.fromTeam(team); binding.pitsTeamCard.fromTeam(team);
filename = evcode + "-" + team.teamNumber + ".pitscoutdata"; filename = evcode + "-" + team.teamNumber + ".pitscoutdata";
@@ -145,7 +146,7 @@ public class PitScoutingFragment extends Fragment {
} }
} }
binding.pitIndicator.bringToFront(); binding.pitFileIndicator.bringToFront();
asm.start(); asm.start();
@@ -153,7 +154,7 @@ public class PitScoutingFragment extends Fragment {
private void enableRescoutButton(){ private void enableRescoutButton(){
set_indicator_color(rescout ? rescout_color : saved_color); set_indicator_color(rescout ? rescout_color : saved_color);
binding.pitIndicator.setOnLongClickListener(v -> { binding.pitFileIndicator.setOnLongClickListener(v -> {
rescout = !rescout; rescout = !rescout;
if(rescout){ if(rescout){
set_indicator_color(rescout_color); set_indicator_color(rescout_color);
@@ -170,7 +171,7 @@ public class PitScoutingFragment extends Fragment {
} }
private void disableRescoutButton(){ private void disableRescoutButton(){
binding.pitIndicator.setOnLongClickListener(null); binding.pitFileIndicator.setOnLongClickListener(null);
} }
@@ -51,89 +51,89 @@ public class PitSelectorFragment extends Fragment {
return binding.getRoot(); return binding.getRoot();
} }
// load_teams(); load_teams();
return binding.getRoot(); return binding.getRoot();
} }
// public void load_teams(){ public void load_teams(){
//// binding.pitFileIndicator.setVisibility(View.GONE); // binding.pitFileIndicator.setVisibility(View.GONE);
//// binding.pitTeamName.setVisibility(View.GONE); // binding.pitTeamName.setVisibility(View.GONE);
//// binding.pitTeamDescription.setVisibility(View.GONE); // binding.pitTeamDescription.setVisibility(View.GONE);
////
//// clear_fields();
// //
// // clear_fields();
// int[] teamNums = new int[event.teams.size()];
//
// for(int i = 0 ; i < event.teams.size(); i++){ int[] teamNums = new int[event.teams.size()];
// teamNums[i] = event.teams.get(i).teamNumber;
// } for(int i = 0 ; i < event.teams.size(); i++){
// teamNums[i] = event.teams.get(i).teamNumber;
// Arrays.sort(teamNums); }
//
// TableLayout table = new TableLayout(getContext()); Arrays.sort(teamNums);
// table.setStretchAllColumns(true);
// binding.teams.addView(table); TableLayout table = new TableLayout(getContext());
// table.setStretchAllColumns(true);
// binding.teams.addView(table);
// for(int i = 0; i < event.teams.size(); i++){
// frcTeam team = null;
// for(int a = 0 ; a < event.teams.size(); a++){ for(int i = 0; i < event.teams.size(); i++){
// if(event.teams.get(a).teamNumber == teamNums[i]){ frcTeam team = null;
// team = event.teams.get(a); for(int a = 0 ; a < event.teams.size(); a++){
// break; if(event.teams.get(a).teamNumber == teamNums[i]){
// } team = event.teams.get(a);
// } break;
// assert team != null; }
// }
//// TableRow tr = new TableRow(getContext()); assert team != null;
//// TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams(
//// FrameLayout.LayoutParams.WRAP_CONTENT, // TableRow tr = new TableRow(getContext());
//// FrameLayout.LayoutParams.WRAP_CONTENT // TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams(
//// ); // FrameLayout.LayoutParams.WRAP_CONTENT,
//// rowParams.setMargins(20,20,20,20); // FrameLayout.LayoutParams.WRAP_CONTENT
//// tr.setLayoutParams(rowParams); // );
//// tr.setPadding(20,20,20,20); // rowParams.setMargins(20,20,20,20);
//// table.addView(tr); // tr.setLayoutParams(rowParams);
// // tr.setPadding(20,20,20,20);
// TeamListOption teamRow = new TeamListOption(getContext()); // table.addView(tr);
// table.addView(teamRow);
// teamRow.fromTeam(team); TeamListOption teamRow = new TeamListOption(getContext());
// table.addView(teamRow);
// teamRow.fromTeam(team);
// String filename = evcode + "-" + team.teamNumber + ".pitscoutdata";
//
// if (FileEditor.fileExist(filename)) { String filename = evcode + "-" + team.teamNumber + ".pitscoutdata";
// final boolean[] rescout = {DataManager.rescout_list.contains(filename)};
// if (FileEditor.fileExist(filename)) {
// teamRow.setColor(DataManager.rescout_list.contains(filename) ? color_rescout : color_found); final boolean[] rescout = {DataManager.rescout_list.contains(filename)};
//
// teamRow.setOnLongClickListener(v -> { teamRow.setColor(DataManager.rescout_list.contains(filename) ? color_rescout : color_found);
// rescout[0] = !rescout[0];
// if(rescout[0]){ teamRow.setOnLongClickListener(v -> {
// DataManager.rescout_list.add(filename); rescout[0] = !rescout[0];
// teamRow.setColor(color_rescout); if(rescout[0]){
// DataManager.save_rescout_list(); DataManager.rescout_list.add(filename);
// }else{ teamRow.setColor(color_rescout);
// DataManager.rescout_list.remove(filename); DataManager.save_rescout_list();
// teamRow.setColor(color_found); }else{
// DataManager.save_rescout_list(); DataManager.rescout_list.remove(filename);
// } teamRow.setColor(color_found);
// DataManager.save_rescout_list();
// }
// return true;
// });
// } else { return true;
// teamRow.setColor(color_not_found); });
// teamRow.setOnLongClickListener(v -> true); } else {
// } teamRow.setColor(color_not_found);
// teamRow.setOnLongClickListener(v -> true);
// }
// frcTeam finalTeam = team;
// teamRow.setOnClickListener(v -> onSelect.onSelect(this, finalTeam));
// } frcTeam finalTeam = team;
// } teamRow.setOnClickListener(v -> onSelect.onSelect(this, finalTeam));
}
}
} }
@@ -15,7 +15,6 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -90,7 +89,7 @@ public class ScoutingFragment extends Fragment {
binding.textMatchAlliance.setVisibility(View.GONE); binding.textMatchAlliance.setVisibility(View.GONE);
binding.textName.setVisibility(View.GONE); binding.textName.setVisibility(View.GONE);
binding.infoBox.setVisibility(View.GONE); binding.textNextMatch.setVisibility(View.GONE);
binding.textRescoutIndicator.setVisibility(View.GONE); binding.textRescoutIndicator.setVisibility(View.GONE);
binding.matchScoutingButton.setEnabled(false); binding.matchScoutingButton.setEnabled(false);
@@ -124,7 +123,20 @@ public class ScoutingFragment extends Fragment {
findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_scouting_event); findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_scouting_event);
}); });
updateDashboard();
binding.textName.setText("Welcome, " + SettingsManager.getUsername() + "!");
int matchNum = SettingsManager.getMatchNum();
int nextMatch = -1;
try {
nextMatch = event.getNextTeamMatch(SettingsManager.getTeamNum(), matchNum).matchIndex;
} catch (Exception e){
AlertManager.error(e);
}
binding.textNextMatch.setText("Our next match: Match " + nextMatch);
binding.textMatchAlliance.setText("Match: " + (matchNum+1) + ", " + SettingsManager.getAllyPos());
binding.textRescoutIndicator.setText("Things to rescout: " + DataManager.rescout_list.size());
return binding.getRoot(); return binding.getRoot();
} }
@@ -153,32 +165,4 @@ public class ScoutingFragment extends Fragment {
}); });
} }
private void updateDashboard() {
binding.textName.setText("Welcome, " + SettingsManager.getUsername() + "!");
int curMatchNum = SettingsManager.getMatchNum();
int nextMatch;
int teamNum = SettingsManager.getTeamNum();
try {
nextMatch = event.getNextTeamMatch(teamNum, curMatchNum).matchIndex;
} catch (Exception e){
AlertManager.error("Sorry, in event ("+evcode+"), your team number ("+teamNum+") wasn't found!", e);
return;
}
binding.textMatchAlliance.setText("Match: " + (curMatchNum+1) + ", " + SettingsManager.getAllyPos());
binding.textRescoutIndicator.setText("Things to rescout: " + DataManager.rescout_list.size());
TextView nextMatchText = new TextView(getContext());
nextMatchText.setText("Our next match: Match " + nextMatch);
nextMatchText.setTextAppearance(com.google.android.material.R.style.TextAppearance_MaterialComponents_Body1);
binding.infoBox.addView(nextMatchText);
int informedBy = event.getMostInformedBy(teamNum, curMatchNum);
TextView mostInformedText = new TextView(getContext());
mostInformedText.setText("Most informed by: Match " + informedBy);
mostInformedText.setTextAppearance(com.google.android.material.R.style.TextAppearance_MaterialComponents_Body1);
binding.infoBox.addView(mostInformedText);
}
} }
@@ -18,6 +18,7 @@ import com.ridgebotics.ridgescout.types.input.NumberType;
import com.ridgebotics.ridgescout.types.input.SliderType; import com.ridgebotics.ridgescout.types.input.SliderType;
import com.ridgebotics.ridgescout.types.input.TallyType; import com.ridgebotics.ridgescout.types.input.TallyType;
import com.ridgebotics.ridgescout.types.input.TextType; import com.ridgebotics.ridgescout.types.input.TextType;
import com.ridgebotics.ridgescout.types.input.ToggleType;
import com.ridgebotics.ridgescout.utility.AlertManager; import com.ridgebotics.ridgescout.utility.AlertManager;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@@ -29,7 +30,8 @@ public class FieldEditorHelper {
paramNumber, paramNumber,
paramString, paramString,
paramStringArray, paramStringArray,
paramNumberArray paramNumberArray,
paramBoolean
} }
public static class parameterType { 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 static class paramNumberArray extends parameterType{
// public int[] val; // public int[] val;
// public paramNumberArray(String name, int[] val){ // public paramNumberArray(String name, int[] val){
@@ -113,6 +124,12 @@ public class FieldEditorHelper {
new paramNumber("Default Y", 0) 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){ private static parameterType[] getSliderParams(SliderType s){
return new parameterType[]{ return new parameterType[]{
@@ -173,6 +190,13 @@ public class FieldEditorHelper {
new paramNumber("Default Y", ((int[]) s.default_value)[1]) 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){ private static void setInputParameter(FieldType t, parameterType[] types){
switch (t.getInputType()){ switch (t.getInputType()){
@@ -248,6 +278,9 @@ public class FieldEditorHelper {
case FIELDPOS: case FIELDPOS:
setFieldPosParam((FieldposType) t, types); setFieldPosParam((FieldposType) t, types);
break; break;
case TOGGLE:
setToggleParam((ToggleType) t, types);
break;
} }
} }
@@ -269,6 +302,8 @@ public class FieldEditorHelper {
return getCheckboxParam((CheckboxType) t); return getCheckboxParam((CheckboxType) t);
case FIELDPOS: case FIELDPOS:
return getFieldPosParam((FieldposType) t); return getFieldPosParam((FieldposType) t);
case TOGGLE:
return getToggleParams((ToggleType) t);
} }
return new parameterType[]{}; return new parameterType[]{};
} }
@@ -305,6 +340,16 @@ public class FieldEditorHelper {
)); ));
return text; 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){ private static View createEdit(Context c, parameterType t){
switch (t.id){ switch (t.id){
@@ -384,6 +429,11 @@ public class FieldEditorHelper {
fieldposType.UUID = UUID.randomUUID().toString(); fieldposType.UUID = UUID.randomUUID().toString();
setFieldPosParam(fieldposType, defaultFieldPosParam); setFieldPosParam(fieldposType, defaultFieldPosParam);
return fieldposType; return fieldposType;
case 7:
ToggleType toggleType = new ToggleType();
toggleType.UUID = UUID.randomUUID().toString();
setToggleParam(toggleType, defaultToggleParam);
return toggleType;
} }
return null; return null;
} }
@@ -21,7 +21,6 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation; import androidx.navigation.Navigation;
import com.google.android.material.button.MaterialButton;
import com.ridgebotics.ridgescout.MainActivity; import com.ridgebotics.ridgescout.MainActivity;
import com.ridgebotics.ridgescout.R; import com.ridgebotics.ridgescout.R;
import com.ridgebotics.ridgescout.databinding.FragmentSettingsFieldsBinding; import com.ridgebotics.ridgescout.databinding.FragmentSettingsFieldsBinding;
@@ -217,7 +216,7 @@ public class FieldsFragment extends Fragment {
AlertDialog dialog = alert.create(); AlertDialog dialog = alert.create();
dialog.show(); dialog.show();
MaterialButton deleteButton = new MaterialButton(getContext()); Button deleteButton = new Button(getContext());
deleteButton.setText("DELETE"); deleteButton.setText("DELETE");
deleteButton.setOnClickListener(l -> { deleteButton.setOnClickListener(l -> {
AlertDialog.Builder alert2 = new AlertDialog.Builder(getContext()); AlertDialog.Builder alert2 = new AlertDialog.Builder(getContext());
@@ -1,8 +1,6 @@
package com.ridgebotics.ridgescout.ui.settings; package com.ridgebotics.ridgescout.ui.settings;
import static android.view.View.VISIBLE; import static android.view.View.VISIBLE;
import static android.widget.LinearLayout.HORIZONTAL;
import static android.widget.LinearLayout.VERTICAL;
import static androidx.navigation.fragment.FragmentKt.findNavController; import static androidx.navigation.fragment.FragmentKt.findNavController;
import static com.ridgebotics.ridgescout.utility.SettingsManager.AllyPosKey; import static com.ridgebotics.ridgescout.utility.SettingsManager.AllyPosKey;
import static com.ridgebotics.ridgescout.utility.SettingsManager.CustomEventsKey; import static com.ridgebotics.ridgescout.utility.SettingsManager.CustomEventsKey;
@@ -15,7 +13,6 @@ import static com.ridgebotics.ridgescout.utility.SettingsManager.UnameKey;
import static com.ridgebotics.ridgescout.utility.SettingsManager.WifiModeKey; import static com.ridgebotics.ridgescout.utility.SettingsManager.WifiModeKey;
import static com.ridgebotics.ridgescout.utility.SettingsManager.YearNumKey; import static com.ridgebotics.ridgescout.utility.SettingsManager.YearNumKey;
import static com.ridgebotics.ridgescout.utility.SettingsManager.defaults; import static com.ridgebotics.ridgescout.utility.SettingsManager.defaults;
import static com.ridgebotics.ridgescout.utility.SettingsManager.getEVCode;
import static com.ridgebotics.ridgescout.utility.SettingsManager.getEditor; import static com.ridgebotics.ridgescout.utility.SettingsManager.getEditor;
import static com.ridgebotics.ridgescout.utility.SettingsManager.prefs; import static com.ridgebotics.ridgescout.utility.SettingsManager.prefs;
@@ -33,17 +30,13 @@ import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ScrollView; import android.widget.ScrollView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.checkbox.MaterialCheckBox; import com.google.android.material.checkbox.MaterialCheckBox;
import com.google.android.material.divider.MaterialDivider;
import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout; import com.google.android.material.textfield.TextInputLayout;
import com.ridgebotics.ridgescout.R; import com.ridgebotics.ridgescout.R;
@@ -55,8 +48,6 @@ import com.ridgebotics.ridgescout.utility.DataManager;
import com.ridgebotics.ridgescout.utility.FileEditor; import com.ridgebotics.ridgescout.utility.FileEditor;
import com.ridgebotics.ridgescout.utility.SettingsManager; import com.ridgebotics.ridgescout.utility.SettingsManager;
import org.w3c.dom.Text;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@@ -74,6 +65,20 @@ public class SettingsFragment extends Fragment {
reloadSettings(); reloadSettings();
binding.fieldsButton.setOnClickListener(v -> {
binding.fieldsButton.setEnabled(false);
binding.fieldsButtons.setVisibility(VISIBLE);
});
binding.fieldsMatchesButton.setOnClickListener(v -> {
FieldsFragment.set_filename(Fields.matchFieldsFilename);
findNavController(this).navigate(R.id.action_navigation_settings_to_navigation_data_fields);
});
binding.fieldsPitsButton.setOnClickListener(v -> {
FieldsFragment.set_filename(Fields.pitsFieldsFilename);
findNavController(this).navigate(R.id.action_navigation_settings_to_navigation_data_fields);
});
return root; return root;
@@ -86,67 +91,28 @@ public class SettingsFragment extends Fragment {
SettingsManager manager = new SettingsManager(getContext()); SettingsManager manager = new SettingsManager(getContext());
ButtonSettingsItem corruptButton = new ButtonSettingsItem();
corruptButton.addButton("Remove corrupted files", view -> {});
manager.addItem(corruptButton);
manager.addItem(new HeaderSettingsItem("Advanced"));
ButtonSettingsItem fieldsButtons = new ButtonSettingsItem();
fieldsButtons.addButton("Edit pit fields", v -> {
FieldsFragment.set_filename(Fields.pitsFieldsFilename);
findNavController(this).navigate(R.id.action_navigation_settings_to_navigation_data_fields);
});
fieldsButtons.addButton("Edit match fields", v -> {
FieldsFragment.set_filename(Fields.matchFieldsFilename);
findNavController(this).navigate(R.id.action_navigation_settings_to_navigation_data_fields);
});
manager.addItem(fieldsButtons);
ButtonSettingsItem noticeButton = new ButtonSettingsItem();
noticeButton.addButton("Edit scout notice", v->editNotice());
noticeButton.setEnabled(!getEVCode().equals("unset"));
manager.addItem(noticeButton);
manager.addItem(new CheckboxSettingsItem(CustomEventsKey, "Custom Events")); manager.addItem(new CheckboxSettingsItem(CustomEventsKey, "Custom Events"));
CheckboxSettingsItem FTPSendMetaFiles = new CheckboxSettingsItem(com.ridgebotics.ridgescout.utility.SettingsManager.FTPSendMetaFiles, "[⚠] Send meta files");
manager.addItem(FTPSendMetaFiles);
manager.addItem(new HeaderSettingsItem("Admin"));
StringSettingsItem FTPKey = new StringSettingsItem(com.ridgebotics.ridgescout.utility.SettingsManager.FTPKey, "Sync Key"); StringSettingsItem FTPKey = new StringSettingsItem(com.ridgebotics.ridgescout.utility.SettingsManager.FTPKey, "Sync Key");
manager.addItem(FTPKey); manager.addItem(FTPKey);
StringSettingsItem FTPServer = new StringSettingsItem(com.ridgebotics.ridgescout.utility.SettingsManager.FTPServer, "Sync Server (Sync)"); StringSettingsItem FTPServer = new StringSettingsItem(com.ridgebotics.ridgescout.utility.SettingsManager.FTPServer, "Sync Server (Sync)");
manager.addItem(FTPServer); manager.addItem(FTPServer);
CheckboxSettingsItem FTPEnabled = new CheckboxSettingsItem(com.ridgebotics.ridgescout.utility.SettingsManager.FTPEnabled, "Sync Enabled", FTPServer, FTPKey, FTPSendMetaFiles); CheckboxSettingsItem FTPSendMetaFiles = new CheckboxSettingsItem(com.ridgebotics.ridgescout.utility.SettingsManager.FTPSendMetaFiles, "⚠ Send meta files");
manager.addItem(FTPSendMetaFiles);
CheckboxSettingsItem FTPEnabled = new CheckboxSettingsItem(com.ridgebotics.ridgescout.utility.SettingsManager.FTPEnabled, "FTP Enabled", FTPServer, FTPKey, FTPSendMetaFiles);
manager.addItem(FTPEnabled); manager.addItem(FTPEnabled);
manager.addItem(new CheckboxSettingsItem(WifiModeKey, "Wifi Mode", FTPEnabled)); manager.addItem(new CheckboxSettingsItem(WifiModeKey, "Wifi Mode", FTPEnabled));
manager.addItem(new NumberSettingsItem(YearNumKey, "Year", 0, 9999));
manager.addItem(new HeaderSettingsItem("Connection"));
manager.addItem(new CheckboxSettingsItem(EnableQuickAllianceChangeKey, "Enable quick alliance swap", null)); manager.addItem(new CheckboxSettingsItem(EnableQuickAllianceChangeKey, "Enable quick alliance swap", null));
manager.addItem(new DropdownSettingsItem(FieldImageKey, "Field Image", new String[]{ manager.addItem(new DropdownSettingsItem(FieldImageKey, "Field Image", new String[]{
"2025", "2025",
"2025 (Flipped)" "2025 (Flipped)"
})); }));
manager.addItem(new NumberSettingsItem(YearNumKey, "Year", 0, 9999));
manager.addItem(new DropdownSettingsItem(AllyPosKey, "Alliance Pos", alliance_pos_list)); manager.addItem(new DropdownSettingsItem(AllyPosKey, "Alliance Pos", alliance_pos_list));
int max = 0; int max = 0;
@@ -168,48 +134,16 @@ public class SettingsFragment extends Fragment {
manager.addItem(new StringSettingsItem(UnameKey, "Username")); manager.addItem(new StringSettingsItem(UnameKey, "Username"));
manager.addItem(new NumberSettingsItem(TeamNumKey, "Team Number", 0, 99999)); manager.addItem(new NumberSettingsItem(TeamNumKey, "Team Number", 0, 99999));
manager.addItem(new HeaderSettingsItem("Scouting"));
binding.SettingsTable.removeAllViews(); binding.SettingsTable.removeAllViews();
manager.getView(binding.SettingsTable); manager.getView(binding.SettingsTable);
if(!DataManager.getevcode().equals("unset")){
// Add "Edit scout notice" button to the bottom of the page= Button editNoticeButton = new Button(getContext());
editNoticeButton.setText("Edit Scout Notice");
binding.SettingsTable.addView(editNoticeButton);
// Add "Field edit" buttons to the bottom of the page editNoticeButton.setOnClickListener(v->editNotice());
// LinearLayout fieldButtons = new LinearLayout(getContext()); }
// fieldButtons.setLayoutParams(new LinearLayout.LayoutParams(
// LinearLayout.LayoutParams.MATCH_PARENT,
// LinearLayout.LayoutParams.WRAP_CONTENT
// ));
// fieldButtons.setOrientation(HORIZONTAL);
//
// Button editMatchFieldsButton = new Button(getContext());
// editMatchFieldsButton.setText("Edit Match Fields");
// editMatchFieldsButton.setOnClickListener(v -> {
// FieldsFragment.set_filename(Fields.matchFieldsFilename);
// findNavController(this).navigate(R.id.action_navigation_settings_to_navigation_data_fields);
// });
// fieldButtons.addView(editMatchFieldsButton);
//
//
// Button editPitsFieldsButton = new Button(getContext());
// editPitsFieldsButton.setText("Edit pits Fields");
// editPitsFieldsButton.setOnClickListener(v -> {
// FieldsFragment.set_filename(Fields.pitsFieldsFilename);
// findNavController(this).navigate(R.id.action_navigation_settings_to_navigation_data_fields);
// });
// fieldButtons.addView(editPitsFieldsButton);
// binding.SettingsTable.addView(fieldButtons);
} }
@@ -413,7 +347,7 @@ public class SettingsFragment extends Fragment {
@Override @Override
public View createView(Context context) { public View createView(Context context) {
LinearLayout ll = new LinearLayout(getContext()); LinearLayout ll = new LinearLayout(getContext());
ll.setOrientation(VERTICAL); ll.setOrientation(LinearLayout.VERTICAL);
tally = new TallyCounterView(getContext()); tally = new TallyCounterView(getContext());
@@ -541,94 +475,6 @@ public class SettingsFragment extends Fragment {
} }
} }
public class HeaderSettingsItem extends SettingsItem<Void> {
String title;
public HeaderSettingsItem(String title) {
super("", title, null);
this.title = title;
}
@Override
public void setEnabled(boolean enabled){
}
@Override
public View createView(Context context) {
LinearLayout ll = new LinearLayout(context);
ll.setOrientation(VERTICAL);
ll.setPadding(0, 20,0,0);
TextView tv = new TextView(context);
tv.setText(title);
tv.setTextAppearance(com.google.android.material.R.style.TextAppearance_MaterialComponents_Headline4);
ll.addView(tv);
ll.addView(new MaterialDivider(context));
return ll;
}
@Override
public Void getValue() {
return null;
}
}
public class ButtonSettingsItem extends SettingsItem<Void> {
List<MaterialButton> buttons = new ArrayList<>();
List<String> titles = new ArrayList<>();
List<View.OnClickListener> callbacks = new ArrayList<>();
boolean enabled = true;
public ButtonSettingsItem() {
super("", "", null);
}
@Override
public void setEnabled(boolean enabled){
this.enabled = enabled;
for(int i = 0; i < buttons.size(); i++){
buttons.get(i).setEnabled(enabled);
}
}
public void addButton(String text, View.OnClickListener onClickListener) {
titles.add(text);
callbacks.add(onClickListener);
}
@Override
public View createView(Context context) {
LinearLayout ll = new LinearLayout(context);
ll.setOrientation(HORIZONTAL);
for(int i = 0; i < titles.size(); i++){
MaterialButton button = new MaterialButton(context);
button.setText(titles.get(i));
button.setOnClickListener(callbacks.get(i));
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f);
layoutParams.setMargins(3, 0, 3, 0);
// layoutParams.weight
button.setLayoutParams(layoutParams);
button.setEnabled(enabled);
// button.weight
buttons.add(button);
ll.addView(button);
}
return ll;
}
@Override
public Void getValue() {
return null;
}
}
public class SettingsManager { public class SettingsManager {
private Context context; private Context context;
private HashMap<String, Object> settings; private HashMap<String, Object> settings;
@@ -651,7 +497,7 @@ public class SettingsFragment extends Fragment {
items.add(item); items.add(item);
LinearLayout itemContainer = new LinearLayout(context); LinearLayout itemContainer = new LinearLayout(context);
itemContainer.setOrientation(VERTICAL); itemContainer.setOrientation(LinearLayout.VERTICAL);
itemContainer.setPadding(32, 0, 32, 8); itemContainer.setPadding(32, 0, 32, 8);
View view = item.createView(context); View view = item.createView(context);
@@ -28,7 +28,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
// This is now deprecated. use HTTPSync // This is now deprecated
// Class to synchronise data over FTP. // Class to synchronise data over FTP.
public class FTPSync extends Thread { public class FTPSync extends Thread {
public static final String remoteBasePath = "/RidgeScout/"; public static final String remoteBasePath = "/RidgeScout/";
@@ -30,7 +30,8 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
// Class to synchronise data over HTTP. // This is now deprsicated
// Class to syncronise data over FTP.
public class HttpSync extends Thread { public class HttpSync extends Thread {
public static final String timestampsFilename = "timestamps"; public static final String timestampsFilename = "timestamps";
@@ -22,7 +22,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import com.google.android.material.button.MaterialButton;
import com.ridgebotics.ridgescout.R; import com.ridgebotics.ridgescout.R;
import com.ridgebotics.ridgescout.databinding.FragmentTransferTbaBinding; import com.ridgebotics.ridgescout.databinding.FragmentTransferTbaBinding;
import com.ridgebotics.ridgescout.types.frcEvent; import com.ridgebotics.ridgescout.types.frcEvent;
@@ -50,6 +49,8 @@ public class TBAEventFragment extends Fragment {
private final int year = SettingsManager.getYearNum(); private final int year = SettingsManager.getYearNum();
private ProgressDialog loadingDialog;
private static JSONObject eventData = null; private static JSONObject eventData = null;
public static void setEventData(JSONObject j){ public static void setEventData(JSONObject j){
eventData = j; eventData = j;
@@ -73,7 +74,7 @@ public class TBAEventFragment extends Fragment {
Table.setStretchAllColumns(true); Table.setStretchAllColumns(true);
AlertManager.startLoading("Loading Teams and Matches..."); startLoading("Loading Teams and Matches...");
Table.removeAllViews(); Table.removeAllViews();
Table.setStretchAllColumns(true); Table.setStretchAllColumns(true);
Table.bringToFront(); Table.bringToFront();
@@ -91,7 +92,7 @@ public class TBAEventFragment extends Fragment {
final RequestTask rq1 = new RequestTask(); final RequestTask rq1 = new RequestTask();
rq1.onResult(matchesStr -> { rq1.onResult(matchesStr -> {
matchTable(matchesStr, teamsStr, eventData); matchTable(matchesStr, teamsStr, eventData);
AlertManager.stopLoading(); stopLoading();
return null; return null;
}); });
rq1.execute((TBAAddress + "event/" + matchKey + "/matches"), TBAHeader); rq1.execute((TBAAddress + "event/" + matchKey + "/matches"), TBAHeader);
@@ -152,7 +153,7 @@ public class TBAEventFragment extends Fragment {
// Save button // Save button
MaterialButton btn = new MaterialButton(getContext()); Button btn = new Button(getContext());
btn.setText("Save"); btn.setText("Save");
btn.setTextSize(18); btn.setTextSize(18);
btn.setLayoutParams(new TableRow.LayoutParams( btn.setLayoutParams(new TableRow.LayoutParams(
@@ -374,12 +375,12 @@ public class TBAEventFragment extends Fragment {
}catch (JSONException j){ }catch (JSONException j){
AlertManager.error("Failed Downloading", j); AlertManager.error("Failed Downloading", j);
AlertManager.stopLoading(); stopLoading();
} }
} }
private boolean saveData(ArrayList<frcMatch> matchData, JSONArray teamData, JSONObject eventData){ private boolean saveData(ArrayList<frcMatch> matchData, JSONArray teamData, JSONObject eventData){
AlertManager.startLoading("Saving data..."); startLoading("Saving data...");
Thread t = new Thread(() -> { Thread t = new Thread(() -> {
try { try {
@@ -430,15 +431,31 @@ public class TBAEventFragment extends Fragment {
AlertManager.toast("Saved!"); AlertManager.toast("Saved!");
getActivity().runOnUiThread(() -> findNavController(this).navigate(R.id.action_navigation_tba_event_to_navigation_transfer)); getActivity().runOnUiThread(() -> findNavController(this).navigate(R.id.action_navigation_tba_event_to_navigation_transfer));
AlertManager.stopLoading(); stopLoading();
}catch(Exception j) { }catch(Exception j) {
AlertManager.error(j); AlertManager.error(j);
AlertManager.stopLoading(); stopLoading();
} }
}); });
t.start(); t.start();
return false; return false;
} }
private void startLoading(String title){
getActivity().runOnUiThread(() -> {
if(loadingDialog != null && loadingDialog.isShowing())
loadingDialog.dismiss();
loadingDialog = ProgressDialog.show(getActivity(), title, "Please wait...");
});
}
private void stopLoading(){
getActivity().runOnUiThread(() -> {
if (loadingDialog != null)
loadingDialog.cancel();
loadingDialog = null;
});
}
} }
@@ -1,135 +0,0 @@
package com.ridgebotics.ridgescout.ui.transfer.codes;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.AsyncTask;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.FileEditor;
import com.ridgebotics.ridgescout.utility.TaskRunner;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.function.Function;
public class CodeGenTask implements Callable<List<Bitmap>> {
// private Function<List<Bitmap>, String> resultFunction = null;
//
// @Override
// protected List<Bitmap> doInBackground(String... strings) {
//
//
// return new ArrayList<>();
// }
//
//
// public void onResult(Function<List<Bitmap>, String> func) {
// this.resultFunction = func;
// }
//
//
// @Override
// protected void onPostExecute(List<Bitmap> result) {
// super.onPostExecute(result);
// if(resultFunction != null){
// resultFunction.apply(result);
// }
// }
private final String data;
private final int randID;
private final int qrSize;
private final int qrCount;
private final int imageSize;
public CodeGenTask(String data, int randID, int qrSize, int qrCount, int imageSize) {
this.data = data;
this.randID = randID;
this.qrSize = qrSize;
this.qrCount = qrCount;
this.imageSize = imageSize;
}
@Override
public List<Bitmap> call() {
List<Bitmap> qrBitmaps = new ArrayList<>();
for(int i=0;i<=((data.length()+1)/qrSize);i++){
final int start = i*qrSize;
int end = (i+1)*qrSize;
if(end >= data.length()){
end = data.length();
}
try {
Bitmap unscaledBitmap = generateQrCode(
FileEditor.byteToChar(FileEditor.internalDataVersion, FileEditor.lengthHeaderBytes) +
String.valueOf(FileEditor.byteToChar(randID, FileEditor.lengthHeaderBytes)) +
FileEditor.byteToChar(i, FileEditor.lengthHeaderBytes) +
FileEditor.byteToChar(qrCount - 1, FileEditor.lengthHeaderBytes) +
data.substring(start, end)
);
if(unscaledBitmap == null) {
AlertManager.error("Generated image was null!");
continue;
}
qrBitmaps.add(Bitmap.createScaledBitmap(unscaledBitmap, imageSize, imageSize, false));
// alert("title", ""+(qrCount-1));
}catch (WriterException e){
AlertManager.error(e);
}
}
return qrBitmaps;
}
private Bitmap generateQrCode(String contents) throws WriterException {
final int size = 512;
if (contents == null) {
return null;
}
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
// The Charset must be UTF-8, Or data will not be transferred properly. IDK why.
hints.put(EncodeHintType.CHARACTER_SET, "ISO-8859-1");
// hints.put(EncodeHintType.);
hints.put(EncodeHintType.MARGIN, 0); /* default = 4 */
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix result;
try {
result = writer.encode(contents, BarcodeFormat.DATA_MATRIX, size, size, hints);
} catch (IllegalArgumentException e) {
// Unsupported format
AlertManager.error(e);
return null;
}
int width = result.getWidth();
int height = result.getHeight();
int[] pixels = new int[width * height];
for (int y = 0; y < height; y++) {
int offset = y * width;
for (int x = 0; x < width; x++) {
pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.WHITE;
}
}
Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
}
@@ -1,10 +1,9 @@
package com.ridgebotics.ridgescout.ui.transfer.codes; package com.ridgebotics.ridgescout.ui.transfer.codes;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.os.CountDownTimer; import android.os.CountDownTimer;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -19,11 +18,16 @@ import androidx.fragment.app.Fragment;
import com.ridgebotics.ridgescout.databinding.FragmentTransferCodeSenderBinding; import com.ridgebotics.ridgescout.databinding.FragmentTransferCodeSenderBinding;
import com.ridgebotics.ridgescout.utility.AlertManager; import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.FileEditor; import com.ridgebotics.ridgescout.utility.FileEditor;
import com.ridgebotics.ridgescout.utility.TaskRunner; import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.EnumMap;
import java.util.Map;
import java.util.Random; import java.util.Random;
// Class to show the code transfer thing. // Class to show the code transfer thing.
@@ -34,28 +38,23 @@ public class CodeGeneratorView extends Fragment {
private TextView qrIndexN; private TextView qrIndexN;
private TextView qrIndexD; private TextView qrIndexD;
private static final int maxQrCount = 256; //The max number that can be stored in a byte private final int maxQrCount = 256; //The max number that can be stored in a byte
private static final int maxQrSize = 800; private final int maxQrSpeed = 5;
private final int minQrSpeed = 300 + maxQrSpeed - 1;
private static final int maxQrSpeed = 50;
private static final int minQrSpeed = 1000;
private static final int defaultQrDelay = 12;
private int imageSize;
private int minQrSize = 0; private int minQrSize = 0;
private final int maxQrSize = 800;
private int qrSize = 200; private int qrSize = 200;
private double qrDelay = 0; private final int defaultQrDelay = 419;
private int qrDelay = 0;
private int qrIndex = 0; private int qrIndex = 0;
private CountDownTimer timer; private CountDownTimer timer;
private int qrCount = 0; private int qrCount = 0;
private List<Bitmap> qrBitmaps = new ArrayList<>(); private ArrayList<Bitmap> qrBitmaps;
private FragmentTransferCodeSenderBinding binding; private FragmentTransferCodeSenderBinding binding;
@@ -78,12 +77,6 @@ public class CodeGeneratorView extends Fragment {
qrIndexN = binding.qrIndexN; qrIndexN = binding.qrIndexN;
qrIndexD = binding.qrIndexD; qrIndexD = binding.qrIndexD;
DisplayMetrics displaymetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
// int height = displaymetrics.heightPixels;
imageSize = displaymetrics.widthPixels;
// = 800;
String compressed = new String(FileEditor.blockCompress(data, FileEditor.lengthHeaderBytes), StandardCharsets.ISO_8859_1); String compressed = new String(FileEditor.blockCompress(data, FileEditor.lengthHeaderBytes), StandardCharsets.ISO_8859_1);
if(compressed.isEmpty()){ if(compressed.isEmpty()){
@@ -92,30 +85,75 @@ public class CodeGeneratorView extends Fragment {
} }
minQrSize = Math.round((float)compressed.length() / maxQrCount)+1; minQrSize = Math.round((float)compressed.length() / maxQrCount)+1;
qrSize += minQrSize;
sendData(compressed);
qrSpeedSlider.setMax(maxQrSpeed*2);
qrSpeedSlider.setProgress(maxQrSpeed + defaultQrDelay);
qrSizeSlider.setMax(maxQrSize-minQrSize); qrSizeSlider.setMax(maxQrSize-minQrSize);
qrSizeSlider.setProgress(qrSize-minQrSize); qrSpeedSlider.setMax((minQrSpeed-maxQrSpeed)*2);
startLoop(); qrSizeSlider.setProgress(minQrSize+qrSize);
qrSpeedSlider.setProgress(defaultQrDelay+5);
sendData(compressed);
return binding.getRoot(); return binding.getRoot();
} }
private Bitmap generateQrCode(String contents) throws WriterException {
final int size = 512;
if (contents == null) {
return null;
}
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
// The Charset must be UTF-8, Or data will not be transferred properly. IDK why.
hints.put(EncodeHintType.CHARACTER_SET, "ISO-8859-1");
// hints.put(EncodeHintType.);
hints.put(EncodeHintType.MARGIN, 0); /* default = 4 */
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix result;
try {
result = writer.encode(contents, BarcodeFormat.DATA_MATRIX, size, size, hints);
} catch (IllegalArgumentException e) {
// Unsupported format
AlertManager.error(e);
return null;
}
int width = result.getWidth();
int height = result.getHeight();
int[] pixels = new int[width * height];
for (int y = 0; y < height; y++) {
int offset = y * width;
for (int x = 0; x < width; x++) {
pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.WHITE;
}
}
Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
private void sendData(String data){ private void sendData(String data){
qrCount = (data.length()/qrSize)+1; qrCount = (data.length()/qrSize)+1;
qrIndexD.setText(String.valueOf(qrCount)); qrIndexD.setText(String.valueOf(qrCount));
// alert("size", ""+binding.qrSizeSlider.getProgress()+"\n"+binding.qrSizeSlider.getMax());
qrSpeedSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { qrSpeedSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override @Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
qrDelay = ((double) progress /maxQrSpeed) - 1; qrDelay = -(minQrSpeed - progress - maxQrSpeed + 1);
// startLoop();
} }
@Override @Override
public void onStartTrackingTouch(SeekBar seekBar) {} public void onStartTrackingTouch(SeekBar seekBar) {}
@@ -135,24 +173,43 @@ public class CodeGeneratorView extends Fragment {
qrCount = ((data.length()+1)/qrSize) +1; qrCount = ((data.length()+1)/qrSize) +1;
qrIndexD.setText(String.valueOf(qrCount)); qrIndexD.setText(String.valueOf(qrCount));
sendData(data); sendData(data);
// startLoop();
} }
}); });
AlertManager.startLoading("Generating codes..."); // qrSizeSlider.setProgress(qr);
new TaskRunner().executeAsync(new CodeGenTask(data, new Random().nextInt(255), qrSize, qrCount, imageSize), result -> { qrBitmaps = new ArrayList<>();
qrBitmaps = result;
AlertManager.stopLoading();
qrIndex = 0;
});
int randID = new Random().nextInt(255);
for(int i=0;i<=((data.length()+1)/qrSize);i++){
final int start = i*qrSize;
int end = (i+1)*qrSize;
if(end >= data.length()){
end = data.length();
}
try {
// alert("test", ""+Math.ceil((double)data.length()/(double)qrSize));
qrBitmaps.add(generateQrCode(
FileEditor.byteToChar(FileEditor.internalDataVersion, FileEditor.lengthHeaderBytes) +
String.valueOf(FileEditor.byteToChar(randID, FileEditor.lengthHeaderBytes)) +
FileEditor.byteToChar(i, FileEditor.lengthHeaderBytes) +
FileEditor.byteToChar(qrCount - 1, FileEditor.lengthHeaderBytes) +
data.substring(start, end)
));
// alert("title", ""+(qrCount-1));
}catch (WriterException e){
AlertManager.error(e);
}
}
qrIndex = 0;
if(timer != null){
timer.cancel();
}
qrLoop();
} }
private void updateQr(){ private void updateQr(){
if(qrBitmaps.isEmpty())
return;
qrImage.setImageBitmap(qrBitmaps.get(qrIndex)); qrImage.setImageBitmap(qrBitmaps.get(qrIndex));
if(qrDelay > 0) { if(qrDelay > 0) {
this.qrIndex += 1; this.qrIndex += 1;
@@ -169,36 +226,13 @@ public class CodeGeneratorView extends Fragment {
qrIndexN.setText(String.valueOf(qrIndex+1)); qrIndexN.setText(String.valueOf(qrIndex+1));
} }
private boolean shouldstop = false; private void qrLoop(){
timer = new CountDownTimer(minQrSpeed-Math.abs(qrDelay)+1, 1000) {
private void startLoop() { public void onTick(long millisUntilFinished) {}
final Handler handler = new Handler(); public void onFinish() {
Runnable runnable = new Runnable() { updateQr();
qrLoop();
@Override
public void run() {
if(shouldstop){
return;
}
try{
updateQr();
}
catch (Exception e) {
AlertManager.error(e);
}
finally{
double a = ((double) maxQrSpeed) / (Math.abs(qrDelay));
a = Math.min(Math.max(a, maxQrSpeed), minQrSpeed);
handler.postDelayed(this, (long) a);
}
} }
}; }.start();
handler.post(runnable);
}
@Override
public void onDestroy() {
super.onDestroy();
shouldstop = true;
} }
} }
@@ -65,7 +65,7 @@ public class CodeOverlayView extends View {
} }
} }
if(barColors != null){ if(barColors != null){
final double width = (double) getWidth() /barColors.length; final double width = getWidth()/barColors.length;
final int top = 0; final int top = 0;
final int bottom = barHeight; final int bottom = barHeight;
@@ -14,69 +14,19 @@ import com.google.zxing.Reader;
import com.google.zxing.Result; import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer; import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.datamatrix.DataMatrixReader; import com.google.zxing.datamatrix.DataMatrixReader;
import com.ridgebotics.ridgescout.utility.TaskRunner;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Callable;
import java.util.function.Function; import java.util.function.Function;
// Background task for code scanning, to not slow down the scanner. // Background task for code scanning, to not slow down the scanner.
//public class CodeScanTask extends AsyncTask<String, String, String>{ public class CodeScanTask extends AsyncTask<String, String, String>{
// private Function<String, String> resultFunction = null; private Function<String, String> resultFunction = null;
// private Bitmap image;
//
// @Override
// protected String doInBackground(String... str) {
// if(image == null){return null;}
//
// int width = image.getWidth();
// int height = image.getHeight();
// int[] pixels = new int[width * height];
// image.getPixels(pixels, 0, width, 0, 0, width, height);
//
// RGBLuminanceSource source = new RGBLuminanceSource(width, height, pixels);
// BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source));
//
// Map<DecodeHintType, Object> hints = new HashMap<>();
// hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
//// hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
// hints.put(DecodeHintType.POSSIBLE_FORMATS, EnumSet.of(BarcodeFormat.DATA_MATRIX));
//
// Reader reader = new DataMatrixReader();
// try {
// Result result = reader.decode(binaryBitmap, hints);
// return result.getText();
// } catch (NotFoundException | ChecksumException | FormatException e) {
//// AlertManager.error(e);
// }
//
// return null;
// }
// public void setImage(Bitmap image){this.image = image;}
// public void onResult(Function<String, String> func) {
// this.resultFunction = func;
// }
//
// @Override
// protected void onPostExecute(String result) {
// super.onPostExecute(result);
// if(resultFunction != null){
// resultFunction.apply(result);
// }
// }
//}
public class CodeScanTask implements Callable<String> {
private Bitmap image; private Bitmap image;
public CodeScanTask(Bitmap image) {
this.image = image;
}
@Override @Override
public String call() { protected String doInBackground(String... str) {
if(image == null){return null;} if(image == null){return null;}
int width = image.getWidth(); int width = image.getWidth();
@@ -102,4 +52,17 @@ public class CodeScanTask implements Callable<String> {
return null; return null;
} }
} public void setImage(Bitmap image){this.image = image;}
public void onResult(Function<String, String> func) {
this.resultFunction = func;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(resultFunction != null){
resultFunction.apply(result);
}
}
}
@@ -6,7 +6,6 @@ import android.Manifest;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.media.Image; import android.media.Image;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
@@ -39,15 +38,11 @@ import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.BuiltByteParser; import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.FileEditor; import com.ridgebotics.ridgescout.utility.FileEditor;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.ridgebotics.ridgescout.utility.TaskRunner;
import org.checkerframework.checker.units.qual.C;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@@ -67,12 +62,21 @@ public class CodeScannerView extends Fragment {
alert.create().show(); alert.create().show();
} }
private float scale = 0;
private final int downscale = 1; private final int downscale = 1;
private LifecycleOwner lifecycle; private LifecycleOwner lifecycle;
private void setImage(Bitmap bmp){ private void setImage(Bitmap bmp){
if(scale == 0) {
scale = ((float) binding.container.getWidth() / bmp.getWidth()) * ((float) 16 / 9);
binding.scannerImage.setTranslationX(0);
binding.scannerImage.setTranslationY(0);
}
scanQRCode(bmp); scanQRCode(bmp);
binding.scannerImage.setImageBitmap(bmp); binding.scannerImage.setImageBitmap(bmp);
binding.scannerThreshold.bringToFront();
// alert("test", getChildCount()+"");
} }
// private Bitmap img // private Bitmap img
@@ -95,38 +99,37 @@ public class CodeScannerView extends Fragment {
final int height = image.getHeight(); final int height = image.getHeight();
int[] pixels = new int[width * height]; int[] pixels = new int[width * height];
for (int i = 0; i < width*height; i++) { for (int y = 0; y < height; y++) {
int L = levelMap[yBuffer.get(i) & 0xff]; for (int x = 0; x < width; x++) {
pixels[i] = 0xff000000 | (L << 16) | (L << 8) | L; int L = levelMap[yBuffer.get() & 0xff];
pixels[y * width + x] = 0xff000000 | (L << 16) | (L << 8) | L;
}
} }
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height); bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
// Bitmap.rota
return bitmap; return bitmap;
} }
public void scanQRCode(Bitmap bitmap) { public void scanQRCode(Bitmap bitmap) {
// CodeScanTask async = new CodeScanTask(); CodeScanTask async = new CodeScanTask();
new TaskRunner().executeAsync(new CodeScanTask(bitmap), data -> { async.setImage(bitmap);
async.onResult(data -> {
if(data != null){ if(data != null){
// alert("test", ""+fileEditor.byteFromChar(data.charAt(0))); // alert("test", ""+fileEditor.byteFromChar(data.charAt(0)));
compileData( compileData(
FileEditor.byteFromChar(data.charAt(0)), FileEditor.byteFromChar(data.charAt(0)),
FileEditor.byteFromChar(data.charAt(1)), FileEditor.byteFromChar(data.charAt(1)),
FileEditor.byteFromChar(data.charAt(2)), FileEditor.byteFromChar(data.charAt(2)),
(FileEditor.byteFromChar(data.charAt(3))+1), (FileEditor.byteFromChar(data.charAt(3))+1),
data.substring(4) data.substring(4)
); );
} }
return null;
}); });
async.execute();
// return contents; // return contents;
@@ -228,23 +231,26 @@ public class CodeScannerView extends Fragment {
void bindPreview(@NonNull ProcessCameraProvider cameraProvider) { void bindPreview(@NonNull ProcessCameraProvider cameraProvider) {
Preview preview = new Preview.Builder().build(); Preview preview = new Preview.Builder()
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
.setTargetRotation(Surface.ROTATION_180)
.build();
CameraSelector cameraSelector = new CameraSelector.Builder() CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK) .requireLensFacing(CameraSelector.LENS_FACING_BACK)
// .addCameraFilter(CameraFilters.NON) // .addCameraFilter(CameraFilters.NON)
.build(); .build();
ExecutorService executor = Executors.newSingleThreadExecutor(); ExecutorService executor = Executors.newSingleThreadExecutor();
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder() ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
// .setTargetAspectRatio(AspectRatio.RATIO_16_9) // .setTargetResolution(new Size(224, 224))
.setOutputImageRotationEnabled(false)
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
// .setOutputImageRotationEnabled(true)
// .setTargetRotation(Surface.ROTATION_0)
.build(); .build();
imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() { imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() {
@OptIn(markerClass = ExperimentalGetImage.class) @Override @OptIn(markerClass = ExperimentalGetImage.class) @Override
public void analyze(@NonNull ImageProxy image) { public void analyze(@NonNull ImageProxy image) {
@@ -263,7 +269,6 @@ public class CodeScannerView extends Fragment {
}); });
cameraProvider.unbindAll(); cameraProvider.unbindAll();
// cameraProvider.ro
cameraProvider.bindToLifecycle(lifecycle, cameraProvider.bindToLifecycle(lifecycle,
cameraSelector, imageAnalysis, preview); cameraSelector, imageAnalysis, preview);
@@ -290,7 +295,6 @@ public class CodeScannerView extends Fragment {
Log.i("title", ""+qrCount); Log.i("title", ""+qrCount);
barColors = new int[qrCount]; barColors = new int[qrCount];
prevQrIndex = qrIndex; prevQrIndex = qrIndex;
qrScannedCount = 0;
} }
final boolean updated; final boolean updated;
@@ -309,20 +313,8 @@ public class CodeScannerView extends Fragment {
if(updated && qrScannedCount >= qrCount){ if(updated && qrScannedCount >= qrCount){
AlertManager.startLoading("Decoding data...");
new TaskRunner().executeAsync(new CodeDecodeTask(), result -> {
AlertManager.stopLoading();
});
}
prevQrIndex = qrIndex;
}
private class CodeDecodeTask implements Callable<Void> {
@Override
public Void call() {
String compiledString = ""; String compiledString = "";
for(int i=0;i<qrDataArr.length;i++){ for(int i=0;i<qrCount;i++){
compiledString += qrDataArr[i]; compiledString += qrDataArr[i];
} }
@@ -350,8 +342,9 @@ public class CodeScannerView extends Fragment {
}catch (Exception e){ }catch (Exception e){
AlertManager.error(e); AlertManager.error(e);
} }
return null;
} }
prevQrIndex = qrIndex;
} }
} }
@@ -62,7 +62,7 @@ public class CustomSpinnerView extends LinearLayout {
this.index = defaultOption; this.index = defaultOption;
if(defaultOption != -1) if(defaultOption != -1)
this.item.setText("" + options.get(defaultOption)); this.item.setText(options.get(defaultOption));
AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
@@ -78,7 +78,7 @@ public class CustomSpinnerView extends LinearLayout {
CustomSpinnerPopup popup = new CustomSpinnerPopup(getContext()).init(options, option -> { CustomSpinnerPopup popup = new CustomSpinnerPopup(getContext()).init(options, option -> {
// dialog.(); // dialog.();
if(!isEnabled()) return; if(!isEnabled()) return;
item.setText("" + option); item.setText(option);
index = options.indexOf(option); index = options.indexOf(option);
if(onClickListener != null) { if(onClickListener != null) {
onClickListener.onClick(option, options.indexOf(option)); onClickListener.onClick(option, options.indexOf(option));
@@ -105,12 +105,12 @@ public class CustomSpinnerView extends LinearLayout {
} }
public void setOption(String option) { public void setOption(String option) {
item.setText("" + option); item.setText(option);
index = options.indexOf(option); index = options.indexOf(option);
} }
public void setOption(int index) { public void setOption(int index) {
item.setText("" + options.get(index)); item.setText(options.get(index));
this.index = index; this.index = index;
} }
@@ -1,7 +1,6 @@
package com.ridgebotics.ridgescout.ui.views; package com.ridgebotics.ridgescout.ui.views;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
@@ -55,20 +54,6 @@ public class MatchScoutingIndicator extends RelativeLayout {
match_indicator_bar_team_num = findViewById(R.id.match_indicator_bar_team_num); match_indicator_bar_team_num = findViewById(R.id.match_indicator_bar_team_num);
box = findViewById(R.id.file_indicator_box); box = findViewById(R.id.file_indicator_box);
coloredBackground = findViewById(R.id.match_indicator_background); coloredBackground = findViewById(R.id.match_indicator_background);
int currentNightMode = getContext().getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
switch (currentNightMode) {
case Configuration.UI_MODE_NIGHT_NO:
// Night mode is not active on device
match_indicator_back_button.setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_IN);
match_indicator_next_button.setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_IN);
break;
case Configuration.UI_MODE_NIGHT_YES:
// Night mode is active on device
match_indicator_back_button.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN);
match_indicator_next_button.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN);
break;
}
} }
public void setUsername(String username){ public void setUsername(String username){
@@ -88,31 +73,19 @@ public class MatchScoutingIndicator extends RelativeLayout {
} }
public void setColor(int color){ public void setColor(int color){
// Set color of main background rectangle Drawable drawable = box.getBackground();
Drawable box_drawable = box.getBackground(); drawable.mutate();
box_drawable.mutate(); drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
box_drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
float[] hsv = new float[3]; float[] hsv = new float[3];
Color.colorToHSV(color,hsv); Color.colorToHSV(color,hsv);
int background_color = Color.HSVToColor(220, new float[]{
hsv[0],
Math.min(hsv[1], 0.75f),
Math.min(hsv[2], 0.5f)
});
// Set color of main background rectangle, slightly dimmer
coloredBackground.setBackgroundColor( coloredBackground.setBackgroundColor(
background_color Color.HSVToColor(220, new float[]{
hsv[0],
Math.min(hsv[1], 0.75f),
Math.min(hsv[2], 0.5f)
})
); );
Drawable left_drawable = match_indicator_back_button.getBackground();
left_drawable.mutate();
left_drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
Drawable right_drawable = match_indicator_next_button.getBackground();
right_drawable.mutate();
right_drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
} }
} }
@@ -1,75 +0,0 @@
package com.ridgebotics.ridgescout.ui.views;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.ridgebotics.ridgescout.R;
// A view for displaying information about a team.
public class PitScoutingIndicator extends RelativeLayout {
public PitScoutingIndicator(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public PitScoutingIndicator(Context context) {
super(context);
init(context);
}
public TextView pit_indicator_username;
public TextView pit_indicator_team_num;
private ConstraintLayout box;
private View coloredBackground;
public void init(Context context) {
LayoutInflater.from(context).inflate(R.layout.view_pit_scouting_indicator, this, true);
pit_indicator_username = findViewById(R.id.pit_indicator_username);
pit_indicator_team_num = findViewById(R.id.pit_indicator_teamnum);
box = findViewById(R.id.pit_indicator_box);
coloredBackground = findViewById(R.id.pit_indicator_background);
}
public void setUsername(String username){
pit_indicator_username.setText(username);
}
public void setTeamNum(int teamNum) {
pit_indicator_team_num.setText(String.valueOf(teamNum));
}
public void setColor(int color){
// Set color of main background rectangle
Drawable box_drawable = box.getBackground();
box_drawable.mutate();
box_drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
float[] hsv = new float[3];
Color.colorToHSV(color,hsv);
int background_color = Color.HSVToColor(220, new float[]{
hsv[0],
Math.min(hsv[1], 0.75f),
Math.min(hsv[2], 0.5f)
});
// Set color of main background rectangle, slightly dimmer
coloredBackground.setBackgroundColor(
background_color
);
}
}
@@ -1,105 +0,0 @@
package com.ridgebotics.ridgescout.ui.views;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class RecyclerAdapter<T> extends RecyclerView.Adapter<RecyclerHolder<T>> {
private List<T> items;
private final int layoutResId;
private final RecyclerHolderFactory<T> viewHolderFactory;
private RecyclerClickListener<T> onItemClickListener;
public RecyclerAdapter(int layoutResId, RecyclerHolderFactory<T> viewHolderFactory) {
this.items = new ArrayList<>();
this.layoutResId = layoutResId;
this.viewHolderFactory = viewHolderFactory;
}
@Override
public RecyclerHolder<T> onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(layoutResId, parent, false);
return viewHolderFactory.createViewHolder(view);
}
@Override
public void onBindViewHolder(RecyclerHolder<T> holder, int position) {
T item = items.get(position);
holder.bind(item, position);
holder.setOnItemClickListener(item, onItemClickListener);
}
@Override
public int getItemCount() {
return items.size();
}
// List management methods
public void setItems(List<T> newItems) {
this.items.clear();
if (newItems != null) {
this.items.addAll(newItems);
}
notifyDataSetChanged();
}
public void addItem(T item) {
items.add(item);
notifyItemInserted(items.size() - 1);
}
public void addItem(int position, T item) {
items.add(position, item);
notifyItemInserted(position);
}
public void removeItem(int position) {
if (position >= 0 && position < items.size()) {
items.remove(position);
notifyItemRemoved(position);
}
}
public void removeItem(T item) {
int position = items.indexOf(item);
if (position != -1) {
removeItem(position);
}
}
public void updateItem(int position, T item) {
if (position >= 0 && position < items.size()) {
items.set(position, item);
notifyItemChanged(position);
}
}
public void clear() {
int size = items.size();
items.clear();
notifyItemRangeRemoved(0, size);
}
public T getItem(int position) {
return items.get(position);
}
public List<T> getItems() {
return new ArrayList<>(items);
}
public void setOnItemClickListener(RecyclerClickListener<T> listener) {
this.onItemClickListener = listener;
}
}
@@ -1,5 +0,0 @@
package com.ridgebotics.ridgescout.ui.views;
public interface RecyclerClickListener<T> {
void onItemClick(T item, int position);
}
@@ -1,19 +0,0 @@
package com.ridgebotics.ridgescout.ui.views;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
public abstract class RecyclerHolder<T> extends RecyclerView.ViewHolder {
public RecyclerHolder(View itemView) {
super(itemView);
}
public abstract void bind(T item, int position);
// Optional method for handling item clicks
public void setOnItemClickListener(T item, RecyclerClickListener<T> listener) {
if (listener != null) {
itemView.setOnClickListener(v -> listener.onItemClick(item, getAdapterPosition()));
}
}
}
@@ -1,7 +0,0 @@
package com.ridgebotics.ridgescout.ui.views;
import android.view.View;
public interface RecyclerHolderFactory<T> {
RecyclerHolder<T> createViewHolder(View itemView);
}
@@ -1,133 +0,0 @@
package com.ridgebotics.ridgescout.ui.views;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.GridLayoutManager;
import java.util.List;
public class RecyclerList<T> extends RecyclerView {
private RecyclerAdapter<T> adapter;
public RecyclerList(Context context) {
super(context);
init();
}
public RecyclerList(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RecyclerList(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
// Set default layout manager
setLayoutManager(new LinearLayoutManager(getContext()));
// Enable optimizations
setHasFixedSize(true);
setItemViewCacheSize(20);
setDrawingCacheEnabled(true);
setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
}
// Setup method to configure the RecyclerView
public RecyclerList<T> setup(int layoutResId, RecyclerHolderFactory<T> RecyclerHolderFactory) {
adapter = new RecyclerAdapter<>(layoutResId, RecyclerHolderFactory);
setAdapter(adapter);
return this;
}
// Layout manager convenience methods
public RecyclerList<T> withLinearLayout() {
setLayoutManager(new LinearLayoutManager(getContext()));
return this;
}
public RecyclerList<T> withLinearLayout(int orientation) {
setLayoutManager(new LinearLayoutManager(getContext(), orientation, false));
return this;
}
public RecyclerList<T> withGridLayout(int spanCount) {
setLayoutManager(new GridLayoutManager(getContext(), spanCount));
return this;
}
public RecyclerList<T> withDivider() {
DividerItemDecoration divider = new DividerItemDecoration(getContext(),
DividerItemDecoration.VERTICAL);
addItemDecoration(divider);
return this;
}
public RecyclerList<T> withItemClickListener(RecyclerClickListener<T> listener) {
if (adapter != null) {
adapter.setOnItemClickListener(listener);
}
return this;
}
// Data management methods
public void setItems(List<T> items) {
if (adapter != null) {
adapter.setItems(items);
}
}
public void addItem(T item) {
if (adapter != null) {
adapter.addItem(item);
}
}
public void addItem(int position, T item) {
if (adapter != null) {
adapter.addItem(position, item);
}
}
public void removeItem(int position) {
if (adapter != null) {
adapter.removeItem(position);
}
}
public void removeItem(T item) {
if (adapter != null) {
adapter.removeItem(item);
}
}
public void updateItem(int position, T item) {
if (adapter != null) {
adapter.updateItem(position, item);
}
}
public void clear() {
if (adapter != null) {
adapter.clear();
}
}
public T getItem(int position) {
return adapter != null ? adapter.getItem(position) : null;
}
public List<T> getItems() {
return adapter != null ? adapter.getItems() : null;
}
public RecyclerAdapter<T> getGenericAdapter() {
return adapter;
}
}
@@ -19,37 +19,34 @@ import com.ridgebotics.ridgescout.R;
import com.ridgebotics.ridgescout.types.frcTeam; import com.ridgebotics.ridgescout.types.frcTeam;
// A view that acts as a row specifically to display a team and their icon in a list formmt. // A view that acts as a row specifically to display a team and their icon in a list formmt.
public class TeamListOption extends RecyclerHolder<frcTeam> { public class TeamListOption extends LinearLayout {
public TeamListOption(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public TeamListOption(Context context) {
super(context);
init(context);
}
// public TeamListOption(Context context, @Nullable AttributeSet attrs) {
// super(context, attrs);
// init(context);
// }
//
// public TeamListOption(Context context) {
// super(context);
// init(context);
// }
//
private TextView teamNumber; private TextView teamNumber;
private TextView teamName; private TextView teamName;
private ImageView teamLogo; private ImageView teamLogo;
private ConstraintLayout box; private ConstraintLayout box;
private View coloredBackground; private View coloredBackground;
//
public TeamListOption(View view) {
super(view);
// LayoutInflater.from(context).inflate(R.layout.view_team_option, this, true);
teamNumber = view.findViewById(R.id.field_option_type); public void init(Context context) {
teamName = view.findViewById(R.id.field_option_name); LayoutInflater.from(context).inflate(R.layout.view_team_option, this, true);
teamLogo = view.findViewById(R.id.team_option_logo);
teamNumber = findViewById(R.id.field_option_type);
teamName = findViewById(R.id.field_option_name);
teamLogo = findViewById(R.id.team_option_logo);
box = view.findViewById(R.id.team_option_box); box = findViewById(R.id.team_option_box);
coloredBackground = view.findViewById(R.id.team_option_background); coloredBackground = findViewById(R.id.team_option_background);
} }
public void setTeamNumber(int num){ public void setTeamNumber(int num){
@@ -62,7 +59,6 @@ public class TeamListOption extends RecyclerHolder<frcTeam> {
public void setTeamLogo(Bitmap bitmap){ public void setTeamLogo(Bitmap bitmap){
teamLogo.setImageBitmap(bitmap); teamLogo.setImageBitmap(bitmap);
showLogo();
} }
public void hideLogo(){ public void hideLogo(){
@@ -72,8 +68,7 @@ public class TeamListOption extends RecyclerHolder<frcTeam> {
teamLogo.setVisibility(View.VISIBLE); teamLogo.setVisibility(View.VISIBLE);
} }
@Override public void fromTeam(frcTeam team){
public void bind(frcTeam team, int position){
setTeamNumber(team.teamNumber); setTeamNumber(team.teamNumber);
setTeamName(team.teamName); setTeamName(team.teamName);
@@ -3,7 +3,6 @@ package com.ridgebotics.ridgescout.utility;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.widget.Toast; import android.widget.Toast;
@@ -114,22 +113,4 @@ public class AlertManager {
}); });
} }
private static ProgressDialog loadingDialog;
public static void startLoading(String title){
((Activity) context).runOnUiThread(() -> {
if(loadingDialog != null && loadingDialog.isShowing())
loadingDialog.dismiss();
loadingDialog = ProgressDialog.show(context, title, "Please wait...");
});
}
public static void stopLoading(){
((Activity) context).runOnUiThread(() -> {
if (loadingDialog != null)
loadingDialog.cancel();
loadingDialog = null;
});
}
} }
@@ -6,7 +6,7 @@ import android.graphics.Color;
public class Colors { public class Colors {
// Lists and stuff // Lists and stuff
public static final int color_found = 0x7f00ff00; public static final int color_found = 0x7f00ff00;
public static final int color_rescout = 0xff007fff; public static final int color_rescout = 0x7f0000ff;
public static final int color_not_found = 0x7f7f0000; public static final int color_not_found = 0x7f7f0000;
@@ -14,9 +14,9 @@ public class Colors {
public static final int unfocused_background_color = 0x50118811; public static final int unfocused_background_color = 0x50118811;
public static final int unsaved_color = 0xffaa0000; public static final int unsaved_color = 0x60ff0000;
public static final int saved_color = 0xff00aa00; public static final int saved_color = 0x6000ff00;
public static final int rescout_color = 0xff007fff; public static final int rescout_color = 0x600000ff;
// Data graphs // Data graphs
@@ -100,7 +100,7 @@ public final class FileEditor {
public static int byteFromChar(char c){ public static int byteFromChar(char c){
byte[] bytes = (String.valueOf(c)).getBytes(StandardCharsets.ISO_8859_1); byte[] bytes = (String.valueOf(c)).getBytes(Charset.defaultCharset());
return Byte.toUnsignedInt(bytes[0]); return Byte.toUnsignedInt(bytes[0]);
} }
@@ -398,10 +398,9 @@ public final class FileEditor {
Arrays.sort(filenames, (o1, o2) -> { Arrays.sort(filenames, (o1, o2) -> {
try { try {
if (!o1.contains("-") || !o2.contains("-")) if (!o1.contains("-") || !o2.contains("-"))
return o2.compareTo(o1); return 0;
return Integer.valueOf(o1.split("-")[1].split("\\.")[0]).compareTo(Integer.valueOf(o2.split("-")[1].split("\\.")[0])); return Integer.valueOf(o1.split("-")[1]).compareTo(Integer.valueOf(o2.split("-")[1]));
} catch (Exception e) { } catch (Exception e) {
AlertManager.error(e);
return 0; return 0;
} }
}); });
@@ -25,24 +25,11 @@ public class ImageRequestTask extends AsyncTask<String, Void, Bitmap> {
try { try {
URL url = new URL(src); URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// We do a little bit of spoofing
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
connection.setDoInput(true); connection.setDoInput(true);
connection.connect(); connection.connect();
InputStream input = connection.getInputStream();
int code = connection.getResponseCode(); return BitmapFactory.decodeStream(input);
switch (code) { } catch (FileNotFoundException e) {
case 200:
InputStream input = connection.getInputStream();
return BitmapFactory.decodeStream(input);
case 403:
// AlertManager.error("Got 403, Going to https://www.thebluealliance.com/avatars may fix this");
return null;
default:
AlertManager.error("Error downloading image " + src, "Got response code: " + code);
return null;
}
} catch (FileNotFoundException e){
return null; return null;
} catch (IOException e){ } catch (IOException e){
AlertManager.error("Error downloading image " + src, e); AlertManager.error("Error downloading image " + src, e);
@@ -1,32 +0,0 @@
package com.ridgebotics.ridgescout.utility;
import android.os.Handler;
import android.os.Looper;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
// https://stackoverflow.com/questions/58767733/the-asynctask-api-is-deprecated-in-android-11-what-are-the-alternatives
public class TaskRunner {
private final Executor executor = Executors.newSingleThreadExecutor(); // change according to your requirements
private final Handler handler = new Handler(Looper.getMainLooper());
public interface Callback<R> {
void onComplete(R result);
}
public <R> void executeAsync(Callable<R> callable, Callback<R> callback) {
executor.execute(() -> {
final R result;
try {
result = callable.call();
handler.post(() -> {
callback.onComplete(result);
});
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
}
+25 -12
View File
@@ -17,23 +17,36 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<LinearLayout <ScrollView
android:id="@+id/table"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:orientation="vertical" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
<com.ridgebotics.ridgescout.ui.views.CustomSpinnerView <LinearLayout
android:id="@+id/data_type_dropdown" android:layout_width="match_parent"
android:layout_width="wrap_content" android:layout_height="match_parent"
android:layout_height="wrap_content" android:paddingBottom="50dp"
app:layout_constraintEnd_toEndOf="parent" android:orientation="vertical">
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> <TableLayout
android:id="@+id/table"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.ridgebotics.ridgescout.ui.views.CustomSpinnerView
android:id="@+id/data_type_dropdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</TableLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
+11 -9
View File
@@ -92,6 +92,17 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text_next_match"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="TextView"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_name" />
<TextView <TextView
android:id="@+id/text_match_alliance" android:id="@+id/text_match_alliance"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@@ -111,15 +122,6 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/event_button" /> app:layout_constraintTop_toBottomOf="@+id/event_button" />
<LinearLayout
android:id="@+id/info_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_name" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
@@ -45,7 +45,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:text="Scouting Notice" android:text="Scouting Notice"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"/> android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"></TextView>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
@@ -4,27 +4,54 @@
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<com.ridgebotics.ridgescout.ui.views.PitScoutingIndicator <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/pit_indicator" android:id="@+id/pit_file_indicator"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="60dp" android:layout_height="wrap_content"
android:background="#60ff0000"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/pit_bar_team_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="4388"
android:textAlignment="center"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/pitUsername"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Username"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/pit_bar_team_num"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<ScrollView <ScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent">
app:layout_constraintTop_toTopOf="parent">
<LinearLayout <LinearLayout
android:id="@+id/pitScoutArea" android:id="@+id/pitScoutArea"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
android:paddingTop="60dp"> android:paddingTop="48dp">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/scouting_notice_box" android:id="@+id/scouting_notice_box"
@@ -33,15 +60,16 @@
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_margin="5dp" android:layout_margin="5dp"
android:background="@drawable/border" android:background="@drawable/border"
android:orientation="horizontal" android:padding="10dp"
android:padding="10dp"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/scouting_notice_text" android:id="@+id/scouting_notice_text"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:text="Scouting Notice" android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"></TextView> android:text="Scouting Notice">
</TextView>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
+42 -56
View File
@@ -10,6 +10,7 @@
android:id="@+id/scrollView2" android:id="@+id/scrollView2"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginBottom="60dp"
android:fillViewport="true" android:fillViewport="true"
android:visibility="visible" android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@@ -17,70 +18,55 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
<LinearLayout <TableLayout
android:id="@+id/SettingsTable"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<TableLayout </TableLayout>
android:id="@+id/SettingsTable"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
<!-- <Button-->
<!-- android:id="@+id/scoutNoticeButton"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_weight="1"-->
<!-- android:layout_margin="5dp"-->
<!-- android:text="Edit Scout notice"-->
<!-- android:textSize="16sp" />-->
<!-- <LinearLayout-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:orientation="horizontal">-->
<!-- <Button-->
<!-- android:id="@+id/fieldsPitsButton"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_weight="1"-->
<!-- android:layout_margin="5dp"-->
<!-- android:text="Edit PIT Fields"-->
<!-- android:textSize="16sp" />-->
<!-- <Button-->
<!-- android:id="@+id/fieldsMatchesButton"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_weight="1"-->
<!-- android:layout_margin="5dp"-->
<!-- android:text="Edit MATCH Fields"-->
<!-- android:textSize="16sp" />-->
<!-- </LinearLayout>-->
</LinearLayout>
</ScrollView> </ScrollView>
<!-- <LinearLayout--> <Button
<!-- android:id="@+id/fieldsButtons"--> android:id="@+id/fieldsButton"
<!-- android:layout_width="match_parent"--> android:layout_width="wrap_content"
<!-- android:layout_height="wrap_content"--> android:layout_height="wrap_content"
<!-- android:layout_marginTop="1dp"--> android:text="Fields"
<!-- android:gravity="center"--> android:textSize="34sp"
<!-- android:orientation="horizontal"--> app:layout_constraintBottom_toBottomOf="@+id/scrollView2"
<!-- android:visibility="gone"--> app:layout_constraintEnd_toEndOf="parent"
<!-- app:layout_constraintEnd_toEndOf="parent"--> app:layout_constraintStart_toStartOf="parent" />
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintBottom_toTopOf="@+id/fieldsButton"-->
<!-- tools:visibility="visible">-->
<!-- </LinearLayout>--> <LinearLayout
android:id="@+id/fieldsButtons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:gravity="center"
android:orientation="horizontal"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@+id/fieldsButton"
tools:visibility="visible">
<Button
android:id="@+id/fieldsPitsButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Pits"
android:textSize="34sp" />
<Button
android:id="@+id/fieldsMatchesButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Matches"
android:textSize="34sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
@@ -14,7 +14,8 @@
android:id="@+id/teams" android:id="@+id/teams"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" /> android:orientation="vertical"
android:paddingTop="48dp" />
</ScrollView> </ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
@@ -7,65 +7,77 @@
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<SeekBar
android:id="@+id/scannerColors"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginTop="15dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<SeekBar
android:id="@+id/scannerThreshold"
android:layout_width="match_parent"
android:layout_height="48dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/scannerColors" />
<SeekBar
android:id="@+id/scannerBrightness"
android:layout_width="match_parent"
android:layout_height="48dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/scannerThreshold" />
<TextView
android:id="@+id/scannerColorsLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginBottom="-12dp"
android:text="Posterize"
app:layout_constraintBottom_toTopOf="@+id/scannerColors"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/scannerThresholdLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginBottom="-12dp"
android:text="Exposure"
app:layout_constraintBottom_toTopOf="@+id/scannerThreshold"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/scannerBrightnessLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginBottom="-12dp"
android:text="Brightness"
app:layout_constraintBottom_toTopOf="@+id/scannerBrightness"
app:layout_constraintStart_toStartOf="parent" />
<ImageView <ImageView
android:id="@+id/scannerImage" android:id="@+id/scannerImage"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:rotation="90"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:scaleX="1"
android:scaleY="1"
android:translationY="-40dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:context=".CodeScannerView" /> tools:context=".CodeScannerView" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="3dp"
android:padding="3dp"
android:background="@drawable/border"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
tools:layout_editor_absoluteX="3dp">
<TextView
android:id="@+id/scannerColorsLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Posterize"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"/>
<SeekBar
android:id="@+id/scannerColors"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginTop="15dp" />
<TextView
android:id="@+id/scannerThresholdLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Exposure"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"/>
<SeekBar
android:id="@+id/scannerThreshold"
android:layout_width="match_parent"
android:layout_height="48dp" />
<TextView
android:id="@+id/scannerBrightnessLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Brightness"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"/>
<SeekBar
android:id="@+id/scannerBrightness"
android:layout_width="match_parent"
android:layout_height="48dp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
@@ -1,10 +1,31 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<SeekBar
android:id="@+id/qrSizeSlider"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginBottom="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/qrImage" />
<SeekBar
android:id="@+id/qrSpeedSlider"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginBottom="60dp"
app:layout_constraintBottom_toTopOf="@+id/qrSizeSlider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.971"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/qrImage"
app:layout_constraintVertical_bias="0.93" />
<ImageView <ImageView
android:id="@+id/qrImage" android:id="@+id/qrImage"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -15,48 +36,23 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<LinearLayout <TextView
android:layout_width="match_parent" android:id="@+id/qrSpeedText"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="3dp" android:layout_marginStart="8dp"
android:orientation="vertical" android:text="QR Speed"
android:background="@drawable/border" app:layout_constraintBottom_toTopOf="@+id/qrSpeedSlider"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" />
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<TextView
<TextView android:id="@+id/qrSizeText"
android:id="@+id/qrSpeedText" android:layout_width="wrap_content"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_height="wrap_content" android:layout_marginStart="8dp"
android:layout_marginStart="8dp" android:text="QR Size"
android:text="QR Speed" app:layout_constraintBottom_toTopOf="@+id/qrSizeSlider"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6" app:layout_constraintStart_toStartOf="parent" />
app:layout_constraintBottom_toTopOf="@+id/qrSpeedSlider" />
<SeekBar
android:id="@+id/qrSpeedSlider"
android:layout_width="match_parent"
android:layout_height="48dp" />
<TextView
android:id="@+id/qrSizeText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="QR Size"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6" />
<SeekBar
android:id="@+id/qrSizeSlider"
android:layout_width="match_parent"
android:layout_height="48dp"
tools:layout_editor_absoluteY="135dp" />
</LinearLayout>
<TextView <TextView
android:id="@+id/qrIndexN" android:id="@+id/qrIndexN"
@@ -64,8 +60,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="0" android:text="0"
app:layout_constraintEnd_toStartOf="@+id/qrIndexSlash" app:layout_constraintEnd_toStartOf="@+id/qrIndexSlash"
app:layout_constraintTop_toBottomOf="@+id/qrImage" app:layout_constraintTop_toBottomOf="@+id/qrImage" />
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"/>
<TextView <TextView
android:id="@+id/qrIndexSlash" android:id="@+id/qrIndexSlash"
@@ -74,8 +69,7 @@
android:text="/" android:text="/"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/qrImage" app:layout_constraintTop_toBottomOf="@+id/qrImage" />
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6" />
<TextView <TextView
android:id="@+id/qrIndexD" android:id="@+id/qrIndexD"
@@ -83,7 +77,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="0" android:text="0"
app:layout_constraintStart_toEndOf="@+id/qrIndexSlash" app:layout_constraintStart_toEndOf="@+id/qrIndexSlash"
app:layout_constraintTop_toBottomOf="@+id/qrImage" app:layout_constraintTop_toBottomOf="@+id/qrImage" />
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
@@ -8,12 +8,9 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="3dp" android:layout_margin="3dp"
android:layout_marginTop="5dp"
android:layout_marginRight="3dp"
android:layout_marginBottom="3dp"
android:background="@drawable/border"
android:orientation="horizontal" android:orientation="horizontal"
android:background="@drawable/border"
tools:ignore="UselessParent"> tools:ignore="UselessParent">
<TextView <TextView
@@ -21,9 +18,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_margin="10dp" android:layout_margin="10dp"
android:overlapAnchor="false" android:textSize="24sp"
android:text="▼ Options" android:overlapAnchor="false"/>
android:textSize="24sp" />
</LinearLayout> </LinearLayout>
@@ -32,9 +28,9 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="9dp" android:layout_marginStart="9dp"
android:layout_marginTop="-6dp" android:layout_marginTop="-5dp"
android:paddingLeft="3dp" android:paddingLeft="3dp"
android:paddingRight="3dp" android:paddingRight="3dp"
android:text="Test" android:text="Test"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1" /> android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"/>
</RelativeLayout> </RelativeLayout>
@@ -11,6 +11,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="5dp" android:layout_margin="5dp"
android:background="@drawable/border" android:background="@drawable/border"
android:padding="3dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
@@ -22,18 +23,16 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent" />
tools:visibility="gone" />
<ImageButton <ImageButton
android:id="@+id/match_indicator_back_button" android:id="@+id/match_indicator_back_button"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="Back"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:src="@drawable/triangle_left" android:src="@drawable/triangle_left"
android:text="Back" android:text="Back"
android:background="@drawable/border" android:background="@color/zxing_transparent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
@@ -43,10 +42,9 @@
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:contentDescription="Next"
android:src="@drawable/triangle_right" android:src="@drawable/triangle_right"
android:text="Next" android:text="Next"
android:background="@drawable/border" android:background="@color/zxing_transparent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
@@ -55,24 +53,24 @@
android:id="@+id/match_indicator_alliance_pos_text" android:id="@+id/match_indicator_alliance_pos_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="58dp" android:layout_marginEnd="4dp"
android:text="Temp" android:text="Temp"
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1" android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
android:textAlignment="center"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/match_indicator_next_button" app:layout_constraintEnd_toStartOf="@+id/match_indicator_next_button"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<TextView <TextView
android:id="@+id/match_indicator_username" android:id="@+id/match_indicator_username"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="58dp" android:layout_marginStart="4dp"
android:text="Temp" android:text="Temp"
android:textAlignment="center" android:textAlignment="center"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6" android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toEndOf="@+id/match_indicator_back_button"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<TextView <TextView
@@ -1,55 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/pit_indicator_box"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="@drawable/border"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<View
android:id="@+id/pit_indicator_background"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="gone" />
<TextView
android:id="@+id/pit_indicator_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="58dp"
android:text="Username"
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/pit_indicator_teamnum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:text="4388"
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</RelativeLayout>
@@ -17,8 +17,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center" android:gravity="center"
android:text="0"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:textSize="24sp" /> android:textSize="24sp" />
<Button <Button
+2 -4
View File
@@ -28,15 +28,13 @@
android:id="@+id/team_option_logo" android:id="@+id/team_option_logo"
android:layout_width="54dp" android:layout_width="54dp"
android:layout_height="54dp" android:layout_height="54dp"
android:layout_margin="2dp" android:layout_margin="3dp"
android:scaleType="fitXY" android:scaleType="fitXY"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1" app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@drawable/ic_robologo" tools:srcCompat="@drawable/ic_robologo" />
tools:visibility="visible" />
<TextView <TextView
android:id="@+id/field_option_name" android:id="@+id/field_option_name"
+1 -5
View File
@@ -1,6 +1,5 @@
[versions] [versions]
agp = "8.11.1" agp = "8.8.0"
asynclayoutinflator = "1.1.0"
junit = "4.13.2" junit = "4.13.2"
junitVersion = "1.1.5" junitVersion = "1.1.5"
espressoCore = "3.5.1" espressoCore = "3.5.1"
@@ -11,13 +10,11 @@ lifecycleLivedataKtx = "2.6.1"
lifecycleViewmodelKtx = "2.6.1" lifecycleViewmodelKtx = "2.6.1"
material3 = "1.3.1" material3 = "1.3.1"
navigationFragment = "2.6.0" navigationFragment = "2.6.0"
navigationFragmentVersion = "2.8.9"
navigationUi = "2.6.0" navigationUi = "2.6.0"
supportAnnotations = "28.0.0" supportAnnotations = "28.0.0"
preference = "1.2.1" preference = "1.2.1"
[libraries] [libraries]
asynclayoutinflator = { module = "androidx.asynclayoutinflator:asynclayoutinflator", version.ref = "asynclayoutinflator" }
junit = { group = "junit", name = "junit", version.ref = "junit" } junit = { group = "junit", name = "junit", version.ref = "junit" }
ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
@@ -28,7 +25,6 @@ lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-lived
lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" } lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
material3 = { module = "androidx.compose.material3:material3", version.ref = "material3" } material3 = { module = "androidx.compose.material3:material3", version.ref = "material3" }
navigation-fragment = { group = "androidx.navigation", name = "navigation-fragment", version.ref = "navigationFragment" } navigation-fragment = { group = "androidx.navigation", name = "navigation-fragment", version.ref = "navigationFragment" }
navigation-fragment-v289 = { module = "androidx.navigation:navigation-fragment", version.ref = "navigationFragmentVersion" }
navigation-ui = { group = "androidx.navigation", name = "navigation-ui", version.ref = "navigationUi" } navigation-ui = { group = "androidx.navigation", name = "navigation-ui", version.ref = "navigationUi" }
support-annotations = { group = "com.android.support", name = "support-annotations", version.ref = "supportAnnotations" } support-annotations = { group = "com.android.support", name = "support-annotations", version.ref = "supportAnnotations" }
preference = { group = "androidx.preference", name = "preference", version.ref = "preference" } preference = { group = "androidx.preference", name = "preference", version.ref = "preference" }
+1 -1
View File
@@ -1,6 +1,6 @@
#Sun Mar 24 10:48:55 MDT 2024 #Sun Mar 24 10:48:55 MDT 2024
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists