diff --git a/README.md b/README.md index bea41d6..5612e6f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Ridgebotics 2025 scouting app in Android TODO: -- Copy matchScoutingView to create pitScoutingView +- Handle saving team list data from TBA without matches. For the practice day. - Make the file browser UI - Add white border around the datamatrix code to allow file transfer in dark mode - Fix the code scanning progress indicator diff --git a/app/src/main/java/com/astatin3/scoutingapp2025/scoutingData/fields.java b/app/src/main/java/com/astatin3/scoutingapp2025/scoutingData/fields.java index c1aa577..6dfc3b8 100644 --- a/app/src/main/java/com/astatin3/scoutingapp2025/scoutingData/fields.java +++ b/app/src/main/java/com/astatin3/scoutingapp2025/scoutingData/fields.java @@ -10,7 +10,7 @@ public class fields { public static ScoutingVersion sv = new ScoutingVersion(); public static final String matchFieldsFilename = "matches.fields"; - public static final String pitsFieldsFilename = "matches.fields"; + public static final String pitsFieldsFilename = "pits.fields"; public static final ScoutingVersion.inputType[][] default_match_fields = new ScoutingVersion.inputType[][] { { diff --git a/app/src/main/java/com/astatin3/scoutingapp2025/ui/data/overviewView.java b/app/src/main/java/com/astatin3/scoutingapp2025/ui/data/overviewView.java index 602931f..ea1f8b2 100644 --- a/app/src/main/java/com/astatin3/scoutingapp2025/ui/data/overviewView.java +++ b/app/src/main/java/com/astatin3/scoutingapp2025/ui/data/overviewView.java @@ -17,6 +17,8 @@ import com.astatin3.scoutingapp2025.types.frcEvent; import com.astatin3.scoutingapp2025.types.frcMatch; import com.astatin3.scoutingapp2025.types.frcTeam; +import java.util.Arrays; + public class overviewView extends ScrollView { public overviewView(@NonNull Context context) { super(context); @@ -48,9 +50,19 @@ public class overviewView extends ScrollView { tv.setTextSize(28); binding.matchTable.addView(tv); + int[] teams = new int[event.teams.size()]; + + for(int i = 0 ; i < event.teams.size(); i++){ + teams[i] = event.teams.get(i).teamNumber; + } + + Arrays.sort(teams); + TableRow tr = null; for(int i=0; i < event.teams.size(); i++){ - frcTeam team = event.teams.get(i); +// frcTeam team = event.teams.get(i); + int num = teams[i]; + if(i % 7 == 0){ if(i != 0) binding.matchTable.addView(tr); @@ -61,8 +73,8 @@ public class overviewView extends ScrollView { text.setTextSize(18); text.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); - text.setText(String.valueOf(team.teamNumber)); - if(fileEditor.fileExist(event.eventCode + "-" + team.teamNumber + ".pitscoutdata")){ + text.setText(String.valueOf(num)); + if(fileEditor.fileExist(event.eventCode + "-" + num + ".pitscoutdata")){ text.setBackgroundColor(0x3000FF00); }else{ text.setBackgroundColor(0x30FF0000); diff --git a/app/src/main/java/com/astatin3/scoutingapp2025/ui/scouting/matchScoutingView.java b/app/src/main/java/com/astatin3/scoutingapp2025/ui/scouting/matchScoutingView.java index 78afb57..32e98fd 100644 --- a/app/src/main/java/com/astatin3/scoutingapp2025/ui/scouting/matchScoutingView.java +++ b/app/src/main/java/com/astatin3/scoutingapp2025/ui/scouting/matchScoutingView.java @@ -54,8 +54,6 @@ public class matchScoutingView extends ConstraintLayout { ArrayList dataTypes; - ArrayList views = new ArrayList<>(); - public void save(){ @@ -98,7 +96,6 @@ public class matchScoutingView extends ConstraintLayout { tv.setText("Failed to load fields.\nTry to either download or create match scouting fields."); tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); binding.MatchScoutArea.addView(tv); -// views.add(tv); return; } @@ -121,19 +118,13 @@ public class matchScoutingView extends ConstraintLayout { update_scouting_data(); }); - binding.middleButton.setOnClickListener(v -> { - if(edited) save(); - }); +// binding.middleButton.setOnClickListener(v -> { +// if(edited) save(); +// }); latest_values = values[values.length-1]; transferValues = fields.sv.get_transfer_values(values); - for(int i = 0; i < views.size(); i++){ - binding.MatchScoutArea.removeView(views.get(i)); - } - -// views = new ArrayList<>(); - create_fields(); update_scouting_data(); } diff --git a/app/src/main/java/com/astatin3/scoutingapp2025/ui/scouting/pitScoutingView.java b/app/src/main/java/com/astatin3/scoutingapp2025/ui/scouting/pitScoutingView.java index 7c0db50..1935e49 100644 --- a/app/src/main/java/com/astatin3/scoutingapp2025/ui/scouting/pitScoutingView.java +++ b/app/src/main/java/com/astatin3/scoutingapp2025/ui/scouting/pitScoutingView.java @@ -1,12 +1,278 @@ package com.astatin3.scoutingapp2025.ui.scouting; import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.TableLayout; +import android.widget.TableRow; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.constraintlayout.widget.ConstraintLayout; +import com.astatin3.scoutingapp2025.SettingsVersionStack.latestSettings; +import com.astatin3.scoutingapp2025.databinding.FragmentScoutingBinding; +import com.astatin3.scoutingapp2025.scoutingData.ScoutingDataWriter; +import com.astatin3.scoutingapp2025.scoutingData.ScoutingVersion; +import com.astatin3.scoutingapp2025.scoutingData.fields; +import com.astatin3.scoutingapp2025.types.frcEvent; +import com.astatin3.scoutingapp2025.types.frcMatch; +import com.astatin3.scoutingapp2025.types.frcTeam; +import com.astatin3.scoutingapp2025.utility.AutoSaveManager; +import com.astatin3.scoutingapp2025.utility.fileEditor; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.function.Function; + public class pitScoutingView extends ConstraintLayout { - public pitScoutingView(@NonNull Context context) { + public pitScoutingView(Context context) { super(context); } + public pitScoutingView(Context context, AttributeSet attributeSet){ + super(context, attributeSet); + } + + + private static final int unsaved_color = 0x60ff0000; + private static final int saved_color = 0x6000ff00; + + boolean edited = false; + + FragmentScoutingBinding binding; + String alliance_position; + String evcode; + frcEvent event; + String filename; + String username; + + ScoutingVersion.inputType[][] values; + ScoutingVersion.inputType[] latest_values; + ScoutingVersion.transferType[][] transferValues; + + AutoSaveManager asm = new AutoSaveManager(this::save); + + ArrayList dataTypes; + + public void save(){ + System.out.println("Saved!"); + edited = false; + set_indicator_color(saved_color); + + ScoutingVersion.dataType[] types = new ScoutingVersion.dataType[latest_values.length]; + + for(int i = 0; i < latest_values.length; i++){ + types[i] = latest_values[i].getViewValue(); + } + + System.out.println(ScoutingDataWriter.save(values.length-1, username, filename, types)); + +// fileEditor.createFile(filename); +// save_fields(); + } + + public void set_indicator_color(int color){ + binding.pitFileIndicator.setBackgroundColor(color); + } + + public void update_asm(){ +// v.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN); + edited = true; + set_indicator_color(unsaved_color); + asm.update(); + } + + + public void init(FragmentScoutingBinding tmp_binding){ + binding = tmp_binding; + + evcode = latestSettings.settings.get_evcode(); + event = frcEvent.decode(fileEditor.readFile(evcode + ".eventdata")); + username = latestSettings.settings.get_username(); + + binding.eventcode.setText(evcode); + + binding.pitBackButton.setOnClickListener(view -> { + if(edited) save(); + binding.pitTeamName.setVisibility(View.GONE); + binding.pitTeamDescription.setVisibility(View.GONE); + clear_fields(); + load_teams(); + }); + + values = fields.load(fields.pitsFieldsFilename); + + if(values == null || values.length == 0){ + TextView tv = new TextView(getContext()); + tv.setText("Failed to load fields.\nTry to either download or create pit scouting fields."); + tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); + binding.pitScoutArea.addView(tv); + return; + } + + latest_values = values[values.length-1]; + transferValues = fields.sv.get_transfer_values(values); + +// create_fields(); +// update_scouting_data(); + + load_teams(); + } + + public void clear_fields(){ + int childCount = binding.pitScoutArea.getChildCount(); + View[] views = new View[childCount]; + + for(int i = 0; i < childCount; i++){ + views[i] = binding.pitScoutArea.getChildAt(i); + } + + for(int i = 0; i < childCount; i++){ + if(!views[i].isShown()) continue; + binding.pitScoutArea.removeView(views[i]); + } + } + + public void load_teams(){ + binding.pitFileIndicator.setVisibility(View.GONE); + binding.pitTeamName.setVisibility(View.GONE); + binding.pitTeamDescription.setVisibility(View.GONE); + + + int[] teamNums = new int[event.teams.size()]; + + for(int i = 0 ; i < event.teams.size(); i++){ + teamNums[i] = event.teams.get(i).teamNumber; + } + + Arrays.sort(teamNums); + + TableLayout table = new TableLayout(getContext()); + table.setStretchAllColumns(true); + binding.pitScoutArea.addView(table); + + + 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; + } + } + + TableRow tr = new TableRow(getContext()); + TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, + FrameLayout.LayoutParams.WRAP_CONTENT + ); + rowParams.setMargins(20,20,20,20); + tr.setLayoutParams(rowParams); + tr.setPadding(20,20,20,20); + table.addView(tr); + + if(fileEditor.fileExist(evcode + "-" + team.teamNumber + ".pitscoutdata")){ + tr.setBackgroundColor(0x3000FF00); + }else{ + tr.setBackgroundColor(0x30FF0000); + } + + TextView tv = new TextView(getContext()); + tv.setText(String.valueOf(team.teamNumber)); + tv.setTextSize(20); + tr.addView(tv); + + tv = new TextView(getContext()); + tv.setText(team.teamName); + tv.setTextSize(16); + tr.addView(tv); + + frcTeam finalTeam = team; + tr.setOnClickListener(v -> { +// binding.pitScoutArea.removeView(table); + loadTeam(finalTeam); + }); + } + } + + public void loadTeam(frcTeam team){ + clear_fields(); + + binding.pitFileIndicator.setVisibility(View.VISIBLE); + binding.pitTeamName.setVisibility(View.VISIBLE); + binding.pitTeamDescription.setVisibility(View.VISIBLE); + + binding.pitTeamName.setText(team.teamName); + binding.pitTeamDescription.setText(team.getDescription()); + binding.pitBarTeamNum.setText(String.valueOf(team.teamNumber)); + + binding.teamName.setText(team.teamName); + binding.teamDescription.setText(team.getDescription()); + + filename = evcode + "-" + team.teamNumber + ".pitscoutdata"; + + boolean new_file = !fileEditor.fileExist(filename); + + if(asm.isRunning){ + asm.stop(); + } + + create_fields(); + + if(new_file){ + default_fields(); + set_indicator_color(unsaved_color); + }else{ + get_fields(); + set_indicator_color(saved_color); + } + + asm.start(); + + } + + private void create_fields() { + if(asm.isRunning){ + asm.stop(); + } + + for(int i = 0 ; i < latest_values.length; i++) { + TextView tv = new TextView(getContext()); + tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); + tv.setText(latest_values[i].name); + tv.setTextSize(24); + binding.pitScoutArea.addView(tv); + + View v = latest_values[i].createView(getContext(), new Function() { + @Override + public Integer apply(ScoutingVersion.dataType dataType) { +// edited = true; + if(asm.isRunning) + update_asm(); + return 0; + } + }); + + binding.pitScoutArea.addView(v); + } + } + + public void default_fields(){ + for(int i = 0; i < latest_values.length; i++){ + ScoutingVersion.inputType input = latest_values[i]; + input.setViewValue(input.default_value); + } + } + + public void get_fields(){ + + ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, values, transferValues); + ScoutingVersion.dataType[] types = psdr.data.array; + + for(int i = 0; i < latest_values.length; i++){ +// types[i] = latest_values[i].getViewValue(); + latest_values[i].setViewValue(types[i]); + } + } } diff --git a/app/src/main/java/com/astatin3/scoutingapp2025/ui/scouting/scoutingFragment.java b/app/src/main/java/com/astatin3/scoutingapp2025/ui/scouting/scoutingFragment.java index a62b19e..c3d25ff 100644 --- a/app/src/main/java/com/astatin3/scoutingapp2025/ui/scouting/scoutingFragment.java +++ b/app/src/main/java/com/astatin3/scoutingapp2025/ui/scouting/scoutingFragment.java @@ -25,6 +25,7 @@ public class scoutingFragment extends Fragment { binding.buttons.setVisibility(View.VISIBLE); binding.matchScoutingView.setVisibility(View.GONE); + binding.pitScoutingView.setVisibility(View.GONE); if(latestSettings.settings.get_evcode().equals("unset")){ binding.noEventError.setVisibility(View.VISIBLE); @@ -35,67 +36,14 @@ public class scoutingFragment extends Fragment { binding.buttons.setVisibility(View.GONE); binding.matchScoutingView.setVisibility(View.VISIBLE); binding.matchScoutingView.init(binding); - -// byte[] bytes = fields.save(); -// System.out.println(bytes.length); -// System.out.println(fields.load(bytes)[0].length); - -// fields.test(); - -// ByteBuilder bb = new ByteBuilder(); -// try { -// bb.addInt(1243); -// bb.addStringArray(new String[]{"Test", "Test2", "Tljewhgr"}); -// bb.addIntArray(new int[]{4, 3, 8, 8}); -// byte[] bytes = bb.build(); -// -// BuiltByteParser bbp = new BuiltByteParser(bytes); -// BuiltByteParser.parsedObject[] objects = bbp.parse().toArray(new BuiltByteParser.parsedObject[0]); -// -// for(BuiltByteParser.parsedObject object : objects){ -// switch (object.getType()){ -// case 0: -// System.out.println((int) object.get()); -// break; -// case 1: -// System.out.println((String) object.get()); -// break; -// case 2: -// System.out.println(Arrays.toString((int[]) object.get())); -// break; -// case 3: -// System.out.println(Arrays.toString((String[]) object.get())); -// break; -// } -// } -// -// -// } catch (ByteBuilder.buildingException e) { -// throw new RuntimeException(e); -// } catch (BuiltByteParser.byteParsingExeption e) { -// throw new RuntimeException(e); -// } - }); -// -// binding.pitScoutingButton.setOnClickListener(v -> { -// msv1 msdata = new msv1(); -//// msdata.types = MatchScoutingVersion.dataType[]5{}; -// System.out.println(msdata.load("test.matchscoutdata")); -// for(MatchScoutingVersion.dataType data : msdata.getTypes().fields){ -//// System.out.println(data.getType()); -// switch (data.getType()){ -// case 0: -// System.out.println((int)data.get()); -// break; -// case 1: -// System.out.println((String) data.get()); -// break; -// } -// } -// }); -// msdata.set + binding.pitScoutingButton.setOnClickListener(v -> { + binding.pitScoutingView.setVisibility(View.VISIBLE); + binding.buttons.setVisibility(View.GONE); + // binding.pitScoutArea.setVisibility(View.VISIBLE); + binding.pitScoutingView.init(binding); + }); return root; } diff --git a/app/src/main/res/layout/fragment_scouting.xml b/app/src/main/res/layout/fragment_scouting.xml index 8ce8933..76e070e 100644 --- a/app/src/main/res/layout/fragment_scouting.xml +++ b/app/src/main/res/layout/fragment_scouting.xml @@ -64,12 +64,14 @@ android:layout_width="0dp" android:layout_height="0dp" android:layout_marginBottom="48dp" + android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="1.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" - app:layout_constraintVertical_bias="1.0"> + app:layout_constraintVertical_bias="1.0" + tools:visibility="gone"> + app:layout_constraintTop_toTopOf="parent">