Delete file menu, proper downloading of images

This commit is contained in:
Michael Mikovsky
2025-07-28 13:43:42 -06:00
parent 05a40e39c3
commit 2d3db09aae
12 changed files with 156 additions and 327 deletions
@@ -60,61 +60,57 @@ public class ScoutingDataWriter {
public ScoutingArray data;
}
public static ParsedScoutingDataResult load(String filename, FieldType[][] values , TransferType[][] transferValues){
public static ParsedScoutingDataResult load(String filename, FieldType[][] values , TransferType[][] transferValues) throws BuiltByteParser.byteParsingExeption{
byte[] bytes = FileEditor.readFile(filename);
BuiltByteParser bbp = new BuiltByteParser(bytes);
try {
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
RawDataType[] rawDataTypes = new RawDataType[objects.size()-2];
// try {
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
RawDataType[] rawDataTypes = new RawDataType[objects.size()-2];
int version = ((int)objects.get(0).get());
int version = ((int)objects.get(0).get());
if(values.length <= version) {
if(values.length <= version) {
// AlertManager.addSimpleError("Error loading " + filename);
AlertManager.error(new BuiltByteParser.byteParsingExeption("Field version (" +version + ") is too recent as compared to latest version (" + (values.length-1) + ")!"));
return null;
}
throw new BuiltByteParser.byteParsingExeption("Field version (" +version + ") is too recent as compared to latest version (" + (values.length-1) + ")!");
}
// System.out.println(version);
String username = (String) objects.get(1).get();
String username = (String) objects.get(1).get();
for(int i = 0; i < values[version].length; i++){
switch (objects.get(i+2).getType()){
case 1: // Int
rawDataTypes[i] = IntType.newNull(values[version][i].UUID);
rawDataTypes[i].forceSetValue(objects.get(i+2).get());
Log.i(ParsedScoutingDataResult.class.toString(),"Loaded INT: " + values[version][i].name + " (" + values[version][i].UUID + ") " + ", ("+ rawDataTypes[i].get() +")");
break;
case 2: // String
rawDataTypes[i] = StringType.newNull(values[version][i].UUID);
rawDataTypes[i].forceSetValue(objects.get(i+2).get());
Log.i(ParsedScoutingDataResult.class.toString(),"Loaded STR: " + values[version][i].name + " (" + values[version][i].UUID + ") " + ", ("+ rawDataTypes[i].get() +")");
break;
case 3: // Int array
rawDataTypes[i] = IntArrType.newNull(values[version][i].UUID);
rawDataTypes[i].forceSetValue(objects.get(i+2).get());
Log.i(ParsedScoutingDataResult.class.toString(),"Loaded intARR: " + values[version][i].name + " (" + values[version][i].UUID + ") " + ", ("+ Arrays.toString((int[]) rawDataTypes[i].get()) +")");
break;
}
for(int i = 0; i < values[version].length; i++){
switch (objects.get(i+2).getType()){
case 1: // Int
rawDataTypes[i] = IntType.newNull(values[version][i].UUID);
rawDataTypes[i].forceSetValue(objects.get(i+2).get());
Log.i(ParsedScoutingDataResult.class.toString(),"Loaded INT: " + values[version][i].name + " (" + values[version][i].UUID + ") " + ", ("+ rawDataTypes[i].get() +")");
break;
case 2: // String
rawDataTypes[i] = StringType.newNull(values[version][i].UUID);
rawDataTypes[i].forceSetValue(objects.get(i+2).get());
Log.i(ParsedScoutingDataResult.class.toString(),"Loaded STR: " + values[version][i].name + " (" + values[version][i].UUID + ") " + ", ("+ rawDataTypes[i].get() +")");
break;
case 3: // Int array
rawDataTypes[i] = IntArrType.newNull(values[version][i].UUID);
rawDataTypes[i].forceSetValue(objects.get(i+2).get());
Log.i(ParsedScoutingDataResult.class.toString(),"Loaded intARR: " + values[version][i].name + " (" + values[version][i].UUID + ") " + ", ("+ Arrays.toString((int[]) rawDataTypes[i].get()) +")");
break;
}
ScoutingArray msa = new ScoutingArray(version, rawDataTypes, values, transferValues);
msa.update();
ParsedScoutingDataResult psda = new ParsedScoutingDataResult();
psda.filename = filename;
psda.username = username;
psda.version = version;
psda.data = msa;
return psda;
} catch (BuiltByteParser.byteParsingExeption e){
AlertManager.error(e);
return null;
}
ScoutingArray msa = new ScoutingArray(version, rawDataTypes, values, transferValues);
msa.update();
ParsedScoutingDataResult psda = new ParsedScoutingDataResult();
psda.filename = filename;
psda.username = username;
psda.version = version;
psda.data = msa;
return psda;
// }
}
// A function that takes in a list of names seperated by commas, and adds a name if it is not included
@@ -23,6 +23,7 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.SettingsManager;
import com.ridgebotics.ridgescout.databinding.FragmentDataTeamsBinding;
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
@@ -97,7 +98,7 @@ public class TeamsFragment extends Fragment {
try {add_match_data(team, mode);}catch(Exception e){AlertManager.error(e);}
}
public void add_pit_data(frcTeam team){
public void add_pit_data(frcTeam team) throws BuiltByteParser.byteParsingExeption {
binding.pitArea.removeAllViews();
final String filename = evcode+"-"+team.teamNumber+".pitscoutdata";
@@ -21,6 +21,7 @@ import androidx.fragment.app.Fragment;
import com.google.android.material.divider.MaterialDivider;
import com.ridgebotics.ridgescout.ui.views.ToggleTitleView;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.SettingsManager;
import com.ridgebotics.ridgescout.databinding.FragmentScoutingMatchBinding;
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
@@ -347,7 +348,7 @@ public class MatchScoutingFragment extends Fragment {
public void get_fields(){
public void get_fields() throws BuiltByteParser.byteParsingExeption{
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.match_values, DataManager.match_transferValues);
RawDataType[] types = psdr.data.array;
@@ -23,6 +23,7 @@ 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.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.SettingsManager;
import com.ridgebotics.ridgescout.databinding.FragmentScoutingPitBinding;
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
@@ -224,7 +225,7 @@ public class PitScoutingFragment extends Fragment {
}
}
public void get_fields(){
public void get_fields() throws BuiltByteParser.byteParsingExeption{
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, pit_values, pit_transferValues);
RawDataType[] types = psdr.data.array;
@@ -30,6 +30,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ScrollView;
@@ -51,6 +52,7 @@ import com.ridgebotics.ridgescout.databinding.FragmentSettingsBinding;
import com.ridgebotics.ridgescout.scoutingData.Fields;
import com.ridgebotics.ridgescout.ui.views.CustomSpinnerView;
import com.ridgebotics.ridgescout.ui.views.TallyCounterView;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.DataManager;
import com.ridgebotics.ridgescout.utility.FileEditor;
import com.ridgebotics.ridgescout.utility.SettingsManager;
@@ -88,7 +90,20 @@ public class SettingsFragment extends Fragment {
ButtonSettingsItem corruptButton = new ButtonSettingsItem();
corruptButton.addButton("Remove corrupted files", view -> {});
corruptButton.addButton("find corrupted files", view -> {
new Thread(() -> {
AlertManager.startLoading("Loading files...");
List<String> filenames = FileEditor.findCorruptedFiles();
AlertManager.stopLoading();
getActivity().runOnUiThread(() -> {
deleteFiles(filenames, true);
});
}).start();
});
corruptButton.addButton("delete files", view -> {
deleteFiles(Arrays.asList(FileEditor.getFiles()), false);
});
// corruptButton.setEnabled(!getEVCode().equals("unset"));
manager.addItem(corruptButton);
manager.addItem(new HeaderSettingsItem("Advanced"));
@@ -242,6 +257,36 @@ public class SettingsFragment extends Fragment {
alert.create().show();
}
private void deleteFiles(List<String> files, boolean defaultOption) {
ScrollView sv = new ScrollView(getContext());
LinearLayout ll = new LinearLayout(getContext());
ll.setOrientation(VERTICAL);
sv.addView(ll);
CheckBox[] checkboxes = new CheckBox[files.size()];
for(int i =0; i < files.size(); i++){
CheckBox cb = new CheckBox(getContext());
cb.setText(files.get(i));
cb.setChecked(defaultOption);
ll.addView(cb);
checkboxes[i] = cb;
}
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
alert.setTitle("Delete files");
alert.setView(sv);
alert.setNeutralButton("Cancel", null);
// alert.setPositiveButton("Save", (dialogInterface, i) -> {
// DataManager.scoutNotice = editText.getText().toString();
// DataManager.save_scout_notice();
// });
alert.setCancelable(false);
alert.create().show();
}
@@ -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;
}
}
@@ -1,7 +1,13 @@
package com.ridgebotics.ridgescout.utility;
import static com.ridgebotics.ridgescout.utility.DataManager.match_transferValues;
import static com.ridgebotics.ridgescout.utility.DataManager.match_values;
import static com.ridgebotics.ridgescout.utility.DataManager.pit_transferValues;
import static com.ridgebotics.ridgescout.utility.DataManager.pit_values;
import android.content.Context;
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
import com.ridgebotics.ridgescout.types.frcEvent;
import com.ridgebotics.ridgescout.types.frcTeam;
@@ -373,25 +379,21 @@ public final class FileEditor {
public static String[] getEventFiles(String evcode){
public static String[] getFiles(){
File f = new File(baseDir);
File[] files = f.listFiles();
if(files == null){return new String[0];}
ArrayList<String> outFiles = new ArrayList<>();
outFiles.add("matches.fields");
outFiles.add("pits.fields");
// outFiles.add(evcode + ".eventdata");
List<String> outFiles = new ArrayList<>();
for (File file : files) {
String name = file.getName();
if(!file.isDirectory() && name.startsWith(evcode)) {
if (!file.isDirectory()) {
outFiles.add(file.getName());
}
}
String[] filenames = outFiles.toArray(new String[0]);
try {
@@ -413,6 +415,24 @@ public final class FileEditor {
return filenames;
}
public static String[] getEventFiles(String evcode){
String[] files = getFiles();
List<String> outFiles = new ArrayList<>();
outFiles.add("matches.fields");
outFiles.add("pits.fields");
for (String file : files) {
if(file.startsWith(evcode)) {
outFiles.add(file);
}
}
return outFiles.toArray(new String[0]);
}
// https://stackoverflow.com/questions/7620401/how-to-convert-image-file-data-in-a-byte-array-to-a-bitmap
// public static String imageToBitMap(byte[] data) throws IOException {
// Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
@@ -425,5 +445,40 @@ public final class FileEditor {
public static boolean setTeams(Context context, String key, ArrayList<frcTeam> teams){
return true;
}
public static List<String> findCorruptedFiles() {
List<String> removeFiles = new ArrayList<>();
String[] localFiles = FileEditor.getFiles();
DataManager.reload_match_fields();
DataManager.reload_pit_fields();
for(int i = 0; i < localFiles.length; i++){
String filename = localFiles[i];
String[] split = filename.split("\\.");
String extention =split[split.length-1];
try {
switch (extention) {
case "matchscoutdata":
ScoutingDataWriter.load(filename, match_values, match_transferValues);
break;
case "pitscoutdata":
ScoutingDataWriter.load(filename, pit_values, pit_transferValues);
break;
default:
continue;
}
} catch (Exception e) {
removeFiles.add(filename);
}
}
return removeFiles;
}
}