Add scout notice, start work on scouting report system

This commit is contained in:
Michael Mikovsky
2025-04-11 22:07:41 -06:00
parent e559b4dac9
commit e280fc8523
18 changed files with 346 additions and 19 deletions
@@ -73,7 +73,7 @@ public class MainActivity extends AppCompatActivity {
appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_scouting,
R.id.navigation_data,
R.id.navigation_data_parent,
R.id.navigation_transfer,
R.id.navigation_settings)
.build();
@@ -120,6 +120,18 @@ public class frcEvent {
return maxMatch;
}
public frcMatch getNextTeamMatch(int teamNum, int curMatch){
frcMatch[] teamMatches = getTeamMatches(teamNum);
for(int i = 0; i < teamMatches.length; i++) {
if (teamMatches[i].matchIndex > curMatch)
return teamMatches[i];
}
return null;
}
// public
// Returns the soonest match that there will be all the possible upcoming data on other teams
@@ -144,4 +156,13 @@ public class frcEvent {
}
}
}
public frcTeam getTeamByNum(int teamNum){
for(int i = 0; i < teams.size(); i++){
frcTeam team = teams.get(i);
if(team.teamNumber == teamNum)
return team;
}
return null;
}
}
@@ -200,8 +200,13 @@ public class CandlestickView extends View {
teamDataArray[i] = (int) teamData.get(i).get();
}
float lowerQuartile = DataProcessing.calculatePercentile(teamDataArray, 25);
float upperQuartile = DataProcessing.calculatePercentile(teamDataArray, 75);
float lowerQuartile = 0;
float upperQuartile = 0;
if(teamDataArray.length != 0) {
lowerQuartile = DataProcessing.calculatePercentile(teamDataArray, 25);
upperQuartile = DataProcessing.calculatePercentile(teamDataArray, 75);
}
System.out.println(locmin + ", " + lowerQuartile + ", " + avg + ", " + upperQuartile + ", " + locmax);
setData(locmin, lowerQuartile, avg, upperQuartile, locmax, absmin, absmax);
@@ -20,6 +20,7 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import com.ridgebotics.ridgescout.R;
import com.ridgebotics.ridgescout.types.frcTeam;
@@ -84,9 +85,6 @@ public class DataFragment extends Fragment {
}
public void load_teams(){
DataManager.reload_event();
if(event == null) return;
int[] teamNums = new int[event.teams.size()];
@@ -113,7 +111,8 @@ public class DataFragment extends Fragment {
frcTeam finalTeam = team;
teamRow.setOnClickListener(v -> {
TeamsFragment.setTeam(finalTeam);
findNavController(this).navigate(R.id.action_navigation_data_to_navigation_data_teams);
((DataParentFragment) getParentFragment()).moveToFragment(new TeamsFragment());
// findNavController(this).navigate(R.id.action_navigation_data_parent_to_navigation_data_teams);
});
}
}
@@ -131,7 +130,8 @@ public class DataFragment extends Fragment {
final int fi = i;
tr.setOnClickListener(v -> {
FieldDataFragment.setFieldIndex(fi);
findNavController(this).navigate(R.id.action_navigation_data_to_navigation_data_field_data);
((DataParentFragment) getParentFragment()).moveToFragment(new FieldDataFragment());
// findNavController(get).navigate(R.id.action_navigation_data_parent_to_navigation_data_field_data);
});
}
}
@@ -0,0 +1,129 @@
package com.ridgebotics.ridgescout.ui.data;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static androidx.navigation.fragment.FragmentKt.findNavController;
import static com.ridgebotics.ridgescout.utility.Colors.datafragment_option_1;
import static com.ridgebotics.ridgescout.utility.Colors.datafragment_option_2;
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
import static com.ridgebotics.ridgescout.utility.DataManager.event;
import static com.ridgebotics.ridgescout.utility.DataManager.match_latest_values;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import com.ridgebotics.ridgescout.R;
import com.ridgebotics.ridgescout.databinding.FragmentDataParentBinding;
import com.ridgebotics.ridgescout.types.frcMatch;
import com.ridgebotics.ridgescout.types.frcTeam;
import com.ridgebotics.ridgescout.ui.FieldBorderedRow;
import com.ridgebotics.ridgescout.ui.TeamListOption;
import com.ridgebotics.ridgescout.utility.DataManager;
import com.ridgebotics.ridgescout.utility.SettingsManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class DataParentFragment extends Fragment {
private FragmentDataParentBinding binding;
private DataFragment dataFragment;
private boolean editBoxEnabled = true;
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentDataParentBinding.inflate(inflater, container, false);
DataManager.reload_event();
if (savedInstanceState == null && dataFragment == null){
dataFragment = new DataFragment();
//add child fragment
getChildFragmentManager()
.beginTransaction()
.add(R.id.data_subfragment, dataFragment, "Data Subfragment")
.commit();
}
if(evcode.equals("unset") || event == null){
binding.reportToggleButton.setVisibility(GONE);
return binding.getRoot();
}
binding.reportToggleButton.setOnClickListener(view -> {
editBoxEnabled =! editBoxEnabled;
binding.ScoutingEditBox.setVisibility(editBoxEnabled ? GONE : VISIBLE);
binding.reportToggleButton.setText(editBoxEnabled ? "▲ report" : "▼ report");
});
generateScoutingTemplate(SettingsManager.getMatchNum());
return binding.getRoot();
}
public void moveToFragment(Fragment newFragment){
// consider using Java coding conventions (upper first char class names!!!)
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.data_subfragment, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
// Generate format for scouting data
public void generateScoutingTemplate(int currentMatch){
int teamNum = SettingsManager.getTeamNum();
boolean isBlueAlliance = false;
frcMatch nextMatch = event.getNextTeamMatch(teamNum, currentMatch);
List<frcTeam> ourAlliance = new ArrayList<>();
List<frcTeam> opposingAlliance = new ArrayList<>();
for(int a = 0; a < nextMatch.blueAlliance.length; a++)
if(nextMatch.blueAlliance[a] != teamNum){
(!isBlueAlliance ? ourAlliance : opposingAlliance).add(event.getTeamByNum(nextMatch.blueAlliance[a]));
}
for(int a = 0; a < nextMatch.redAlliance.length; a++)
if(nextMatch.redAlliance[a] != teamNum){
(isBlueAlliance ? ourAlliance : opposingAlliance).add(event.getTeamByNum(nextMatch.redAlliance[a]));
}
String output = "Match: " + (nextMatch.matchIndex+1) + "\n";
output += "## Our Alliance ##";
output += getTeamNameAndNum(ourAlliance.get(0));
output += getTeamNameAndNum(ourAlliance.get(1));
output += "\n## Opposing Alliance ##";
output += getTeamNameAndNum(opposingAlliance.get(0));
output += getTeamNameAndNum(opposingAlliance.get(1));
output += getTeamNameAndNum(opposingAlliance.get(2));
binding.scoutingReportEdittext.setText(output);
}
private static String getTeamNameAndNum(frcTeam team){
return "\n" + team.teamNumber + " " + team.teamName + ": \n";
}
}
@@ -109,6 +109,11 @@ public class MatchScoutingFragment extends Fragment {
create_fields();
update_scouting_data();
if(DataManager.scoutNotice.isEmpty())
binding.scoutingNoticeBox.setVisibility(View.GONE);
else
binding.scoutingNoticeText.setText(DataManager.scoutNotice);
return binding.getRoot();
}
@@ -56,6 +56,10 @@ public class PitScoutingFragment extends Fragment {
return binding.getRoot();
}
if(DataManager.scoutNotice.isEmpty())
binding.scoutingNoticeBox.setVisibility(View.GONE);
else
binding.scoutingNoticeText.setText(DataManager.scoutNotice);
loadTeam();
@@ -124,16 +124,11 @@ public class ScoutingFragment extends Fragment {
binding.textName.setText("Welcome, " + SettingsManager.getUsername() + "!");
int nextMatch = -1;
int teamNum = SettingsManager.getTeamNum();
for(int i = SettingsManager.getMatchNum(); i < event.matches.size(); i++){ // Loop through matches and find next match
boolean foundMatch = false;
for(int a = 0; a < 3; a++) if(event.matches.get(i).blueAlliance[a] == teamNum){nextMatch = i+1; foundMatch = true;}
for(int a = 0; a < 3; a++) if(event.matches.get(i).redAlliance[a] == teamNum){nextMatch = i+1; foundMatch = true;}
if(foundMatch) break;
}
int matchNum = SettingsManager.getMatchNum();
int nextMatch = event.getNextTeamMatch(SettingsManager.getTeamNum(), matchNum).matchIndex;
binding.textNextMatch.setText("Our next match: Match " + nextMatch);
binding.textMatchAlliance.setText("Match: " + (SettingsManager.getMatchNum()+1) + ", " + SettingsManager.getAllyPos());
binding.textMatchAlliance.setText("Match: " + (matchNum+1) + ", " + SettingsManager.getAllyPos());
binding.textRescoutIndicator.setText("Things to rescout: " + DataManager.rescout_list.size());
return binding.getRoot();
@@ -16,7 +16,9 @@ import static com.ridgebotics.ridgescout.utility.SettingsManager.defaults;
import static com.ridgebotics.ridgescout.utility.SettingsManager.getEditor;
import static com.ridgebotics.ridgescout.utility.SettingsManager.prefs;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputType;
@@ -25,7 +27,10 @@ import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -130,6 +135,14 @@ public class SettingsFragment extends Fragment {
binding.SettingsTable.removeAllViews();
manager.getView(binding.SettingsTable);
if(!DataManager.getevcode().equals("unset")){
Button editNoticeButton = new Button(getContext());
editNoticeButton.setText("Edit Scout Notice");
binding.SettingsTable.addView(editNoticeButton);
editNoticeButton.setOnClickListener(v->editNotice());
}
}
@@ -141,6 +154,27 @@ public class SettingsFragment extends Fragment {
}
private void editNotice(){
ScrollView sv = new ScrollView(getContext());
EditText editText = new EditText(getContext());
editText.setText(DataManager.scoutNotice);
sv.addView(editText);
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
alert.setTitle("Edit Notice");
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();
}
@@ -25,8 +25,9 @@ public class DataManager {
SettingsManager.setEVCode("unset");
evcode = "unset";
}else{
AlertManager.toast("Reloaded event!");
reload_rescout_list();
reload_scout_notice();
AlertManager.toast("Reloaded event!");
}
}
@@ -90,4 +91,36 @@ public class DataManager {
AlertManager.error("Error saving scout fields", e);
}
}
public static String scoutNotice = "";
public static void reload_scout_notice(){
if(!FileEditor.fileExist(evcode + ".scoutnotice")) {scoutNotice = ""; return;}
byte[] file = FileEditor.readFile(evcode + ".scoutnotice");
if(file == null) {scoutNotice = ""; return;}
try {
BuiltByteParser bbp = new BuiltByteParser(file);
scoutNotice = (String) (bbp.parse().get(0).get());
} catch (Exception e){
AlertManager.error("Error loading scout notice", e);
rescout_list = new ArrayList<>();
}
}
public static void save_scout_notice() {
try {
if(scoutNotice.isEmpty()){
FileEditor.deleteFile(evcode + ".scoutnotice");
return;
}
ByteBuilder bb = new ByteBuilder();
bb.addString(scoutNotice);
FileEditor.writeFile(evcode + ".scoutnotice", bb.build());
} catch (Exception e){
AlertManager.error("Error saving scout notice", e);
}
}
}