22 Commits

Author SHA1 Message Date
Astatin3 15be86453e Update version number 2024-10-12 20:43:37 -06:00
Astatin3 795fa4e85a KCMT Hotfix 2024-10-12 20:37:18 -06:00
Astatin3 fb0718c4ec Add FTP server 2024-10-06 16:06:43 -06:00
Astatin3 03a1507ce2 Make settings better, work on ftp transfer 2024-10-05 18:47:36 -06:00
Michael Mikovsky 2b753fcdb4 Fix README button 2024-10-01 07:34:27 -06:00
Astatin3 ca703aab60 Updata F-Droid metadata 2024-10-01 07:32:00 -06:00
Astatin3 4854587ea9 Add changes to README and TODO 2024-09-30 15:57:52 -06:00
Astatin3 d957a1db5e Temporarily disable AI stuff for ChiefDelphi Release 2024-09-28 12:50:38 -06:00
Astatin3 60d56473f5 Add more types of fields, F-droid fixes 2024-09-28 12:43:19 -06:00
Michael Mikovsky d607f95a8a Add images in README.md 2024-09-25 14:59:43 -06:00
Astatin3 62a4452581 Edit README, add Images 2024-09-25 14:49:47 -06:00
astatin3 b62d04dac5 Work on report menu 2024-09-22 11:06:40 -06:00
Astatin3 07c6e9a2aa Make use sharedprefrences 2024-09-20 15:59:35 -06:00
Astatin3 9f5ebd4215 AI intigration 2024-09-18 19:44:30 -06:00
Astatin3 0a9f846e77 Forgor to update version number 2024-09-18 09:00:02 -06:00
Astatin3 f37f12178b Actually fix app not showing up 2024-09-18 08:56:55 -06:00
Astatin3 e537aab819 Attempt to fix app not showing up issue 2024-09-18 08:49:26 -06:00
Astatin3 9607241c53 Work on scouting reporting 2024-09-18 08:22:38 -06:00
Astatin3 4764aea990 Add icon.png, change readme 2024-09-16 12:40:07 -06:00
Astatin3 e0c76fb4ef Update output-metadata.json 2024-09-15 23:15:24 -06:00
Astatin3 9c254bb249 Fdroid - update versionName 2024-09-15 23:15:13 -06:00
Astatin3 3f88c9a05e Attempt to get F-Droid working 2024-09-15 22:47:45 -06:00
104 changed files with 3030 additions and 1359 deletions
+1
View File
@@ -1,6 +1,7 @@
# Gradle files
.gradle/
build/
release/
# Local configuration file (sdk path, etc)
local.properties
Binary file not shown.
+34 -37
View File
@@ -1,40 +1,37 @@
# ScoutingApp2025
Ridgebotics 2025 scouting app in Android
![Ridgescout](https://github.com/Team4388/ScoutingApp2025/blob/main/metadata/en-US/images/featureGraphic.png?raw=true)
## TODO:
#### Scouting:
- Make the "Report" menu, A tool that lets users select data to display from the the teams and compare menus.
- Make practice mode
#### Data Analysis:
- Statbotics intigration???
- AI overview of scouting data for a team???
- Make the "Compare" menu, cross comparing team's stats.
#### Functionality:
- Add more types of data fields.
- Test the scouting app
- Deploy to F-Droid
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
alt="Get it on F-Droid"
height="80">](https://f-droid.org/packages/com.ridgebotics.ridgescout/)
**Note**: The F-Droid version of this app is not currently up to date with the GitHub release
## In Progress:
#### Scouting:
#### Data Analysis:
#### Functionality:
- Make server software to allow for easy sync over wifi - FTP
[**Read the wiki**](https://github.com/Team4388/ScoutingApp2025/wiki)
[**Test Data**](https://github.com/Team4388/ScoutingApp2025/blob/main/2024week0-1728149849985.scoutbundle)
#### Here is an overview of the main features currently included in the app:
- This project is written for Android! No need for some kind of janky laptop charging setup.
- Similar to ScoutingPASS, there are many diffrent types of fields that can be used to collect data.
- The app is designed to handle updates to the fields on the fly, without loosing any data!
- Unlike other scouting solutions, scouters can disable any field they did not measure, and disabled fields will not be included in any calculations.
- Dynamic displays based off of the diffrent fields.
- Data transfer including 2D codes, Bluetooth, and File Bundle.
- Exporting using CSV.
- Deployment on F-Droid
- Data cloud sync using an FTP server
#### Things that are yet to be implemented:
- A page that lets users cross-compare scouting data between teams. (Compare)
- A page that lets scouters more easily make reports to the drive team before a match starts (Report)
#### Things that may or may not be implemented:
- Practice mode
- Statbotics intgration
- Scout error estimation using OPR-like calculation
- - Would most likely require Statbotics
### Screenshots
|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)|
## Done:
#### Scouting:
- Add an "unselect" option to all of the scouting fields
- When a field is created, make updated scouting data return null values, not the default value
- Fix scouting offset bug
#### Data Analysis:
- Add "history" view type to the teams view menu.
- Sentiment analysis of text input type
- Add CSV exporting of match scouting data.
#### Functionality:
- Improve the code scanning progress indicator. It has a rounding error, I think.
- Fix navigation crashes.
- Make everything use Fragments instead of views that toggle visibility
- Make the file browser UI
- Bluetooth data sync
- Formalize error messages & stacktraces
- Make pit and match data field builder UIs. I don't want to have to keep editing a variable
- Make the system for blank and unselected fields better.
+38
View File
@@ -0,0 +1,38 @@
### TODO:
##### Scouting:
- Make practice mode??
##### Data Analysis:
- Statbotics intigration???
##### Functionality:
### In Progress:
##### Scouting:
##### Data Analysis:
- AI overview of scouting data for a team???
- Make the "Report" menu, A tool that lets users select data to display from the the teams and compare menus.
- Make the "Compare" menu, cross comparing team's stats.
##### Functionality:
### Done:
##### Scouting:
- Add an "unselect" option to all of the scouting fields
- When a field is created, make updated scouting data return null values, not the default value
- Fix scouting offset bug
##### Data Analysis:
- Add "history" view type to the teams view menu.
- Sentiment analysis of text input type
- Add CSV exporting of match scouting data.
##### Functionality:
- Improve the code scanning progress indicator. It has a rounding error, I think.
- Fix navigation crashes.
- Make everything use Fragments instead of views that toggle visibility
- Make the file browser UI
- Bluetooth data sync
- Formalize error messages & stacktraces
- Make pit and match data field builder UIs. I don't want to have to keep editing a variable
- Make the system for blank and unselected fields better.
- Write docs
- Deploy to F-Droid
- Add more types of data fields.
- Make server software to allow for easy sync over wifi - FTP
- Test the scouting app
+16 -6
View File
@@ -13,15 +13,23 @@ plugins {
//}
android {
namespace = "com.astatin3.scoutingapp2025"
namespace = "com.ridgebotics.ridgescout"
compileSdk = 34
dependenciesInfo {
// Disables dependency metadata when building APKs.
includeInApk = false
// Disables dependency metadata when building Android App Bundles.
includeInBundle = false
}
defaultConfig {
applicationId = "com.astatin3.scoutingapp2025"
applicationId = "com.ridgebotics.ridgescout"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
versionCode = 6
versionName = "0.6"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
@@ -53,6 +61,7 @@ dependencies {
implementation(libs.lifecycle.viewmodel.ktx)
implementation(libs.navigation.fragment)
implementation(libs.navigation.ui)
implementation(libs.preference)
// implementation(libs.support.annotations)
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
@@ -71,13 +80,14 @@ dependencies {
implementation("com.github.PhilJay:MPAndroidChart:v3.1.0")
// implementation("com.google.firebase:firebase-ml-modeldownloader:24.1.2")
// implementation(platform("com.google.firebase:firebase-bom:33.1.2"))
implementation("org.tensorflow:tensorflow-lite-task-text:0.3.0")
implementation("com.squareup.okhttp3:okhttp:4.9.0")
implementation("commons-net:commons-net:3.10.0")
// implementation("com.github.DeveloperPaul123:SimpleBluetoothLibrary:1.5.1")
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025;
package com.ridgebotics.ridgescout;
import android.content.Context;
@@ -21,6 +21,6 @@ public class ExampleInstrumentedTest {
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.astatin3.scoutingapp2025", appContext.getPackageName());
assertEquals("com.ridgebotics.ridgescout", appContext.getPackageName());
}
}
+10 -4
View File
@@ -7,7 +7,7 @@
android:required="true" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />-->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
@@ -15,8 +15,8 @@
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />-->
<!-- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />-->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA"/>
@@ -29,8 +29,12 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.ScoutingApp2025"
android:theme="@style/Theme.RidgeScout"
android:hardwareAccelerated="true"
android:networkSecurityConfig="@xml/network_security_config"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".MainActivity"
@@ -42,6 +46,8 @@
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.GET_CONTENT" />
<category android:name="android.intent.category.OPEN_FILE" />
</intent-filter>
<intent-filter>
<data android:mimeType="*/*" />
</intent-filter>
</activity>
@@ -1,9 +0,0 @@
package com.astatin3.scoutingapp2025.SettingsVersionStack;
public class latestSettings {
public static sv1 settings = new sv1();
public static void update(){
settings.init_settings();
settings.update();
}
}
@@ -1,110 +0,0 @@
package com.astatin3.scoutingapp2025.SettingsVersionStack;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import java.nio.charset.StandardCharsets;
public abstract class settingsVersion {
private static final String settingsFilename = "settings.txt";
public abstract void defaultSettings();
public abstract int getVersion();
public abstract void update();
public static String get_settings_file_content(){
byte[] data = fileEditor.readFile(settingsFilename);
if(data == null){return "";}
return new String(data, StandardCharsets.UTF_8);
}
public int get_file_version(){
String[] fileContent = get_settings_file_content().split("\n");
try{
return Integer.parseInt(fileContent[0]);
}catch(Exception e){
return -1;
}
}
public void set_file_version(int version){
String[] fileContent = get_settings_file_content().split("\n");
String output = String.valueOf(version);
for(int i = 0; i < fileContent.length; i++){
output += ("\n" + fileContent[i]);
}
fileEditor.writeFile(settingsFilename, output.getBytes(StandardCharsets.UTF_8));
}
public String readTag(String search_tag){
String[] fileContent = get_settings_file_content().split("\n");
try{
for(String line : fileContent){
if(line.isEmpty()){
continue;
}
String[] split = line.split("=");
if(split[0].equals(search_tag)){
if(split[1].equals("<empty>")){
return "";
}else if(split[1].equals("<null>")){
return null;
}else {
return split[1];
}
}
}
}catch (Exception e){
AlertManager.error(e);
}
return null;
}
public void init_settings(){
if(!fileEditor.fileExist(settingsFilename)){
fileEditor.createFile(settingsFilename);
set_file_version(getVersion());
defaultSettings();
}
}
public String writeTag(String tag_name, String data){
final boolean already_exists = readTag(tag_name) != null;
if(data == null){
data = "<null>";
}else if(data.equals("")){
data = "<empty>";
}
if(!already_exists){
String fileContent = get_settings_file_content();
String output = fileContent + "\n" + tag_name + "=" + data;
fileEditor.writeFile(settingsFilename, output.getBytes(StandardCharsets.UTF_8));
return output;
}else{
String[] fileContent = get_settings_file_content().split("\n");
try{
for(int i = 0; i < fileContent.length; i++){
if(fileContent[i].isEmpty()){
continue;
}
String[] split = fileContent[i].split("=");
if(split[0].equals(tag_name)){
fileContent[i] = tag_name + "=" + data;
String output = String.join("\n", fileContent);
fileEditor.writeFile(settingsFilename, output.getBytes(StandardCharsets.UTF_8));
return output;
}
}
}catch (Exception e){
e.printStackTrace();
}
}
return "No idea how this happened";
}
}
@@ -1,51 +0,0 @@
package com.astatin3.scoutingapp2025.SettingsVersionStack;
public class sv0 extends settingsVersion {
@Override
public int getVersion() {
return 0;
}
@Override
public void update(){
// int file_version = get_file_version();
// if(file_version == getVersion()) {
// return;
// }else if(file_version < getVersion()){
// super.update();
// }
// set_file_version(getVersion());
}
@Override
public void defaultSettings() {
writeTag("username", "Username");
writeTag("selected_event_code", "unset");
// writeTag("practice_mode", "false");
writeTag("wifi_mode", "false");
}
public void set_username(String name){
writeTag("username", name);
}
public String get_username(){
return readTag("username");
}
public void set_evcode(String evcode){
writeTag("selected_event_code", evcode);
}
public String get_evcode(){
return readTag("selected_event_code");
}
// public void set_practice_mode(boolean value) {
// writeTag("practice_mode", value ? "true" : "false");
// }
// public boolean get_practice_mode(){
// return readTag("practice_mode").equals("true");
// }
public void set_wifi_mode(boolean value){
writeTag("wifi_mode", value ? "true" : "false");
}
public boolean get_wifi_mode(){
return readTag("wifi_mode").equals("true");
}
}
@@ -1,84 +0,0 @@
package com.astatin3.scoutingapp2025.SettingsVersionStack;
import java.util.UUID;
public class sv1 extends sv0 {
@Override
public int getVersion() {
return 0;
}
@Override
public void update(){
int file_version = get_file_version();
if(file_version == getVersion()) {
return;
}else if(file_version < getVersion()){
super.update();
}
set_file_version(getVersion());
}
@Override
public void defaultSettings() {
writeTag("username", "Username");
writeTag("selected_event_code", "unset");
// writeTag("practice_mode", "false");
writeTag("wifi_mode", "false");
writeTag("team_num", "4388");
writeTag("match_num", "0");
writeTag("alliance_pos", "red-1");
writeTag("data_view_mode", "0");
writeTag("bt_uuid", UUID.randomUUID().toString());
}
public int get_match_num(){
return Integer.parseInt(readTag("match_num"));
}
public void set_match_num(int num){
writeTag("match_num", String.valueOf(num));
}
@Override
public void set_evcode(String evcode){
set_match_num(0);
writeTag("selected_event_code", evcode);
}
public String get_alliance_pos(){
return readTag("alliance_pos");
}
public void set_alliance_pos(String pos){
writeTag("alliance_pos", pos);
}
public int get_team_num(){return Integer.parseInt(readTag("team_num"));}
public void set_team_num(String str){
if(str.isEmpty()) {
set_team_num(0);
return;
}
set_team_num(Integer.parseInt(str));
}
public void set_team_num(int num){writeTag("team_num", String.valueOf(num));}
public int get_data_view_mode(){
return Integer.parseInt(readTag("data_view_mode"));
}
public void set_data_view_mode(int mode){
writeTag("data_view_mode", String.valueOf(mode));
}
public void setUUID(UUID uuid){
writeTag("bt_uuid", uuid.toString());
}
public UUID getUUID(){
return UUID.fromString(readTag("bt_uuid"));
}
}
@@ -1,79 +0,0 @@
package com.astatin3.scoutingapp2025.types;
import androidx.annotation.NonNull;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.BuiltByteParser;
import com.astatin3.scoutingapp2025.utility.ByteBuilder;
import java.util.ArrayList;
public class frcEvent {
public static final int typecode = 254;
public String eventCode;
public String name;
public ArrayList<frcMatch> matches;
public ArrayList<frcTeam> teams;
public byte[] encode() {
try {
ByteBuilder bb = new ByteBuilder()
.addString(eventCode)
.addString(name);
for (frcTeam teams : teams) {
bb.addRaw(frcTeam.typecode, teams.encode());
}
for (frcMatch match : matches) {
bb.addRaw(frcMatch.typecode, match.encode());
}
return bb.build();
} catch (ByteBuilder.buildingException e) {
AlertManager.error(e);
return null;
}
}
public static frcEvent decode(byte[] bytes) {
try {
ArrayList<BuiltByteParser.parsedObject> objects =
new BuiltByteParser(bytes).parse();
frcEvent frc = new frcEvent();
frc.eventCode = (String) objects.get(0).get();
frc.name = (String) objects.get(1).get();
frc.matches = new ArrayList<>();
frc.teams = new ArrayList<>();
for (BuiltByteParser.parsedObject object : objects) {
if (object.getType() == frcTeam.typecode) {
frc.teams.add(frcTeam.decode((byte[]) object.get()));
} else if (object.getType() == frcMatch.typecode) {
frc.matches.add(frcMatch.decode((byte[]) object.get()));
}
}
return frc;
} catch (BuiltByteParser.byteParsingExeption e) {
AlertManager.error(e);
return null;
}
}
@NonNull
public String toString() {
return (
"frcEvent Name: " +
name +
", Code: " +
eventCode +
" numTeams: " +
teams.size() +
" numMatches: " +
matches.size()
);
}
}
@@ -1,24 +0,0 @@
package com.astatin3.scoutingapp2025.ui.data;
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 com.astatin3.scoutingapp2025.databinding.FragmentDataReportBinding;
public class ReportFragment extends Fragment {
FragmentDataReportBinding binding;
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentDataReportBinding.inflate(inflater, container, false);
return binding.getRoot();
}
}
@@ -1,226 +0,0 @@
package com.astatin3.scoutingapp2025.ui.settings;
import android.app.AlertDialog;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Spinner;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.databinding.FragmentSettingsBinding;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.astatin3.scoutingapp2025.SettingsVersionStack.latestSettings;
import com.skydoves.powerspinner.IconSpinnerAdapter;
import com.skydoves.powerspinner.IconSpinnerItem;
import com.skydoves.powerspinner.OnSpinnerItemSelectedListener;
import com.skydoves.powerspinner.PowerSpinnerView;
import java.util.ArrayList;
import java.util.List;
public class settingsFragment extends Fragment {
private FragmentSettingsBinding binding;
private android.widget.ScrollView ScrollArea;
private android.widget.TableLayout Table;
private void setDropdownItems(Spinner dropdown, String[] items){
ArrayAdapter<String> adapter = new ArrayAdapter<>(requireActivity(), android.R.layout.simple_spinner_item, items);
dropdown.setAdapter(adapter);
}
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
binding = FragmentSettingsBinding.inflate(inflater, container, false);
View root = binding.getRoot();
EditText username = binding.username;
username.setText(latestSettings.settings.get_username());
username.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
latestSettings.settings.set_username(username.getText().toString());
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count) {}
});
PowerSpinnerView spinnerView = binding.eventDropdown;
List<IconSpinnerItem> iconSpinnerItems = new ArrayList<>();
String target_event_name = latestSettings.settings.get_evcode();
int target_index = -1;
ArrayList<String> evlist = fileEditor.getEventList();
for(int i = 0; i < evlist.size(); i++){
if(evlist.get(i).equals(target_event_name)){
target_index = i;
}
iconSpinnerItems.add(new IconSpinnerItem(evlist.get(i)));
}
IconSpinnerAdapter iconSpinnerAdapter = new IconSpinnerAdapter(spinnerView);
spinnerView.setSpinnerAdapter(iconSpinnerAdapter);
spinnerView.setItems(iconSpinnerItems);
// spinnerView.setLifecycleOwner(this);
if(!iconSpinnerItems.isEmpty() && target_index != -1){
spinnerView.selectItemByIndex(target_index);
}
spinnerView.setOnSpinnerItemSelectedListener(new OnSpinnerItemSelectedListener<IconSpinnerItem>() {
@Override
public void onItemSelected(int oldIndex, @Nullable IconSpinnerItem oldItem, int newIndex,
IconSpinnerItem newItem) {
latestSettings.settings.set_evcode(newItem.getText().toString());
}
});
PowerSpinnerView alliance_pos_spinnerView = binding.alliancePosDropdown;
List<IconSpinnerItem> alliance_pos_iconSpinnerItems = new ArrayList<>();
String target_alliance_pos = latestSettings.settings.get_alliance_pos();
int alliance_pos_target_index = -1;
String[] alliance_pos_list = new String[]{"red-1", "red-2", "red-3",
"blue-1", "blue-2", "blue-3"};
for(int i = 0; i < alliance_pos_list.length; i++){
if(alliance_pos_list[i].equals(target_alliance_pos)){
alliance_pos_target_index = i;
}
alliance_pos_iconSpinnerItems.add(new IconSpinnerItem(alliance_pos_list[i]));
}
IconSpinnerAdapter alliance_pos_iconSpinnerAdapter = new IconSpinnerAdapter(alliance_pos_spinnerView);
alliance_pos_spinnerView.setSpinnerAdapter(alliance_pos_iconSpinnerAdapter);
alliance_pos_spinnerView.setItems(alliance_pos_iconSpinnerItems);
alliance_pos_spinnerView.setLifecycleOwner(this);
if(alliance_pos_target_index != -1){
alliance_pos_spinnerView.selectItemByIndex(alliance_pos_target_index);
}
alliance_pos_spinnerView.setOnSpinnerItemSelectedListener(new OnSpinnerItemSelectedListener<IconSpinnerItem>() {
@Override
public void onItemSelected(int oldIndex, @Nullable IconSpinnerItem oldItem, int newIndex,
IconSpinnerItem newItem) {
latestSettings.settings.set_alliance_pos(newItem.getText().toString());
}
});
//
// CheckBox practice_mode = binding.practiceMode;
// practice_mode.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
// @Override
// public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
// latestSettings.settings.set_practice_mode(isChecked);
// }
//
// });
//
// practice_mode.setChecked(latestSettings.settings.get_practice_mode());
EditText team_num = binding.teamNumber;
team_num.setText(String.valueOf(latestSettings.settings.get_team_num()));
team_num.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
latestSettings.settings.set_team_num(team_num.getText().toString());
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count) {}
});
CheckBox wifi_mode = binding.wifiMode;
wifi_mode.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
latestSettings.settings.set_wifi_mode(isChecked);
}
});
wifi_mode.setChecked(latestSettings.settings.get_wifi_mode());
Button reset_button = binding.resetButton;
reset_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
alert.setTitle("Warning");
alert.setMessage("Do you really want to reset settings?");
alert.setCancelable(true);
alert.setPositiveButton("Ok", (dialog, which) -> {
latestSettings.settings.defaultSettings();
username.setText(latestSettings.settings.get_username());
spinnerView.clearSelectedItem();
// practice_mode.setChecked(latestSettings.settings.get_practice_mode());
wifi_mode.setChecked(latestSettings.settings.get_wifi_mode());
alliance_pos_spinnerView.selectItemByIndex(0);
team_num.setText(String.valueOf(latestSettings.settings.get_team_num()));
});
alert.setNegativeButton("Cancel", null);
alert.create().show();
}
});
return root;
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
@@ -1,36 +1,31 @@
package com.astatin3.scoutingapp2025;
package com.ridgebotics.ridgescout;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.MenuItem;
import com.astatin3.scoutingapp2025.scoutingData.fields;
import com.astatin3.scoutingapp2025.utility.SentimentAnalysis;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.ridgebotics.ridgescout.databinding.ActivityMainBinding;
import com.ridgebotics.ridgescout.scoutingData.fields;
import com.ridgebotics.ridgescout.utility.SentimentAnalysis;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.fileEditor;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.AnimBuilder;
import androidx.navigation.NavController;
import androidx.navigation.NavDestination;
import androidx.navigation.NavOptions;
import androidx.navigation.NavOptionsBuilder;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.astatin3.scoutingapp2025.databinding.ActivityMainBinding;
import com.astatin3.scoutingapp2025.SettingsVersionStack.latestSettings;
import com.ridgebotics.ridgescout.utility.settingsManager;
import com.google.android.material.navigation.NavigationBarView;
import java.util.Objects;
import kotlin.Unit;
import kotlin.jvm.functions.Function1;
import java.util.TimeZone;
public class MainActivity extends AppCompatActivity {
@@ -45,7 +40,9 @@ public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
latestSettings.update();
settingsManager.prefs = this.getSharedPreferences(
"com.ridgebotics.ridgescout", Context.MODE_PRIVATE);
if(!fileEditor.fileExist(fields.matchFieldsFilename)){
fields.save(fields.matchFieldsFilename, fields.default_match_fields);
@@ -55,6 +52,9 @@ public class MainActivity extends AppCompatActivity {
fields.save(fields.pitsFieldsFilename, fields.default_pit_fields);
}
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
AlertManager.init(this);
SentimentAnalysis.init(this);
@@ -73,30 +73,6 @@ public class MainActivity extends AppCompatActivity {
navView = findViewById(R.id.nav_view);
// appBarConfiguration = new AppBarConfiguration.Builder(
// R.id.navigation_scouting,
// R.id.navigation_match_scouting,
// R.id.navigation_team_selector,
// R.id.navigation_pit_scouting,
//
// R.id.navigation_data,
// R.id.navigation_data_status,
// R.id.navigation_data_teams,
// R.id.navigation_data_compile,
// R.id.navigation_data_fields_chooser,
// R.id.navigation_data_fields,
//
// R.id.navigation_transfer,
// R.id.navigation_file_selector,
// R.id.navigation_transfer_selector,
// R.id.navigation_code_generator,
// R.id.navigation_code_scanner,
// R.id.navigation_bluetooth_sender,
// R.id.navigation_bluetooth_receiver,
// R.id.navigation_tba,
//
// R.id.navigation_settings)
// .build();
appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_scouting,
@@ -1,17 +1,19 @@
package com.astatin3.scoutingapp2025.scoutingData;
package com.ridgebotics.ridgescout.scoutingData;
import com.astatin3.scoutingapp2025.scoutingData.transfer.transferType;
import com.astatin3.scoutingapp2025.types.ScoutingArray;
import com.astatin3.scoutingapp2025.types.data.dataType;
import com.astatin3.scoutingapp2025.types.data.stringType;
import com.astatin3.scoutingapp2025.types.input.inputType;
import com.astatin3.scoutingapp2025.types.data.intType;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.astatin3.scoutingapp2025.utility.BuiltByteParser;
import com.astatin3.scoutingapp2025.utility.ByteBuilder;
import com.ridgebotics.ridgescout.scoutingData.transfer.transferType;
import com.ridgebotics.ridgescout.types.ScoutingArray;
import com.ridgebotics.ridgescout.types.data.dataType;
import com.ridgebotics.ridgescout.types.data.intArrType;
import com.ridgebotics.ridgescout.types.data.stringType;
import com.ridgebotics.ridgescout.types.input.inputType;
import com.ridgebotics.ridgescout.types.data.intType;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.fileEditor;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.ByteBuilder;
import java.util.ArrayList;
import java.util.Arrays;
public class ScoutingDataWriter {
// private static final int int_type_id = 255;
@@ -32,6 +34,9 @@ public class ScoutingDataWriter {
bb.addString((String) data[i].forceGetValue());
System.out.println("Saved STR: " + data[i].getName() + ", ("+ data[i].get() +")");
break;
case NUMARR:
bb.addIntArray((int[]) data[i].forceGetValue());
System.out.println("Saved INT Array: " + data[i].getName() + ", ("+ Arrays.toString((int[]) data[i].get()) +")");
}
}
byte[] bytes = bb.build();
@@ -73,6 +78,11 @@ public class ScoutingDataWriter {
dataTypes[i].forceSetValue(objects.get(i+2).get());
System.out.println("Loaded STR: " + values[version][i].name + ", ("+ dataTypes[i].get() +")");
break;
case 3: // Int array
dataTypes[i] = intArrType.newNull(values[version][i].name);
dataTypes[i].forceSetValue(objects.get(i+2).get());
System.out.println("Loaded intARR: " + values[version][i].name + ", ("+ Arrays.toString((int[])dataTypes[i].get()) +")");
break;
}
}
@@ -1,16 +1,17 @@
package com.astatin3.scoutingapp2025.scoutingData;
package com.ridgebotics.ridgescout.scoutingData;
import com.astatin3.scoutingapp2025.types.input.dropdownType;
import com.astatin3.scoutingapp2025.types.input.inputType;
import com.astatin3.scoutingapp2025.types.input.tallyType;
import com.astatin3.scoutingapp2025.types.input.textType;
import com.astatin3.scoutingapp2025.types.input.sliderType;
import com.astatin3.scoutingapp2025.types.input.textType;
import com.astatin3.scoutingapp2025.ui.scouting.TallyCounterView;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.astatin3.scoutingapp2025.utility.BuiltByteParser;
import com.astatin3.scoutingapp2025.utility.ByteBuilder;
import com.ridgebotics.ridgescout.types.input.checkboxType;
import com.ridgebotics.ridgescout.types.input.dropdownType;
import com.ridgebotics.ridgescout.types.input.fieldposType;
import com.ridgebotics.ridgescout.types.input.inputType;
import com.ridgebotics.ridgescout.types.input.numberType;
import com.ridgebotics.ridgescout.types.input.tallyType;
import com.ridgebotics.ridgescout.types.input.textType;
import com.ridgebotics.ridgescout.types.input.sliderType;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.fileEditor;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.ByteBuilder;
import java.util.ArrayList;
@@ -22,6 +23,7 @@ public class fields {
public static final inputType[][] default_match_fields = new inputType[][] {
{
new fieldposType("Auto start pos", new int[]{0,0}),
new tallyType("Auto Notes", 0),
new sliderType("Auto Performance", 5, 0, 10),
new textType("Auto Comments", ""),
@@ -32,16 +34,13 @@ public class fields {
new textType("Overall Driving Comments", ""),
new sliderType("Score area (AMP <-> Speaker)", 5, 0, 10),
new dropdownType("End Condition", new String[]{"Nothing", "Attempted Climb", "Successful Climbed", "Climbed with multiple robots", "Climbed with trap"}, 0),
new dropdownType("Robot Condition", new String[]{"Everything was working", "Something seemed to be broken", "Something was broken", "Missing robot (Joe Johnson)"}, 0),
new dropdownType("Robot Condition", new String[]{"Everything was working", "Something was maybe broken", "Something was broken", "Robot was disabled for part of the match", "Missing robot (Joe Johnson)"}, 0),
new textType("Other Comments", "")
}
};
public static final inputType[][] default_pit_fields = new inputType[][] {
{
new sliderType("How good is robot", 5, 0, 10),
new textType("notes", ""),
},{
new sliderType("How good is robot", 5, 0, 10),
new sliderType("Test", 1, 0, 10),
new textType("notes", ""),
@@ -115,6 +114,15 @@ public class fields {
case inputType.tallyType:
t = new tallyType();
break;
case inputType.numberType:
t = new numberType();
break;
case inputType.checkboxType:
t = new checkboxType();
break;
case inputType.fieldposType:
t = new fieldposType();
break;
}
t.decode((byte[]) obj.get());
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.scoutingData.transfer;
package com.ridgebotics.ridgescout.scoutingData.transfer;
public class createTransferType extends transferType {
public transferValue getType() {return transferValue.CREATE;}
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.scoutingData.transfer;
package com.ridgebotics.ridgescout.scoutingData.transfer;
public class directTransferType extends transferType {
public transferValue getType() {return transferValue.DIRECT;}
@@ -1,6 +1,6 @@
package com.astatin3.scoutingapp2025.scoutingData.transfer;
package com.ridgebotics.ridgescout.scoutingData.transfer;
import com.astatin3.scoutingapp2025.types.input.inputType;
import com.ridgebotics.ridgescout.types.input.inputType;
public abstract class transferType {
public enum transferValue {
@@ -1,12 +1,12 @@
package com.astatin3.scoutingapp2025.types;
package com.ridgebotics.ridgescout.types;
import com.astatin3.scoutingapp2025.scoutingData.transfer.createTransferType;
import com.astatin3.scoutingapp2025.scoutingData.transfer.directTransferType;
import com.astatin3.scoutingapp2025.scoutingData.transfer.transferType;
import com.astatin3.scoutingapp2025.types.data.dataType;
import com.astatin3.scoutingapp2025.types.data.intType;
import com.astatin3.scoutingapp2025.types.data.stringType;
import com.astatin3.scoutingapp2025.types.input.inputType;
import com.ridgebotics.ridgescout.scoutingData.transfer.createTransferType;
import com.ridgebotics.ridgescout.scoutingData.transfer.directTransferType;
import com.ridgebotics.ridgescout.scoutingData.transfer.transferType;
import com.ridgebotics.ridgescout.types.data.dataType;
import com.ridgebotics.ridgescout.types.data.intType;
import com.ridgebotics.ridgescout.types.data.stringType;
import com.ridgebotics.ridgescout.types.input.inputType;
public class ScoutingArray {
public int version;
@@ -1,9 +1,10 @@
package com.astatin3.scoutingapp2025.types.data;
package com.ridgebotics.ridgescout.types.data;
public abstract class dataType {
public enum valueTypes {
NUM,
STRING
NUMARR,
STRING,
}
private Object value;
@@ -0,0 +1,54 @@
package com.ridgebotics.ridgescout.types.data;
public class intArrType extends dataType {
public static final int[] nullval = new int[]{255, 255};
// public static final int unselectedval = 1;
public valueTypes getValueType() {
return valueTypes.NUMARR;
}
// public Object getNullValue(){
// return nullval;
// }
// public Object getUnselectedValue(){
// return unselectedval;
// }
public Object get(){
return (int[]) forceGetValue();
}
public void set(Object value){
forceSetValue((int[]) value);
}
public intArrType(String name, int[] value) {
super(name);
set(value);
}
public static intArrType newNull(String name){
return new intArrType(name, nullval);
}
// public static intType newUnselected(String name){
// final intType a = new intType(name, 0);
// a.forceSetValue(unselectedval);
// return a;
// }
public static boolean isNull(int[] obj){
return obj == nullval;
}
public boolean isNull() {
return isNull((int[]) forceGetValue());
}
// public static boolean isUnselected(int obj){
// return obj == unselectedval;
// }
// public boolean isUnselected() {
// return isUnselected((int) forceGetValue());
// }
}
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.types.data;
package com.ridgebotics.ridgescout.types.data;
public class intType extends dataType {
public static final int nullval = 255;
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.types.data;
package com.ridgebotics.ridgescout.types.data;
public class stringType extends dataType{
public static final String nullval = "null";
@@ -1,9 +1,9 @@
package com.astatin3.scoutingapp2025.types;
package com.ridgebotics.ridgescout.types;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.BuiltByteParser;
import com.astatin3.scoutingapp2025.utility.ByteBuilder;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.ByteBuilder;
import com.ridgebotics.ridgescout.utility.fileEditor;
import java.util.ArrayList;
import java.util.Objects;
@@ -0,0 +1,144 @@
package com.ridgebotics.ridgescout.types;
import static com.ridgebotics.ridgescout.utility.DataManager.event;
import android.widget.TableRow;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.ByteBuilder;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
public class frcEvent {
public static final int typecode = 254;
public String eventCode;
public String name;
public ArrayList<frcMatch> matches;
public ArrayList<frcTeam> teams;
public byte[] encode() {
try {
ByteBuilder bb = new ByteBuilder()
.addString(eventCode)
.addString(name);
for (frcTeam teams : teams) {
bb.addRaw(frcTeam.typecode, teams.encode());
}
for (frcMatch match : matches) {
bb.addRaw(frcMatch.typecode, match.encode());
}
return bb.build();
} catch (ByteBuilder.buildingException e) {
AlertManager.error(e);
return null;
}
}
public static frcEvent decode(byte[] bytes) {
try {
ArrayList<BuiltByteParser.parsedObject> objects =
new BuiltByteParser(bytes).parse();
frcEvent frc = new frcEvent();
frc.eventCode = (String) objects.get(0).get();
frc.name = (String) objects.get(1).get();
frc.matches = new ArrayList<>();
frc.teams = new ArrayList<>();
for (BuiltByteParser.parsedObject object : objects) {
if (object.getType() == frcTeam.typecode) {
frc.teams.add(frcTeam.decode((byte[]) object.get()));
} else if (object.getType() == frcMatch.typecode) {
frc.matches.add(frcMatch.decode((byte[]) object.get()));
}
}
return frc;
} catch (BuiltByteParser.byteParsingExeption e) {
AlertManager.error(e);
return null;
}
}
@NonNull
public String toString() {
return (
"frcEvent Name: " +
name +
", Code: " +
eventCode +
" numTeams: " +
teams.size() +
" numMatches: " +
matches.size()
);
}
// A func that will return every match a team is in.
public frcMatch[] getTeamMatches(int teamNum){
List<frcMatch> teamMatches = new ArrayList<>();
for(int i = 0; i < matches.size(); i++){
frcMatch match = matches.get(i);
boolean isTeamMatch = false;
isTeamMatch = IntStream.of(match.redAlliance).anyMatch(x -> x == teamNum);
isTeamMatch = isTeamMatch || IntStream.of(match.blueAlliance).anyMatch(x -> x == teamNum);
if(isTeamMatch)
teamMatches.add(match);
}
return teamMatches.toArray(new frcMatch[0]);
}
// A func that will return the most recent match a team is in. (Not up until the current match)
public int getMostRecentTeamMatch(int teamNum, int curMatch){
frcMatch[] teamMatches = getTeamMatches(teamNum);
int maxMatch = - 1;
for(int i = 0; i < teamMatches.length; i++) {
if (teamMatches[i].matchIndex < curMatch &&
teamMatches[i].matchIndex > maxMatch) {
maxMatch = teamMatches[i].matchIndex;
}
}
if(maxMatch == -1)
return curMatch;
else
return maxMatch;
}
// 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);
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];
if(teamNum == ourTeamNum)
continue;
int matchNum = event.getMostRecentTeamMatch(teamNum, teamMatches[i].matchIndex);
if(maxMatch < matchNum)
maxMatch = matchNum;
}
}
}
}
@@ -1,10 +1,10 @@
package com.astatin3.scoutingapp2025.types;
package com.ridgebotics.ridgescout.types;
import androidx.annotation.NonNull;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.BuiltByteParser;
import com.astatin3.scoutingapp2025.utility.ByteBuilder;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.ByteBuilder;
import java.util.ArrayList;
import java.util.Arrays;
@@ -60,4 +60,14 @@ public class frcMatch {
return "frcMatch Num: " + matchIndex + ", Blue: " + Arrays.toString(blueAlliance) + ", Red: " + Arrays.toString(redAlliance);
}
public String getTeamAlliance(int teamNum){
if(redAlliance[0] == teamNum) return "red-1";
if(redAlliance[1] == teamNum) return "red-2";
if(redAlliance[2] == teamNum) return "red-3";
if(blueAlliance[0] == teamNum) return "blue-1";
if(blueAlliance[1] == teamNum) return "blue-2";
if(blueAlliance[2] == teamNum) return "blue-3";
return "";
}
}
@@ -1,10 +1,10 @@
package com.astatin3.scoutingapp2025.types;
package com.ridgebotics.ridgescout.types;
import androidx.annotation.NonNull;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.BuiltByteParser;
import com.astatin3.scoutingapp2025.utility.ByteBuilder;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.ByteBuilder;
import java.util.ArrayList;
@@ -0,0 +1,228 @@
package com.ridgebotics.ridgescout.types.input;
import android.content.Context;
import android.graphics.Color;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.charts.PieChart;
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.github.mikephil.charting.data.PieData;
import com.github.mikephil.charting.data.PieDataSet;
import com.github.mikephil.charting.data.PieEntry;
import com.ridgebotics.ridgescout.types.data.dataType;
import com.ridgebotics.ridgescout.types.data.intType;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.ByteBuilder;
import com.skydoves.powerspinner.IconSpinnerAdapter;
import com.skydoves.powerspinner.IconSpinnerItem;
import com.skydoves.powerspinner.OnSpinnerItemSelectedListener;
import com.skydoves.powerspinner.PowerSpinnerView;
import com.skydoves.powerspinner.SpinnerGravity;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
public class checkboxType extends inputType {
public int get_byte_id() {return checkboxType;}
public inputTypes getInputType(){return inputTypes.CHECKBOX;}
public dataType.valueTypes getValueType(){return dataType.valueTypes.NUM;}
public Object get_fallback_value(){return 0;}
public checkboxType(){};
public String get_type_name(){return "Checkbox";}
public checkboxType(String name, int isChecked){
super(name);
this.default_value = isChecked;
}
public byte[] encode() throws ByteBuilder.buildingException {
ByteBuilder bb = new ByteBuilder();
bb.addString(name);
bb.addInt((int)default_value);
return bb.build();
}
public void decode(byte[] bytes) throws BuiltByteParser.byteParsingExeption {
BuiltByteParser bbp = new BuiltByteParser(bytes);
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
name = (String) objects.get(0).get();
default_value = objects.get(1).get();
}
// public PowerSpinnerView dropdown = null;
public CheckBox checkBox = null;
public View createView(Context context, Function<dataType, Integer> onUpdate){
checkBox = new CheckBox(context);
checkBox.setText(name);
checkBox.setTextSize(24);
setViewValue(default_value);
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
onUpdate.apply(getViewValue());
}
});
return checkBox;
}
public void setViewValue(Object value) {
if(checkBox == null) return;
if(intType.isNull((int) value)){
nullify();
return;
}
isBlank = false;
checkBox.setVisibility(View.VISIBLE);
checkBox.setChecked((int) value == 1);
}
public void nullify(){
isBlank = true;
checkBox.setVisibility(View.GONE);
}
public dataType getViewValue(){
if(checkBox == null) return null;
if(checkBox.getVisibility() == View.GONE) return new intType(name, intType.nullval);
return new intType(name, checkBox.isChecked() ? 1 : 0);
}
public void add_individual_view(LinearLayout parent, dataType data){
if(data.isNull()) return;
CheckBox cb = new CheckBox(parent.getContext());
cb.setText(name);
cb.setChecked((int) data.get() == 1);
cb.setEnabled(false);
parent.addView(cb);
}
public static int[] colors = {0x7f00ff00, 0x7f7f0000};
public void add_compiled_view(LinearLayout parent, dataType[] data){
PieChart chart = new PieChart(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);
parent.addView(chart);
int numTrue = 0;
int numFalse = 0;
for(int i = 0; i < data.length; i++)
if(!data[i].isNull()){
if((int) data[i].get() == 1)
numTrue += 1;
else
numFalse += 1;
}
List<PieEntry> entries = new ArrayList<>();
entries.add(new PieEntry((float) numTrue, "True"));
entries.add(new PieEntry((float) numFalse, "False"));
PieDataSet pieDataSet = new PieDataSet(entries, name);
pieDataSet.setColors(colors);
PieData pieData = new PieData(pieDataSet);
chart.setDrawHoleEnabled(false);
chart.setData(pieData);
}
public void add_history_view(LinearLayout parent, dataType[] 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);
LineData lineData = new LineData();
List<Entry> entries = new ArrayList<>();
for (int a = 0; a < data.length; a++) {
if(data[a].isNull()) continue;
entries.add(
new Entry(a,
((int) data[a].get())
)
);
}
LineDataSet dataSet = new LineDataSet(entries, "is checked");
dataSet.setColor(Color.RED);
dataSet.setValueTextColor(Color.BLACK);
dataSet.setDrawCircles(false);
dataSet.setDrawValues(false);
dataSet.setValueTextColor(Color.RED);
lineData.addDataSet(dataSet);
chart.setData(lineData);
chart.invalidate();
chart.getDescription().setEnabled(false);
chart.setTouchEnabled(false);
chart.setDragEnabled(false);
chart.setScaleEnabled(false);
chart.getXAxis().setTextColor(Color.WHITE);
chart.getAxisLeft().setTextColor(Color.WHITE);
chart.getAxisRight().setTextColor(Color.WHITE);
chart.getAxisLeft().setAxisMinimum(0.f);
chart.getAxisLeft().setAxisMaximum(1.f);
chart.getAxisRight().setAxisMinimum(0.f);
chart.getAxisRight().setAxisMaximum(1.f);
Legend legend = chart.getLegend();
legend.setTextColor(Color.WHITE);
chart.invalidate();
parent.addView(chart);
}
}
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.types.input;
package com.ridgebotics.ridgescout.types.input;
import android.content.Context;
import android.graphics.Color;
@@ -11,10 +11,10 @@ import android.widget.TextView;
import androidx.annotation.Nullable;
import com.astatin3.scoutingapp2025.types.data.dataType;
import com.astatin3.scoutingapp2025.types.data.intType;
import com.astatin3.scoutingapp2025.utility.BuiltByteParser;
import com.astatin3.scoutingapp2025.utility.ByteBuilder;
import com.ridgebotics.ridgescout.types.data.dataType;
import com.ridgebotics.ridgescout.types.data.intType;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.ByteBuilder;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.charts.PieChart;
import com.github.mikephil.charting.components.Legend;
@@ -0,0 +1,230 @@
package com.ridgebotics.ridgescout.types.input;
import static android.text.InputType.TYPE_CLASS_NUMBER;
import android.content.Context;
import android.graphics.Color;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
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.R;
import com.ridgebotics.ridgescout.types.data.dataType;
import com.ridgebotics.ridgescout.types.data.intArrType;
import com.ridgebotics.ridgescout.types.data.intType;
import com.ridgebotics.ridgescout.ui.scouting.FieldPosView;
import com.ridgebotics.ridgescout.ui.scouting.MultiFieldPosView;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.ByteBuilder;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
public class fieldposType extends inputType {
public int get_byte_id() {return fieldposType;}
public inputTypes getInputType(){return inputTypes.FIELDPOS;}
public dataType.valueTypes getValueType(){return dataType.valueTypes.NUM;}
public Object get_fallback_value(){return 0;}
public fieldposType(){}
public String get_type_name(){return "Field Pos";}
public fieldposType(String name, int[] default_value){
super(name);
this.default_value = default_value;
}
public byte[] encode() throws ByteBuilder.buildingException {
ByteBuilder bb = new ByteBuilder();
bb.addString(name);
bb.addIntArray((int[]) default_value);
return bb.build();
}
public void decode(byte[] bytes) throws BuiltByteParser.byteParsingExeption {
BuiltByteParser bbp = new BuiltByteParser(bytes);
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
name = (String) objects.get(0).get();
default_value = objects.get(1).get();
System.out.println("Defalt value!!!!!" + default_value);
}
public FieldPosView field = null;
public View createView(Context context, Function<dataType, Integer> onUpdate){
field = new FieldPosView(context, pos -> {
onUpdate.apply(new intArrType(name, pos));
});
setViewValue(default_value);
return field;
}
public void setViewValue(Object value) {
if(field == null) return;
if(intArrType.isNull((int[]) value)){
nullify();
return;
}
isBlank = false;
field.setVisibility(View.VISIBLE);
field.setPos((int[]) value);
}
public void nullify(){
isBlank = true;
field.setVisibility(View.GONE);
}
public dataType getViewValue(){
if(field == null) return null;
if(field.getVisibility() == View.GONE) return intArrType.newNull(name);
return new intArrType(name, field.getPos());
}
public void add_individual_view(LinearLayout parent, dataType data){
if(data.isNull()) return;
FieldPosView fp = new FieldPosView(parent.getContext());
fp.setEnabled(false);
fp.setPos((int[]) data.get());
parent.addView(fp);
}
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(dataType[] 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(dataType[] 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, dataType[] data){
MultiFieldPosView mfp = new MultiFieldPosView(parent.getContext());
for(int i = 0; i < data.length; i++){
if(data[i].isNull()) continue;
mfp.addPos((int[]) data[i].get());
}
parent.addView(mfp);
}
public void add_history_view(LinearLayout parent, dataType[] 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 = 0;
int max = 255;
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, 255-(float)((int[]) data[i].get())[1]));
}
LineDataSet dataSet = new LineDataSet(entries, "Field position Y value");
dataSet.setColor(Color.BLUE);
dataSet.setValueTextColor(Color.BLACK);
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(Color.RED);
chart.getXAxis().setTextColor(Color.WHITE);
chart.getAxisLeft().setTextColor(Color.WHITE);
chart.getAxisRight().setTextColor(Color.WHITE);
Legend legend = chart.getLegend();
legend.setTextColor(Color.WHITE);
chart.getAxisLeft().setAxisMinimum(min);
chart.getAxisLeft().setAxisMaximum(max);
chart.getAxisRight().setAxisMinimum(min);
chart.getAxisRight().setAxisMaximum(max);
parent.addView(chart);
}
}
@@ -1,16 +1,12 @@
package com.astatin3.scoutingapp2025.types.input;
package com.ridgebotics.ridgescout.types.input;
import android.content.Context;
import android.view.View;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.astatin3.scoutingapp2025.types.data.dataType;
import com.astatin3.scoutingapp2025.ui.data.FieldEditorHelper;
import com.astatin3.scoutingapp2025.utility.BuiltByteParser;
import com.astatin3.scoutingapp2025.utility.ByteBuilder;
import com.ridgebotics.ridgescout.types.data.dataType;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.ByteBuilder;
import java.util.function.Function;
@@ -19,11 +15,18 @@ public abstract class inputType {
public static final int dropdownType = 254;
public static final int notesType = 253;
public static final int tallyType = 252;
public static final int numberType = 251;
public static final int checkboxType = 250;
public static final int fieldposType = 249;
public enum inputTypes {
SLIDER,
DROPDOWN,
NOTES_INPUT,
TALLY
TALLY,
NUMBER,
CHECKBOX,
FIELDPOS
}
public String name;
public Object default_value;
@@ -0,0 +1,319 @@
package com.ridgebotics.ridgescout.types.input;
import static android.text.InputType.TYPE_CLASS_NUMBER;
import android.content.Context;
import android.graphics.Color;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
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.dataType;
import com.ridgebotics.ridgescout.types.data.intType;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.ByteBuilder;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
public class numberType extends inputType {
public int get_byte_id() {return numberType;}
public inputTypes getInputType(){return inputTypes.NUMBER;}
public dataType.valueTypes getValueType(){return dataType.valueTypes.NUM;}
public Object get_fallback_value(){return 0;}
public numberType(){}
public String get_type_name(){return "Number";}
public numberType(String name, int default_value){
super(name);
this.default_value = default_value;
}
public byte[] encode() throws ByteBuilder.buildingException {
ByteBuilder bb = new ByteBuilder();
bb.addString(name);
bb.addInt((int)default_value);
return bb.build();
}
public void decode(byte[] bytes) throws BuiltByteParser.byteParsingExeption {
BuiltByteParser bbp = new BuiltByteParser(bytes);
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
name = (String) objects.get(0).get();
default_value = objects.get(1).get();
}
public EditText num = null;
public View createView(Context context, Function<dataType, Integer> onUpdate){
num = new EditText(context);
num.setInputType(TYPE_CLASS_NUMBER);
num.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
onUpdate.apply(getViewValue());}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count) {}
});
setViewValue(default_value);
return num;
}
public void setViewValue(Object value) {
if(num == null) return;
if(intType.isNull((int)value)){
nullify();
return;
}
isBlank = false;
num.setVisibility(View.VISIBLE);
num.setText(String.valueOf(value));
}
public void nullify(){
isBlank = true;
num.setVisibility(View.GONE);
}
public dataType getViewValue(){
if(num == null) return null;
if(num.getVisibility() == View.GONE) return intType.newNull(name);
return new intType(name, safeToInt(num.getText().toString()));
}
private int safeToInt(String num){
if(num.isEmpty())
return intType.nullval;
try {
return Integer.parseInt(num);
}catch (NumberFormatException e){
return intType.nullval;
}
}
public void add_individual_view(LinearLayout parent, dataType 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(dataType[] 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(dataType[] 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, dataType[] 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(Color.BLUE);
dataSet.setValueTextColor(Color.BLACK);
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(Color.RED);
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(Color.RED);
chart.getXAxis().setTextColor(Color.WHITE);
chart.getAxisLeft().setTextColor(Color.WHITE);
chart.getAxisRight().setTextColor(Color.WHITE);
Legend legend = chart.getLegend();
legend.setTextColor(Color.WHITE);
parent.addView(chart);
}
public void add_history_view(LinearLayout parent, dataType[] 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);
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(Color.BLUE);
dataSet.setValueTextColor(Color.BLACK);
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(Color.RED);
chart.getXAxis().setTextColor(Color.WHITE);
chart.getAxisLeft().setTextColor(Color.WHITE);
chart.getAxisRight().setTextColor(Color.WHITE);
Legend legend = chart.getLegend();
legend.setTextColor(Color.WHITE);
chart.getAxisLeft().setAxisMinimum(min);
chart.getAxisLeft().setAxisMaximum(max);
chart.getAxisRight().setAxisMinimum(min);
chart.getAxisRight().setAxisMaximum(max);
parent.addView(chart);
}
}
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.types.input;
package com.ridgebotics.ridgescout.types.input;
import android.content.Context;
import android.graphics.Color;
@@ -9,12 +9,11 @@ import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import com.astatin3.scoutingapp2025.types.data.dataType;
import com.astatin3.scoutingapp2025.types.data.intType;
import com.astatin3.scoutingapp2025.types.data.stringType;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.BuiltByteParser;
import com.astatin3.scoutingapp2025.utility.ByteBuilder;
import com.ridgebotics.ridgescout.types.data.dataType;
import com.ridgebotics.ridgescout.types.data.intType;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.ByteBuilder;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.data.Entry;
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.types.input;
package com.ridgebotics.ridgescout.types.input;
import android.content.Context;
import android.graphics.Color;
@@ -9,11 +9,11 @@ import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.astatin3.scoutingapp2025.types.data.dataType;
import com.astatin3.scoutingapp2025.types.data.intType;
import com.astatin3.scoutingapp2025.ui.scouting.TallyCounterView;
import com.astatin3.scoutingapp2025.utility.BuiltByteParser;
import com.astatin3.scoutingapp2025.utility.ByteBuilder;
import com.ridgebotics.ridgescout.types.data.dataType;
import com.ridgebotics.ridgescout.types.data.intType;
import com.ridgebotics.ridgescout.ui.scouting.TallyCounterView;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.ByteBuilder;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.data.Entry;
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.types.input;
package com.ridgebotics.ridgescout.types.input;
import android.content.Context;
import android.graphics.Color;
@@ -12,11 +12,11 @@ import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.astatin3.scoutingapp2025.types.data.dataType;
import com.astatin3.scoutingapp2025.types.data.stringType;
import com.astatin3.scoutingapp2025.utility.SentimentAnalysis;
import com.astatin3.scoutingapp2025.utility.BuiltByteParser;
import com.astatin3.scoutingapp2025.utility.ByteBuilder;
import com.ridgebotics.ridgescout.types.data.dataType;
import com.ridgebotics.ridgescout.types.data.stringType;
import com.ridgebotics.ridgescout.utility.SentimentAnalysis;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.ByteBuilder;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.data.Entry;
@@ -1,7 +1,7 @@
package com.astatin3.scoutingapp2025.ui;
package com.ridgebotics.ridgescout.ui;
import static com.astatin3.scoutingapp2025.utility.DataManager.evcode;
import static com.astatin3.scoutingapp2025.utility.DataManager.event;
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
import static com.ridgebotics.ridgescout.utility.DataManager.event;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -16,13 +16,11 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.SettingsVersionStack.latestSettings;
import com.astatin3.scoutingapp2025.databinding.FragmentTeamSelectorBinding;
import com.astatin3.scoutingapp2025.types.frcEvent;
import com.astatin3.scoutingapp2025.types.frcTeam;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.DataManager;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.ridgebotics.ridgescout.databinding.FragmentTeamSelectorBinding;
import com.ridgebotics.ridgescout.types.frcTeam;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.DataManager;
import com.ridgebotics.ridgescout.utility.fileEditor;
import java.util.Arrays;
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.ui.data;
package com.ridgebotics.ridgescout.ui.data;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -9,8 +9,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.databinding.FragmentDataCompareBinding;
import com.astatin3.scoutingapp2025.databinding.FragmentDataReportBinding;
import com.ridgebotics.ridgescout.databinding.FragmentDataCompareBinding;
public class CompareFragment extends Fragment {
FragmentDataCompareBinding binding;
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.ui.data;
package com.ridgebotics.ridgescout.ui.data;
import static androidx.navigation.fragment.FragmentKt.findNavController;
@@ -13,13 +13,13 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.R;
import com.astatin3.scoutingapp2025.SettingsVersionStack.latestSettings;
import com.astatin3.scoutingapp2025.databinding.FragmentDataBinding;
import com.astatin3.scoutingapp2025.types.frcTeam;
import com.astatin3.scoutingapp2025.ui.TeamSelectorFragment;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.astatin3.scoutingapp2025.types.frcEvent;
import com.ridgebotics.ridgescout.R;
import com.ridgebotics.ridgescout.utility.settingsManager;
import com.ridgebotics.ridgescout.databinding.FragmentDataBinding;
import com.ridgebotics.ridgescout.types.frcTeam;
import com.ridgebotics.ridgescout.ui.TeamSelectorFragment;
import com.ridgebotics.ridgescout.utility.fileEditor;
import com.ridgebotics.ridgescout.types.frcEvent;
public class DataFragment extends Fragment {
@@ -33,17 +33,19 @@ public class DataFragment extends Fragment {
binding = FragmentDataBinding.inflate(inflater, container, false);
View root = binding.getRoot();
String evcode = latestSettings.settings.get_evcode();
String evcode = settingsManager.getEVCode();
binding.fieldsButton.setOnClickListener(v -> {
findNavController(this).navigate(R.id.action_navigation_data_to_navigation_data_fields_chooser);
});
if(evcode.equals("unset")){
binding.noEventError.setVisibility(View.VISIBLE);
binding.buttons.setVisibility(View.VISIBLE);
binding.teamsButton.setVisibility(View.GONE);
binding.compareButton.setVisibility(View.GONE);
binding.reportButton.setVisibility(View.GONE);
binding.teamsButton.setEnabled(false);
binding.compareButton.setEnabled(false);
binding.reportButton.setEnabled(false);
binding.fieldsButton.setVisibility(View.VISIBLE);
@@ -69,11 +71,7 @@ public class DataFragment extends Fragment {
});
binding.reportButton.setOnClickListener(v -> {
findNavController(this).navigate(R.id.action_navigation_data_to_navigation_data_report);
});
binding.fieldsButton.setOnClickListener(v -> {
findNavController(this).navigate(R.id.action_navigation_data_to_navigation_data_fields_chooser);
findNavController(this).navigate(R.id.action_navigation_data_to_navigation_data_report_selector);
});
return root;
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.ui.data;
package com.ridgebotics.ridgescout.ui.data;
import static android.text.InputType.TYPE_CLASS_NUMBER;
@@ -8,19 +8,22 @@ import android.widget.EditText;
import android.widget.TableLayout;
import android.widget.TextView;
import com.astatin3.scoutingapp2025.types.input.dropdownType;
import com.astatin3.scoutingapp2025.types.input.inputType;
import com.astatin3.scoutingapp2025.types.input.sliderType;
import com.astatin3.scoutingapp2025.types.input.tallyType;
import com.astatin3.scoutingapp2025.types.input.textType;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.google.android.material.textfield.TextInputEditText;
import com.ridgebotics.ridgescout.types.input.checkboxType;
import com.ridgebotics.ridgescout.types.input.dropdownType;
import com.ridgebotics.ridgescout.types.input.fieldposType;
import com.ridgebotics.ridgescout.types.input.inputType;
import com.ridgebotics.ridgescout.types.input.numberType;
import com.ridgebotics.ridgescout.types.input.sliderType;
import com.ridgebotics.ridgescout.types.input.tallyType;
import com.ridgebotics.ridgescout.types.input.textType;
import com.ridgebotics.ridgescout.utility.AlertManager;
public class FieldEditorHelper {
private enum parameterTypeEnum {
paramNumber,
paramString,
paramStringArray
paramStringArray,
paramNumberArray
}
public static class parameterType {
@@ -55,6 +58,15 @@ public class FieldEditorHelper {
}
}
// public static class paramNumberArray extends parameterType{
// public int[] val;
// public paramNumberArray(String name, int[] val){
// this.name = name + " (Number array)";
// this.val = val;
// this.id = parameterTypeEnum.paramNumberArray;
// }
// }
public static final parameterType[] defaultSliderParams = new parameterType[]{
new paramNumber("Min", 0),
new paramNumber("Max", 10),
@@ -70,6 +82,16 @@ public class FieldEditorHelper {
public static final parameterType[] defaultTallyParams = new parameterType[]{
new paramNumber("Default Value", 0)
};
public static final parameterType[] defaultNumberParams = new parameterType[]{
new paramNumber("Default Value", 0)
};
public static final parameterType[] defaultCheckboxParam = new parameterType[]{
new paramNumber("Default Value ( 1 or 0 )", 0)
};
public static final parameterType[] defaultFieldPosParam = new parameterType[]{
new paramNumber("Default X", 0),
new paramNumber("Default Y", 0)
};
private static parameterType[] getSliderParams(sliderType s){
@@ -99,6 +121,25 @@ public class FieldEditorHelper {
};
}
private static parameterType[] getNumberParams(numberType s){
return new parameterType[]{
new paramNumber("Default Value", (int) s.default_value)
};
}
private static parameterType[] getCheckboxParam(checkboxType s){
return new parameterType[]{
new paramNumber("Default Value ( 1 or 0 )", (int) s.default_value)
};
}
private static parameterType[] getFieldPosParam(fieldposType s){
return new parameterType[]{
new paramNumber("Default X", ((int[]) s.default_value)[0]),
new paramNumber("Default Y", ((int[]) s.default_value)[1])
};
}
public static void setSliderParams(sliderType s, parameterType[] types){
@@ -120,6 +161,22 @@ public class FieldEditorHelper {
s.default_value = ((paramNumber) types[0]).val;
}
public static void setNumberParams(numberType s, parameterType[] types){
s.default_value = ((paramNumber) types[0]).val;
}
public static void setCheckboxParam(checkboxType s, parameterType[] types){
s.default_value = ((paramNumber) types[0]).val;
}
public static void setFieldPosParam(fieldposType s, parameterType[] types){
s.default_value = new int[]{
((paramNumber) types[0]).val,
((paramNumber) types[1]).val
};
}
private static void setInputParameter(inputType t, parameterType[] types){
switch (t.getInputType()){
case TALLY:
@@ -134,6 +191,15 @@ public class FieldEditorHelper {
case NOTES_INPUT:
setTextParams((textType) t, types);
break;
case NUMBER:
setNumberParams((numberType) t, types);
break;
case CHECKBOX:
setCheckboxParam((checkboxType) t, types);
break;
case FIELDPOS:
setFieldPosParam((fieldposType) t, types);
break;
}
}
@@ -149,6 +215,12 @@ public class FieldEditorHelper {
return getDropdownParams((dropdownType) t);
case NOTES_INPUT:
return getTextParams((textType) t);
case NUMBER:
return getNumberParams((numberType) t);
case CHECKBOX:
return getCheckboxParam((checkboxType) t);
case FIELDPOS:
return getFieldPosParam((fieldposType) t);
}
return new parameterType[]{};
}
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.ui.data;
package com.ridgebotics.ridgescout.ui.data;
import static androidx.navigation.fragment.FragmentKt.findNavController;
@@ -11,9 +11,9 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.R;
import com.astatin3.scoutingapp2025.databinding.FragmentDataFieldsChooserBinding;
import com.astatin3.scoutingapp2025.scoutingData.fields;
import com.ridgebotics.ridgescout.R;
import com.ridgebotics.ridgescout.databinding.FragmentDataFieldsChooserBinding;
import com.ridgebotics.ridgescout.scoutingData.fields;
public class FieldsChooserFragment extends Fragment {
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.ui.data;
package com.ridgebotics.ridgescout.ui.data;
import android.annotation.SuppressLint;
import android.app.Activity;
@@ -21,15 +21,18 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import com.astatin3.scoutingapp2025.R;
import com.astatin3.scoutingapp2025.databinding.FragmentDataFieldsBinding;
import com.astatin3.scoutingapp2025.scoutingData.fields;
import com.astatin3.scoutingapp2025.types.input.dropdownType;
import com.astatin3.scoutingapp2025.types.input.inputType;
import com.astatin3.scoutingapp2025.types.input.sliderType;
import com.astatin3.scoutingapp2025.types.input.tallyType;
import com.astatin3.scoutingapp2025.types.input.textType;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.ridgebotics.ridgescout.R;
import com.ridgebotics.ridgescout.databinding.FragmentDataFieldsBinding;
import com.ridgebotics.ridgescout.scoutingData.fields;
import com.ridgebotics.ridgescout.types.input.checkboxType;
import com.ridgebotics.ridgescout.types.input.dropdownType;
import com.ridgebotics.ridgescout.types.input.fieldposType;
import com.ridgebotics.ridgescout.types.input.inputType;
import com.ridgebotics.ridgescout.types.input.numberType;
import com.ridgebotics.ridgescout.types.input.sliderType;
import com.ridgebotics.ridgescout.types.input.tallyType;
import com.ridgebotics.ridgescout.types.input.textType;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.skydoves.powerspinner.IconSpinnerAdapter;
import com.skydoves.powerspinner.IconSpinnerItem;
import com.skydoves.powerspinner.PowerSpinnerView;
@@ -52,10 +55,8 @@ public class FieldsFragment extends Fragment {
@Nullable Bundle savedInstanceState) {
binding = FragmentDataFieldsBinding.inflate(inflater, container, false);
binding.revertVersionButton.setVisibility(View.VISIBLE);
binding.valueEditScrollview.setOnTouchListener((v, event) -> true);
binding.saveButton.setVisibility(View.GONE);
binding.cancelEditButton.setVisibility(View.GONE);
binding.editButton.setVisibility(View.GONE);
@@ -121,6 +122,25 @@ public class FieldsFragment extends Fragment {
tr.setBackgroundColor(unfocused_background_color);
}
}
if(values.length > 1) {
binding.revertVersionButton.setVisibility(View.VISIBLE);
binding.revertVersionButton.setOnClickListener(v -> {
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
alert.setTitle("Warning!");
alert.setMessage("If there is any data set this version, it will be deleted!");
alert.setPositiveButton("OK", (dialog, which) -> {
inputType[][] newArr = new inputType[values.length - 1][];
System.arraycopy(values, 0, newArr, 0, values.length - 1);
if(fields.save(filename, newArr))
AlertManager.toast("Saved");
load_field_menu();
});
alert.setNegativeButton("Cancel", null);
alert.setCancelable(true);
alert.create().show();
});
}
}
private void display_fields(inputType[] version_values) {
@@ -179,10 +199,7 @@ public class FieldsFragment extends Fragment {
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
alert.setTitle("Warning!");
alert.setMessage("Changing or removing some values will result in lost data!\nBut this will create a new field version, and you can revert at any time.");
alert.setPositiveButton("OK", null);
alert.setNegativeButton("Cancel", null);
alert.setCancelable(true);
alert.setOnDismissListener(b -> {
alert.setPositiveButton("OK", (dialog, which) -> {
inputType[][] currentValues = fields.load(filename);
assert currentValues != null;
inputType[][] newValues = new inputType[currentValues.length+1][];
@@ -195,11 +212,13 @@ public class FieldsFragment extends Fragment {
}
// newValues[newValues.length-1] = values[values.length-1];
boolean saved = fields.save(filename, newValues);
AlertManager.alert("Saved", String.valueOf(saved));
if(fields.save(filename, newValues))
AlertManager.toast("Saved");
Navigation.findNavController((Activity) getContext(), R.id.nav_host_fragment_activity_main).navigate(R.id.action_navigation_data_fields_to_navigation_data_fields_chooser);
});
alert.setNegativeButton("Cancel", null);
alert.setCancelable(true);
alert.create().show();
}
@@ -381,6 +400,9 @@ public class FieldsFragment extends Fragment {
iconSpinnerItems.add(new IconSpinnerItem("Text"));
iconSpinnerItems.add(new IconSpinnerItem("Dropdown"));
iconSpinnerItems.add(new IconSpinnerItem("Tally"));
iconSpinnerItems.add(new IconSpinnerItem("Number"));
iconSpinnerItems.add(new IconSpinnerItem("Checkbox"));
iconSpinnerItems.add(new IconSpinnerItem("Field Position"));
IconSpinnerAdapter iconSpinnerAdapter = new IconSpinnerAdapter(dropdown);
@@ -445,6 +467,24 @@ public class FieldsFragment extends Fragment {
FieldEditorHelper.setTallyParams(tally, FieldEditorHelper.defaultTallyParams);
addField_Part_4(tally);
break;
case 4:
numberType num = new numberType();
num.name = title;
FieldEditorHelper.setNumberParams(num, FieldEditorHelper.defaultNumberParams);
addField_Part_4(num);
break;
case 5:
checkboxType cb = new checkboxType();
cb.name = title;
FieldEditorHelper.setCheckboxParam(cb, FieldEditorHelper.defaultCheckboxParam);
addField_Part_4(cb);
break;
case 6:
fieldposType fp = new fieldposType();
fp.name = title;
FieldEditorHelper.setFieldPosParam(fp, FieldEditorHelper.defaultFieldPosParam);
addField_Part_4(fp);
break;
}
@@ -479,7 +519,7 @@ public class FieldsFragment extends Fragment {
newValues[newValues.length-1] = field;
values[values.length-1] = newValues;
AlertManager.alert("Test", String.valueOf(binding.fieldsArea.getReorderedIndexes()));
// AlertManager.alert("Test", String.valueOf(binding.fieldsArea.getReorderedIndexes()));
//TableRow tr = getTableRow(field);
//binding.fieldsArea.addView(tr);
@@ -0,0 +1,89 @@
package com.ridgebotics.ridgescout.ui.data;
import static com.ridgebotics.ridgescout.utility.DataManager.event;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TableRow;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.ridgebotics.ridgescout.databinding.FragmentDataReportBinding;
import com.ridgebotics.ridgescout.types.frcMatch;
import com.ridgebotics.ridgescout.utility.DataManager;
import com.ridgebotics.ridgescout.utility.ollama.OllamaClient;
import com.ridgebotics.ridgescout.utility.ollama.PromptCreator;
import com.ridgebotics.ridgescout.utility.settingsManager;
public class ReportFragment extends Fragment {
FragmentDataReportBinding binding;
private static frcMatch match;
public static void setMatch(frcMatch m){
match = m;
}
private final int ourTeamNum = settingsManager.getTeamNum();
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentDataReportBinding.inflate(inflater, container, false);
binding.teamNumber.setText(String.valueOf(ourTeamNum));
binding.AyEyeBox.setVisibility(View.VISIBLE);
binding.AyEyeButton.setVisibility(View.GONE);
DataManager.reload_event();
DataManager.reload_pit_fields();
DataManager.reload_match_fields();
binding.AyEyeBox.setText("TBD!\n This is meant to be a tool that lets scouters more easily write reports to the drive team before matches. There are some plans for LLM integration into this menu ");
// binding.AyEyeButton.setText("Create Prompt");
// binding.AyEyeButton.setOnClickListener(a ->{
// getPrompt();
// binding.AyEyeButton.setText("Generate Overview");
// binding.AyEyeButton.setOnClickListener(b ->{
// AIDataOverview();
// binding.AyEyeButton.setVisibility(View.GONE);
// });
// });
return binding.getRoot();
}
private void getPrompt(){
binding.AyEyeBox.setVisibility(View.VISIBLE);
String prompt = PromptCreator.genMatchPrompt(0);
binding.AyEyeBox.setText(prompt);
}
private void AIDataOverview(){
String prompt = binding.AyEyeBox.getText().toString();
binding.AyEyeBox.setText("");
OllamaClient.run(prompt, new OllamaClient.ollamaListener() {
@Override
public void onResponse(String response) {
// System.out.println(response);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
binding.AyEyeBox.setText(binding.AyEyeBox.getText()+response);
}
});
}
@Override
public void onComplete() {
System.out.println(binding.AyEyeBox.getText());
}
});
}
}
@@ -0,0 +1,82 @@
package com.ridgebotics.ridgescout.ui.data;
import static androidx.navigation.fragment.FragmentKt.findNavController;
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
import static com.ridgebotics.ridgescout.utility.DataManager.event;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.ridgebotics.ridgescout.R;
import com.ridgebotics.ridgescout.databinding.FragmentDataReportSelectorBinding;
import com.ridgebotics.ridgescout.types.frcMatch;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.DataManager;
import com.ridgebotics.ridgescout.utility.settingsManager;
public class ReportSelectorFragment extends Fragment {
FragmentDataReportSelectorBinding binding;
private final int teamNum = settingsManager.getTeamNum();
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentDataReportSelectorBinding.inflate(inflater, container, false);
binding.matchTable.setStretchAllColumns(true);
DataManager.reload_event();
frcMatch[] teamMatches = event.getTeamMatches(teamNum);
if(teamMatches.length == 0){
AlertManager.error("Team number " + teamNum + " could not be found in event " + evcode);
findNavController(this).navigate(R.id.action_navigation_data_report_selector_to_navigation_data);
}
for(int i = 0; i < teamMatches.length; i++){
addTableRow(teamMatches[i]);
}
return binding.getRoot();
}
@SuppressLint("SetTextI18n")
private void addTableRow(frcMatch match){
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);
tr.setBackgroundColor(0x5000ff00);
binding.matchTable.addView(tr);
TextView tv = new TextView(getContext());
tv.setText("Match " + match.matchIndex);
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
tr.addView(tv);
tv = new TextView(getContext());
tv.setText("Pos " + match.getTeamAlliance(teamNum));
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
tr.addView(tv);
tr.setOnClickListener(v -> {
ReportFragment.setMatch(match);
findNavController(this).navigate(R.id.action_navigation_data_report_selector_to_navigation_data_report);
});
}
}
@@ -1,12 +1,12 @@
package com.astatin3.scoutingapp2025.ui.data;
package com.ridgebotics.ridgescout.ui.data;
import static com.astatin3.scoutingapp2025.utility.DataManager.evcode;
import static com.astatin3.scoutingapp2025.utility.DataManager.match_latest_values;
import static com.astatin3.scoutingapp2025.utility.DataManager.match_transferValues;
import static com.astatin3.scoutingapp2025.utility.DataManager.match_values;
import static com.astatin3.scoutingapp2025.utility.DataManager.pit_latest_values;
import static com.astatin3.scoutingapp2025.utility.DataManager.pit_transferValues;
import static com.astatin3.scoutingapp2025.utility.DataManager.pit_values;
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
import static com.ridgebotics.ridgescout.utility.DataManager.match_latest_values;
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_latest_values;
import static com.ridgebotics.ridgescout.utility.DataManager.pit_transferValues;
import static com.ridgebotics.ridgescout.utility.DataManager.pit_values;
import android.os.Bundle;
import android.view.Gravity;
@@ -22,13 +22,14 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.SettingsVersionStack.latestSettings;
import com.astatin3.scoutingapp2025.databinding.FragmentDataTeamsBinding;
import com.astatin3.scoutingapp2025.scoutingData.ScoutingDataWriter;
import com.astatin3.scoutingapp2025.types.data.dataType;
import com.astatin3.scoutingapp2025.types.frcTeam;
import com.astatin3.scoutingapp2025.utility.DataManager;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.settingsManager;
import com.ridgebotics.ridgescout.databinding.FragmentDataTeamsBinding;
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
import com.ridgebotics.ridgescout.types.data.dataType;
import com.ridgebotics.ridgescout.types.frcTeam;
import com.ridgebotics.ridgescout.utility.DataManager;
import com.ridgebotics.ridgescout.utility.fileEditor;
import com.google.android.material.divider.MaterialDivider;
import com.skydoves.powerspinner.IconSpinnerAdapter;
import com.skydoves.powerspinner.IconSpinnerItem;
@@ -64,7 +65,7 @@ public class TeamsFragment extends Fragment {
table.setStretchAllColumns(true);
binding.teamsArea.addView(table);
loadTeam(latestSettings.settings.get_data_view_mode());
loadTeam(settingsManager.getDataMode());
return binding.getRoot();
}
@@ -114,7 +115,7 @@ public class TeamsFragment extends Fragment {
public void onItemSelected(int oldIndex, @Nullable IconSpinnerItem oldItem, int newIndex,
IconSpinnerItem newItem) {
latestSettings.settings.set_data_view_mode(newIndex);
settingsManager.setDataMode(newIndex);
loadTeam(newIndex);
}
});
@@ -282,41 +283,46 @@ public class TeamsFragment extends Fragment {
public void add_individual_views(LinearLayout ll, String[] files) {
for (int i = 0; i < files.length; i++) {
String[] split = files[i].split("-");
int match_num = Integer.parseInt(split[1]);
try {
String[] split = files[i].split("-");
int match_num = Integer.parseInt(split[1]);
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[i], match_values, match_transferValues);
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[i], match_values, match_transferValues);
TextView tv = new TextView(getContext());
tv.setLayoutParams(new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
));
tv.setPadding(0, 40, 0, 5);
tv.setGravity(Gravity.CENTER_HORIZONTAL);
tv.setText("M" + (match_num) + " " + split[2] + "-" + split[3] + " by " + psda.username);
tv.setTextSize(30);
ll.addView(tv);
for (int a = 0; a < psda.data.array.length; a++) {
tv = new TextView(getContext());
TextView tv = new TextView(getContext());
tv.setLayoutParams(new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
));
tv.setPadding(0, 40, 0, 5);
tv.setGravity(Gravity.CENTER_HORIZONTAL);
tv.setText(psda.data.array[a].getName());
tv.setTextSize(25);
if (psda.data.array[a].isNull()) {
tv.setBackgroundColor(0xffff0000);
tv.setTextColor(0xff000000);
}
tv.setText("M" + (match_num) + " " + split[2] + "-" + split[3] + " by " + psda.username);
tv.setTextSize(30);
ll.addView(tv);
for (int a = 0; a < psda.data.array.length; a++) {
tv = new TextView(getContext());
tv.setLayoutParams(new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
));
tv.setGravity(Gravity.CENTER_HORIZONTAL);
tv.setText(psda.data.array[a].getName());
tv.setTextSize(25);
match_latest_values[a].add_individual_view(ll, psda.data.array[a]);
if (psda.data.array[a].isNull()) {
tv.setBackgroundColor(0xffff0000);
tv.setTextColor(0xff000000);
}
ll.addView(tv);
match_latest_values[a].add_individual_view(ll, psda.data.array[a]);
}
}catch (Exception e){
e.printStackTrace();
AlertManager.alert("Warning!", "Failure to load file " + files[i]);
}
}
}
@@ -329,10 +335,14 @@ public class TeamsFragment extends Fragment {
public void add_compiled_views(LinearLayout ll, String[] files){
dataType[][] data = new dataType[match_latest_values.length][files.length];
for (int i = 0; i < files.length; i++) {
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[i], match_values, match_transferValues);
for (int a = 0; a < data.length; a++) {
data[a][i] = psda.data.array[a];
try {
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[i], match_values, match_transferValues);
for (int a = 0; a < data.length; a++) {
data[a][i] = psda.data.array[a];
}
} catch (Exception e){
e.printStackTrace();
AlertManager.alert("Warning!", "Failure to load file " + files[i]);
}
}
@@ -359,10 +369,14 @@ public class TeamsFragment extends Fragment {
public void add_history_views(LinearLayout ll, String[] files){
dataType[][] data = new dataType[match_latest_values.length][files.length];
for (int i = 0; i < files.length; i++) {
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[i], match_values, match_transferValues);
for (int a = 0; a < data.length; a++) {
data[a][i] = psda.data.array[a];
try {
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[i], match_values, match_transferValues);
for (int a = 0; a < data.length; a++) {
data[a][i] = psda.data.array[a];
}
}catch (Exception e){
e.printStackTrace();
AlertManager.alert("Warning!", "Failure to load file " + files[i]);
}
}
@@ -0,0 +1,115 @@
package com.ridgebotics.ridgescout.ui.scouting;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.ridgebotics.ridgescout.R;
public class FieldPosView extends FrameLayout {
private int x = -1;
private int y = -1;
private Paint paint;
private static final float POINT_RADIUS = 10f;
private ImageView imageView;
private boolean enabled = true;
public interface onTapListener {
void onUpdate(int[] pos);
};
public FieldPosView(Context context) {
super(context);
init(context, pos -> {});
}
public FieldPosView(Context context, onTapListener tapListener) {
super(context);
init(context, tapListener);
}
public FieldPosView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, pos -> {});
}
@SuppressLint("ClickableViewAccessibility")
private void init(Context context, onTapListener tl) {
// Initialize paint
paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
// Create and add ImageView
imageView = new ImageView(context);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT
);
imageView.setLayoutParams(params);
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
imageView.setAdjustViewBounds(true);
addView(imageView);
// Set touch listener
setOnTouchListener((v, event) -> {
if (enabled && event.getAction() == MotionEvent.ACTION_DOWN) {
x = (int) ((event.getX()/getWidth())*255);
y = (int) ((event.getY()/getHeight())*255);
tl.onUpdate(getPos());
invalidate();
return true;
}
return false;
});
setImageResource(R.drawable.field_2024);
}
public void setPos(int[] pos){
if(pos.length == 0) return;
x = pos[0];
y = pos[1];
invalidate();
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (x >= 0 && y >= 0) {
canvas.drawCircle(
((float) x /255)*getWidth(),
((float) y /255)*getHeight(),
POINT_RADIUS, paint);
}
}
public void setImageResource(int resId) {
imageView.setImageResource(resId);
}
public void setImageDrawable(Drawable drawable) {
imageView.setImageDrawable(drawable);
}
public void setImageBitmap(Bitmap bitmap) {
imageView.setImageBitmap(bitmap);
}
public int[] getPos() {
return new int[]{
x,
y
};
}
}
@@ -1,12 +1,11 @@
package com.astatin3.scoutingapp2025.ui.scouting;
package com.ridgebotics.ridgescout.ui.scouting;
import static com.astatin3.scoutingapp2025.utility.DataManager.evcode;
import static com.astatin3.scoutingapp2025.utility.DataManager.event;
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
import static com.ridgebotics.ridgescout.utility.DataManager.event;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
@@ -15,17 +14,17 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.SettingsVersionStack.latestSettings;
import com.astatin3.scoutingapp2025.databinding.FragmentScoutingMatchBinding;
import com.astatin3.scoutingapp2025.scoutingData.ScoutingDataWriter;
import com.astatin3.scoutingapp2025.types.data.dataType;
import com.astatin3.scoutingapp2025.types.frcMatch;
import com.astatin3.scoutingapp2025.types.frcTeam;
import com.astatin3.scoutingapp2025.types.input.inputType;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.AutoSaveManager;
import com.astatin3.scoutingapp2025.utility.DataManager;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.ridgebotics.ridgescout.utility.settingsManager;
import com.ridgebotics.ridgescout.databinding.FragmentScoutingMatchBinding;
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
import com.ridgebotics.ridgescout.types.data.dataType;
import com.ridgebotics.ridgescout.types.frcMatch;
import com.ridgebotics.ridgescout.types.frcTeam;
import com.ridgebotics.ridgescout.types.input.inputType;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.AutoSaveManager;
import com.ridgebotics.ridgescout.utility.DataManager;
import com.ridgebotics.ridgescout.utility.fileEditor;
import java.util.ArrayList;
import java.util.function.Function;
@@ -42,8 +41,8 @@ public class MatchScoutingFragment extends Fragment {
DataManager.reload_match_fields();
alliance_position = latestSettings.settings.get_alliance_pos();
username = latestSettings.settings.get_username();
alliance_position = settingsManager.getAllyPos();
username = settingsManager.getUsername();
binding.username.setText(username);
binding.alliancePosText.setText(alliance_position);
@@ -65,12 +64,12 @@ public class MatchScoutingFragment extends Fragment {
cur_match_num = latestSettings.settings.get_match_num();
cur_match_num = settingsManager.getMatchNum();
update_match_num();
binding.nextButton.setOnClickListener(v -> {
if(edited) save();
latestSettings.settings.set_match_num(cur_match_num+1);
settingsManager.setMatchNum(cur_match_num+1);
cur_match_num += 1;
update_match_num();
update_scouting_data();
@@ -84,7 +83,7 @@ public class MatchScoutingFragment extends Fragment {
if(edited) save();
alliance_position = incrementMatchPos(alliance_position);
latestSettings.settings.set_alliance_pos(alliance_position);
settingsManager.setAllyPos(alliance_position);
binding.alliancePosText.setText(alliance_position);
update_match_num();
@@ -94,7 +93,7 @@ public class MatchScoutingFragment extends Fragment {
binding.backButton.setOnClickListener(v -> {
if(edited) save();
latestSettings.settings.set_match_num(cur_match_num-1);
settingsManager.setMatchNum(cur_match_num-1);
cur_match_num -= 1;
update_match_num();
update_scouting_data();
@@ -311,8 +310,14 @@ public class MatchScoutingFragment extends Fragment {
default_fields();
set_indicator_color(unsaved_color);
}else{
get_fields();
set_indicator_color(saved_color);
try {
get_fields();
set_indicator_color(saved_color);
} catch (Exception e){
AlertManager.error(e);
default_fields();
set_indicator_color(unsaved_color);
}
}
asm.start();
@@ -0,0 +1,86 @@
package com.ridgebotics.ridgescout.ui.scouting;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.ridgebotics.ridgescout.R;
import java.util.ArrayList;
import java.util.List;
public class MultiFieldPosView extends FrameLayout {
private Paint paint;
private static final float POINT_RADIUS = 10f;
private ImageView imageView;
private List<Integer[]> points = new ArrayList<>();
public MultiFieldPosView(Context context) {
super(context);
init(context);
}
public MultiFieldPosView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
@SuppressLint("ClickableViewAccessibility")
private void init(Context context) {
// Initialize paint
paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
// Create and add ImageView
imageView = new ImageView(context);
LayoutParams params = new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT
);
imageView.setLayoutParams(params);
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
imageView.setAdjustViewBounds(true);
addView(imageView);
setImageResource(R.drawable.field_2024);
}
public void addPos(int[] pos){
if(pos.length != 2) return;
points.add(new Integer[]{
pos[0],
pos[1]
});
invalidate();
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
for(int i = 0; i < points.size(); i++){
int x = points.get(i)[0];
int y = points.get(i)[1];
if (x >= 0 && y >= 0) {
canvas.drawCircle(
((float) x / 255) * getWidth(),
((float) y / 255) * getHeight(),
POINT_RADIUS, paint);
}
}
}
public void setImageResource(int resId) {
imageView.setImageResource(resId);
}
}
@@ -1,9 +1,9 @@
package com.astatin3.scoutingapp2025.ui.scouting;
package com.ridgebotics.ridgescout.ui.scouting;
import static com.astatin3.scoutingapp2025.utility.DataManager.evcode;
import static com.astatin3.scoutingapp2025.utility.DataManager.pit_latest_values;
import static com.astatin3.scoutingapp2025.utility.DataManager.pit_transferValues;
import static com.astatin3.scoutingapp2025.utility.DataManager.pit_values;
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
import static com.ridgebotics.ridgescout.utility.DataManager.pit_latest_values;
import static com.ridgebotics.ridgescout.utility.DataManager.pit_transferValues;
import static com.ridgebotics.ridgescout.utility.DataManager.pit_values;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -15,15 +15,16 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.SettingsVersionStack.latestSettings;
import com.astatin3.scoutingapp2025.databinding.FragmentScoutingPitBinding;
import com.astatin3.scoutingapp2025.scoutingData.ScoutingDataWriter;
import com.astatin3.scoutingapp2025.types.data.dataType;
import com.astatin3.scoutingapp2025.types.frcTeam;
import com.astatin3.scoutingapp2025.types.input.inputType;
import com.astatin3.scoutingapp2025.utility.AutoSaveManager;
import com.astatin3.scoutingapp2025.utility.DataManager;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.settingsManager;
import com.ridgebotics.ridgescout.databinding.FragmentScoutingPitBinding;
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
import com.ridgebotics.ridgescout.types.data.dataType;
import com.ridgebotics.ridgescout.types.frcTeam;
import com.ridgebotics.ridgescout.types.input.inputType;
import com.ridgebotics.ridgescout.utility.AutoSaveManager;
import com.ridgebotics.ridgescout.utility.DataManager;
import com.ridgebotics.ridgescout.utility.fileEditor;
import java.util.ArrayList;
import java.util.function.Function;
@@ -43,7 +44,7 @@ public class PitScoutingFragment extends Fragment {
binding = FragmentScoutingPitBinding.inflate(inflater, container, false);
username = latestSettings.settings.get_username();
username = settingsManager.getUsername();
DataManager.reload_pit_fields();
loadTeam();
@@ -74,9 +75,10 @@ public class PitScoutingFragment extends Fragment {
types[i] = pit_latest_values[i].getViewValue();
}
if(ScoutingDataWriter.save(pit_values.length-1, username, filename, types))
if(ScoutingDataWriter.save(pit_values.length-1, username, filename, types)) {
System.out.println("Saved!");
else
AlertManager.toast("Saved " + filename);
}else
System.out.println("Error saving");
}
@@ -92,50 +94,6 @@ public class PitScoutingFragment extends Fragment {
}
// public void init(frcEvent event){
//
// evcode = event.eventCode;
// this.event = event;
// 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 = transferType.get_transfer_values(values);
// }
//
// 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 loadTeam(){
// clear_fields();
@@ -147,9 +105,6 @@ public class PitScoutingFragment extends Fragment {
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);
@@ -164,8 +119,14 @@ public class PitScoutingFragment extends Fragment {
default_fields();
set_indicator_color(unsaved_color);
}else{
get_fields();
set_indicator_color(saved_color);
try {
get_fields();
set_indicator_color(saved_color);
} catch (Exception e){
AlertManager.error(e);
default_fields();
set_indicator_color(unsaved_color);
}
}
asm.start();
@@ -195,11 +156,7 @@ public class PitScoutingFragment extends Fragment {
int fi = i;
tv.setOnClickListener(p -> {
// boolean blank = !latest_values[fi].getViewValue().isNull();
// System.out.println(blank);
asm.update();
update_asm();
if(!pit_latest_values[fi].isBlank){
tv.setBackgroundColor(0xffff0000);
@@ -1,8 +1,8 @@
package com.astatin3.scoutingapp2025.ui.scouting;
package com.ridgebotics.ridgescout.ui.scouting;
import static androidx.navigation.fragment.FragmentKt.findNavController;
import static com.astatin3.scoutingapp2025.utility.DataManager.event;
import static com.ridgebotics.ridgescout.utility.DataManager.event;
import android.os.Bundle;
import android.view.KeyEvent;
@@ -15,12 +15,12 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.R;
import com.astatin3.scoutingapp2025.SettingsVersionStack.latestSettings;
import com.astatin3.scoutingapp2025.databinding.FragmentScoutingBinding;
import com.astatin3.scoutingapp2025.types.frcTeam;
import com.astatin3.scoutingapp2025.ui.TeamSelectorFragment;
import com.astatin3.scoutingapp2025.utility.DataManager;
import com.ridgebotics.ridgescout.R;
import com.ridgebotics.ridgescout.utility.settingsManager;
import com.ridgebotics.ridgescout.databinding.FragmentScoutingBinding;
import com.ridgebotics.ridgescout.types.frcTeam;
import com.ridgebotics.ridgescout.ui.TeamSelectorFragment;
import com.ridgebotics.ridgescout.utility.DataManager;
public class ScoutingFragment extends Fragment {
@@ -34,11 +34,13 @@ public class ScoutingFragment extends Fragment {
binding.buttons.setVisibility(View.VISIBLE);
String evcode = latestSettings.settings.get_evcode();
String evcode = settingsManager.getEVCode();
if(evcode.equals("unset")){
binding.noEventError.setVisibility(View.VISIBLE);
binding.buttons.setVisibility(View.GONE);
binding.matchScoutingButton.setEnabled(false);
binding.pitScoutingButton.setEnabled(false);
binding.statusButton.setEnabled(false);
is_main_page = false;
return binding.getRoot();
}
@@ -1,6 +1,6 @@
package com.astatin3.scoutingapp2025.ui.scouting;
package com.ridgebotics.ridgescout.ui.scouting;
import static com.astatin3.scoutingapp2025.utility.DataManager.event;
import static com.ridgebotics.ridgescout.utility.DataManager.event;
import android.os.Bundle;
import android.view.Gravity;
@@ -14,11 +14,11 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.databinding.FragmentScoutingStatusBinding;
import com.astatin3.scoutingapp2025.utility.DataManager;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.astatin3.scoutingapp2025.types.frcEvent;
import com.astatin3.scoutingapp2025.types.frcMatch;
import com.ridgebotics.ridgescout.databinding.FragmentScoutingStatusBinding;
import com.ridgebotics.ridgescout.utility.DataManager;
import com.ridgebotics.ridgescout.utility.fileEditor;
import com.ridgebotics.ridgescout.types.frcEvent;
import com.ridgebotics.ridgescout.types.frcMatch;
import java.util.Arrays;
@@ -40,6 +40,7 @@ public class StatusFragment extends Fragment {
}
public static int color_found = 0x7f00ff00;
public static int color_not_found = 0x7f7f0000;
private void addTableText(TableRow tr, String textStr){
TextView text = new TextView(getContext());
text.setTextSize(18);
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.ui.scouting;
package com.ridgebotics.ridgescout.ui.scouting;
import android.content.Context;
import android.util.AttributeSet;
@@ -7,7 +7,7 @@ import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.astatin3.scoutingapp2025.R;
import com.ridgebotics.ridgescout.R;
public class TallyCounterView extends LinearLayout {
private int count = 0;
@@ -0,0 +1,256 @@
package com.ridgebotics.ridgescout.ui.settings;
import static android.text.InputType.TYPE_CLASS_NUMBER;
import static com.ridgebotics.ridgescout.utility.settingsManager.AllyPosKey;
import static com.ridgebotics.ridgescout.utility.settingsManager.FTPEnabled;
import static com.ridgebotics.ridgescout.utility.settingsManager.FTPServer;
import static com.ridgebotics.ridgescout.utility.settingsManager.SelEVCodeKey;
import static com.ridgebotics.ridgescout.utility.settingsManager.TeamNumKey;
import static com.ridgebotics.ridgescout.utility.settingsManager.UnameKey;
import static com.ridgebotics.ridgescout.utility.settingsManager.WifiModeKey;
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.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TableRow;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.google.android.material.divider.MaterialDivider;
import com.ridgebotics.ridgescout.databinding.FragmentSettingsBinding;
import com.ridgebotics.ridgescout.types.data.intType;
import com.ridgebotics.ridgescout.utility.fileEditor;
import com.ridgebotics.ridgescout.utility.settingsManager;
import com.skydoves.powerspinner.IconSpinnerAdapter;
import com.skydoves.powerspinner.IconSpinnerItem;
import com.skydoves.powerspinner.OnSpinnerItemSelectedListener;
import com.skydoves.powerspinner.PowerSpinnerView;
import com.skydoves.powerspinner.SpinnerGravity;
import org.checkerframework.checker.units.qual.C;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class settingsFragment extends Fragment {
private FragmentSettingsBinding binding;
private android.widget.ScrollView ScrollArea;
private android.widget.TableLayout Table;
// private void setDropdownItems(Spinner dropdown, String[] items){
// ArrayAdapter<String> adapter = new ArrayAdapter<>(requireActivity(), android.R.layout.simple_spinner_item, items);
// dropdown.setAdapter(adapter);
// }
private View[] concatArrays(View[] a, View[] b){
return Stream.of(a, b).flatMap(Stream::of).toArray(View[]::new);
}
private View[] addViews(View[] a){
for(int i = 0; i < a.length; i++){
binding.SettingsTable.addView(a[i]);
}
return a;
}
private int safeToInt(String num){
if(num.isEmpty())
return 0;
try {
return Integer.parseInt(num);
}catch (NumberFormatException e){
return 0;
}
}
private View[] createHeading(String name){
TextView tv = new TextView(getContext());
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
TableRow.LayoutParams params = new TableRow.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
params.topMargin = 100;
tv.setLayoutParams(params);
tv.setTextSize(20);
tv.setText(name);
View divider = new MaterialDivider(getContext());
return new View[]{tv, divider};
}
private View[] addStringEdit(String name, String key){
View[] heading = createHeading(name);
EditText et = new EditText(getContext());
et.setText(prefs.getString(key, (String) defaults.get(key)));
et.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
getEditor().putString(key, s.toString()).apply();
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count) {}
});
return concatArrays(heading, new View[]{et});
}
private View[] addNumberEdit(String name, String key){
View[] heading = createHeading(name);
EditText et = new EditText(getContext());
et.setText(String.valueOf(prefs.getInt(key, (Integer) defaults.get(key))));
et.setInputType(TYPE_CLASS_NUMBER);
et.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
getEditor().putInt(key, safeToInt(s.toString())).apply();
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count) {}
});
return concatArrays(heading, new View[]{et});
}
private PowerSpinnerView addDropdownEdit(String name, String[] options, String key){
PowerSpinnerView dropdown = new PowerSpinnerView(getContext());
List<IconSpinnerItem> iconSpinnerItems = new ArrayList<>();
for(int i = 0; i < options.length; i++){
iconSpinnerItems.add(new IconSpinnerItem(options[i]));
}
IconSpinnerAdapter iconSpinnerAdapter = new IconSpinnerAdapter(dropdown);
dropdown.setGravity(Gravity.CENTER);
dropdown.setSpinnerAdapter(iconSpinnerAdapter);
dropdown.setItems(iconSpinnerItems);
dropdown.setHint("Unselected");
dropdown.setPadding(10,20,10,20);
dropdown.setBackgroundColor(0xf0000000);
dropdown.setTextColor(0xff00ff00);
dropdown.setTextSize(14.5f);
dropdown.setArrowGravity(SpinnerGravity.END);
dropdown.setArrowPadding(8);
dropdown.setSpinnerPopupElevation(14);
return dropdown;
}
private View[] addDropdownByString(String name, String[] options, String key){
View[] heading = createHeading(name);
PowerSpinnerView dropdown = addDropdownEdit(name, options, key);
int index = Arrays.asList(options).indexOf(prefs.getString(key, (String) defaults.get(key)));
System.out.println(index);
if(options.length != 0 && index != -1){
dropdown.selectItemByIndex(index);
}
dropdown.setOnSpinnerItemSelectedListener(
(OnSpinnerItemSelectedListener<IconSpinnerItem>)
(oldIndex, oldItem, newIndex, newItem) -> getEditor().putString(key, newItem.getText().toString()).apply()
);
return concatArrays(heading, new View[]{dropdown});
}
private View[] addDropdownByIndex(String name, String[] options, String key){
View[] heading = createHeading(name);
PowerSpinnerView dropdown = addDropdownEdit(name, options, key);
int index = prefs.getInt(key, (Integer) defaults.get(key));
if(dropdown.length() != 0 && index != -1){
dropdown.selectItemByIndex(index);
}
dropdown.setOnSpinnerItemSelectedListener(
(OnSpinnerItemSelectedListener<IconSpinnerItem>)
(oldIndex, oldItem, newIndex, newItem) -> getEditor().putInt(key, newIndex).apply()
);
return concatArrays(heading, new View[]{dropdown});
}
private View[] addCheckbox(String name, String key, View[] dependency){
CheckBox cb = new CheckBox(getContext());
cb.setText(name);
cb.setTextSize(22);
boolean checked = prefs.getBoolean(key, (Boolean) defaults.get(key));
cb.setChecked(checked);
if(dependency != null && !checked){
for(int i = 0; i < dependency.length; i++){
dependency[i].setVisibility(View.GONE);
}
}
cb.setOnCheckedChangeListener((buttonView, isChecked) -> {
getEditor().putBoolean(key, isChecked).apply();
if(dependency != null){
for(int i = 0; i < dependency.length; i++){
dependency[i].setVisibility(isChecked ? View.VISIBLE : View.GONE);
System.out.println(dependency[i]);
}
}
});
return new View[]{new MaterialDivider(getContext()), cb};
}
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
binding = FragmentSettingsBinding.inflate(inflater, container, false);
View root = binding.getRoot();
String[] alliance_pos_list = new String[]{"red-1", "red-2", "red-3",
"blue-1", "blue-2", "blue-3"};
addViews(addStringEdit("Username", UnameKey));
addViews(addDropdownByString("Event Code", fileEditor.getEventList().toArray(new String[0]), SelEVCodeKey));
addViews(addDropdownByString("Alliance Position", alliance_pos_list, AllyPosKey));
addViews(addNumberEdit("Team Number", TeamNumKey));
View[] FTPDependency = addStringEdit("FTP Server", FTPServer);
View[] WifiDependency = addCheckbox("FTP Enabled", FTPEnabled, FTPDependency);
addViews(addCheckbox("Wifi Mode", WifiModeKey, concatArrays(FTPDependency, WifiDependency)));
addViews(WifiDependency);
addViews(FTPDependency);
return root;
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
@@ -1,32 +1,26 @@
package com.astatin3.scoutingapp2025.ui.transfer;
package com.ridgebotics.ridgescout.ui.transfer;
import static com.astatin3.scoutingapp2025.utility.DataManager.evcode;
import static com.astatin3.scoutingapp2025.utility.DataManager.event;
import static com.astatin3.scoutingapp2025.utility.DataManager.match_latest_values;
import static com.astatin3.scoutingapp2025.utility.DataManager.pit_latest_values;
import static com.astatin3.scoutingapp2025.utility.SharePrompt.shareContent;
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 static com.ridgebotics.ridgescout.utility.DataManager.pit_latest_values;
import static com.ridgebotics.ridgescout.utility.SharePrompt.shareContent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import androidx.core.content.FileProvider;
import com.astatin3.scoutingapp2025.scoutingData.ScoutingDataWriter;
import com.astatin3.scoutingapp2025.types.data.dataType;
import com.astatin3.scoutingapp2025.types.frcMatch;
import com.astatin3.scoutingapp2025.types.frcTeam;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.DataManager;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
import com.ridgebotics.ridgescout.types.data.dataType;
import com.ridgebotics.ridgescout.types.frcMatch;
import com.ridgebotics.ridgescout.types.frcTeam;
import com.ridgebotics.ridgescout.utility.DataManager;
import com.ridgebotics.ridgescout.utility.fileEditor;
public class CSVExport {
private static String[] alliances = {"red", "blue"};
private static String safeCSV(String input){
return input.replace("\n", "").replace(",", ".").replace(";", ".");
}
public static void exportMatches(Context c){
DataManager.reload_event();
@@ -64,10 +58,15 @@ public class CSVExport {
if(!fileEditor.fileExist(filename)){
data += ("null,".repeat(match_latest_values.length));
}else{
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.match_values, DataManager.match_transferValues);
dataType[] types = psdr.data.array;
for(int i = 0; i < types.length; i++) {
data += (types[i].get() + ",");
try {
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.match_values, DataManager.match_transferValues);
dataType[] types = psdr.data.array;
for (int i = 0; i < types.length; i++) {
data += (safeCSV(types[i].get().toString()) + ",");
}
} catch (Exception e){
e.printStackTrace();
data += ("null,".repeat(pit_latest_values.length));
}
}
@@ -86,7 +85,7 @@ public class CSVExport {
String data = "";
data += ("teamnum,teamname,city,teamnum,stateOrProv,school,country,startingYear,");
data += ("teamnum,teamname,city,stateOrProv,school,country,startingYear,");
for(int i = 0; i < pit_latest_values.length; i++){
data += (pit_latest_values[i].name + ",");
}
@@ -108,10 +107,15 @@ public class CSVExport {
if(!fileEditor.fileExist(filename)){
data += ("null,".repeat(pit_latest_values.length));
}else{
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.pit_values, DataManager.pit_transferValues);
dataType[] types = psdr.data.array;
for(int i = 0; i < types.length; i++) {
data += (types[i].get() + ",");
try {
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.pit_values, DataManager.pit_transferValues);
dataType[] types = psdr.data.array;
for (int i = 0; i < types.length; i++) {
data += (safeCSV(types[i].get().toString()) + ",");
}
} catch (Exception e){
e.printStackTrace();
data += ("null,".repeat(pit_latest_values.length));
}
}
@@ -0,0 +1,163 @@
package com.ridgebotics.ridgescout.ui.transfer;
//import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
import static com.ridgebotics.ridgescout.utility.fileEditor.baseDir;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.settingsManager;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPCmd;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class FTPSync extends Thread {
public static final String remoteBasePath = "/RidgeScout/";
public static final long timeTolerance = 60000; // One min
public static long lastSyncTime = 0;
public interface onResult {
void onResult(boolean error, int upCount, int downCount);
}
public onResult onResult;
public static void sync(onResult onResult){
// DataManager.reload_event();
FTPSync ftpSync = new FTPSync();
ftpSync.onResult = onResult;
ftpSync.start();
lastSyncTime = new Date().getTime();
}
FTPClient ftpClient;
// private class FileDate {
// public String filename;
// public Calendar lastModified;
// }
private int upCount = 0;
private int downCount = 0;
private void downloadFile(FTPFile remoteFile, File localFile) throws IOException {
try (FileOutputStream fos = new FileOutputStream(localFile)) {
ftpClient.retrieveFile(remoteBasePath + remoteFile.getName(), fos);
}
Date d = getUtcTimestamp(remoteFile);
System.out.println(d);
setLocalFileTimestamp(localFile, d);
}
private void uploadFile(File localFile) throws IOException {
try (FileInputStream fis = new FileInputStream(localFile)) {
ftpClient.storeFile(remoteBasePath + localFile.getName(), fis);
}
setLocalFileTimestamp(localFile, new Date());
}
private FTPFile findRemoteFile(FTPFile[] remoteFiles, String fileName) {
for (FTPFile file : remoteFiles) {
if (file.getName().equals(fileName)) {
return file;
}
}
return null;
}
private Date getUtcTimestamp(FTPFile file) {
return file.getTimestamp().getTime();
}
private Date getLocalFileUtcTimestamp(File file) {
return new Date(file.lastModified());
}
private void setLocalFileTimestamp(File file, Date date) {
file.setLastModified(date.getTime());
}
// private long longAbs(long n){
// return n>0 ? n : -n;
// }
private boolean toleranceCompareAfter(Date d1, Date d2){
long diff = d1.getTime() - d2.getTime();
System.out.println(diff);
return diff > timeTolerance;
}
public void run() {
try {
// localTimeZone = TimeZone.getDefault();
ftpClient = new FTPClient();
InetAddress address = InetAddress.getByName(settingsManager.getFTPServer());
ftpClient.connect(address);
ftpClient.login("anonymous", null);
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
File localDir = new File(baseDir);
File[] localFiles = localDir.listFiles();
FTPFile[] remoteFiles = ftpClient.listFiles(remoteBasePath);
if (localFiles != null) {
for (File localFile : localFiles) {
if (localFile.isFile()) {
FTPFile remoteFile = findRemoteFile(remoteFiles, localFile.getName());
//
// Date t1 = getLocalFileUtcTimestamp(localFile);
// Date t2 = getUtcTimestamp(remoteFile);
////
// System.out.println("- " + t1.getTime() + (t1.after(t2) ? ">" : "<") + t2.getTime());
if (remoteFile == null || toleranceCompareAfter(getLocalFileUtcTimestamp(localFile), (getUtcTimestamp(remoteFile)))) {
uploadFile(localFile);
System.out.println("Uploaded " + localFile.getName());
upCount++;
}else{
System.out.println("Did not upload " + localFile.getName());
}
}
}
}
for (FTPFile remoteFile : remoteFiles) {
if (!remoteFile.isDirectory()) {
File localFile = new File(baseDir, remoteFile.getName());
// Date t1 = getLocalFileUtcTimestamp(localFile);
// Date t2 = getUtcTimestamp(remoteFile);
////
// System.out.println("- " + t1 + (t1.after(t2) ? ">" : "<") + t2);
if (!localFile.exists() || toleranceCompareAfter(getUtcTimestamp(remoteFile), (getLocalFileUtcTimestamp(localFile)))) {
downloadFile(remoteFile, localFile);
System.out.println("Downloaded " + localFile.getName());
downCount++;
}else{
System.out.println("Did not download " + remoteFile.getName());
}
}
}
} catch (Exception e) {
AlertManager.error(e);
onResult.onResult(true, upCount, downCount);
} finally {
onResult.onResult(false, upCount, downCount);
}
}
}
@@ -1,18 +1,18 @@
package com.astatin3.scoutingapp2025.ui.transfer;
package com.ridgebotics.ridgescout.ui.transfer;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import com.astatin3.scoutingapp2025.MainActivity;
import com.astatin3.scoutingapp2025.types.file;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.BuiltByteParser;
import com.astatin3.scoutingapp2025.utility.ByteBuilder;
import com.astatin3.scoutingapp2025.utility.DataManager;
import com.astatin3.scoutingapp2025.utility.SharePrompt;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.ridgebotics.ridgescout.MainActivity;
import com.ridgebotics.ridgescout.types.file;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.ByteBuilder;
import com.ridgebotics.ridgescout.utility.DataManager;
import com.ridgebotics.ridgescout.utility.SharePrompt;
import com.ridgebotics.ridgescout.utility.fileEditor;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -1,6 +1,6 @@
package com.astatin3.scoutingapp2025.ui.transfer;
package com.ridgebotics.ridgescout.ui.transfer;
import static com.astatin3.scoutingapp2025.utility.DataManager.evcode;
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -15,11 +15,11 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.databinding.FragmentTransferFileSelectorBinding;
import com.astatin3.scoutingapp2025.types.file;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.ByteBuilder;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.ridgebotics.ridgescout.databinding.FragmentTransferFileSelectorBinding;
import com.ridgebotics.ridgescout.types.file;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.ByteBuilder;
import com.ridgebotics.ridgescout.utility.fileEditor;
import java.util.ArrayList;
import java.util.Arrays;
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.ui.transfer;
package com.ridgebotics.ridgescout.ui.transfer;
import android.os.Bundle;
import android.view.Gravity;
@@ -14,14 +14,14 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.databinding.FragmentTransferTbaBinding;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.RequestTask;
import com.astatin3.scoutingapp2025.types.frcEvent;
import com.astatin3.scoutingapp2025.types.frcMatch;
import com.astatin3.scoutingapp2025.types.frcTeam;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.astatin3.scoutingapp2025.utility.JSONUtil;
import com.ridgebotics.ridgescout.databinding.FragmentTransferTbaBinding;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.RequestTask;
import com.ridgebotics.ridgescout.types.frcEvent;
import com.ridgebotics.ridgescout.types.frcMatch;
import com.ridgebotics.ridgescout.types.frcTeam;
import com.ridgebotics.ridgescout.utility.fileEditor;
import com.ridgebotics.ridgescout.utility.JSONUtil;
import org.json.JSONArray;
import org.json.JSONException;
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.ui.transfer;
package com.ridgebotics.ridgescout.ui.transfer;
import static androidx.navigation.fragment.FragmentKt.findNavController;
@@ -13,11 +13,14 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.R;
import com.astatin3.scoutingapp2025.SettingsVersionStack.latestSettings;
import com.astatin3.scoutingapp2025.databinding.FragmentTransferBinding;
import com.astatin3.scoutingapp2025.ui.transfer.bluetooth.BluetoothSenderFragment;
import com.astatin3.scoutingapp2025.ui.transfer.codes.CodeGeneratorView;
import com.ridgebotics.ridgescout.R;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.settingsManager;
import com.ridgebotics.ridgescout.databinding.FragmentTransferBinding;
import com.ridgebotics.ridgescout.ui.transfer.bluetooth.BluetoothSenderFragment;
import com.ridgebotics.ridgescout.ui.transfer.codes.CodeGeneratorView;
import java.util.Date;
public class TransferFragment extends Fragment {
private FragmentTransferBinding binding;
@@ -45,7 +48,7 @@ public class TransferFragment extends Fragment {
binding = FragmentTransferBinding.inflate(inflater, container, false);
evcode = latestSettings.settings.get_evcode();
evcode = settingsManager.getEVCode();
binding.downloadButton.setOnClickListener(v -> {
start_download();
@@ -66,11 +69,31 @@ public class TransferFragment extends Fragment {
alert.create().show();
});
if(!settingsManager.getWifiMode()) {
binding.TBAButton.setEnabled(false);
binding.SyncButton.setEnabled(false);
}
if(!settingsManager.getFTPEnabled() ||
new Date().getTime()-FTPSync.lastSyncTime < FTPSync.timeTolerance) {
binding.SyncButton.setEnabled(false);
}
binding.SyncButton.setOnClickListener(v -> {
binding.SyncButton.setEnabled(false);
FTPSync.sync((error, upcount, downcount) -> getActivity().runOnUiThread(() -> {
// binding.SyncButton.setEnabled(true);
AlertManager.toast((!error ? "Synced! " : "Error Syncing. ") + upcount + " Up " + downcount + " Down");
}));
});
if(evcode.equals("unset")){
binding.noEventError.setVisibility(View.VISIBLE);
binding.uploadButton.setVisibility(View.GONE);
binding.CSVButton.setVisibility(View.GONE);
binding.downloadButton.setVisibility(View.VISIBLE);
binding.uploadButton.setEnabled(false);
binding.CSVButton.setEnabled(false);
binding.downloadButton.setEnabled(true);
return binding.getRoot();
}
@@ -106,9 +129,6 @@ public class TransferFragment extends Fragment {
builder.show();
});
if(!latestSettings.settings.get_wifi_mode())
binding.TBAButton.setVisibility(View.GONE);
return binding.getRoot();
}
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.ui.transfer;
package com.ridgebotics.ridgescout.ui.transfer;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -9,7 +9,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.databinding.FragmentTransferSelectorBinding;
import com.ridgebotics.ridgescout.databinding.FragmentTransferSelectorBinding;
public class TransferSelectorFragment extends Fragment {
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.ui.transfer.bluetooth;
package com.ridgebotics.ridgescout.ui.transfer.bluetooth;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
@@ -12,12 +12,11 @@ import android.os.Build;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.AlertManager;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
@@ -75,9 +74,9 @@ public class BluetoothReceiver {
permissionsNeeded.add(Manifest.permission.BLUETOOTH_ADMIN);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
permissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
// if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// permissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
// }
}
}
@@ -95,11 +94,11 @@ public class BluetoothReceiver {
boolean hasBasicPermissions = ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_GRANTED;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return hasBasicPermissions && ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
} else {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// return hasBasicPermissions && ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
// } else {
return hasBasicPermissions;
}
// }
}
}
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.ui.transfer.bluetooth;
package com.ridgebotics.ridgescout.ui.transfer.bluetooth;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -11,11 +11,11 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.databinding.FragmentTransferBluetoothReceiverBinding;
import com.astatin3.scoutingapp2025.types.file;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.BuiltByteParser;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.ridgebotics.ridgescout.databinding.FragmentTransferBluetoothReceiverBinding;
import com.ridgebotics.ridgescout.types.file;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.fileEditor;
import java.io.IOException;
import java.util.ArrayList;
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.ui.transfer.bluetooth;
package com.ridgebotics.ridgescout.ui.transfer.bluetooth;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
@@ -12,7 +12,7 @@ import android.os.Build;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.AlertManager;
import java.io.IOException;
import java.io.OutputStream;
@@ -70,7 +70,7 @@ public class BluetoothSender {
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
permissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
// permissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
}
}
@@ -89,11 +89,11 @@ public class BluetoothSender {
boolean hasBasicPermissions = ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_GRANTED;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return hasBasicPermissions && ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
} else {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// return hasBasicPermissions && ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
// } else {
return hasBasicPermissions;
}
// }
}
}
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.ui.transfer.bluetooth;
package com.ridgebotics.ridgescout.ui.transfer.bluetooth;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothDevice;
@@ -15,9 +15,9 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.databinding.FragmentTransferBluetoothSenderBinding;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.ridgebotics.ridgescout.databinding.FragmentTransferBluetoothSenderBinding;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.fileEditor;
import java.io.IOException;
import java.util.ArrayList;
@@ -1,11 +1,9 @@
package com.astatin3.scoutingapp2025.ui.transfer.codes;
package com.ridgebotics.ridgescout.ui.transfer.codes;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -15,12 +13,11 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.fragment.app.Fragment;
import com.astatin3.scoutingapp2025.databinding.FragmentTransferCodeSenderBinding;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.fileEditor;
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;
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.ui.transfer.codes;
package com.ridgebotics.ridgescout.ui.transfer.codes;
// From https://github.com/dlazaro66/QRCodeReaderView/blob/master/samples/src/main/java/com/example/qr_readerexample/PointsOverlayView.java
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.ui.transfer.codes;
package com.ridgebotics.ridgescout.ui.transfer.codes;
import android.graphics.Bitmap;
import android.os.AsyncTask;
@@ -1,14 +1,14 @@
package com.astatin3.scoutingapp2025.ui.transfer.codes;
package com.ridgebotics.ridgescout.ui.transfer.codes;
import static androidx.core.math.MathUtils.clamp;
import android.Manifest;
import android.app.AlertDialog;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.media.Image;
import android.os.Bundle;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Surface;
@@ -27,16 +27,17 @@ import androidx.camera.core.ImageProxy;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.LifecycleOwner;
import com.astatin3.scoutingapp2025.databinding.FragmentTransferCodeReceiverBinding;
import com.astatin3.scoutingapp2025.databinding.FragmentTransferCodeSenderBinding;
import com.astatin3.scoutingapp2025.types.file;
import com.astatin3.scoutingapp2025.utility.AlertManager;
import com.astatin3.scoutingapp2025.utility.BuiltByteParser;
import com.astatin3.scoutingapp2025.utility.fileEditor;
import com.ridgebotics.ridgescout.databinding.FragmentTransferCodeReceiverBinding;
import com.ridgebotics.ridgescout.databinding.FragmentTransferCodeSenderBinding;
import com.ridgebotics.ridgescout.types.file;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
import com.ridgebotics.ridgescout.utility.fileEditor;
import com.google.common.util.concurrent.ListenableFuture;
import java.nio.ByteBuffer;
@@ -152,6 +153,9 @@ public class CodeScannerView extends Fragment {
this.lifecycle = getViewLifecycleOwner();
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.CAMERA}, 1);
}
uiHandler = new Handler();
@@ -1,9 +1,8 @@
package com.astatin3.scoutingapp2025.utility;
package com.ridgebotics.ridgescout.utility;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.os.Looper;
import android.widget.Toast;
import java.io.PrintWriter;
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.utility;
package com.ridgebotics.ridgescout.utility;
import android.os.Handler;
import android.os.Looper;
@@ -1,7 +1,8 @@
package com.astatin3.scoutingapp2025.utility;
package com.ridgebotics.ridgescout.utility;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
public class BuiltByteParser {
public static final Integer boolType = 0;
@@ -121,6 +122,7 @@ public class BuiltByteParser {
intArrayObject ia = new intArrayObject();
ia.arr = intArr;
System.out.println(Arrays.toString(intArr));
objects.add(ia);
break;
case 4:
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.utility;
package com.ridgebotics.ridgescout.utility;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -1,10 +1,9 @@
package com.astatin3.scoutingapp2025.utility;
package com.ridgebotics.ridgescout.utility;
import com.astatin3.scoutingapp2025.SettingsVersionStack.latestSettings;
import com.astatin3.scoutingapp2025.scoutingData.fields;
import com.astatin3.scoutingapp2025.scoutingData.transfer.transferType;
import com.astatin3.scoutingapp2025.types.frcEvent;
import com.astatin3.scoutingapp2025.types.input.inputType;
import com.ridgebotics.ridgescout.scoutingData.fields;
import com.ridgebotics.ridgescout.scoutingData.transfer.transferType;
import com.ridgebotics.ridgescout.types.frcEvent;
import com.ridgebotics.ridgescout.types.input.inputType;
public class DataManager {
public static String evcode;
@@ -15,7 +14,7 @@ public class DataManager {
}
public static String getevcode() {
return latestSettings.settings.get_evcode();
return settingsManager.getEVCode();
}
public static inputType[][] match_values;
@@ -1,9 +1,8 @@
package com.astatin3.scoutingapp2025.utility;
package com.ridgebotics.ridgescout.utility;
import org.json.JSONArray;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.utility;
package com.ridgebotics.ridgescout.utility;
import android.content.Context;
import android.util.AttributeSet;
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.utility;
package com.ridgebotics.ridgescout.utility;
import android.os.AsyncTask;
@@ -7,7 +7,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.function.Function;
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.utility;
package com.ridgebotics.ridgescout.utility;
import android.content.Context;
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025.utility;
package com.ridgebotics.ridgescout.utility;
import android.content.Context;
import android.content.Intent;
@@ -1,11 +1,9 @@
package com.astatin3.scoutingapp2025.utility;
package com.ridgebotics.ridgescout.utility;
import android.content.Context;
import com.astatin3.scoutingapp2025.types.frcEvent;
import com.astatin3.scoutingapp2025.types.frcTeam;
import com.astatin3.scoutingapp2025.SettingsVersionStack.latestSettings;
import com.ridgebotics.ridgescout.types.frcEvent;
import com.ridgebotics.ridgescout.types.frcTeam;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
@@ -17,19 +15,25 @@ import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
public final class fileEditor {
private final static String baseDir = "/data/data/com.astatin3.scoutingapp2025/";
public final static String baseDir = "/data/data/com.ridgebotics.ridgescout/";
public static final byte internalDataVersion = 0x01;
public static final int maxCompressedBlockSize = 4096;
// private TimeZone localTimeZone = TimeZone.getDefault();
@@ -45,7 +49,6 @@ public final class fileEditor {
}
public static char byteToChar(int num){
return new String(toBytes(num, 1), StandardCharsets.ISO_8859_1).charAt(0);
}
@@ -191,7 +194,22 @@ public final class fileEditor {
// public static Calendar getLastModified(String filepath){
// File f = new File(baseDir + filepath);
// if(f.exists()){
// Calendar calendar = Calendar.getInstance();
// calendar.setTimeInMillis(f.lastModified());
// return calendar;
// }
// return null;
// }
//
// public static void setLastModified(String filepath, Calendar calendar){
// File f = new File(baseDir + filepath);
// if(f.exists()){
// f.setLastModified(calendar.getTimeInMillis());
// }
// }
@@ -200,6 +218,10 @@ public final class fileEditor {
FileOutputStream output = new FileOutputStream(baseDir + filepath);
output.write(data);
output.close();
// Date d = new Date();
new File(baseDir + filepath).setLastModified(new Date().getTime());
return true;
}
catch (IOException e) {
@@ -268,8 +290,8 @@ public final class fileEditor {
public static boolean setEvent(frcEvent event){
final String filename = (event.eventCode + ".eventdata");
if(latestSettings.settings.get_evcode().equals("unset")){
latestSettings.settings.set_evcode(event.eventCode);
if(settingsManager.getEVCode().equals("unset")){
settingsManager.setEVCode(event.eventCode);
}
return writeFile(filename, event.encode());
@@ -343,18 +365,19 @@ public final class fileEditor {
String[] filenames = outFiles.toArray(new String[0]);
Arrays.sort(filenames, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
try {
Arrays.sort(filenames, (o1, o2) -> {
try {
if(!o1.contains("-") || !o2.contains("-"))
if (!o1.contains("-") || !o2.contains("-"))
return 0;
return Integer.valueOf(o1.split("-")[1]).compareTo(Integer.valueOf(o2.split("-")[1]));
} catch (Exception e){
} catch (Exception e) {
return 0;
}
}
});
});
} catch (Exception e){
e.printStackTrace();
}
return filenames;
@@ -0,0 +1,89 @@
package com.ridgebotics.ridgescout.utility.ollama;
import androidx.annotation.NonNull;
import com.ridgebotics.ridgescout.utility.AlertManager;
//import com.ridgebotics.ridgescout.utility.ollama.types.Messages;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.OkHttpClient;
public class OllamaClient {
private static final String MODEL_KEY = "llama3";
private static final String OLLAMA_URL_KEY = "http://199.204.135.71:11434";
private static final String GENERATE_PATH = "/api/generate";
public interface ollamaListener {
void onResponse(String response);
void onComplete();
}
private static String promptToJson(String prompt){
try {
JSONObject jobj = new JSONObject();
jobj.put("model", "llama3");
jobj.put("prompt", prompt);
return jobj.toString();
} catch (JSONException e){
AlertManager.error(e);
}
return "{}";
}
public static void run(String prompt, ollamaListener listener){
// ChatRequest chatRequest = new ChatRequest(MODEL_KEY, llamaMessages.messages,true);
RequestBody body = RequestBody.create(promptToJson(prompt), MediaType.parse("application/json"));
Request request = new Request.Builder()
.url(OLLAMA_URL_KEY+GENERATE_PATH)
.post(body)
.build();
new OkHttpClient().newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
AlertManager.error(e);
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
responseStreamer(response, listener);
}
});
}
private static void responseStreamer(Response r, ollamaListener listener){
String line;
ResponseBody body = r.body();
if(body == null)
return;
try {
while ((line = body.source().readUtf8Line()) != null) {
// System.out.println(line);
JSONObject json = new JSONObject(line);
listener.onResponse(json.getString("response"));
if(json.getBoolean("done"))
listener.onComplete();
}
} catch (IOException | NumberFormatException | IllegalStateException | JSONException e) {
// addMessage(chatResponse,fullResponse.toString(),stopButton,sendButton);
AlertManager.error(e);
}
}
}
@@ -0,0 +1,152 @@
package com.ridgebotics.ridgescout.utility.ollama;
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 static com.ridgebotics.ridgescout.utility.DataManager.pit_latest_values;
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
import com.ridgebotics.ridgescout.types.data.dataType;
import com.ridgebotics.ridgescout.types.data.intType;
import com.ridgebotics.ridgescout.types.data.stringType;
import com.ridgebotics.ridgescout.types.frcMatch;
import com.ridgebotics.ridgescout.types.input.dropdownType;
import com.ridgebotics.ridgescout.types.input.inputType;
import com.ridgebotics.ridgescout.types.input.sliderType;
import com.ridgebotics.ridgescout.utility.DataManager;
import com.ridgebotics.ridgescout.utility.fileEditor;
public class PromptCreator {
private static String fieldSummary(inputType field){
String summary = field.name + ": ";
switch (field.getInputType()){
case DROPDOWN:
summary += "The index of a dropdown with the possible options: [" +String.join(", ", ((dropdownType) field).text_options) + "]";
break;
case SLIDER:
sliderType slider = (sliderType) field;
summary += "A slider with the range ["+slider.min+","+slider.max+"]";
break;
case TALLY:
summary += "A tally counter";
break;
case NOTES_INPUT:
summary += "Raw text input";
break;
}
return summary;
}
public static String genMatchPrompt(int matchIndex){
String prompt = "Below is a list of data collected from an FRC match. Generate a qualitative and concise summary of the teams listed, using both numerical and textual data collected in the summary. Additionally, rank the teams in order of their performance.\n\n";
frcMatch curmatch = event.matches.get(matchIndex);
prompt += "## Pit scouting\n"; prompt += "This is a list of the different fields that are present in the pit scouting data:\n";
for(int i = 0; i < pit_latest_values.length; i++){
prompt += (i+1) + ") " + fieldSummary(pit_latest_values[i]) + "\n";
}
prompt += ("\nData:\n");
for(int a = 0; a < 6; a++){
int teamNum = 0;
if(a < 3)
teamNum = curmatch.redAlliance[a];
else
teamNum = curmatch.blueAlliance[a-3];
prompt += "\nTeam " + teamNum + " pit scout data:\n";
String filename = evcode+"-"+teamNum+".pitscoutdata";
if (!fileEditor.fileExist(filename)) continue;
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.pit_values, DataManager.pit_transferValues);
dataType[] types = psdr.data.array;
for(int i = 0; i < types.length; i++) {
boolean isNull = true;
switch (types[i].getValueType()){
case NUM:
isNull = intType.isNull((int) types[i].get());
break;
case STRING:
isNull = stringType.isNull((String) types[i].get());
break;
}
if(isNull){
prompt += match_latest_values[i].name + ": null\n";
}else{
prompt += match_latest_values[i].name + ": " + types[i].get() + "\n";
}
}
}
prompt += "\n## Match scouting\n";
prompt += "This is a list of the different fields that are present in the match scouting data:\n";
for(int i = 0; i < match_latest_values.length; i++){
prompt += (i+1) + ") " + fieldSummary(match_latest_values[i]) + "\n";
}
prompt += ("\nData:\n");
for(int a = 0; a < 6; a++){
int teamNum = 0;
if(a < 3)
teamNum = curmatch.redAlliance[a];
else
teamNum = curmatch.blueAlliance[a-3];
prompt += "\nTeam " + teamNum + " Match scout data for match " + curmatch.matchIndex +":\n";
frcMatch[] matchNums = event.getTeamMatches(teamNum);
for(int b = 0; b < matchNums.length; b++) {
frcMatch match = matchNums[b];
String alliance = "";
int alliancePos = 0;
for(int c = 0; c < 6; c++) {
if(c<3){
if(match.redAlliance[c] != teamNum) continue;
alliance = "red";
alliancePos = c+1;
break;
}else{
if(match.blueAlliance[c-3] != teamNum) continue;
alliance = "blue";
alliancePos = c-2;
break;
}
}
String filename = evcode + "-" + match.matchIndex + "-" + alliance + "-" + alliancePos + "-" + teamNum + ".matchscoutdata";
if (!fileEditor.fileExist(filename)) continue;
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.match_values, DataManager.match_transferValues);
dataType[] types = psdr.data.array;
for (int i = 0; i < types.length; i++) {
boolean isNull = true;
switch (types[i].getValueType()){
case NUM:
isNull = intType.isNull((int) types[i].get());
break;
case STRING:
isNull = stringType.isNull((String) types[i].get());
break;
}
if(isNull){
prompt += match_latest_values[i].name + ": null\n";
}else{
prompt += match_latest_values[i].name + ": " + types[i].get() + "\n";
}
}
prompt += "\n";
}
}
return prompt;
}
}
@@ -0,0 +1,99 @@
package com.ridgebotics.ridgescout.utility;
import android.content.SharedPreferences;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class settingsManager {
public static SharedPreferences prefs;
public static SharedPreferences.Editor editor;
public static final String UnameKey = "username";
public static final String SelEVCodeKey = "selected_event_code";
public static final String WifiModeKey = "wifi_mode";
public static final String TeamNumKey = "team_num";
public static final String MatchNumKey = "match_num";
public static final String AllyPosKey = "alliance_pos";
public static final String DataModeKey = "data_view_mode";
public static final String BtUUIDKey = "bt_uuid";
public static final String FTPEnabled = "ftp_enabled";
public static final String FTPServer = "ftp_server";
public static Map defaults = getDefaults();
private static Map getDefaults(){
Map<String, Object> hm = new HashMap<>();
hm.put(UnameKey, "Username");
hm.put(SelEVCodeKey, "unset");
hm.put(WifiModeKey, false);
hm.put(TeamNumKey, 4388);
hm.put(MatchNumKey, 0);
hm.put(AllyPosKey, "red-1");
hm.put(DataModeKey, 0);
hm.put(BtUUIDKey, UUID.randomUUID().toString());
hm.put(FTPEnabled, false);
hm.put(FTPServer, "0.0.0.0");
return hm;
}
public static SharedPreferences.Editor getEditor(){
if(editor == null) editor = prefs.edit();
return editor;
}
public static void resetSettings(){
getEditor() .putString(UnameKey, (String) defaults.get( UnameKey )).apply();
getEditor() .putString(SelEVCodeKey,(String) defaults.get( SelEVCodeKey)).apply();
getEditor().putBoolean(WifiModeKey, (boolean) defaults.get( WifiModeKey )).apply();
getEditor() .putInt(TeamNumKey, (int) defaults.get( TeamNumKey )).apply();
getEditor() .putInt(MatchNumKey, (int) defaults.get( MatchNumKey )).apply();
getEditor() .putString(AllyPosKey, (String) defaults.get( AllyPosKey )).apply();
getEditor() .putInt(DataModeKey, (int) defaults.get( DataModeKey )).apply();
getEditor() .putString(BtUUIDKey, (String) defaults.get( BtUUIDKey )).apply();
getEditor().putBoolean(FTPEnabled, (boolean) defaults.get(FTPEnabled )).apply();
getEditor() .putString(FTPServer, (String) defaults.get( BtUUIDKey )).apply();
}
// IDK why I decided to format these functions like this. It looks cool though.
public static String getUsername(){return prefs.getString( UnameKey, (String) defaults.get(UnameKey));}
public static void setUsername(String str){ getEditor().putString( UnameKey,str).apply();}
public static String getEVCode(){return prefs.getString( SelEVCodeKey, (String) defaults.get(SelEVCodeKey));}
public static void setEVCode(String str){ getEditor().putString( SelEVCodeKey,str).apply();}
public static boolean getWifiMode(){return prefs.getBoolean( WifiModeKey, (boolean) defaults.get(WifiModeKey));}
public static void setWifiMode(boolean bool){getEditor().putBoolean( WifiModeKey,bool).apply();}
public static int getTeamNum(){return prefs.getInt( TeamNumKey, (int) defaults.get(TeamNumKey));}
public static void setTeamNum(int num){ getEditor().putInt( TeamNumKey,num).apply();}
public static int getMatchNum(){return prefs.getInt( MatchNumKey, (int) defaults.get(MatchNumKey));}
public static void setMatchNum(int num){ getEditor().putInt( MatchNumKey,num).apply();}
public static String getAllyPos(){return prefs.getString( AllyPosKey, (String) defaults.get(AllyPosKey));}
public static void setAllyPos(String str){ getEditor().putString( AllyPosKey,str).apply();}
public static int getDataMode(){return prefs.getInt( DataModeKey, (int) defaults.get(DataModeKey));}
public static void setDataMode(int num){ getEditor().putInt( DataModeKey,num).apply();}
public static String getBtUUID(){return prefs.getString( BtUUIDKey, (String) defaults.get(BtUUIDKey));}
public static void setBtUUID(String str){ getEditor().putString( BtUUIDKey,str).apply();}
public static boolean getFTPEnabled(){return prefs.getBoolean( FTPEnabled, (boolean) defaults.get(FTPEnabled));}
public static void setFTPEnabled(boolean bool){getEditor().putBoolean( FTPEnabled,bool).apply();}
public static String getFTPServer(){return prefs.getString( FTPServer, (String) defaults.get(FTPServer));}
public static void setFTPServer(String str){ getEditor().putString( FTPServer,str).apply();}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

@@ -101,12 +101,12 @@
android:layout_height="match_parent"
android:paddingBottom="60dp">
<com.astatin3.scoutingapp2025.utility.ReorderableTableLayout
<com.ridgebotics.ridgescout.utility.ReorderableTableLayout
android:id="@+id/fieldsArea"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.astatin3.scoutingapp2025.utility.ReorderableTableLayout>
</com.ridgebotics.ridgescout.utility.ReorderableTableLayout>
</ScrollView>
</LinearLayout>
@@ -1,18 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TBD"
android:textSize="34sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/team_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1234"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/AyEyeButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="AyEye" />
<TableLayout
android:id="@+id/teamMatchesTable"
android:layout_width="409dp"
android:layout_height="wrap_content"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:stretchColumns="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/team_number">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent" />
</TableLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@+id/team_number">
<EditText
android:id="@+id/AyEyeBox"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</EditText>
</ScrollView>
</TableLayout>
</ScrollView>
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableLayout
android:id="@+id/match_table"
android:layout_width="match_parent"
android:layout_height="match_parent">
</TableLayout>
</ScrollView>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
+4 -169
View File
@@ -7,7 +7,6 @@
tools:context=".ui.settings.settingsFragment">
<ScrollView
android:id="@+id/ScrollArea"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="60dp"
@@ -18,177 +17,13 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
<TableLayout
android:id="@+id/SettingsTable"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
android:layout_height="wrap_content">
</TableLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- <CheckBox-->
<!-- android:id="@+id/practice_mode"-->
<!-- android:layout_width="412dp"-->
<!-- android:layout_height="79dp"-->
<!-- android:layout_marginTop="20dp"-->
<!-- android:text="Practice Mode"-->
<!-- android:textSize="24sp"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintHorizontal_bias="0.0"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@+id/eventDropdown" />-->
<TextView
android:id="@+id/textView2"
android:layout_width="66dp"
android:layout_height="24dp"
android:layout_marginTop="16dp"
android:text="Name"
android:textAlignment="center"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/username"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="text"
android:text="Username"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
<TextView
android:id="@+id/textView1"
android:layout_width="107dp"
android:layout_height="24dp"
android:layout_marginStart="152dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="152dp"
android:text="Event Code"
android:textAlignment="center"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/username" />
<com.skydoves.powerspinner.PowerSpinnerView
android:id="@+id/eventDropdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/black_2"
android:gravity="center"
android:hint="No events selected"
android:padding="10dp"
android:textColor="@color/main_500"
android:textColorHint="@color/teal_700"
android:textSize="14.5sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView1"
app:spinner_arrow_gravity="end"
app:spinner_arrow_padding="8dp"
app:spinner_divider_color="@color/teal_200"
app:spinner_divider_show="true"
app:spinner_divider_size="0.4dp"
app:spinner_popup_background="@color/black_2"
app:spinner_popup_elevation="14dp" />
<TextView
android:id="@+id/alliance_pos_text"
android:layout_width="107dp"
android:layout_height="24dp"
android:layout_marginStart="152dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="152dp"
android:text="Alliance Position"
android:textAlignment="center"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/eventDropdown" />
<com.skydoves.powerspinner.PowerSpinnerView
android:id="@+id/alliance_pos_dropdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/black_2"
android:gravity="center"
android:hint="No events selected"
android:padding="10dp"
android:textColor="@color/main_500"
android:textColorHint="@color/teal_700"
android:textSize="14.5sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/alliance_pos_text"
app:spinner_arrow_gravity="end"
app:spinner_arrow_padding="8dp"
app:spinner_divider_color="@color/teal_200"
app:spinner_divider_show="true"
app:spinner_divider_size="0.4dp"
app:spinner_popup_background="@color/black_2"
app:spinner_popup_elevation="14dp" />
<TextView
android:id="@+id/team_num_settings_label"
android:layout_width="107dp"
android:layout_height="24dp"
android:layout_marginStart="152dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="152dp"
android:text="Team number"
android:textAlignment="center"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/alliance_pos_dropdown" />
<EditText
android:id="@+id/team_number"
android:layout_width="193dp"
android:layout_height="65dp"
android:ems="10"
android:gravity="center"
android:inputType="number"
android:padding="10dp"
android:text="4388"
android:textColor="@color/main_500"
android:textColorHint="@color/teal_700"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/team_num_settings_label" />
<CheckBox
android:id="@+id/wifi_mode"
android:layout_width="412dp"
android:layout_height="79dp"
android:layout_marginTop="24dp"
android:text="Wifi Mode"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/team_number" />
<Button
android:id="@+id/reset_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Reset Settings"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
+18 -5
View File
@@ -33,7 +33,7 @@
android:layout_height="wrap_content"
android:text="Upload"
android:textSize="34sp"
app:layout_constraintBottom_toTopOf="@+id/CSVButton"
app:layout_constraintBottom_toTopOf="@+id/SyncButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@@ -44,21 +44,34 @@
android:layout_height="wrap_content"
android:text="Download"
android:textSize="34sp"
app:layout_constraintBottom_toTopOf="@+id/CSVButton"
app:layout_constraintBottom_toTopOf="@+id/SyncButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/uploadButton" />
<Button
android:id="@+id/SyncButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SYNC"
android:textSize="34sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/CSVButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CSV"
android:textSize="34sp"
app:layout_constraintBottom_toBottomOf="@+id/TBAButton"
app:layout_constraintBottom_toTopOf="@+id/TBAButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/uploadButton" />
app:layout_constraintTop_toBottomOf="@+id/SyncButton" />
<Button
android:id="@+id/TBAButton"
@@ -69,7 +82,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/CSVButton" />
app:layout_constraintTop_toBottomOf="@+id/SyncButton" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -7,7 +7,7 @@
<fragment
android:id="@+id/navigation_scouting"
android:name="com.astatin3.scoutingapp2025.ui.scouting.ScoutingFragment"
android:name="com.ridgebotics.ridgescout.ui.scouting.ScoutingFragment"
android:label="@string/title_scouting"
tools:layout="@layout/fragment_scouting">
<action
@@ -26,18 +26,22 @@
app:popExitAnim="@anim/pop_exit_anim" />
<action
android:id="@+id/action_navigation_scouting_to_navigation_scouting_status"
app:destination="@id/navigation_scouting_status" />
app:destination="@id/navigation_scouting_status"
app:enterAnim="@anim/enter_anim"
app:exitAnim="@anim/exit_anim"
app:popEnterAnim="@anim/enter_anim"
app:popExitAnim="@anim/pop_exit_anim"/>
</fragment>
<fragment
android:id="@+id/navigation_match_scouting"
android:name="com.astatin3.scoutingapp2025.ui.scouting.MatchScoutingFragment"
android:name="com.ridgebotics.ridgescout.ui.scouting.MatchScoutingFragment"
tools:layout="@layout/fragment_scouting_match">
</fragment>
<fragment
android:id="@+id/navigation_team_selector"
android:name="com.astatin3.scoutingapp2025.ui.TeamSelectorFragment"
android:name="com.ridgebotics.ridgescout.ui.TeamSelectorFragment"
tools:layout="@layout/fragment_team_selector">
<action
android:id="@+id/action_navigation_team_selector_to_navigation_pit_scouting"
@@ -57,7 +61,7 @@
<fragment
android:id="@+id/navigation_pit_scouting"
android:name="com.astatin3.scoutingapp2025.ui.scouting.PitScoutingFragment"
android:name="com.ridgebotics.ridgescout.ui.scouting.PitScoutingFragment"
tools:layout="@layout/fragment_scouting_pit"/>
@@ -67,7 +71,7 @@
<fragment
android:id="@+id/navigation_data"
android:name="com.astatin3.scoutingapp2025.ui.data.DataFragment"
android:name="com.ridgebotics.ridgescout.ui.data.DataFragment"
android:label="@string/title_data"
tools:layout="@layout/fragment_data">
<action
@@ -77,13 +81,6 @@
app:exitAnim="@anim/exit_anim"
app:popEnterAnim="@anim/enter_anim"
app:popExitAnim="@anim/pop_exit_anim" />
<action
android:id="@+id/action_navigation_data_to_navigation_data_report"
app:destination="@id/navigation_data_report"
app:enterAnim="@anim/enter_anim"
app:exitAnim="@anim/exit_anim"
app:popEnterAnim="@anim/enter_anim"
app:popExitAnim="@anim/pop_exit_anim" />
<action
android:id="@+id/action_navigation_data_to_navigation_data_fields_chooser"
app:destination="@id/navigation_data_fields_chooser"
@@ -91,42 +88,49 @@
app:exitAnim="@anim/exit_anim"
app:popEnterAnim="@anim/enter_anim"
app:popExitAnim="@anim/pop_exit_anim" />
<action
android:id="@+id/action_navigation_data_to_navigation_data_report_selector"
app:destination="@id/navigation_data_report_selector"
app:enterAnim="@anim/enter_anim"
app:exitAnim="@anim/exit_anim"
app:popEnterAnim="@anim/enter_anim"
app:popExitAnim="@anim/pop_exit_anim"/>
<action
android:id="@+id/action_navigation_data_to_navigation_data_compare"
app:destination="@id/navigation_data_compare"
app:enterAnim="@anim/enter_anim"
app:exitAnim="@anim/exit_anim"
app:popEnterAnim="@anim/enter_anim"
app:popExitAnim="@anim/pop_exit_anim" />
app:popExitAnim="@anim/pop_exit_anim"/>
</fragment>
<fragment
android:id="@+id/navigation_scouting_status"
android:name="com.astatin3.scoutingapp2025.ui.scouting.StatusFragment"
android:name="com.ridgebotics.ridgescout.ui.scouting.StatusFragment"
tools:layout="@layout/fragment_scouting_status">
</fragment>
<fragment
android:id="@+id/navigation_data_teams"
android:name="com.astatin3.scoutingapp2025.ui.data.TeamsFragment"
android:name="com.ridgebotics.ridgescout.ui.data.TeamsFragment"
tools:layout="@layout/fragment_data_teams">
</fragment>
<fragment
android:id="@+id/navigation_data_compare"
android:name="com.astatin3.scoutingapp2025.ui.data.CompareFragment"
android:name="com.ridgebotics.ridgescout.ui.data.CompareFragment"
tools:layout="@layout/fragment_data_report">
</fragment>
<fragment
android:id="@+id/navigation_data_report"
android:name="com.astatin3.scoutingapp2025.ui.data.ReportFragment"
android:name="com.ridgebotics.ridgescout.ui.data.ReportFragment"
tools:layout="@layout/fragment_data_report">
</fragment>
<fragment
android:id="@+id/navigation_data_fields_chooser"
android:name="com.astatin3.scoutingapp2025.ui.data.FieldsChooserFragment"
android:name="com.ridgebotics.ridgescout.ui.data.FieldsChooserFragment"
tools:layout="@layout/fragment_data_fields_chooser">
<action
android:id="@+id/action_navigation_data_fields_chooser_to_navigation_data_fields"
@@ -139,11 +143,31 @@
<fragment
android:id="@+id/navigation_data_fields"
android:name="com.astatin3.scoutingapp2025.ui.data.FieldsFragment"
android:name="com.ridgebotics.ridgescout.ui.data.FieldsFragment"
tools:layout="@layout/fragment_data_fields">
<action
android:id="@+id/action_navigation_data_fields_to_navigation_data_fields_chooser"
app:destination="@id/navigation_data_fields_chooser" />
app:destination="@id/navigation_data_fields_chooser"
app:enterAnim="@anim/enter_anim"
app:exitAnim="@anim/exit_anim"
app:popEnterAnim="@anim/enter_anim"
app:popExitAnim="@anim/pop_exit_anim" />
</fragment>
<fragment
android:id="@+id/navigation_data_report_selector"
android:name="com.ridgebotics.ridgescout.ui.data.ReportSelectorFragment"
tools:layout="@layout/fragment_data_report_selector">
<action
android:id="@+id/action_navigation_data_report_selector_to_navigation_data_report"
app:destination="@id/navigation_data_report"
app:enterAnim="@anim/enter_anim"
app:exitAnim="@anim/exit_anim"
app:popEnterAnim="@anim/enter_anim"
app:popExitAnim="@anim/pop_exit_anim"/>
<action
android:id="@+id/action_navigation_data_report_selector_to_navigation_data"
app:destination="@id/navigation_data" />
</fragment>
@@ -152,7 +176,7 @@
<fragment
android:id="@+id/navigation_transfer"
android:name="com.astatin3.scoutingapp2025.ui.transfer.TransferFragment"
android:name="com.ridgebotics.ridgescout.ui.transfer.TransferFragment"
android:label="@string/title_transfer"
tools:layout="@layout/fragment_transfer">
<action
@@ -180,7 +204,7 @@
<fragment
android:id="@+id/navigation_file_selector"
android:name="com.astatin3.scoutingapp2025.ui.transfer.FileSelectorFragment"
android:name="com.ridgebotics.ridgescout.ui.transfer.FileSelectorFragment"
tools:layout="@layout/fragment_transfer_file_selector">
<action
android:id="@+id/action_navigation_file_selector_to_navigation_transfer_selector"
@@ -193,7 +217,7 @@
<fragment
android:id="@+id/navigation_transfer_selector"
android:name="com.astatin3.scoutingapp2025.ui.transfer.TransferSelectorFragment"
android:name="com.ridgebotics.ridgescout.ui.transfer.TransferSelectorFragment"
tools:layout="@layout/fragment_transfer_selector">
<action
android:id="@+id/action_navigation_transfer_selector_to_navigation_code_generator"
@@ -227,31 +251,31 @@
<fragment
android:id="@+id/navigation_code_generator"
android:name="com.astatin3.scoutingapp2025.ui.transfer.codes.CodeGeneratorView"
android:name="com.ridgebotics.ridgescout.ui.transfer.codes.CodeGeneratorView"
tools:layout="@layout/fragment_transfer_code_sender">
</fragment>
<fragment
android:id="@+id/navigation_code_scanner"
android:name="com.astatin3.scoutingapp2025.ui.transfer.codes.CodeScannerView"
android:name="com.ridgebotics.ridgescout.ui.transfer.codes.CodeScannerView"
tools:layout="@layout/fragment_transfer_code_receiver">
</fragment>
<fragment
android:id="@+id/navigation_bluetooth_sender"
android:name="com.astatin3.scoutingapp2025.ui.transfer.bluetooth.BluetoothSenderFragment"
android:name="com.ridgebotics.ridgescout.ui.transfer.bluetooth.BluetoothSenderFragment"
tools:layout="@layout/fragment_transfer_bluetooth_sender">
</fragment>
<fragment
android:id="@+id/navigation_bluetooth_receiver"
android:name="com.astatin3.scoutingapp2025.ui.transfer.bluetooth.BluetoothReceiverFragment"
android:name="com.ridgebotics.ridgescout.ui.transfer.bluetooth.BluetoothReceiverFragment"
tools:layout="@layout/fragment_transfer_bluetooth_receiver">
</fragment>
<fragment
android:id="@+id/navigation_tba"
android:name="com.astatin3.scoutingapp2025.ui.transfer.TBAFragment"
android:name="com.ridgebotics.ridgescout.ui.transfer.TBAFragment"
tools:layout="@layout/fragment_transfer_tba">
</fragment>
@@ -260,7 +284,7 @@
<fragment
android:id="@+id/navigation_settings"
android:name="com.astatin3.scoutingapp2025.ui.settings.settingsFragment"
android:name="com.ridgebotics.ridgescout.ui.settings.settingsFragment"
android:label="@string/title_settings"
tools:layout="@layout/fragment_settings">
</fragment>
+1 -1
View File
@@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.ScoutingApp2025" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<style name="Theme.RidgeScout" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/main_200</item>
<item name="colorPrimaryVariant">@color/main_700</item>
+1 -1
View File
@@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.ScoutingApp2025" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<style name="Theme.RidgeScout" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/main_500</item>
<item name="colorPrimaryVariant">@color/main_700</item>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
@@ -1,4 +1,4 @@
package com.astatin3.scoutingapp2025;
package com.ridgebotics.ridgescout;
import org.junit.Test;
+2
View File
@@ -11,6 +11,7 @@ lifecycleViewmodelKtx = "2.6.1"
navigationFragment = "2.6.0"
navigationUi = "2.6.0"
supportAnnotations = "28.0.0"
preference = "1.2.1"
[libraries]
junit = { group = "junit", name = "junit", version.ref = "junit" }
@@ -24,6 +25,7 @@ lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-view
navigation-fragment = { group = "androidx.navigation", name = "navigation-fragment", version.ref = "navigationFragment" }
navigation-ui = { group = "androidx.navigation", name = "navigation-ui", version.ref = "navigationUi" }
support-annotations = { group = "com.android.support", name = "support-annotations", version.ref = "supportAnnotations" }
preference = { group = "androidx.preference", name = "preference", version.ref = "preference" }
[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
+3
View File
@@ -0,0 +1,3 @@
This is a scouting app for First Robotics Compitition matches by Ridgebotics, that includes many features.
Wiki: https://github.com/team4388/ScoutingApp2025/wiki
Binary file not shown.

After

Width:  |  Height:  |  Size: 373 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Some files were not shown because too many files have changed in this diff Show More