From 05a40e39c3e057fd292e2398c2b5f62a790065a8 Mon Sep 17 00:00:00 2001 From: Michael Mikovsky <77305074+Astatin3@users.noreply.github.com> Date: Sun, 27 Jul 2025 21:57:33 -0600 Subject: [PATCH] Stuff --- .../ridgescout/types/ColabArray.java | 4 + .../ridgescout/types/frcEvent.java | 57 +++++--- .../ui/scouting/ScoutingFragment.java | 47 ++++--- .../ui/transfer/codes/CodeGeneratorView.java | 15 -- .../ui/views/CustomSpinnerView.java | 4 +- .../ridgescout/ui/views/RecyclerAdapter.java | 105 ++++++++++++++ .../ui/views/RecyclerClickListener.java | 5 + .../ridgescout/ui/views/RecyclerHolder.java | 19 +++ .../ui/views/RecyclerHolderFactory.java | 7 + .../ridgescout/ui/views/RecyclerList.java | 133 ++++++++++++++++++ app/src/main/res/layout/fragment_scouting.xml | 20 ++- 11 files changed, 353 insertions(+), 63 deletions(-) create mode 100644 app/src/main/java/com/ridgebotics/ridgescout/types/ColabArray.java create mode 100644 app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerAdapter.java create mode 100644 app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerClickListener.java create mode 100644 app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerHolder.java create mode 100644 app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerHolderFactory.java create mode 100644 app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerList.java diff --git a/app/src/main/java/com/ridgebotics/ridgescout/types/ColabArray.java b/app/src/main/java/com/ridgebotics/ridgescout/types/ColabArray.java new file mode 100644 index 0000000..dcf0f18 --- /dev/null +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/ColabArray.java @@ -0,0 +1,4 @@ +package com.ridgebotics.ridgescout.types; + +public class ColabArray { +} diff --git a/app/src/main/java/com/ridgebotics/ridgescout/types/frcEvent.java b/app/src/main/java/com/ridgebotics/ridgescout/types/frcEvent.java index 163a494..e855443 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/types/frcEvent.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/frcEvent.java @@ -9,14 +9,13 @@ import com.ridgebotics.ridgescout.utility.ByteBuilder; import com.ridgebotics.ridgescout.utility.SettingsManager; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.stream.IntStream; // Class to contain data for an entire event. // Easily encoded and decoded to binary format. public class frcEvent { - - public static final int typecode = 254; public String eventCode; public String name; public ArrayList matches; @@ -134,29 +133,29 @@ public class frcEvent { return null; } -// public // Returns the soonest match that there will be all the possible upcoming data on other teams - public void getReportMatches(int ourTeamNum){ - frcMatch[] teamMatches = event.getTeamMatches(ourTeamNum); + public int getMostInformedBy(int ourTeamNum, int curMatch){ + frcMatch teamMatch = getNextTeamMatch(ourTeamNum, curMatch); - 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]; + int maxMatch = Integer.MIN_VALUE; - if(teamNum == ourTeamNum) - continue; + for(int a = 0; a < 6; a++){ + int teamNum; + if(a < 3) + teamNum = teamMatch.redAlliance[a]; + else + teamNum = teamMatch.blueAlliance[a-3]; - int matchNum = event.getMostRecentTeamMatch(teamNum, teamMatches[i].matchIndex); - if(maxMatch < matchNum) - maxMatch = matchNum; - } + if(teamNum == ourTeamNum) + continue; + + int matchNum = event.getMostRecentTeamMatch(teamNum, teamMatch.matchIndex); + if(maxMatch < matchNum) + maxMatch = matchNum; } + + return maxMatch; } public frcTeam getTeamByNum(int teamNum){ @@ -168,6 +167,26 @@ public class frcEvent { return null; } + public List 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 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){ return getIsBlueAlliance(teamNum, matches.get(matchNum)); diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/ScoutingFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/ScoutingFragment.java index 05c25e3..380930a 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/ScoutingFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/ScoutingFragment.java @@ -15,6 +15,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.EditText; import android.widget.LinearLayout; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -89,7 +90,7 @@ public class ScoutingFragment extends Fragment { binding.textMatchAlliance.setVisibility(View.GONE); binding.textName.setVisibility(View.GONE); - binding.textNextMatch.setVisibility(View.GONE); + binding.infoBox.setVisibility(View.GONE); binding.textRescoutIndicator.setVisibility(View.GONE); binding.matchScoutingButton.setEnabled(false); @@ -123,21 +124,7 @@ public class ScoutingFragment extends Fragment { findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_scouting_event); }); - - binding.textName.setText("Welcome, " + SettingsManager.getUsername() + "!"); - - int matchNum = SettingsManager.getMatchNum(); - int nextMatch = -1; - int teamNum = SettingsManager.getTeamNum(); - try { - nextMatch = event.getNextTeamMatch(teamNum, matchNum).matchIndex; - } catch (Exception e){ - AlertManager.error("Sorry, in event ("+evcode+"), your team number ("+teamNum+") wasn't found!", 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()); + updateDashboard(); return binding.getRoot(); } @@ -166,4 +153,32 @@ 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); + } } \ No newline at end of file diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/codes/CodeGeneratorView.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/codes/CodeGeneratorView.java index 6599574..d0b88d4 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/codes/CodeGeneratorView.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/codes/CodeGeneratorView.java @@ -1,8 +1,6 @@ package com.ridgebotics.ridgescout.ui.transfer.codes; -import android.app.Activity; import android.graphics.Bitmap; -import android.graphics.Color; import android.os.Bundle; import android.os.CountDownTimer; import android.os.Handler; @@ -21,25 +19,12 @@ import androidx.fragment.app.Fragment; import com.ridgebotics.ridgescout.databinding.FragmentTransferCodeSenderBinding; import com.ridgebotics.ridgescout.utility.AlertManager; import com.ridgebotics.ridgescout.utility.FileEditor; -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.TaskRunner; -import java.lang.reflect.Executable; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.EnumMap; import java.util.List; -import java.util.Map; import java.util.Random; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; // Class to show the code transfer thing. public class CodeGeneratorView extends Fragment { diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/views/CustomSpinnerView.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/views/CustomSpinnerView.java index 07d9568..34e5b0b 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/views/CustomSpinnerView.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/views/CustomSpinnerView.java @@ -62,7 +62,7 @@ public class CustomSpinnerView extends LinearLayout { this.index = defaultOption; if(defaultOption != -1) - this.item.setText(options.get(defaultOption)); + this.item.setText("▼ " + options.get(defaultOption)); AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); @@ -110,7 +110,7 @@ public class CustomSpinnerView extends LinearLayout { } public void setOption(int index) { - item.setText(options.get(index)); + item.setText("▼ " + options.get(index)); this.index = index; } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerAdapter.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerAdapter.java new file mode 100644 index 0000000..a51b763 --- /dev/null +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerAdapter.java @@ -0,0 +1,105 @@ +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 extends RecyclerView.Adapter> { + private List items; + private final int layoutResId; + private final RecyclerHolderFactory viewHolderFactory; + private RecyclerClickListener onItemClickListener; + + public RecyclerAdapter(int layoutResId, RecyclerHolderFactory viewHolderFactory) { + this.items = new ArrayList<>(); + this.layoutResId = layoutResId; + this.viewHolderFactory = viewHolderFactory; + } + + @Override + public RecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()) + .inflate(layoutResId, parent, false); + return viewHolderFactory.createViewHolder(view); + } + + @Override + public void onBindViewHolder(RecyclerHolder 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 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 getItems() { + return new ArrayList<>(items); + } + + public void setOnItemClickListener(RecyclerClickListener listener) { + this.onItemClickListener = listener; + } +} diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerClickListener.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerClickListener.java new file mode 100644 index 0000000..14c97d7 --- /dev/null +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerClickListener.java @@ -0,0 +1,5 @@ +package com.ridgebotics.ridgescout.ui.views; + +public interface RecyclerClickListener { + void onItemClick(T item, int position); +} \ No newline at end of file diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerHolder.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerHolder.java new file mode 100644 index 0000000..c98c7c8 --- /dev/null +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerHolder.java @@ -0,0 +1,19 @@ +package com.ridgebotics.ridgescout.ui.views; + +import android.view.View; +import androidx.recyclerview.widget.RecyclerView; + +public abstract class RecyclerHolder 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 listener) { + if (listener != null) { + itemView.setOnClickListener(v -> listener.onItemClick(item, getAdapterPosition())); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerHolderFactory.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerHolderFactory.java new file mode 100644 index 0000000..2be4e9f --- /dev/null +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerHolderFactory.java @@ -0,0 +1,7 @@ +package com.ridgebotics.ridgescout.ui.views; + +import android.view.View; + +public interface RecyclerHolderFactory { + RecyclerHolder createViewHolder(View itemView); +} diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerList.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerList.java new file mode 100644 index 0000000..1abe293 --- /dev/null +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/views/RecyclerList.java @@ -0,0 +1,133 @@ +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 extends RecyclerView { + private RecyclerAdapter 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 setup(int layoutResId, RecyclerHolderFactory RecyclerHolderFactory) { + adapter = new RecyclerAdapter<>(layoutResId, RecyclerHolderFactory); + setAdapter(adapter); + return this; + } + + // Layout manager convenience methods + public RecyclerList withLinearLayout() { + setLayoutManager(new LinearLayoutManager(getContext())); + return this; + } + + public RecyclerList withLinearLayout(int orientation) { + setLayoutManager(new LinearLayoutManager(getContext(), orientation, false)); + return this; + } + + public RecyclerList withGridLayout(int spanCount) { + setLayoutManager(new GridLayoutManager(getContext(), spanCount)); + return this; + } + + public RecyclerList withDivider() { + DividerItemDecoration divider = new DividerItemDecoration(getContext(), + DividerItemDecoration.VERTICAL); + addItemDecoration(divider); + return this; + } + + public RecyclerList withItemClickListener(RecyclerClickListener listener) { + if (adapter != null) { + adapter.setOnItemClickListener(listener); + } + return this; + } + + // Data management methods + public void setItems(List 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 getItems() { + return adapter != null ? adapter.getItems() : null; + } + + public RecyclerAdapter getGenericAdapter() { + return adapter; + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_scouting.xml b/app/src/main/res/layout/fragment_scouting.xml index ec8291f..b38c19c 100644 --- a/app/src/main/res/layout/fragment_scouting.xml +++ b/app/src/main/res/layout/fragment_scouting.xml @@ -92,17 +92,6 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> - - + +