mirror of
https://github.com/Team4388/RidgeScout.git
synced 2026-06-09 00:37:59 -06:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 534207ebb1 | |||
| d458ad7669 | |||
| 3e045bfcb7 | |||
| c78fa58754 | |||
| 18748301cd | |||
| a15deda539 | |||
| 0846f5a3b3 | |||
| 554cad2abd | |||
| 7d41a5e5a9 | |||
| 4cb20f4769 | |||
| 6b4b919e5f | |||
| 9440583f78 | |||
| ea9ea39368 | |||
| bf72d1cbe5 | |||
| f3ce5a6e55 | |||
| 8e2c491273 | |||
| 38ccf17281 | |||
| 46af23909f | |||
| cf3856805b | |||
| ff84760ab2 | |||
| 1df7928da1 | |||
| f701397577 | |||
| b264a3bb73 | |||
| 8381d21eff | |||
| 19e377fd9e | |||
| 1a4ccf4f92 | |||
| 78620d2031 | |||
| 15be86453e | |||
| 795fa4e85a | |||
| 86432693aa | |||
| fecf7e5d2b | |||
| fb0718c4ec | |||
| 03a1507ce2 | |||
| 2b753fcdb4 | |||
| ca703aab60 | |||
| 4854587ea9 | |||
| d957a1db5e | |||
| 60d56473f5 | |||
| d607f95a8a | |||
| 62a4452581 | |||
| b62d04dac5 | |||
| 07c6e9a2aa | |||
| 9f5ebd4215 | |||
| 0a9f846e77 | |||
| f37f12178b | |||
| e537aab819 | |||
| 9607241c53 | |||
| 4764aea990 | |||
| e0c76fb4ef | |||
| 9c254bb249 | |||
| 3f88c9a05e |
@@ -1,6 +1,7 @@
|
||||
# Gradle files
|
||||
.gradle/
|
||||
build/
|
||||
release/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
@@ -1,40 +1,36 @@
|
||||
# ScoutingApp2025
|
||||
Ridgebotics 2025 scouting app in Android
|
||||

|
||||
|
||||
## 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:
|
||||
- Statbotics intgration
|
||||
- Scout error estimation using OPR-like calculation
|
||||
- - Would most likely require Statbotics
|
||||
|
||||
### Screenshots
|
||||
|Match scouting interface|Field editor|Teams data viewer|
|
||||
|-|-|-|
|
||||
||||
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
### TODO:
|
||||
##### Scouting:
|
||||
##### Data Analysis:
|
||||
- Statbotics intigration???
|
||||
##### Functionality:
|
||||
- Test new FTP thing
|
||||
- UUIDs instead of names for the fields
|
||||
- Fix data storage crashes
|
||||
- Match selector instead of list for individual team views
|
||||
|
||||
### In Progress:
|
||||
##### Scouting:
|
||||
- Make scouting UI look much better
|
||||
##### Data Analysis:
|
||||
##### Functionality:
|
||||
|
||||
### Done:
|
||||
##### Scouting:
|
||||
- Make practice mode
|
||||
- Description for fields
|
||||
##### Data Analysis:
|
||||
##### Functionality:
|
||||
- "Send Meta Files" button
|
||||
- Year selector
|
||||
+17
-10
@@ -1,6 +1,3 @@
|
||||
import com.android.build.api.dsl.AaptOptions
|
||||
import com.android.build.api.dsl.AndroidResources
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.androidApplication)
|
||||
// id("com.google.gms.google-services")
|
||||
@@ -13,15 +10,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 = 11 // **IMPORTANT** Increment this before releasing on github
|
||||
versionName = "1.4"// **IMPORTANT** Change this before releasing on github (<Year num since 2024>.<Update Version>)
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
@@ -48,11 +53,13 @@ dependencies {
|
||||
|
||||
implementation(libs.appcompat)
|
||||
implementation(libs.material)
|
||||
implementation(libs.material3)
|
||||
implementation(libs.constraintlayout)
|
||||
implementation(libs.lifecycle.livedata.ktx)
|
||||
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)
|
||||
@@ -67,17 +74,17 @@ dependencies {
|
||||
|
||||
implementation("com.journeyapps:zxing-android-embedded:4.3.0")
|
||||
|
||||
implementation("com.github.skydoves:powerspinner:1.2.7")
|
||||
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")
|
||||
|
||||
+2
-2
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
-9
@@ -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();
|
||||
}
|
||||
}
|
||||
-110
@@ -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,150 +0,0 @@
|
||||
package com.astatin3.scoutingapp2025.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 java.util.ArrayList;
|
||||
|
||||
public class fields {
|
||||
// public static ScoutingVersion sv = new ScoutingVersion();
|
||||
|
||||
public static final String matchFieldsFilename = "matches.fields";
|
||||
public static final String pitsFieldsFilename = "pits.fields";
|
||||
|
||||
public static final inputType[][] default_match_fields = new inputType[][] {
|
||||
{
|
||||
new tallyType("Auto Notes", 0),
|
||||
new sliderType("Auto Performance", 5, 0, 10),
|
||||
new textType("Auto Comments", ""),
|
||||
new tallyType("Teleop Notes", 0),
|
||||
new sliderType("Teleop Performance", 5, 0, 10),
|
||||
new textType("Teleop Comments", ""),
|
||||
new sliderType("Overall Driving Performance", 5, 0, 10),
|
||||
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 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", ""),
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static boolean save(String filename, inputType[][] values){
|
||||
try {
|
||||
ByteBuilder bb = new ByteBuilder();
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
bb.addRaw(127, save_version(values[i]));
|
||||
}
|
||||
fileEditor.writeFile(filename, bb.build());
|
||||
return true;
|
||||
}catch (ByteBuilder.buildingException e) {
|
||||
AlertManager.error(e);
|
||||
return false;
|
||||
// throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] save_version(inputType[] values) throws ByteBuilder.buildingException {
|
||||
ByteBuilder bb = new ByteBuilder();
|
||||
for(int i =0; i < values.length; i++){
|
||||
bb.addRaw(values[i].get_byte_id(), values[i].encode());
|
||||
}
|
||||
return bb.build();
|
||||
}
|
||||
|
||||
public static inputType[][] load(String filename){
|
||||
byte[] bytes = fileEditor.readFile(filename);
|
||||
|
||||
// System.out.println(bytes);
|
||||
|
||||
try {
|
||||
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
||||
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
||||
inputType[][] values = new inputType[objects.size()][];
|
||||
|
||||
for(int i = 0 ; i < objects.size(); i++){
|
||||
values[i] = load_version((byte[]) objects.get(i).get());
|
||||
}
|
||||
|
||||
|
||||
return values;
|
||||
} catch (Exception e) {
|
||||
AlertManager.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static inputType[] load_version(byte[] bytes) throws BuiltByteParser.byteParsingExeption{
|
||||
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
||||
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
||||
inputType[] output = new inputType[objects.size()];
|
||||
|
||||
for(int i = 0 ; i < objects.size(); i++){
|
||||
BuiltByteParser.parsedObject obj = objects.get(i);
|
||||
inputType t = null;
|
||||
switch (obj.getType()){
|
||||
case inputType.slider_type_id:
|
||||
t = new sliderType();
|
||||
break;
|
||||
case inputType.dropdownType:
|
||||
t = new dropdownType();
|
||||
break;
|
||||
case inputType.notesType:
|
||||
t = new textType();
|
||||
break;
|
||||
case inputType.tallyType:
|
||||
t = new tallyType();
|
||||
break;
|
||||
}
|
||||
|
||||
t.decode((byte[]) obj.get());
|
||||
output[i] = t;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// public static void test(){
|
||||
// ScoutingVersion.transferType[][] transferValues = sv.get_transfer_values(values);
|
||||
//
|
||||
// ScoutingVersion.ScoutingArray msa = sv.new ScoutingArray(0, new ScoutingVersion.dataType[]{
|
||||
// sv.new stringType("name", "test-username"),
|
||||
// sv.new intType("How good is robot", 12)
|
||||
// }, values, transferValues);
|
||||
//
|
||||
// msa.update();
|
||||
//
|
||||
// for(ScoutingVersion.dataType dt : msa.array){
|
||||
// if(dt == null) continue;
|
||||
// switch (dt.getValueType()){
|
||||
// case NUM:
|
||||
// System.out.println(dt.name + " " + (int) dt.get());
|
||||
// break;
|
||||
// case STRING:
|
||||
// System.out.println(dt.name + " " + (String) dt.get());
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -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.FragmentDataCompareBinding;
|
||||
import com.astatin3.scoutingapp2025.databinding.FragmentDataReportBinding;
|
||||
|
||||
public class CompareFragment extends Fragment {
|
||||
FragmentDataCompareBinding binding;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
binding = FragmentDataCompareBinding.inflate(inflater, container, false);
|
||||
return binding.getRoot();
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package com.astatin3.scoutingapp2025.ui.data;
|
||||
|
||||
|
||||
import static androidx.navigation.fragment.FragmentKt.findNavController;
|
||||
|
||||
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.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;
|
||||
|
||||
public class DataFragment extends Fragment {
|
||||
|
||||
private FragmentDataBinding binding;
|
||||
|
||||
private boolean submenu = false;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
binding = FragmentDataBinding.inflate(inflater, container, false);
|
||||
View root = binding.getRoot();
|
||||
|
||||
String evcode = latestSettings.settings.get_evcode();
|
||||
|
||||
|
||||
|
||||
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.fieldsButton.setVisibility(View.VISIBLE);
|
||||
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
frcEvent event = frcEvent.decode(fileEditor.readFile(evcode + ".eventdata"));
|
||||
|
||||
binding.teamsButton.setOnClickListener(v -> {
|
||||
TeamSelectorFragment.setPits_mode(false);
|
||||
TeamSelectorFragment.setOnSelect(new TeamSelectorFragment.onTeamSelected() {
|
||||
@Override
|
||||
public void onSelect(TeamSelectorFragment self, frcTeam team) {
|
||||
TeamsFragment.setTeam(team);
|
||||
findNavController(self).navigate(R.id.action_navigation_team_selector_to_navigation_data_teams);
|
||||
}
|
||||
});
|
||||
findNavController(this).navigate(R.id.action_navigation_data_to_navigation_team_selector);
|
||||
});
|
||||
|
||||
binding.compareButton.setOnClickListener(v -> {
|
||||
findNavController(this).navigate(R.id.action_navigation_data_to_navigation_data_compare);
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.astatin3.scoutingapp2025.ui.data;
|
||||
|
||||
import static androidx.navigation.fragment.FragmentKt.findNavController;
|
||||
|
||||
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.R;
|
||||
import com.astatin3.scoutingapp2025.databinding.FragmentDataFieldsChooserBinding;
|
||||
import com.astatin3.scoutingapp2025.scoutingData.fields;
|
||||
|
||||
public class FieldsChooserFragment extends Fragment {
|
||||
|
||||
FragmentDataFieldsChooserBinding binding;
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
binding = FragmentDataFieldsChooserBinding.inflate(inflater, container, false);
|
||||
|
||||
binding.matchScoutingButton.setOnClickListener(v -> {
|
||||
FieldsFragment.set_filename(fields.matchFieldsFilename);
|
||||
findNavController(this).navigate(R.id.action_navigation_data_fields_chooser_to_navigation_data_fields);
|
||||
});
|
||||
|
||||
binding.pitScoutingButton.setOnClickListener(v -> {
|
||||
FieldsFragment.set_filename(fields.pitsFieldsFilename);
|
||||
findNavController(this).navigate(R.id.action_navigation_data_fields_chooser_to_navigation_data_fields);
|
||||
});
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
}
|
||||
@@ -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,384 +0,0 @@
|
||||
package com.astatin3.scoutingapp2025.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 android.os.Bundle;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
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.google.android.material.divider.MaterialDivider;
|
||||
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;
|
||||
|
||||
public class TeamsFragment extends Fragment {
|
||||
FragmentDataTeamsBinding binding;
|
||||
|
||||
private static frcTeam team;
|
||||
public static void setTeam(frcTeam tmpteam){
|
||||
team = tmpteam;
|
||||
}
|
||||
|
||||
private static final int background_color = 0x5000ff00;
|
||||
private static final int unsaved_background_color = 0x2000ff00;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
binding = FragmentDataTeamsBinding.inflate(inflater, container, false);
|
||||
|
||||
binding.teamsArea.removeAllViews();
|
||||
|
||||
DataManager.reload_match_fields();
|
||||
DataManager.reload_pit_fields();
|
||||
|
||||
TableLayout table = new TableLayout(getContext());
|
||||
table.setStretchAllColumns(true);
|
||||
binding.teamsArea.addView(table);
|
||||
|
||||
loadTeam(latestSettings.settings.get_data_view_mode());
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
public void loadTeam(int mode) {
|
||||
binding.teamsArea.removeAllViews();
|
||||
|
||||
LinearLayout ll = new LinearLayout(getContext());
|
||||
ll.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
ll.setOrientation(LinearLayout.VERTICAL);
|
||||
binding.teamsArea.addView(ll);
|
||||
|
||||
|
||||
|
||||
PowerSpinnerView dropdown = new PowerSpinnerView(getContext());
|
||||
|
||||
List<IconSpinnerItem> iconSpinnerItems = new ArrayList<>();
|
||||
|
||||
iconSpinnerItems.add(new IconSpinnerItem("Individual"));
|
||||
iconSpinnerItems.add(new IconSpinnerItem("Compiled"));
|
||||
iconSpinnerItems.add(new IconSpinnerItem("History"));
|
||||
|
||||
IconSpinnerAdapter iconSpinnerAdapter = new IconSpinnerAdapter(dropdown);
|
||||
dropdown.setSpinnerAdapter(iconSpinnerAdapter);
|
||||
dropdown.setItems(iconSpinnerItems);
|
||||
|
||||
dropdown.selectItemByIndex(0);
|
||||
|
||||
dropdown.setPadding(10,20,10,20);
|
||||
dropdown.setBackgroundColor(0xf0000000);
|
||||
dropdown.setTextColor(0xff00ff00);
|
||||
dropdown.setTextSize(15);
|
||||
dropdown.setArrowGravity(SpinnerGravity.END);
|
||||
dropdown.setArrowPadding(8);
|
||||
// dropdown.setSpinnerItemHeight(46);
|
||||
dropdown.setSpinnerPopupElevation(14);
|
||||
|
||||
|
||||
dropdown.selectItemByIndex(mode);
|
||||
|
||||
|
||||
dropdown.setOnSpinnerItemSelectedListener(new OnSpinnerItemSelectedListener<IconSpinnerItem>() {
|
||||
@Override
|
||||
public void onItemSelected(int oldIndex, @Nullable IconSpinnerItem oldItem, int newIndex,
|
||||
IconSpinnerItem newItem) {
|
||||
|
||||
latestSettings.settings.set_data_view_mode(newIndex);
|
||||
loadTeam(newIndex);
|
||||
}
|
||||
});
|
||||
|
||||
ll.addView(dropdown);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TextView tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setText(String.valueOf(team.teamNumber));
|
||||
tv.setTextSize(28);
|
||||
ll.addView(tv);
|
||||
|
||||
tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setText(team.teamName);
|
||||
tv.setTextSize(28);
|
||||
ll.addView(tv);
|
||||
|
||||
tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setText(team.getDescription());
|
||||
tv.setTextSize(16);
|
||||
ll.addView(tv);
|
||||
|
||||
add_pit_data(ll, team);
|
||||
add_match_data(ll, team, mode);
|
||||
}
|
||||
|
||||
public void add_pit_data(LinearLayout ll, frcTeam team){
|
||||
final String filename = evcode+"-"+team.teamNumber+".pitscoutdata";
|
||||
|
||||
ll.addView(new MaterialDivider(getContext()));
|
||||
|
||||
TextView tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setPadding(0,10,0,10);
|
||||
tv.setText("----- Pit data -----");
|
||||
tv.setTextSize(30);
|
||||
ll.addView(tv);
|
||||
|
||||
ll.addView(new MaterialDivider(getContext()));
|
||||
|
||||
if(!fileEditor.fileExist(filename)){
|
||||
tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setText("No pit data has been collected!");
|
||||
tv.setTextSize(23);
|
||||
ll.addView(tv);
|
||||
return;
|
||||
}
|
||||
|
||||
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(filename, pit_values, pit_transferValues);
|
||||
|
||||
tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setPadding(0, 20, 0, 5);
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setText("Pit scouting 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);
|
||||
|
||||
if(psda.data.array[a].isNull()){
|
||||
tv.setBackgroundColor(0xffff0000);
|
||||
tv.setTextColor(0xff000000);
|
||||
}
|
||||
|
||||
|
||||
ll.addView(tv);
|
||||
|
||||
|
||||
pit_latest_values[a].add_individual_view(ll, psda.data.array[a]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void add_match_data(LinearLayout ll, frcTeam team, int mode){
|
||||
String[] files = fileEditor.getMatchesByTeamNum(evcode, team.teamNumber);
|
||||
|
||||
ll.addView(new MaterialDivider(getContext()));
|
||||
|
||||
TextView tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setText("----- Match data -----");
|
||||
tv.setPadding(0,10,0,10);
|
||||
tv.setTextSize(30);
|
||||
ll.addView(tv);
|
||||
|
||||
ll.addView(new MaterialDivider(getContext()));
|
||||
|
||||
|
||||
|
||||
if(files.length == 0){
|
||||
tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setText("No match data has been collected!");
|
||||
tv.setTextSize(23);
|
||||
ll.addView(tv);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mode){
|
||||
case 0:
|
||||
add_individual_views(ll,files);
|
||||
break;
|
||||
case 1:
|
||||
add_compiled_views(ll,files);
|
||||
break;
|
||||
case 2:
|
||||
add_history_views(ll,files);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
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]);
|
||||
|
||||
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());
|
||||
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);
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < match_latest_values.length; i++){
|
||||
TextView tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setPadding(0, 20, 0, 5);
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setText(match_latest_values[i].name);
|
||||
tv.setTextSize(30);
|
||||
ll.addView(tv);
|
||||
|
||||
match_latest_values[i].add_compiled_view(ll, data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < match_latest_values.length; i++){
|
||||
TextView tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setPadding(0, 20, 0, 5);
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setText(match_latest_values[i].name);
|
||||
tv.setTextSize(30);
|
||||
ll.addView(tv);
|
||||
|
||||
match_latest_values[i].add_history_view(ll, data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
package com.astatin3.scoutingapp2025.ui.scouting;
|
||||
|
||||
import static androidx.navigation.fragment.FragmentKt.findNavController;
|
||||
|
||||
import static com.astatin3.scoutingapp2025.utility.DataManager.event;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
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.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;
|
||||
|
||||
public class ScoutingFragment extends Fragment {
|
||||
|
||||
private FragmentScoutingBinding binding;
|
||||
private boolean is_main_page = true;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
binding = FragmentScoutingBinding.inflate(inflater, container, false);
|
||||
|
||||
binding.buttons.setVisibility(View.VISIBLE);
|
||||
|
||||
String evcode = latestSettings.settings.get_evcode();
|
||||
|
||||
if(evcode.equals("unset")){
|
||||
binding.noEventError.setVisibility(View.VISIBLE);
|
||||
binding.buttons.setVisibility(View.GONE);
|
||||
is_main_page = false;
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
DataManager.reload_event();
|
||||
|
||||
if(event.matches.isEmpty())
|
||||
binding.matchScoutingButton.setVisibility(View.GONE);
|
||||
|
||||
binding.matchScoutingButton.setOnClickListener(v -> {
|
||||
findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_match_scouting);
|
||||
});
|
||||
|
||||
binding.pitScoutingButton.setOnClickListener(v -> {
|
||||
TeamSelectorFragment.setPits_mode(true);
|
||||
TeamSelectorFragment.setOnSelect(new TeamSelectorFragment.onTeamSelected() {
|
||||
@Override
|
||||
public void onSelect(TeamSelectorFragment self, frcTeam team) {
|
||||
PitScoutingFragment.setTeam(team);
|
||||
findNavController(self).navigate(R.id.action_navigation_team_selector_to_navigation_pit_scouting);
|
||||
}
|
||||
});
|
||||
findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_team_selector);
|
||||
});
|
||||
|
||||
binding.statusButton.setOnClickListener(v -> {
|
||||
findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_scouting_status);
|
||||
});
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if(getView() == null){
|
||||
return;
|
||||
}
|
||||
|
||||
getView().setFocusableInTouchMode(true);
|
||||
getView().requestFocus();
|
||||
getView().setOnKeyListener(new View.OnKeyListener() {
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
|
||||
if (event.getAction() == KeyEvent.ACTION_UP
|
||||
&& keyCode == KeyEvent.KEYCODE_BACK
|
||||
&& !is_main_page){
|
||||
|
||||
// binding.buttons.setVisibility(View.VISIBLE);
|
||||
// binding.matchScoutingView.setVisibility(View.GONE);
|
||||
// binding.pitScoutingView.setVisibility(View.GONE);
|
||||
is_main_page = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
package com.astatin3.scoutingapp2025.ui.scouting;
|
||||
|
||||
import static com.astatin3.scoutingapp2025.utility.DataManager.event;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.Gravity;
|
||||
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.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 java.util.Arrays;
|
||||
|
||||
public class StatusFragment extends Fragment {
|
||||
FragmentScoutingStatusBinding binding;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
binding = FragmentScoutingStatusBinding.inflate(inflater, container, false);
|
||||
|
||||
DataManager.reload_event();
|
||||
binding.matchTable.removeAllViews();
|
||||
binding.matchTable.setStretchAllColumns(true);
|
||||
add_pit_scouting(event);
|
||||
add_match_scouting(event);
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
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);
|
||||
text.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); // Text align center
|
||||
text.setText(textStr);
|
||||
tr.addView(text);
|
||||
}
|
||||
|
||||
public void add_pit_scouting(frcEvent event){
|
||||
TextView tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new TableRow.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setText("Pit Scouting");
|
||||
tv.setTextSize(28);
|
||||
binding.matchTable.addView(tv);
|
||||
|
||||
int[] teams = new int[event.teams.size()];
|
||||
|
||||
for(int i = 0 ; i < event.teams.size(); i++){
|
||||
teams[i] = event.teams.get(i).teamNumber;
|
||||
}
|
||||
|
||||
Arrays.sort(teams);
|
||||
|
||||
TableRow tr = null;
|
||||
for(int i=0; i < event.teams.size(); i++){
|
||||
// frcTeam team = event.teams.get(i);
|
||||
int num = teams[i];
|
||||
|
||||
if(i % 7 == 0){
|
||||
if(i != 0)
|
||||
binding.matchTable.addView(tr);
|
||||
tr = new TableRow(getContext());
|
||||
}
|
||||
|
||||
TextView text = new TextView(getContext());
|
||||
text.setTextSize(18);
|
||||
text.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
||||
|
||||
text.setText(String.valueOf(num));
|
||||
if(fileEditor.fileExist(event.eventCode + "-" + num + ".pitscoutdata")){
|
||||
text.setBackgroundColor(color_found);
|
||||
}else{
|
||||
text.setBackgroundColor(color_not_found);
|
||||
}
|
||||
tr.addView(text);
|
||||
}
|
||||
if(tr != null)
|
||||
binding.matchTable.addView(tr);
|
||||
}
|
||||
|
||||
|
||||
public void add_match_scouting(frcEvent event){
|
||||
|
||||
TextView tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new TableRow.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setText("Match Scouting");
|
||||
tv.setTextSize(28);
|
||||
binding.matchTable.addView(tv);
|
||||
|
||||
TableRow tr = new TableRow(getContext());
|
||||
addTableText(tr, "#");
|
||||
addTableText(tr, "Red-1");
|
||||
addTableText(tr, "Red-2");
|
||||
addTableText(tr, "Red-3");
|
||||
addTableText(tr, "Blue-1");
|
||||
addTableText(tr, "Blue-2");
|
||||
addTableText(tr, "Blue-3");
|
||||
binding.matchTable.addView(tr);
|
||||
|
||||
for(frcMatch match : event.matches){
|
||||
|
||||
tr = new TableRow(getContext());
|
||||
addTableText(tr, String.valueOf(match.matchIndex));
|
||||
//
|
||||
for(int i=0;i<6;i++){
|
||||
TextView text = new TextView(getContext());
|
||||
text.setTextSize(18);
|
||||
text.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
||||
|
||||
int team_num;
|
||||
String alliance_position;
|
||||
|
||||
if(i < 3){
|
||||
team_num = match.redAlliance[i];
|
||||
alliance_position = "red-"+(i+1);
|
||||
}else{
|
||||
team_num = match.blueAlliance[i-3];
|
||||
alliance_position = "blue-"+(i-2);
|
||||
}
|
||||
|
||||
text.setText(String.valueOf(team_num));
|
||||
if(fileEditor.fileExist(event.eventCode + "-" + match.matchIndex + "-" + alliance_position + "-" + team_num + ".matchscoutdata")){
|
||||
text.setBackgroundColor(color_found);
|
||||
}else{
|
||||
text.setBackgroundColor(color_not_found);
|
||||
}
|
||||
tr.addView(text);
|
||||
}
|
||||
|
||||
// addTableText(tr, String.valueOf(match.matchIndex));
|
||||
// addTableText(tr, String.valueOf(match.blueAlliance[0]));
|
||||
// addTableText(tr, String.valueOf(match.blueAlliance[1]));
|
||||
// addTableText(tr, String.valueOf(match.blueAlliance[2]));
|
||||
// addTableText(tr, String.valueOf(match.redAlliance[0]));
|
||||
// addTableText(tr, String.valueOf(match.redAlliance[1]));
|
||||
// addTableText(tr, String.valueOf(match.redAlliance[2]));
|
||||
// if (toggle) {
|
||||
// tr.setBackgroundColor(0x30000000);
|
||||
// }
|
||||
//
|
||||
// toggle = !toggle;
|
||||
binding.matchTable.addView(tr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,38 +0,0 @@
|
||||
package com.astatin3.scoutingapp2025.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;
|
||||
|
||||
public class DataManager {
|
||||
public static String evcode;
|
||||
public static frcEvent event;
|
||||
public static void reload_event(){
|
||||
evcode = getevcode();
|
||||
event = frcEvent.decode(fileEditor.readFile(evcode + ".eventdata"));
|
||||
}
|
||||
|
||||
public static String getevcode() {
|
||||
return latestSettings.settings.get_evcode();
|
||||
}
|
||||
|
||||
public static inputType[][] match_values;
|
||||
public static inputType[] match_latest_values;
|
||||
public static transferType[][] match_transferValues;
|
||||
public static void reload_match_fields(){
|
||||
match_values = fields.load(fields.matchFieldsFilename);
|
||||
match_latest_values = match_values[match_values.length-1];
|
||||
match_transferValues = transferType.get_transfer_values(match_values);
|
||||
}
|
||||
|
||||
public static inputType[][] pit_values;
|
||||
public static inputType[] pit_latest_values;
|
||||
public static transferType[][] pit_transferValues;
|
||||
public static void reload_pit_fields(){
|
||||
pit_values = fields.load(fields.pitsFieldsFilename);
|
||||
pit_latest_values = pit_values[pit_values.length-1];
|
||||
pit_transferValues = transferType.get_transfer_values(pit_values);
|
||||
}
|
||||
}
|
||||
+46
-53
@@ -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,
|
||||
@@ -113,18 +89,16 @@ public class MainActivity extends AppCompatActivity {
|
||||
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
|
||||
NavigationUI.setupWithNavController(navView, navController);
|
||||
|
||||
navView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
||||
clearBackStack();
|
||||
navController.navigate(item.getItemId(), savedInstanceState, new NavOptions.Builder()
|
||||
.setEnterAnim(R.anim.enter_anim)
|
||||
.setExitAnim(R.anim.exit_anim)
|
||||
.setPopEnterAnim(R.anim.pop_enter_anim)
|
||||
.setPopExitAnim(R.anim.pop_exit_anim).build()
|
||||
);
|
||||
return true;
|
||||
}
|
||||
navView.setOnItemSelectedListener(item -> {
|
||||
backPressed = null;
|
||||
clearBackStack();
|
||||
navController.navigate(item.getItemId(), savedInstanceState, new NavOptions.Builder()
|
||||
.setEnterAnim(R.anim.enter_anim)
|
||||
.setExitAnim(R.anim.exit_anim)
|
||||
.setPopEnterAnim(R.anim.pop_enter_anim)
|
||||
.setPopExitAnim(R.anim.pop_exit_anim).build()
|
||||
);
|
||||
return true;
|
||||
});
|
||||
|
||||
}
|
||||
@@ -140,11 +114,9 @@ public class MainActivity extends AppCompatActivity {
|
||||
|
||||
|
||||
|
||||
|
||||
public interface activityResultRelay {
|
||||
void onActivityResult(int requestCode, int resultCode, Intent data);
|
||||
}
|
||||
|
||||
public static activityResultRelay resultRelay = null;
|
||||
public static void setResultRelay(activityResultRelay tmpresultRelay){
|
||||
resultRelay = tmpresultRelay;
|
||||
@@ -159,4 +131,25 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface onBackPressed {
|
||||
boolean onBackPressed();
|
||||
}
|
||||
|
||||
public onBackPressed backPressed = null;
|
||||
public void setOnBackPressed(onBackPressed onBackPressed){
|
||||
this.backPressed = onBackPressed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if(backPressed != null) {
|
||||
if (backPressed.onBackPressed()) {
|
||||
super.onBackPressed();
|
||||
}
|
||||
} else {super.onBackPressed();}
|
||||
}
|
||||
|
||||
}
|
||||
+21
-11
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
package com.ridgebotics.ridgescout.scoutingData;
|
||||
|
||||
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;
|
||||
|
||||
public class fields {
|
||||
// public static ScoutingVersion sv = new ScoutingVersion();
|
||||
|
||||
public static final String matchFieldsFilename = "matches.fields";
|
||||
public static final String pitsFieldsFilename = "pits.fields";
|
||||
|
||||
public static final inputType[][] default_match_fields = new inputType[][] {
|
||||
{
|
||||
new fieldposType("Auto start pos", "Where does the robot start its auto?", new int[]{0,0}),
|
||||
|
||||
new tallyType("Auto L4 Coral", "How many coral did this robot score in L4 during auto?", 0),
|
||||
new tallyType("Auto L3 Coral", "How many coral did this robot score in L3 during auto?", 0),
|
||||
new tallyType("Auto L2 Coral", "How many coral did this robot score in L2 during auto?", 0),
|
||||
new tallyType("Auto L1/Trough Coral", "How many coral did this robot score in L1 during auto?", 0),
|
||||
new tallyType("Auto Processor Algae", "How many algae did this robot score in the Barge during auto?", 0),
|
||||
new tallyType("Auto Barge Algae", "How many algae did this robot score in the Barge during auto?", 0),
|
||||
|
||||
new dropdownType("Auto Quality", "How did the robot drive during auto?", new String[]{"Smooth", "Jittery"}, 0),
|
||||
new textType("Auto Comments", "Anything interesting about auto", ""),
|
||||
|
||||
new tallyType("Teleop L4 Coral", "How many coral did this robot score in L4 during auto?", 0),
|
||||
new tallyType("Teleop L3 Coral", "How many coral did this robot score in L3 during auto?", 0),
|
||||
new tallyType("Teleop L2 Coral", "How many coral did this robot score in L2 during auto?", 0),
|
||||
new tallyType("Teleop L1 Coral", "How many coral did this robot score in L1 during auto?", 0),
|
||||
new tallyType("Teleop Processor Algae", "How many algae did this robot score in the Barge during auto?", 0),
|
||||
new tallyType("Teleop Barge Algae", "How many algae did this robot score in the Barge during auto?", 0),
|
||||
|
||||
new checkboxType("Upper Algae Removal", "Did the robot remove upper Algae?", 0),
|
||||
new checkboxType("Lower Algae Removal", "Did the robot remove lower Algae?", 0),
|
||||
|
||||
new dropdownType("Teleop Quality", "How did the robot drive during Teleop?", new String[]{"Smooth", "Jittery"}, 0),
|
||||
new textType("Teleop Comments", "Anything interesting about Teleop", ""),
|
||||
|
||||
new dropdownType("Climb State", "What was the final condition of the robot?", new String[]{"Nothing", "Continued Cycling", "Park", "Attempted Shallow", "Shallow", "Attempted Deep", "Deep"}, 0),
|
||||
|
||||
new dropdownType("Robot Condition", "Was anything broken?", new String[]{"Everything was working", "Something was maybe broken", "Something was broken", "Robot was disabled for part of the match", "Missing robot"}, 0),
|
||||
|
||||
new textType("Other Comments", "Any other comments you have", "")
|
||||
}
|
||||
};
|
||||
|
||||
public static final inputType[][] default_pit_fields = new inputType[][] {
|
||||
{
|
||||
new dropdownType("Drivetrain type", "What type of drivetrain does this team have?", new String[]{"Swerve Drive", "Tank Drive (Differential)", "Other, Info in comments"}, 0),
|
||||
new dropdownType("Intake type", "What type of intake does this team have?", new String[]{"Ground only", "Player Station only", "Both", "Other, Info in comments"}, 0),
|
||||
new dropdownType("Intake Consistency", "How consistent is the robot at intakeing?", new String[]{"Does not work", "Worked a few times during testing", "Works most of the time", "Fails sometimes", "Never fails"}, 0),
|
||||
|
||||
new dropdownType("Score Area", "What does this robot score?", new String[]{"Only Algae", "Mostly Algae", "Both", "Mostly Coral", "Only Coral"}, 0),
|
||||
|
||||
new checkboxType("L4 Scoring", "Will the robot score in Layer 4?", 0),
|
||||
new checkboxType("L3 Scoring", "Will the robot score in Layer 3?", 0),
|
||||
new checkboxType("L2 Scoring", "Will the robot score in Layer 3?", 0),
|
||||
new checkboxType("L1/Trough Scoring", "Will the robot score in Layer 1?", 0),
|
||||
new checkboxType("Processor Scoring", "Will the robot score in the Processor?", 0),
|
||||
new checkboxType("Barge Scoring", "Will the robot score algae in the Barge?", 0),
|
||||
new dropdownType("Scoring Consistency", "How consistent is the robot at Scoring?", new String[]{"Does not work", "Worked a few times during testing", "Works most of the time", "Fails sometimes", "Never fails"}, 0),
|
||||
|
||||
new textType("Auto Capability", "What autos does this team have?", ""),
|
||||
new dropdownType("Auto Consistency", "How consistent is the robot at Auto?", new String[]{"Does not work", "Worked a few times during testing", "Works most of the time", "Fails sometimes", "Never fails"}, 0),
|
||||
|
||||
new dropdownType("Climb type", "What does the robot do to climb?", new String[]{"No Climb", "Only Shallow", "Only Deep", "Both Shallow and Deep"}, 0),
|
||||
new dropdownType("Climb Consistency", "How consistent is the robot at climbing?", new String[]{"Does not work", "Worked a few times during testing", "Works most of the time", "Fails sometimes", "Never fails"}, 0),
|
||||
|
||||
new textType("Cool Comments", "Is there anything cool about the robot?", ""),
|
||||
|
||||
new textType("Comments", "Things go here", "Day 1:\n\nDay 2:\n\nDay 3:\n")
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static boolean save(String filename, inputType[][] values){
|
||||
try {
|
||||
ByteBuilder bb = new ByteBuilder();
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
bb.addRaw(127, save_version(values[i]));
|
||||
}
|
||||
fileEditor.writeFile(filename, bb.build());
|
||||
return true;
|
||||
}catch (ByteBuilder.buildingException e) {
|
||||
AlertManager.error(e);
|
||||
return false;
|
||||
// throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] save_version(inputType[] values) throws ByteBuilder.buildingException {
|
||||
ByteBuilder bb = new ByteBuilder();
|
||||
for(int i =0; i < values.length; i++){
|
||||
bb.addRaw(values[i].get_byte_id(), values[i].encode());
|
||||
}
|
||||
return bb.build();
|
||||
}
|
||||
|
||||
public static inputType[][] load(String filename){
|
||||
byte[] bytes = fileEditor.readFile(filename);
|
||||
|
||||
// System.out.println(bytes);
|
||||
|
||||
try {
|
||||
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
||||
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
||||
inputType[][] values = new inputType[objects.size()][];
|
||||
|
||||
for(int i = 0 ; i < objects.size(); i++){
|
||||
values[i] = load_version((byte[]) objects.get(i).get());
|
||||
}
|
||||
|
||||
|
||||
return values;
|
||||
} catch (Exception e) {
|
||||
AlertManager.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static inputType[] load_version(byte[] bytes) throws BuiltByteParser.byteParsingExeption{
|
||||
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
||||
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
||||
inputType[] output = new inputType[objects.size()];
|
||||
|
||||
for(int i = 0 ; i < objects.size(); i++){
|
||||
BuiltByteParser.parsedObject obj = objects.get(i);
|
||||
inputType t = null;
|
||||
switch (obj.getType()){
|
||||
case inputType.slider_type_id:
|
||||
t = new sliderType();
|
||||
break;
|
||||
case inputType.dropdownType:
|
||||
t = new dropdownType();
|
||||
break;
|
||||
case inputType.notesType:
|
||||
t = new textType();
|
||||
break;
|
||||
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());
|
||||
output[i] = t;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// public static void test(){
|
||||
// ScoutingVersion.transferType[][] transferValues = sv.get_transfer_values(values);
|
||||
//
|
||||
// ScoutingVersion.ScoutingArray msa = sv.new ScoutingArray(0, new ScoutingVersion.dataType[]{
|
||||
// sv.new stringType("name", "test-username"),
|
||||
// sv.new intType("How good is robot", 12)
|
||||
// }, values, transferValues);
|
||||
//
|
||||
// msa.update();
|
||||
//
|
||||
// for(ScoutingVersion.dataType dt : msa.array){
|
||||
// if(dt == null) continue;
|
||||
// switch (dt.getValueType()){
|
||||
// case NUM:
|
||||
// System.out.println(dt.name + " " + (int) dt.get());
|
||||
// break;
|
||||
// case STRING:
|
||||
// System.out.println(dt.name + " " + (String) dt.get());
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// }
|
||||
}
|
||||
+1
-1
@@ -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
-1
@@ -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;}
|
||||
+2
-2
@@ -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 {
|
||||
+8
-8
@@ -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;
|
||||
+7
-2
@@ -1,9 +1,14 @@
|
||||
package com.astatin3.scoutingapp2025.types.data;
|
||||
package com.ridgebotics.ridgescout.types.data;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
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
-1
@@ -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
-1
@@ -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";
|
||||
+5
-5
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
-4
@@ -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 "";
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -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,227 @@
|
||||
package com.ridgebotics.ridgescout.types.input;
|
||||
|
||||
import android.app.Activity;
|
||||
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 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, String description, int isChecked){
|
||||
super(name, description);
|
||||
this.default_value = isChecked;
|
||||
}
|
||||
|
||||
|
||||
public byte[] encode() throws ByteBuilder.buildingException {
|
||||
ByteBuilder bb = new ByteBuilder();
|
||||
bb.addString(name);
|
||||
bb.addString(description);
|
||||
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();
|
||||
description = (String) objects.get(1).get();
|
||||
default_value = objects.get(2).get();
|
||||
}
|
||||
|
||||
// public PowerSpinnerView dropdown = null;
|
||||
|
||||
public CheckBox checkBox = null;
|
||||
|
||||
public View createView(Context context, Function<dataType, Integer> onUpdate){
|
||||
checkBox = new CheckBox(context);
|
||||
checkBox.setTextAppearance(com.google.android.material.R.style.TextAppearance_MaterialComponents_Headline6);
|
||||
checkBox.setText(name);
|
||||
|
||||
setViewValue(default_value);
|
||||
checkBox.setOnCheckedChangeListener((buttonView, 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.setTextAppearance(com.google.android.material.R.style.TextAppearance_MaterialComponents_Headline6);
|
||||
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);
|
||||
}
|
||||
|
||||
public String toString(dataType data){
|
||||
return (int) data.get() == 1 ? "true" : "false";
|
||||
}
|
||||
}
|
||||
|
||||
+29
-55
@@ -1,5 +1,8 @@
|
||||
package com.astatin3.scoutingapp2025.types.input;
|
||||
package com.ridgebotics.ridgescout.types.input;
|
||||
|
||||
import static com.google.android.material.internal.ContextUtils.getActivity;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.view.Gravity;
|
||||
@@ -11,10 +14,11 @@ 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.ui.CustomSpinnerView;
|
||||
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;
|
||||
@@ -24,13 +28,9 @@ 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.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.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -42,8 +42,8 @@ public class dropdownType extends inputType {
|
||||
public Object get_fallback_value(){return 0;}
|
||||
public dropdownType(){};
|
||||
public String get_type_name(){return "Dropdown";}
|
||||
public dropdownType(String name, String[] text_options, int defaultSelIndex){
|
||||
super(name);
|
||||
public dropdownType(String name, String description, String[] text_options, int defaultSelIndex){
|
||||
super(name, description);
|
||||
this.text_options = text_options;
|
||||
this.default_value = defaultSelIndex;
|
||||
}
|
||||
@@ -52,6 +52,7 @@ public class dropdownType extends inputType {
|
||||
public byte[] encode() throws ByteBuilder.buildingException {
|
||||
ByteBuilder bb = new ByteBuilder();
|
||||
bb.addString(name);
|
||||
bb.addString(description);
|
||||
bb.addInt((int)default_value);
|
||||
bb.addStringArray(text_options);
|
||||
return bb.build();
|
||||
@@ -61,55 +62,24 @@ public class dropdownType extends inputType {
|
||||
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
||||
|
||||
name = (String) objects.get(0).get();
|
||||
default_value = objects.get(1).get();
|
||||
text_options = (String[]) objects.get(2).get();
|
||||
description = (String) objects.get(1).get();
|
||||
default_value = objects.get(2).get();
|
||||
text_options = (String[]) objects.get(3).get();
|
||||
}
|
||||
|
||||
public PowerSpinnerView dropdown = null;
|
||||
public CustomSpinnerView dropdown = null;
|
||||
|
||||
public View createView(Context context, Function<dataType, Integer> onUpdate){
|
||||
dropdown = new PowerSpinnerView(context);
|
||||
dropdown = new CustomSpinnerView(context);
|
||||
|
||||
List<IconSpinnerItem> iconSpinnerItems = new ArrayList<>();
|
||||
for(int i = 0; i < text_options.length; i++){
|
||||
iconSpinnerItems.add(new IconSpinnerItem(text_options[i]));
|
||||
}
|
||||
IconSpinnerAdapter iconSpinnerAdapter = new IconSpinnerAdapter(dropdown);
|
||||
ArrayList<String> iconSpinnerItems = new ArrayList<>(Arrays.asList(text_options));
|
||||
|
||||
dropdown.setGravity(Gravity.CENTER);
|
||||
dropdown.setTitle(name);
|
||||
dropdown.setOptions(iconSpinnerItems, (int) default_value);
|
||||
onUpdate.apply(getViewValue());
|
||||
|
||||
dropdown.setSpinnerAdapter(iconSpinnerAdapter);
|
||||
dropdown.setItems(iconSpinnerItems);
|
||||
dropdown.setOnClickListener((item, index) -> onUpdate.apply(getViewValue()));
|
||||
|
||||
dropdown.selectItemByIndex((int) default_value);
|
||||
|
||||
dropdown.setPadding(10,20,10,20);
|
||||
dropdown.setBackgroundColor(0xf0000000);
|
||||
dropdown.setTextColor(0xff00ff00);
|
||||
dropdown.setTextSize(14.5f);
|
||||
dropdown.setArrowGravity(SpinnerGravity.END);
|
||||
dropdown.setArrowPadding(8);
|
||||
// dropdown.setSpinnerItemHeight(46);
|
||||
dropdown.setSpinnerPopupElevation(14);
|
||||
|
||||
|
||||
|
||||
|
||||
dropdown.setOnSpinnerItemSelectedListener(new OnSpinnerItemSelectedListener<IconSpinnerItem>() {
|
||||
@Override
|
||||
public void onItemSelected(int oldIndex, @Nullable IconSpinnerItem oldItem, int newIndex,
|
||||
IconSpinnerItem newItem) {
|
||||
onUpdate.apply(getViewValue());
|
||||
}
|
||||
});
|
||||
|
||||
// dropdown.setLifecycleOwner(context.life);
|
||||
// slider.addOnChangeListener(new Slider.OnChangeListener() {
|
||||
// @Override
|
||||
// public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
|
||||
// onUpdate.apply(getViewValue());
|
||||
// }
|
||||
// });
|
||||
return dropdown;
|
||||
|
||||
}
|
||||
@@ -123,7 +93,7 @@ public class dropdownType extends inputType {
|
||||
isBlank = false;
|
||||
|
||||
dropdown.setVisibility(View.VISIBLE);
|
||||
dropdown.selectItemByIndex((int) value);
|
||||
dropdown.setOption((int) value);
|
||||
}
|
||||
public void nullify(){
|
||||
isBlank = true;
|
||||
@@ -132,7 +102,7 @@ public class dropdownType extends inputType {
|
||||
public dataType getViewValue(){
|
||||
if(dropdown == null) return null;
|
||||
if(dropdown.getVisibility() == View.GONE) return new intType(name, intType.nullval);
|
||||
return new intType(name, dropdown.getSelectedIndex());
|
||||
return new intType(name, dropdown.getIndex());
|
||||
}
|
||||
|
||||
|
||||
@@ -275,5 +245,9 @@ public class dropdownType extends inputType {
|
||||
chart.invalidate();
|
||||
parent.addView(chart);
|
||||
}
|
||||
|
||||
public String toString(dataType data){
|
||||
return text_options[(int) data.get()];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
package com.ridgebotics.ridgescout.types.input;
|
||||
|
||||
import static android.text.InputType.TYPE_CLASS_NUMBER;
|
||||
|
||||
import android.app.Activity;
|
||||
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, String description, int[] default_value){
|
||||
super(name, description);
|
||||
this.default_value = default_value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public byte[] encode() throws ByteBuilder.buildingException {
|
||||
ByteBuilder bb = new ByteBuilder();
|
||||
bb.addString(name);
|
||||
bb.addString(description);
|
||||
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();
|
||||
description = (String) objects.get(1).get();
|
||||
default_value = objects.get(2).get();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
if(((int[]) value)[0] == 255 && ((int[]) value)[1] == 255){
|
||||
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);
|
||||
}
|
||||
|
||||
public String toString(dataType data){
|
||||
int[] intarr = (int[]) data.get();
|
||||
return "[" + intarr[0] + "," + intarr[1] + "]";
|
||||
}
|
||||
}
|
||||
|
||||
+19
-10
@@ -1,16 +1,13 @@
|
||||
package com.astatin3.scoutingapp2025.types.input;
|
||||
package com.ridgebotics.ridgescout.types.input;
|
||||
|
||||
import android.app.Activity;
|
||||
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,21 +16,30 @@ 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 String description;
|
||||
public Object default_value;
|
||||
public abstract inputTypes getInputType();
|
||||
public abstract dataType.valueTypes getValueType();
|
||||
public abstract Object get_fallback_value();
|
||||
public abstract int get_byte_id();
|
||||
public inputType(){}
|
||||
public inputType(String name){
|
||||
public inputType(String name, String description){
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public abstract String get_type_name();
|
||||
@@ -101,4 +107,7 @@ public abstract class inputType {
|
||||
|
||||
|
||||
public abstract void add_history_view(LinearLayout parent, dataType[] data);
|
||||
|
||||
|
||||
public abstract String toString(dataType data);
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
package com.ridgebotics.ridgescout.types.input;
|
||||
|
||||
import static android.text.InputType.TYPE_CLASS_NUMBER;
|
||||
|
||||
import android.app.Activity;
|
||||
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, String description, int default_value){
|
||||
super(name, description);
|
||||
this.default_value = default_value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public byte[] encode() throws ByteBuilder.buildingException {
|
||||
ByteBuilder bb = new ByteBuilder();
|
||||
bb.addString(name);
|
||||
bb.addString(description);
|
||||
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();
|
||||
description = (String) objects.get(1).get();
|
||||
default_value = objects.get(2).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);
|
||||
}
|
||||
|
||||
public String toString(dataType data){
|
||||
return String.valueOf((int) data.get());
|
||||
}
|
||||
}
|
||||
|
||||
+19
-13
@@ -1,5 +1,6 @@
|
||||
package com.astatin3.scoutingapp2025.types.input;
|
||||
package com.ridgebotics.ridgescout.types.input;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.view.View;
|
||||
@@ -9,12 +10,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;
|
||||
@@ -36,8 +36,8 @@ public class sliderType extends inputType {
|
||||
public Object get_fallback_value(){return 0;}
|
||||
public sliderType(){};
|
||||
public String get_type_name(){return "Slider";}
|
||||
public sliderType(String name, int defaultValue, int min, int max){
|
||||
super(name);
|
||||
public sliderType(String name, String description, int defaultValue, int min, int max){
|
||||
super(name, description);
|
||||
this.default_value = defaultValue;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
@@ -49,6 +49,7 @@ public class sliderType extends inputType {
|
||||
public byte[] encode() throws ByteBuilder.buildingException {
|
||||
ByteBuilder bb = new ByteBuilder();
|
||||
bb.addString(name);
|
||||
bb.addString(description);
|
||||
bb.addInt((int)default_value);
|
||||
bb.addInt(min);
|
||||
bb.addInt(max);
|
||||
@@ -58,10 +59,11 @@ public class sliderType extends inputType {
|
||||
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
||||
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
||||
|
||||
name = (String) objects.get(0).get();
|
||||
default_value = objects.get(1).get();
|
||||
min = (int) objects.get(2).get();
|
||||
max = (int) objects.get(3).get();
|
||||
name = (String) objects.get(0).get();
|
||||
description = (String) objects.get(1).get();
|
||||
default_value = objects.get(2).get();
|
||||
min = (int) objects.get(3).get();
|
||||
max = (int) objects.get(4).get();
|
||||
}
|
||||
|
||||
|
||||
@@ -303,4 +305,8 @@ public class sliderType extends inputType {
|
||||
|
||||
parent.addView(chart);
|
||||
}
|
||||
|
||||
public String toString(dataType data){
|
||||
return String.valueOf((int) data.get());
|
||||
}
|
||||
}
|
||||
+16
-10
@@ -1,5 +1,6 @@
|
||||
package com.astatin3.scoutingapp2025.types.input;
|
||||
package com.ridgebotics.ridgescout.types.input;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.view.Gravity;
|
||||
@@ -9,11 +10,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;
|
||||
@@ -31,8 +32,8 @@ public class tallyType extends inputType {
|
||||
public Object get_fallback_value(){return 0;}
|
||||
public tallyType(){}
|
||||
public String get_type_name(){return "Tally";}
|
||||
public tallyType(String name, int default_value){
|
||||
super(name);
|
||||
public tallyType(String name, String description, int default_value){
|
||||
super(name, description);
|
||||
this.default_value = default_value;
|
||||
}
|
||||
|
||||
@@ -43,6 +44,7 @@ public class tallyType extends inputType {
|
||||
public byte[] encode() throws ByteBuilder.buildingException {
|
||||
ByteBuilder bb = new ByteBuilder();
|
||||
bb.addString(name);
|
||||
bb.addString(description);
|
||||
bb.addInt((int)default_value);
|
||||
return bb.build();
|
||||
}
|
||||
@@ -51,7 +53,8 @@ public class tallyType extends inputType {
|
||||
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
||||
|
||||
name = (String) objects.get(0).get();
|
||||
default_value = objects.get(1).get();
|
||||
description = (String) objects.get(1).get();
|
||||
default_value = objects.get(2).get();
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +75,6 @@ public class tallyType extends inputType {
|
||||
|
||||
public void setViewValue(Object value) {
|
||||
if(tally == null) return;
|
||||
System.out.println(value);
|
||||
if(intType.isNull((int)value)){
|
||||
nullify();
|
||||
return;
|
||||
@@ -296,5 +298,9 @@ public class tallyType extends inputType {
|
||||
|
||||
parent.addView(chart);
|
||||
}
|
||||
|
||||
public String toString(dataType data){
|
||||
return String.valueOf((int) data.get());
|
||||
}
|
||||
}
|
||||
|
||||
+17
-10
@@ -1,5 +1,6 @@
|
||||
package com.astatin3.scoutingapp2025.types.input;
|
||||
package com.ridgebotics.ridgescout.types.input;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.text.Editable;
|
||||
@@ -12,11 +13,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;
|
||||
@@ -34,8 +35,8 @@ public class textType extends inputType {
|
||||
public dataType.valueTypes getValueType(){return dataType.valueTypes.STRING;}
|
||||
public Object get_fallback_value(){return "<no-notes>";}
|
||||
public textType(){}
|
||||
public textType(String name, String default_text){
|
||||
super(name);
|
||||
public textType(String name, String description, String default_text){
|
||||
super(name, description);
|
||||
this.default_value = default_text;
|
||||
}
|
||||
public String get_type_name(){return "Text";}
|
||||
@@ -49,6 +50,7 @@ public class textType extends inputType {
|
||||
public byte[] encode() throws ByteBuilder.buildingException {
|
||||
ByteBuilder bb = new ByteBuilder();
|
||||
bb.addString(name);
|
||||
bb.addString(description);
|
||||
bb.addString((String) default_value);
|
||||
return bb.build();
|
||||
}
|
||||
@@ -56,8 +58,9 @@ public class textType extends inputType {
|
||||
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
||||
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
||||
|
||||
name = (String) objects.get(0).get();
|
||||
default_value = objects.get(1).get();
|
||||
name = (String) objects.get(0).get();
|
||||
description = (String) objects.get(1).get();
|
||||
default_value = objects.get(2).get();
|
||||
}
|
||||
|
||||
|
||||
@@ -227,5 +230,9 @@ public class textType extends inputType {
|
||||
parent.addView(chart);
|
||||
|
||||
}
|
||||
|
||||
public String toString(dataType data){
|
||||
return String.valueOf(data.get());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
package com.ridgebotics.ridgescout.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class BackgroundView extends View {
|
||||
private List<Circle> circles;
|
||||
private Paint whitePaint;
|
||||
private Paint greenPaint;
|
||||
private Random random;
|
||||
|
||||
// Physics simulation constants
|
||||
private static final float GRAVITY = 9.8f;
|
||||
private static final float DAMPING = 0.5f;
|
||||
private static final float CIRCLE_SPAWN_INTERVAL = 500; // milliseconds
|
||||
private long lastSpawnTime = 0;
|
||||
|
||||
// Screen dimensions
|
||||
private int screenWidth;
|
||||
private int screenHeight;
|
||||
|
||||
public BackgroundView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
initialize();
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
// Setup paints
|
||||
whitePaint = new Paint();
|
||||
whitePaint.setColor(Color.WHITE);
|
||||
whitePaint.setStyle(Paint.Style.STROKE);
|
||||
whitePaint.setStrokeWidth(2);
|
||||
|
||||
greenPaint = new Paint();
|
||||
greenPaint.setColor(Color.GREEN);
|
||||
greenPaint.setStyle(Paint.Style.FILL);
|
||||
|
||||
circles = new ArrayList<>();
|
||||
random = new Random();
|
||||
|
||||
// Get screen dimensions after layout
|
||||
ViewTreeObserver vto = getViewTreeObserver();
|
||||
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
screenWidth = getWidth();
|
||||
screenHeight = getHeight();
|
||||
getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
// Spawn new circles periodically
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if (currentTime - lastSpawnTime > CIRCLE_SPAWN_INTERVAL) {
|
||||
spawnCircle();
|
||||
lastSpawnTime = currentTime;
|
||||
}
|
||||
|
||||
// First pass: detect all collisions
|
||||
List<Collision> collisions = new ArrayList<>();
|
||||
for (int i = 0; i < circles.size(); i++) {
|
||||
Circle circle = circles.get(i);
|
||||
|
||||
// Wall and floor collisions
|
||||
if (circle.x - circle.radius < 0) {
|
||||
circle.x = circle.radius;
|
||||
circle.velocityX *= -DAMPING;
|
||||
}
|
||||
if (circle.x + circle.radius > screenWidth) {
|
||||
circle.x = screenWidth - circle.radius;
|
||||
circle.velocityX *= -DAMPING;
|
||||
}
|
||||
if (circle.y + circle.radius > screenHeight) {
|
||||
circle.y = screenHeight - circle.radius;
|
||||
circle.velocityY = 0;
|
||||
}
|
||||
|
||||
// Detect collisions with other circles
|
||||
for (int j = i + 1; j < circles.size(); j++) {
|
||||
Circle otherCircle = circles.get(j);
|
||||
float dx = otherCircle.x - circle.x;
|
||||
float dy = otherCircle.y - circle.y;
|
||||
float distance = (float) Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
if (distance < circle.radius + otherCircle.radius) {
|
||||
collisions.add(new Collision(circle, otherCircle, dx, dy, distance));
|
||||
}
|
||||
}
|
||||
|
||||
// Apply gravity
|
||||
circle.velocityY += GRAVITY * 0.1f;
|
||||
}
|
||||
|
||||
// Second pass: resolve collisions
|
||||
for (Collision collision : collisions) {
|
||||
Circle c1 = collision.circle1;
|
||||
Circle c2 = collision.circle2;
|
||||
float dx = collision.dx;
|
||||
float dy = collision.dy;
|
||||
float distance = collision.distance;
|
||||
|
||||
// Calculate overlap
|
||||
float overlap = (c1.radius + c2.radius - distance) / 2;
|
||||
|
||||
// Separate circles
|
||||
float separationX = overlap * dx / distance;
|
||||
float separationY = overlap * dy / distance;
|
||||
|
||||
c1.x -= separationX;
|
||||
c1.y -= separationY;
|
||||
c2.x += separationX;
|
||||
c2.y += separationY;
|
||||
|
||||
// Dampen velocities
|
||||
c1.velocityX *= DAMPING;
|
||||
c1.velocityY *= DAMPING;
|
||||
c2.velocityX *= DAMPING;
|
||||
c2.velocityY *= DAMPING;
|
||||
}
|
||||
|
||||
// Draw and update circles
|
||||
Iterator<Circle> iterator = circles.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Circle circle = iterator.next();
|
||||
|
||||
// Update position
|
||||
circle.x += circle.velocityX;
|
||||
circle.y += circle.velocityY;
|
||||
|
||||
// Draw circle
|
||||
Paint paint = circle.isGreen ? greenPaint : whitePaint;
|
||||
canvas.drawCircle(circle.x, circle.y, circle.radius, paint);
|
||||
|
||||
// Remove circles that have fallen off screen
|
||||
if (circle.y > screenHeight + circle.radius) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger redraw
|
||||
invalidate();
|
||||
}
|
||||
|
||||
// Collision tracking class
|
||||
private static class Collision {
|
||||
Circle circle1, circle2;
|
||||
float dx, dy, distance;
|
||||
|
||||
Collision(Circle c1, Circle c2, float dx, float dy, float distance) {
|
||||
this.circle1 = c1;
|
||||
this.circle2 = c2;
|
||||
this.dx = dx;
|
||||
this.dy = dy;
|
||||
this.distance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
private void spawnCircle() {
|
||||
// More likely to spawn white circles
|
||||
boolean isGreen = random.nextFloat() < 0.2f;
|
||||
|
||||
float radius = isGreen ?
|
||||
120: // Green: 20-60
|
||||
80; // White: 10-30
|
||||
|
||||
float x = random.nextFloat() * screenWidth;
|
||||
float velocityX = (random.nextFloat() - 0.5f) * 5;
|
||||
|
||||
circles.add(new Circle(x, -radius, radius, velocityX, 0, isGreen));
|
||||
}
|
||||
|
||||
// Circle class to represent individual circles
|
||||
private static class Circle {
|
||||
float x, y;
|
||||
float radius;
|
||||
float velocityX, velocityY;
|
||||
boolean isGreen;
|
||||
|
||||
Circle(float x, float y, float radius, float velocityX, float velocityY, boolean isGreen) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.radius = radius;
|
||||
this.velocityX = velocityX;
|
||||
this.velocityY = velocityY;
|
||||
this.isGreen = isGreen;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package com.ridgebotics.ridgescout.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TableLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.appbar.MaterialToolbar;
|
||||
import com.google.android.material.divider.MaterialDivider;
|
||||
import com.ridgebotics.ridgescout.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CustomSpinnerPopup extends TableLayout {
|
||||
|
||||
public CustomSpinnerPopup(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public CustomSpinnerPopup(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public interface OnOptionSelectedListener {
|
||||
void onOptionSelected(String option);
|
||||
}
|
||||
|
||||
public CustomSpinnerPopup init(List<String> options, OnOptionSelectedListener onOptionSelectedListener, int defaultOption){
|
||||
CheckBox[] checkBoxes = new CheckBox[options.size()];
|
||||
setPadding(16, 16, 16, 16);
|
||||
for(int i = 0; i < options.size(); i++){
|
||||
final CheckBox cb = new CheckBox(getContext());
|
||||
cb.setText(options.get(i));
|
||||
cb.setTextAppearance(com.google.android.material.R.style.TextAppearance_MaterialComponents_Headline5);
|
||||
cb.setChecked(i == defaultOption);
|
||||
|
||||
if(i > 0)
|
||||
addView(new MaterialDivider(getContext()));
|
||||
|
||||
addView(cb);
|
||||
checkBoxes[i] = cb;
|
||||
|
||||
final int fi = i;
|
||||
cb.setOnClickListener(a -> {
|
||||
onOptionSelectedListener.onOptionSelected(options.get(fi));
|
||||
for (CheckBox checkBox : checkBoxes)
|
||||
checkBox.setChecked(false);
|
||||
cb.setChecked(true);
|
||||
});
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// public static CustomSpinnerPopup newInstance(ArrayList<String> options) {
|
||||
// CustomSpinnerPopup dialog = new CustomSpinnerPopup();
|
||||
// Bundle args = new Bundle();
|
||||
// args.putStringArrayList("options", options);
|
||||
//
|
||||
//
|
||||
//
|
||||
//// dialog.setArguments(args);
|
||||
// return dialog;
|
||||
// }
|
||||
|
||||
// @Override
|
||||
// public void onCreate(Bundle savedInstanceState) {
|
||||
// super.onCreate(savedInstanceState);
|
||||
// setStyle(DialogFragment.STYLE_NORMAL, R.style.FullScreenDialogStyle);
|
||||
// if (getArguments() != null) {
|
||||
// options = getArguments().getStringArrayList("options");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Nullable
|
||||
// @Override
|
||||
// public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
// @Nullable Bundle savedInstanceState) {
|
||||
// View view = inflater.inflate(R.layout.view_custom_spinner_popup, container, false);
|
||||
//
|
||||
// // Setup toolbar
|
||||
// MaterialToolbar toolbar = view.findViewById(R.id.toolbar);
|
||||
// toolbar.setNavigationOnClickListener(v -> dismiss());
|
||||
// toolbar.setTitle("Select an Option");
|
||||
//
|
||||
// // Setup RecyclerView
|
||||
// recyclerView = view.findViewById(R.id.recyclerView);
|
||||
// recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
// adapter = new CustomSpinnerOptionsAdapter(options, option -> {
|
||||
// if (listener != null) {
|
||||
// listener.onOptionSelected(option);
|
||||
// }
|
||||
// dismiss();
|
||||
// });
|
||||
// recyclerView.setAdapter(adapter);
|
||||
//
|
||||
// return view;
|
||||
// }
|
||||
//
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
package com.ridgebotics.ridgescout.ui;
|
||||
|
||||
import static android.app.PendingIntent.getActivity;
|
||||
import static com.ridgebotics.ridgescout.utility.settingsManager.getEditor;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.ridgebotics.ridgescout.R;
|
||||
import com.ridgebotics.ridgescout.databinding.ViewCustomSpinnerBinding;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CustomSpinnerView extends LinearLayout {
|
||||
|
||||
public interface onClickListener {
|
||||
void onClick(String item, int index);
|
||||
}
|
||||
|
||||
public CustomSpinnerView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public CustomSpinnerView(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private List<String> options;
|
||||
private onClickListener onClickListener;
|
||||
|
||||
private TextView title;
|
||||
private TextView item;
|
||||
|
||||
private int index = -1;
|
||||
|
||||
public void init(Context context) {
|
||||
LayoutInflater.from(context).inflate(R.layout.view_custom_spinner, this, true);
|
||||
|
||||
title = findViewById(R.id.title);
|
||||
item = findViewById(R.id.item);
|
||||
}
|
||||
|
||||
public void setOnClickListener(onClickListener listener){
|
||||
this.onClickListener = listener;
|
||||
}
|
||||
|
||||
|
||||
public void setOptions(List<String> options, String defaultOption){
|
||||
setOptions(options, options.indexOf(defaultOption));
|
||||
}
|
||||
|
||||
public void setOptions(List<String> options, int defaultOption){
|
||||
this.options = options;
|
||||
this.index = defaultOption;
|
||||
|
||||
if(defaultOption != -1)
|
||||
this.item.setText(options.get(defaultOption));
|
||||
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
|
||||
ScrollView sv = new ScrollView(getContext());
|
||||
// sv.setLayoutDirection(ScrollView.SCROLL_AXIS_VERTICAL);
|
||||
|
||||
LinearLayout ll = new LinearLayout(getContext());
|
||||
ll.setOrientation(LinearLayout.VERTICAL);
|
||||
sv.addView(ll);
|
||||
|
||||
builder.setPositiveButton("OK", (dialog, which) -> {});
|
||||
CustomSpinnerPopup popup = new CustomSpinnerPopup(getContext()).init(options, option -> {
|
||||
// dialog.();
|
||||
if(!isEnabled()) return;
|
||||
item.setText(option);
|
||||
index = options.indexOf(option);
|
||||
if(onClickListener != null) {
|
||||
onClickListener.onClick(option, options.indexOf(option));
|
||||
}
|
||||
}, index);
|
||||
|
||||
ll.addView(popup);
|
||||
|
||||
// popup.setLayoutDirection(0);
|
||||
builder.setView(sv);
|
||||
AlertDialog dialog = builder.create();
|
||||
|
||||
|
||||
// popup.setOnOptionSelectedListener();
|
||||
|
||||
this.setOnClickListener(v -> {
|
||||
if(!isEnabled()) return;
|
||||
dialog.show();
|
||||
});
|
||||
}
|
||||
|
||||
public void setTitle(String text){
|
||||
title.setText(text);
|
||||
}
|
||||
|
||||
public void setOption(String option) {
|
||||
item.setText(option);
|
||||
index = options.indexOf(option);
|
||||
}
|
||||
|
||||
public void setOption(int index) {
|
||||
item.setText(options.get(index));
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public int getIndex(){
|
||||
return index;
|
||||
}
|
||||
public String getOption(){
|
||||
return options.get(index);
|
||||
}
|
||||
}
|
||||
+8
-10
@@ -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;
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.ridgebotics.ridgescout.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
import com.ridgebotics.ridgescout.R;
|
||||
|
||||
public class ToggleTitleView extends ConstraintLayout {
|
||||
public ToggleTitleView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public ToggleTitleView(@NonNull Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public interface OnToggleListener {
|
||||
void onToggle(boolean enabled);
|
||||
}
|
||||
|
||||
TextView titleView;
|
||||
CheckBox toggle_title_checkbox;
|
||||
TextView toggle_title_description;
|
||||
OnToggleListener onToggleListener;
|
||||
|
||||
|
||||
|
||||
public void init(Context context){
|
||||
LayoutInflater.from(context).inflate(R.layout.view_toggle_title, this, true);
|
||||
|
||||
titleView = findViewById(R.id.toggle_title);
|
||||
toggle_title_checkbox = findViewById(R.id.toggle_title_checkbox);
|
||||
toggle_title_description = findViewById(R.id.toggle_title_description);
|
||||
|
||||
toggle_title_checkbox.setOnCheckedChangeListener((compoundButton, checked) -> {
|
||||
// If checkbox has already updated
|
||||
if(enabled == checked) return;
|
||||
|
||||
if (checked)
|
||||
enable();
|
||||
else
|
||||
disable();
|
||||
|
||||
onToggleListener.onToggle(!checked);
|
||||
});
|
||||
}
|
||||
|
||||
public void setTitle(String title){
|
||||
titleView.setText(title);
|
||||
}
|
||||
|
||||
public void setDescription(String description){
|
||||
toggle_title_description.setText(description);
|
||||
}
|
||||
|
||||
public void setOnToggleListener(OnToggleListener onToggleListener){
|
||||
this.onToggleListener = onToggleListener;
|
||||
}
|
||||
|
||||
public boolean enabled = true;
|
||||
|
||||
public boolean isEnabled(){return enabled;}
|
||||
|
||||
public void disable(){
|
||||
enabled = false;
|
||||
toggle_title_checkbox.setChecked(false);
|
||||
toggle_title_description.setVisibility(View.GONE);
|
||||
setBackgroundColor(0xffff0000);
|
||||
titleView.setTextColor(0xff000000);
|
||||
}
|
||||
public void enable(){
|
||||
enabled = true;
|
||||
toggle_title_checkbox.setChecked(true);
|
||||
toggle_title_description.setVisibility(View.VISIBLE);
|
||||
setBackgroundColor(0x00000000);
|
||||
titleView.setTextAppearance(com.google.android.material.R.style.TextAppearance_MaterialComponents_Headline5);
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled){
|
||||
if(enabled)
|
||||
disable();
|
||||
else
|
||||
enable();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.ridgebotics.ridgescout.ui.data;
|
||||
|
||||
|
||||
import static android.view.View.VISIBLE;
|
||||
import static androidx.navigation.fragment.FragmentKt.findNavController;
|
||||
|
||||
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.ridgebotics.ridgescout.R;
|
||||
import com.ridgebotics.ridgescout.scoutingData.fields;
|
||||
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 {
|
||||
|
||||
private FragmentDataBinding binding;
|
||||
|
||||
private boolean submenu = false;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
binding = FragmentDataBinding.inflate(inflater, container, false);
|
||||
View root = binding.getRoot();
|
||||
|
||||
String evcode = settingsManager.getEVCode();
|
||||
|
||||
binding.fieldsButton.setOnClickListener(v -> {
|
||||
binding.fieldsButton.setEnabled(false);
|
||||
binding.fieldsButtons.setVisibility(VISIBLE);
|
||||
});
|
||||
|
||||
binding.fieldsMatchesButton.setOnClickListener(v -> {
|
||||
FieldsFragment.set_filename(fields.matchFieldsFilename);
|
||||
findNavController(this).navigate(R.id.action_navigation_data_to_navigation_data_fields);
|
||||
});
|
||||
|
||||
binding.fieldsPitsButton.setOnClickListener(v -> {
|
||||
FieldsFragment.set_filename(fields.pitsFieldsFilename);
|
||||
findNavController(this).navigate(R.id.action_navigation_data_to_navigation_data_fields);
|
||||
});
|
||||
|
||||
if(evcode.equals("unset")){
|
||||
binding.noEventError.setVisibility(VISIBLE);
|
||||
|
||||
binding.buttons.setVisibility(VISIBLE);
|
||||
binding.teamsButton.setEnabled(false);
|
||||
binding.fieldsButton.setVisibility(VISIBLE);
|
||||
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
frcEvent event = frcEvent.decode(fileEditor.readFile(evcode + ".eventdata"));
|
||||
|
||||
binding.teamsButton.setOnClickListener(v -> {
|
||||
TeamSelectorFragment.setPits_mode(false);
|
||||
TeamSelectorFragment.setOnSelect((self, team) -> {
|
||||
TeamsFragment.setTeam(team);
|
||||
findNavController(self).navigate(R.id.action_navigation_team_selector_to_navigation_data_teams);
|
||||
});
|
||||
findNavController(this).navigate(R.id.action_navigation_data_to_navigation_team_selector);
|
||||
});
|
||||
return root;
|
||||
}
|
||||
}
|
||||
+109
-16
@@ -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,25 +58,52 @@ 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 paramString("Description", ""),
|
||||
new paramNumber("Min", 0),
|
||||
new paramNumber("Max", 10),
|
||||
new paramNumber("Default Value", 5)
|
||||
};
|
||||
public static final parameterType[] defaultDropdownParams = new parameterType[]{
|
||||
new paramString("Description", ""),
|
||||
new paramStringArray("Default Value", new String[]{"Zero","One","Two","Three"}),
|
||||
new paramNumber("Default Option", 0),
|
||||
};
|
||||
public static final parameterType[] defaultTextParams = new parameterType[]{
|
||||
new paramString("Description", ""),
|
||||
new paramString("Default Value", "")
|
||||
};
|
||||
public static final parameterType[] defaultTallyParams = new parameterType[]{
|
||||
new paramString("Description", ""),
|
||||
new paramNumber("Default Value", 0)
|
||||
};
|
||||
public static final parameterType[] defaultNumberParams = new parameterType[]{
|
||||
new paramString("Description", ""),
|
||||
new paramNumber("Default Value", 0)
|
||||
};
|
||||
public static final parameterType[] defaultCheckboxParam = new parameterType[]{
|
||||
new paramString("Description", ""),
|
||||
new paramNumber("Default Value ( 1 or 0 )", 0)
|
||||
};
|
||||
public static final parameterType[] defaultFieldPosParam = new parameterType[]{
|
||||
new paramString("Description", ""),
|
||||
new paramNumber("Default X", 0),
|
||||
new paramNumber("Default Y", 0)
|
||||
};
|
||||
|
||||
|
||||
private static parameterType[] getSliderParams(sliderType s){
|
||||
return new parameterType[]{
|
||||
new paramString("Description", s.description),
|
||||
new paramNumber("Min", s.min),
|
||||
new paramNumber("Max", s.max),
|
||||
new paramNumber("Default Value", (int) s.default_value)
|
||||
@@ -82,6 +112,7 @@ public class FieldEditorHelper {
|
||||
|
||||
private static parameterType[] getDropdownParams(dropdownType s){
|
||||
return new parameterType[]{
|
||||
new paramString("Description", s.description),
|
||||
new paramStringArray("Default Value",s.text_options),
|
||||
new paramNumber("Default Option", (int) s.default_value),
|
||||
};
|
||||
@@ -89,37 +120,84 @@ public class FieldEditorHelper {
|
||||
|
||||
private static parameterType[] getTextParams(textType s){
|
||||
return new parameterType[]{
|
||||
new paramString("Description", s.description),
|
||||
new paramString("Default Value", (String) s.default_value)
|
||||
};
|
||||
}
|
||||
|
||||
private static parameterType[] getTallyParams(tallyType s){
|
||||
return new parameterType[]{
|
||||
new paramString("Description", s.description),
|
||||
new paramNumber("Default Value", (int) s.default_value)
|
||||
};
|
||||
}
|
||||
|
||||
private static parameterType[] getNumberParams(numberType s){
|
||||
return new parameterType[]{
|
||||
new paramString("Description", s.description),
|
||||
new paramNumber("Default Value", (int) s.default_value)
|
||||
};
|
||||
}
|
||||
|
||||
private static parameterType[] getCheckboxParam(checkboxType s){
|
||||
return new parameterType[]{
|
||||
new paramString("Description", s.description),
|
||||
new paramNumber("Default Value ( 1 or 0 )", (int) s.default_value)
|
||||
};
|
||||
}
|
||||
|
||||
private static parameterType[] getFieldPosParam(fieldposType s){
|
||||
return new parameterType[]{
|
||||
new paramString("Description", s.description),
|
||||
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){
|
||||
s.min = ((paramNumber) types[0]).val;
|
||||
s.max = ((paramNumber) types[1]).val;
|
||||
s.default_value = ((paramNumber) types[2]).val;
|
||||
s.description = ((paramString) types[0]).val;
|
||||
s.min = ((paramNumber) types[1]).val;
|
||||
s.max = ((paramNumber) types[2]).val;
|
||||
s.default_value = ((paramNumber) types[3]).val;
|
||||
}
|
||||
|
||||
public static void setDropdownParams(dropdownType s, parameterType[] types){
|
||||
s.text_options = ((paramStringArray) types[0]).val;
|
||||
s.default_value = ((paramNumber) types[1]).val;
|
||||
s.description = ((paramString) types[0]).val;
|
||||
s.text_options = ((paramStringArray) types[1]).val;
|
||||
s.default_value = ((paramNumber) types[2]).val;
|
||||
}
|
||||
|
||||
public static void setTextParams(textType s, parameterType[] types){
|
||||
s.default_value = ((paramString) types[0]).val;
|
||||
s.description = ((paramString) types[0]).val;
|
||||
s.default_value = ((paramString) types[1]).val;
|
||||
}
|
||||
|
||||
public static void setTallyParams(tallyType s, parameterType[] types){
|
||||
s.default_value = ((paramNumber) types[0]).val;
|
||||
s.description = ((paramString) types[0]).val;
|
||||
s.default_value = ((paramNumber) types[1]).val;
|
||||
}
|
||||
|
||||
public static void setNumberParams(numberType s, parameterType[] types){
|
||||
s.description = ((paramString) types[0]).val;
|
||||
s.default_value = ((paramNumber) types[1]).val;
|
||||
}
|
||||
|
||||
public static void setCheckboxParam(checkboxType s, parameterType[] types){
|
||||
s.description = ((paramString) types[0]).val;
|
||||
s.default_value = ((paramNumber) types[1]).val;
|
||||
}
|
||||
|
||||
public static void setFieldPosParam(fieldposType s, parameterType[] types){
|
||||
s.description = ((paramString) types[0]).val;
|
||||
s.default_value = new int[]{
|
||||
((paramNumber) types[1]).val,
|
||||
((paramNumber) types[2]).val
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private static void setInputParameter(inputType t, parameterType[] types){
|
||||
switch (t.getInputType()){
|
||||
case TALLY:
|
||||
@@ -134,6 +212,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 +236,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[]{};
|
||||
}
|
||||
+103
-62
@@ -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,19 +21,20 @@ 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.skydoves.powerspinner.IconSpinnerAdapter;
|
||||
import com.skydoves.powerspinner.IconSpinnerItem;
|
||||
import com.skydoves.powerspinner.PowerSpinnerView;
|
||||
import com.skydoves.powerspinner.SpinnerGravity;
|
||||
import com.ridgebotics.ridgescout.MainActivity;
|
||||
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.ui.CustomSpinnerView;
|
||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -52,10 +53,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);
|
||||
@@ -68,6 +67,25 @@ public class FieldsFragment extends Fragment {
|
||||
|
||||
load_field_menu();
|
||||
|
||||
((MainActivity) getActivity()).setOnBackPressed(() -> {
|
||||
if(binding.saveButton.getVisibility() == View.GONE) return true;
|
||||
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
|
||||
alert.setTitle("Warning!");
|
||||
alert.setMessage("You have not saved your progress!");
|
||||
alert.setPositiveButton("Return", null);
|
||||
alert.setNeutralButton("Quit without saving", (dialogInterface, i) -> {
|
||||
binding.saveButton.setVisibility(View.GONE);
|
||||
if(getActivity() != null)
|
||||
getActivity().onBackPressed();
|
||||
});
|
||||
alert.setCancelable(true);
|
||||
|
||||
alert.create().show();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@@ -121,6 +139,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) {
|
||||
@@ -135,6 +172,8 @@ public class FieldsFragment extends Fragment {
|
||||
binding.addButton.setVisibility(View.VISIBLE);
|
||||
binding.downButton.setVisibility(View.VISIBLE);
|
||||
|
||||
updateUpDownAvailability();
|
||||
|
||||
binding.valueEditContainer.setVisibility(View.GONE);
|
||||
|
||||
for(int i = 0; i < version_values.length; i++){
|
||||
@@ -147,6 +186,12 @@ public class FieldsFragment extends Fragment {
|
||||
binding.saveButton.setOnClickListener(this::buttonfunc);
|
||||
}
|
||||
|
||||
// Make sure the user cannot move fields when they shouldn't
|
||||
private void updateUpDownAvailability(){
|
||||
binding.upButton.setEnabled(selindex != -1 && selindex != 0);
|
||||
binding.downButton.setEnabled(selindex != -1 && selindex != values[values.length-1].length-1);
|
||||
}
|
||||
|
||||
private void addRow(inputType field){
|
||||
TableRow tr = getTableRow(field);
|
||||
|
||||
@@ -155,6 +200,7 @@ public class FieldsFragment extends Fragment {
|
||||
tr.setOnClickListener(v -> {
|
||||
binding.editButton.setVisibility(View.VISIBLE);
|
||||
trOnClick(values[values.length-1], tr);
|
||||
updateUpDownAvailability();
|
||||
});
|
||||
|
||||
binding.upButton.setOnClickListener(v -> {
|
||||
@@ -163,6 +209,7 @@ public class FieldsFragment extends Fragment {
|
||||
binding.fieldsArea.updateRowOrder(selindex, selindex - 1);
|
||||
selindex -= 1;
|
||||
}
|
||||
updateUpDownAvailability();
|
||||
});
|
||||
|
||||
binding.downButton.setOnClickListener(v -> {
|
||||
@@ -171,6 +218,7 @@ public class FieldsFragment extends Fragment {
|
||||
binding.fieldsArea.updateRowOrder(selindex, selindex + 1);
|
||||
selindex += 1;
|
||||
}
|
||||
updateUpDownAvailability();
|
||||
});
|
||||
|
||||
}
|
||||
@@ -179,10 +227,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 +240,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);
|
||||
Navigation.findNavController((Activity) getContext(), R.id.nav_host_fragment_activity_main).navigate(R.id.action_navigation_data_fields_to_navigation_data);
|
||||
});
|
||||
alert.setNegativeButton("Cancel", null);
|
||||
alert.setCancelable(true);
|
||||
alert.create().show();
|
||||
}
|
||||
|
||||
@@ -371,50 +418,26 @@ public class FieldsFragment extends Fragment {
|
||||
|
||||
private void addField_Part_2(String title) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle("Title");
|
||||
builder.setTitle("Select Type");
|
||||
|
||||
final PowerSpinnerView dropdown = new PowerSpinnerView(getContext());
|
||||
final CustomSpinnerView dropdown = new CustomSpinnerView(getContext());
|
||||
List<String> options = new ArrayList<>();
|
||||
|
||||
List<IconSpinnerItem> iconSpinnerItems = new ArrayList<>();
|
||||
options.add("Slider");
|
||||
options.add("Text");
|
||||
options.add("Dropdown");
|
||||
options.add("Tally");
|
||||
options.add("Number");
|
||||
options.add("Checkbox");
|
||||
options.add("Field Position");
|
||||
|
||||
iconSpinnerItems.add(new IconSpinnerItem("Slider"));
|
||||
iconSpinnerItems.add(new IconSpinnerItem("Text"));
|
||||
iconSpinnerItems.add(new IconSpinnerItem("Dropdown"));
|
||||
iconSpinnerItems.add(new IconSpinnerItem("Tally"));
|
||||
|
||||
IconSpinnerAdapter iconSpinnerAdapter = new IconSpinnerAdapter(dropdown);
|
||||
|
||||
dropdown.setGravity(Gravity.CENTER);
|
||||
|
||||
dropdown.setSpinnerAdapter(iconSpinnerAdapter);
|
||||
dropdown.setItems(iconSpinnerItems);
|
||||
|
||||
dropdown.selectItemByIndex(0);
|
||||
|
||||
dropdown.setPadding(10,20,10,20);
|
||||
dropdown.setBackgroundColor(0xf0000000);
|
||||
dropdown.setTextColor(0xff00ff00);
|
||||
dropdown.setTextSize(14.5f);
|
||||
dropdown.setArrowGravity(SpinnerGravity.END);
|
||||
dropdown.setArrowPadding(8);
|
||||
// dropdown.setSpinnerItemHeight(46);
|
||||
dropdown.setSpinnerPopupElevation(14);
|
||||
dropdown.setOptions(options, 0);
|
||||
dropdown.setTitle("Type");
|
||||
|
||||
builder.setView(dropdown);
|
||||
|
||||
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
addField_Part_3(title, dropdown.getSelectedIndex());
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
|
||||
builder.setPositiveButton("OK", (dialog, which) -> addField_Part_3(title, dropdown.getIndex()));
|
||||
|
||||
builder.show();
|
||||
}
|
||||
@@ -445,6 +468,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 +520,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,358 @@
|
||||
package com.ridgebotics.ridgescout.ui.data;
|
||||
|
||||
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;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.ridgebotics.ridgescout.ui.CustomSpinnerView;
|
||||
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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TeamsFragment extends Fragment {
|
||||
FragmentDataTeamsBinding binding;
|
||||
|
||||
private static frcTeam team;
|
||||
public static void setTeam(frcTeam tmpteam){
|
||||
team = tmpteam;
|
||||
}
|
||||
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
binding = FragmentDataTeamsBinding.inflate(inflater, container, false);
|
||||
|
||||
DataManager.reload_match_fields();
|
||||
DataManager.reload_pit_fields();
|
||||
|
||||
binding.dataTypeSpinner.setTitle("Data Mode");
|
||||
|
||||
List<String> options = new ArrayList<>();
|
||||
options.add("Individual");
|
||||
options.add("Compiled");
|
||||
options.add("History");
|
||||
|
||||
binding.dataTypeSpinner.setOptions(options, 0);
|
||||
|
||||
binding.dataTypeSpinner.setOnClickListener((item, index) -> {
|
||||
settingsManager.setDataMode(index);
|
||||
loadTeam(index);
|
||||
});
|
||||
|
||||
// binding.teamsMainElem.
|
||||
|
||||
loadTeam(settingsManager.getDataMode());
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
public void loadTeam(int mode) {
|
||||
|
||||
// LinearLayout ll = new LinearLayout(getContext());
|
||||
// ll.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
// ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
// ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
// ));
|
||||
// ll.setOrientation(LinearLayout.VERTICAL);
|
||||
// binding.teamsArea.addView(ll);
|
||||
|
||||
|
||||
|
||||
|
||||
binding.teamName2.setText(String.valueOf(team.teamNumber));
|
||||
|
||||
binding.teamDescription2.setText(team.getDescription());
|
||||
|
||||
// tv = new TextView(getContext());
|
||||
// tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
// ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
// ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
// ));
|
||||
// tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
// tv.setText(team.getDescription());
|
||||
// tv.setTextSize(16);
|
||||
// ll.addView(tv);
|
||||
|
||||
try {add_pit_data(team);}catch(Exception e){AlertManager.error(e);}
|
||||
try {add_match_data(team, mode);}catch(Exception e){AlertManager.error(e);}
|
||||
}
|
||||
|
||||
public void add_pit_data(frcTeam team){
|
||||
binding.pitArea.removeAllViews();
|
||||
final String filename = evcode+"-"+team.teamNumber+".pitscoutdata";
|
||||
|
||||
// ll.addView(new MaterialDivider(getContext()));
|
||||
|
||||
// TextView tv = new TextView(getContext());
|
||||
// tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
// ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
// ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
// ));
|
||||
// tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
// tv.setPadding(0,10,0,10);
|
||||
// tv.setText("----- Pit data -----");
|
||||
// tv.setTextSize(30);
|
||||
// ll.addView(tv);
|
||||
|
||||
// ll.addView(new MaterialDivider(getContext()));
|
||||
|
||||
if(!fileEditor.fileExist(filename)){
|
||||
TextView tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setText("No pit data has been collected!");
|
||||
tv.setTextSize(23);
|
||||
binding.pitArea.addView(tv);
|
||||
return;
|
||||
}
|
||||
|
||||
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(filename, pit_values, pit_transferValues);
|
||||
|
||||
TextView tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setPadding(0, 20, 0, 5);
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setText("Pit scouting by " + psda.username);
|
||||
tv.setTextSize(30);
|
||||
binding.pitArea.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);
|
||||
|
||||
if(psda.data.array[a].isNull()){
|
||||
tv.setBackgroundColor(0xffff0000);
|
||||
tv.setTextColor(0xff000000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
binding.pitArea.addView(tv);
|
||||
|
||||
|
||||
pit_latest_values[a].add_individual_view(binding.pitArea, psda.data.array[a]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int matchIndex = 0;
|
||||
|
||||
public void add_match_data(frcTeam team, int mode){
|
||||
binding.matchArea.removeAllViews();
|
||||
binding.individualViewSelector.setVisibility(View.GONE);
|
||||
String[] files = fileEditor.getMatchesByTeamNum(evcode, team.teamNumber);
|
||||
|
||||
if(files.length == 0){
|
||||
TextView tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setText("No match data has been collected!");
|
||||
tv.setTextSize(23);
|
||||
binding.matchArea.addView(tv);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mode){
|
||||
case 0:
|
||||
add_individual_views(files);
|
||||
break;
|
||||
case 1:
|
||||
add_compiled_views(files);
|
||||
break;
|
||||
case 2:
|
||||
add_history_views(files);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void add_individual_views(String[] files) {
|
||||
|
||||
|
||||
matchIndex = 0;
|
||||
|
||||
binding.individualViewSelector.setVisibility(View.VISIBLE);
|
||||
|
||||
binding.matchesPlusBtn.setOnClickListener(view -> {
|
||||
matchIndex++;
|
||||
update_individual_view(files);
|
||||
});
|
||||
|
||||
binding.matchesMinusBtn.setOnClickListener(view -> {
|
||||
matchIndex--;
|
||||
update_individual_view(files);
|
||||
});
|
||||
|
||||
update_individual_view(files);
|
||||
}
|
||||
|
||||
private void update_individual_view(String[] files){
|
||||
binding.matchesPlusBtn.setEnabled(matchIndex < files.length - 1);
|
||||
binding.matchesMinusBtn.setEnabled(matchIndex > 0);
|
||||
binding.matchArea.removeAllViews();
|
||||
|
||||
|
||||
try {
|
||||
String[] split = files[matchIndex].split("-");
|
||||
int match_num = Integer.parseInt(split[1]);
|
||||
binding.matchNum.setText(split[1]);
|
||||
|
||||
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[matchIndex], 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);
|
||||
binding.matchArea.addView(tv);
|
||||
|
||||
for (int i = 0; i < psda.data.array.length; i++) {
|
||||
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[i].getName());
|
||||
tv.setTextSize(25);
|
||||
|
||||
if (psda.data.array[i].isNull()) {
|
||||
tv.setBackgroundColor(0xffff0000);
|
||||
tv.setTextColor(0xff000000);
|
||||
}
|
||||
|
||||
binding.matchArea.addView(tv);
|
||||
|
||||
|
||||
if(psda.data.array[i] != null)
|
||||
match_latest_values[i].add_individual_view(binding.matchArea, psda.data.array[i]);
|
||||
}
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
AlertManager.alert("Warning!", "Failure to load file " + files[matchIndex]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void add_compiled_views(String[] files){
|
||||
dataType[][] data = new dataType[match_latest_values.length][files.length];
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
try {
|
||||
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[i], match_values, match_transferValues);
|
||||
for (int a = 0; a < data.length; a++) {
|
||||
if(psda.data.array[a] != null && psda.data.array[a].get() != null)
|
||||
data[a][i] = psda.data.array[a];
|
||||
}
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
AlertManager.alert("Warning!", "Failure to load file " + files[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < match_latest_values.length; i++){
|
||||
TextView tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setPadding(0, 20, 0, 5);
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setText(match_latest_values[i].name);
|
||||
tv.setTextSize(30);
|
||||
binding.matchArea.addView(tv);
|
||||
|
||||
if(data[i] != null)
|
||||
match_latest_values[i].add_compiled_view(binding.matchArea, data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void add_history_views(String[] files){
|
||||
dataType[][] data = new dataType[match_latest_values.length][files.length];
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
try {
|
||||
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[i], match_values, match_transferValues);
|
||||
for (int a = 0; a < data.length; a++) {
|
||||
if(psda.data.array[a] != null && psda.data.array[a].get() != null)
|
||||
data[a][i] = psda.data.array[a];
|
||||
}
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
AlertManager.alert("Warning!", "Failure to load file " + files[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < match_latest_values.length; i++){
|
||||
TextView tv = new TextView(getContext());
|
||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
tv.setPadding(0, 20, 0, 5);
|
||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
tv.setText(match_latest_values[i].name);
|
||||
tv.setTextSize(30);
|
||||
binding.matchArea.addView(tv);
|
||||
|
||||
if(data[i] != null)
|
||||
match_latest_values[i].add_history_view(binding.matchArea, data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,383 @@
|
||||
package com.ridgebotics.ridgescout.ui.scouting;
|
||||
|
||||
import static android.widget.LinearLayout.HORIZONTAL;
|
||||
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
|
||||
import static com.ridgebotics.ridgescout.utility.DataManager.event;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TableRow;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.ridgebotics.ridgescout.databinding.FragmentScoutingEventBinding;
|
||||
import com.ridgebotics.ridgescout.types.frcTeam;
|
||||
import com.ridgebotics.ridgescout.ui.CustomSpinnerView;
|
||||
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 com.ridgebotics.ridgescout.utility.settingsManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class EventFragment extends Fragment {
|
||||
FragmentScoutingEventBinding binding;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
binding = FragmentScoutingEventBinding.inflate(inflater, container, false);
|
||||
|
||||
reloadTable();
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
public void reloadTable() {
|
||||
DataManager.reload_event();
|
||||
binding.teamsTable.removeAllViews();
|
||||
binding.teamsTable.setStretchAllColumns(true);
|
||||
binding.matchTable.removeAllViews();
|
||||
binding.matchTable.setStretchAllColumns(true);
|
||||
add_pit_scouting(event);
|
||||
add_match_scouting(event);
|
||||
}
|
||||
|
||||
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);
|
||||
text.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); // Text align center
|
||||
text.setText(textStr);
|
||||
tr.addView(text);
|
||||
}
|
||||
|
||||
public void add_pit_scouting(frcEvent event){
|
||||
|
||||
if(settingsManager.getCustomEvents()){
|
||||
binding.teamsMinusBtn.setVisibility(View.VISIBLE);
|
||||
binding.teamsMinusBtn.setOnClickListener(view -> removeTeam());
|
||||
binding.teamsPlusBtn.setVisibility(View.VISIBLE);
|
||||
binding.teamsPlusBtn.setOnClickListener(view -> addTeam());
|
||||
}
|
||||
|
||||
int[] teams = new int[event.teams.size()];
|
||||
|
||||
for(int i = 0 ; i < event.teams.size(); i++){
|
||||
teams[i] = event.teams.get(i).teamNumber;
|
||||
}
|
||||
|
||||
Arrays.sort(teams);
|
||||
|
||||
TableRow tr = null;
|
||||
for(int i=0; i < event.teams.size(); i++){
|
||||
// frcTeam team = event.teams.get(i);
|
||||
int num = teams[i];
|
||||
|
||||
if(i % 7 == 0){
|
||||
if(i != 0)
|
||||
binding.teamsTable.addView(tr);
|
||||
tr = new TableRow(getContext());
|
||||
}
|
||||
|
||||
TextView text = new TextView(getContext());
|
||||
text.setTextSize(18);
|
||||
text.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
||||
|
||||
text.setText(String.valueOf(num));
|
||||
if(fileEditor.fileExist(event.eventCode + "-" + num + ".pitscoutdata")){
|
||||
text.setBackgroundColor(color_found);
|
||||
}else{
|
||||
text.setBackgroundColor(color_not_found);
|
||||
}
|
||||
tr.addView(text);
|
||||
}
|
||||
if(tr != null)
|
||||
binding.teamsTable.addView(tr);
|
||||
}
|
||||
|
||||
|
||||
public void add_match_scouting(frcEvent event){
|
||||
|
||||
|
||||
if(settingsManager.getCustomEvents()){
|
||||
binding.matchesMinusBtn.setVisibility(View.VISIBLE);
|
||||
binding.matchesMinusBtn.setOnClickListener(view -> removeMatch());
|
||||
binding.matchesPlusBtn.setVisibility(View.VISIBLE);
|
||||
binding.matchesPlusBtn.setOnClickListener(view -> addMatch());
|
||||
}
|
||||
|
||||
TableRow tr = new TableRow(getContext());
|
||||
addTableText(tr, "#");
|
||||
addTableText(tr, "Red-1");
|
||||
addTableText(tr, "Red-2");
|
||||
addTableText(tr, "Red-3");
|
||||
addTableText(tr, "Blue-1");
|
||||
addTableText(tr, "Blue-2");
|
||||
addTableText(tr, "Blue-3");
|
||||
binding.matchTable.addView(tr);
|
||||
|
||||
for(frcMatch match : event.matches){
|
||||
|
||||
tr = new TableRow(getContext());
|
||||
addTableText(tr, String.valueOf(match.matchIndex));
|
||||
//
|
||||
for(int i=0;i<6;i++){
|
||||
TextView text = new TextView(getContext());
|
||||
text.setTextSize(18);
|
||||
text.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
||||
|
||||
int team_num;
|
||||
String alliance_position;
|
||||
|
||||
if(i < 3){
|
||||
team_num = match.redAlliance[i];
|
||||
alliance_position = "red-"+(i+1);
|
||||
}else{
|
||||
team_num = match.blueAlliance[i-3];
|
||||
alliance_position = "blue-"+(i-2);
|
||||
}
|
||||
|
||||
text.setText(String.valueOf(team_num));
|
||||
if(fileEditor.fileExist(event.eventCode + "-" + match.matchIndex + "-" + alliance_position + "-" + team_num + ".matchscoutdata")){
|
||||
text.setBackgroundColor(color_found);
|
||||
}else{
|
||||
text.setBackgroundColor(color_not_found);
|
||||
}
|
||||
tr.addView(text);
|
||||
}
|
||||
|
||||
binding.matchTable.addView(tr);
|
||||
}
|
||||
}
|
||||
|
||||
public void addTeam(){
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle("Add team");
|
||||
|
||||
LinearLayout ll = new LinearLayout(getContext());
|
||||
ll.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
EditText teamNum = new EditText(getContext());
|
||||
teamNum.setHint("Team Number");
|
||||
teamNum.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
ll.addView(teamNum);
|
||||
|
||||
EditText teamName = new EditText(getContext());
|
||||
teamName.setHint("Team Name");
|
||||
ll.addView(teamName);
|
||||
|
||||
EditText school = new EditText(getContext());
|
||||
school.setHint("School");
|
||||
ll.addView(school);
|
||||
|
||||
EditText city = new EditText(getContext());
|
||||
city.setHint("City");
|
||||
ll.addView(city);
|
||||
|
||||
EditText stateOrProv = new EditText(getContext());
|
||||
stateOrProv.setHint("State Or Province");
|
||||
ll.addView(stateOrProv);
|
||||
|
||||
EditText country = new EditText(getContext());
|
||||
country.setHint("Country");
|
||||
ll.addView(country);
|
||||
|
||||
EditText startingYear = new EditText(getContext());
|
||||
startingYear.setHint("Starting Year");
|
||||
startingYear.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
ll.addView(startingYear);
|
||||
|
||||
builder.setView(ll);
|
||||
|
||||
builder.setNeutralButton("Cancel", (dialogInterface, i) -> {});
|
||||
builder.setPositiveButton("OK", (dialogInterface, i) -> {
|
||||
if(teamNum.getText().toString().isEmpty() || teamName.getText().toString().isEmpty()) return;
|
||||
frcTeam team = new frcTeam();
|
||||
team.teamNumber = Integer.parseInt(teamNum.getText().toString());
|
||||
team.teamName = teamName.getText().toString();
|
||||
team.school = school.getText().toString();
|
||||
team.city = city.getText().toString();
|
||||
team.country = country.getText().toString();
|
||||
team.stateOrProv = stateOrProv.getText().toString();
|
||||
team.startingYear = safeToInt(startingYear.getText().toString());
|
||||
|
||||
event.teams.add(team);
|
||||
fileEditor.setEvent(event);
|
||||
reloadTable();
|
||||
});
|
||||
|
||||
builder.create().show();
|
||||
|
||||
}
|
||||
public void removeTeam(){
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle("Remove team");
|
||||
|
||||
CustomSpinnerView dropdown = new CustomSpinnerView(getContext());
|
||||
|
||||
List<String> teamNums = new ArrayList<>();
|
||||
for(int i = 0 ;i < event.teams.size(); i++)
|
||||
teamNums.add(String.valueOf(event.teams.get(i).teamNumber));
|
||||
|
||||
|
||||
dropdown.setTitle("Teams");
|
||||
dropdown.setOptions(teamNums, -1);
|
||||
|
||||
builder.setView(dropdown);
|
||||
|
||||
builder.setNeutralButton("Cancel", (dialogInterface, i) -> {});
|
||||
builder.setPositiveButton("OK", (dialogInterface, i) -> {
|
||||
|
||||
int index = dropdown.getIndex();
|
||||
System.out.println(index);
|
||||
if(!(index >= 0 && index < teamNums.size())) return;
|
||||
|
||||
event.teams.remove(index);
|
||||
fileEditor.setEvent(event);
|
||||
reloadTable();
|
||||
});
|
||||
|
||||
builder.create().show();
|
||||
|
||||
}
|
||||
public void addMatch(){
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle("Add match");
|
||||
|
||||
List<String> teamNums = new ArrayList<>();
|
||||
for(int i = 0 ;i < event.teams.size(); i++)
|
||||
teamNums.add(String.valueOf(event.teams.get(i).teamNumber));
|
||||
|
||||
ScrollView sv = new ScrollView(getContext());
|
||||
// sv.setLayoutDirection(ScrollView.SCROLL_AXIS_VERTICAL);
|
||||
|
||||
LinearLayout ll = new LinearLayout(getContext());
|
||||
ll.setOrientation(LinearLayout.VERTICAL);
|
||||
sv.addView(ll);
|
||||
|
||||
CustomSpinnerView Red1dropdown = new CustomSpinnerView(getContext());
|
||||
Red1dropdown.setTitle("Red-1");
|
||||
Red1dropdown.setOptions(teamNums, -1);
|
||||
ll.addView(Red1dropdown);
|
||||
|
||||
CustomSpinnerView Red2dropdown = new CustomSpinnerView(getContext());
|
||||
Red2dropdown.setTitle("Red-2");
|
||||
Red2dropdown.setOptions(teamNums, -1);
|
||||
ll.addView(Red2dropdown);
|
||||
|
||||
CustomSpinnerView Red3dropdown = new CustomSpinnerView(getContext());
|
||||
Red3dropdown.setTitle("Red-3");
|
||||
Red3dropdown.setOptions(teamNums, -1);
|
||||
ll.addView(Red3dropdown);
|
||||
|
||||
|
||||
CustomSpinnerView Blue1dropdown = new CustomSpinnerView(getContext());
|
||||
Blue1dropdown.setTitle("Blue-1");
|
||||
Blue1dropdown.setOptions(teamNums, -1);
|
||||
ll.addView(Blue1dropdown);
|
||||
|
||||
CustomSpinnerView Blue2dropdown = new CustomSpinnerView(getContext());
|
||||
Blue2dropdown.setTitle("Blue-2");
|
||||
Blue2dropdown.setOptions(teamNums, -1);
|
||||
ll.addView(Blue2dropdown);
|
||||
|
||||
CustomSpinnerView Blue3dropdown = new CustomSpinnerView(getContext());
|
||||
Blue3dropdown.setTitle("Blue-3");
|
||||
Blue3dropdown.setOptions(teamNums, -1);
|
||||
ll.addView(Blue3dropdown);
|
||||
|
||||
builder.setView(sv);
|
||||
|
||||
builder.setNeutralButton("Cancel", (dialogInterface, i) -> {});
|
||||
builder.setPositiveButton("OK", (dialogInterface, i) -> {
|
||||
int red1index = Red1dropdown.getIndex();
|
||||
int red2index = Red2dropdown.getIndex();
|
||||
int red3index = Red3dropdown.getIndex();
|
||||
int blue1index = Blue1dropdown.getIndex();
|
||||
int blue2index = Blue2dropdown.getIndex();
|
||||
int blue3index = Blue3dropdown.getIndex();
|
||||
|
||||
if(red1index == -1 || red2index == -1 || red3index == -1 || blue1index == -1 || blue2index == -1 || blue3index == -1) return;
|
||||
|
||||
frcMatch match = new frcMatch();
|
||||
match.matchIndex = event.matches.size() + 1;
|
||||
match.redAlliance = new int[] {
|
||||
event.teams.get(red1index).teamNumber,
|
||||
event.teams.get(red2index).teamNumber,
|
||||
event.teams.get(red3index).teamNumber
|
||||
};
|
||||
match.blueAlliance = new int[] {
|
||||
event.teams.get(blue1index).teamNumber,
|
||||
event.teams.get(blue2index).teamNumber,
|
||||
event.teams.get(blue3index).teamNumber
|
||||
};
|
||||
|
||||
event.matches.add(match);
|
||||
fileEditor.setEvent(event);
|
||||
reloadTable();
|
||||
});
|
||||
|
||||
builder.create().show();
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
public void removeMatch(){
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle("Remove match");
|
||||
|
||||
List<String> matches = new ArrayList<>();
|
||||
for(int i = 0 ;i < event.matches.size(); i++) {
|
||||
frcMatch match = event.matches.get(i);
|
||||
matches.add(match.matchIndex + " - " + Arrays.toString(match.redAlliance) + ", " + Arrays.toString(match.blueAlliance));
|
||||
}
|
||||
|
||||
CustomSpinnerView dropdown = new CustomSpinnerView(getContext());
|
||||
dropdown.setTitle("Matches");
|
||||
dropdown.setOptions(matches, -1);
|
||||
|
||||
builder.setView(dropdown);
|
||||
|
||||
builder.setNeutralButton("Cancel", (dialogInterface, i) -> {});
|
||||
builder.setPositiveButton("OK", (dialogInterface, i) -> {
|
||||
if(dropdown.getIndex() == -1) return;
|
||||
event.matches.remove(dropdown.getIndex());
|
||||
fileEditor.setEvent(event);
|
||||
reloadTable();
|
||||
});
|
||||
|
||||
builder.create().show();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public int safeToInt(String str){
|
||||
try{
|
||||
return Integer.parseInt(str);
|
||||
}catch (Exception e){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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_2025);
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
||||
+68
-68
@@ -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,19 @@ 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.google.android.material.divider.MaterialDivider;
|
||||
import com.ridgebotics.ridgescout.ui.ToggleTitleView;
|
||||
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 +43,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);
|
||||
@@ -64,13 +65,9 @@ public class MatchScoutingFragment extends Fragment {
|
||||
|
||||
|
||||
|
||||
|
||||
cur_match_num = latestSettings.settings.get_match_num();
|
||||
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 +81,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 +91,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();
|
||||
@@ -104,6 +101,14 @@ public class MatchScoutingFragment extends Fragment {
|
||||
// if(edited) save();
|
||||
// });
|
||||
|
||||
cur_match_num = settingsManager.getMatchNum();
|
||||
|
||||
if(cur_match_num >= event.matches.size()) {
|
||||
cur_match_num = 0;
|
||||
settingsManager.setMatchNum(0);
|
||||
}
|
||||
|
||||
update_match_num();
|
||||
create_fields();
|
||||
update_scouting_data();
|
||||
|
||||
@@ -135,15 +140,10 @@ public class MatchScoutingFragment extends Fragment {
|
||||
int cur_match_num;
|
||||
String username;
|
||||
String filename;
|
||||
|
||||
boolean edited = false;
|
||||
|
||||
TextView[] titles;
|
||||
|
||||
ToggleTitleView[] titles;
|
||||
AutoSaveManager asm = new AutoSaveManager(this::save);
|
||||
|
||||
ArrayList<dataType> dataTypes;
|
||||
|
||||
|
||||
|
||||
public void save(){
|
||||
@@ -187,48 +187,41 @@ public class MatchScoutingFragment extends Fragment {
|
||||
asm.stop();
|
||||
}
|
||||
|
||||
titles = new TextView[DataManager.match_latest_values.length];
|
||||
titles = new ToggleTitleView[DataManager.match_latest_values.length];
|
||||
|
||||
for(int i = 0 ; i < DataManager.match_latest_values.length; i++) {
|
||||
final TextView tv = new TextView(getContext());
|
||||
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
||||
tv.setText(DataManager.match_latest_values[i].name);
|
||||
tv.setPadding(8,8,8,8);
|
||||
tv.setTextSize(24);
|
||||
titles[i] = tv;
|
||||
binding.MatchScoutArea.addView(new MaterialDivider(getContext()));
|
||||
|
||||
default_text_color = tv.getCurrentTextColor();
|
||||
|
||||
final View v = DataManager.match_latest_values[i].createView(getContext(), new Function<dataType, Integer>() {
|
||||
@Override
|
||||
public Integer apply(dataType dataType) {
|
||||
// edited = true;
|
||||
if(asm.isRunning)
|
||||
update_asm();
|
||||
return 0;
|
||||
}
|
||||
final ToggleTitleView ttv = new ToggleTitleView(getContext());
|
||||
ttv.setTitle(DataManager.match_latest_values[i].name);
|
||||
ttv.setDescription(DataManager.match_latest_values[i].description);
|
||||
titles[i] = ttv;
|
||||
|
||||
|
||||
final View v = DataManager.match_latest_values[i].createView(getContext(), dataType -> {
|
||||
// edited = true;
|
||||
if(asm.isRunning)
|
||||
update_asm();
|
||||
return 0;
|
||||
});
|
||||
|
||||
binding.MatchScoutArea.addView(tv);
|
||||
binding.MatchScoutArea.addView(ttv);
|
||||
int fi = i;
|
||||
tv.setOnClickListener(p -> {
|
||||
// boolean blank = !latest_values[fi].getViewValue().isNull();
|
||||
|
||||
// System.out.println(blank);
|
||||
ttv.setOnToggleListener(enabled -> {
|
||||
if(asm.isRunning)
|
||||
update_asm();
|
||||
|
||||
if(!DataManager.match_latest_values[fi].isBlank){
|
||||
tv.setBackgroundColor(0xffff0000);
|
||||
tv.setTextColor(0xff000000);
|
||||
// System.out.println("Checked!");
|
||||
|
||||
if(enabled){
|
||||
DataManager.match_latest_values[fi].nullify();
|
||||
}else{
|
||||
tv.setBackgroundColor(0x00000000);
|
||||
tv.setTextColor(default_text_color);
|
||||
}else
|
||||
DataManager.match_latest_values[fi].setViewValue(DataManager.match_latest_values[fi].default_value);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
binding.MatchScoutArea.addView(v);
|
||||
}
|
||||
}
|
||||
@@ -298,6 +291,13 @@ public class MatchScoutingFragment extends Fragment {
|
||||
frcMatch match = event.matches.get(cur_match_num);
|
||||
frcTeam team = get_team(match);
|
||||
|
||||
if(team == null) {
|
||||
AlertManager.error("This team does not exist!");
|
||||
binding.teamName.setText("ERROR!");
|
||||
binding.teamDescription.setText("ERROR!");
|
||||
return;
|
||||
}
|
||||
|
||||
binding.teamName.setText(team.teamName);
|
||||
binding.teamDescription.setText(team.getDescription());
|
||||
|
||||
@@ -311,8 +311,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();
|
||||
@@ -326,8 +332,7 @@ public class MatchScoutingFragment extends Fragment {
|
||||
inputType input = DataManager.match_latest_values[i];
|
||||
input.setViewValue(input.default_value);
|
||||
|
||||
titles[i].setBackgroundColor(0x00000000);
|
||||
titles[i].setTextColor(default_text_color);
|
||||
titles[i].enable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,6 +343,7 @@ public class MatchScoutingFragment extends Fragment {
|
||||
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.match_values, DataManager.match_transferValues);
|
||||
dataType[] types = psdr.data.array;
|
||||
|
||||
|
||||
for(int i = 0; i < DataManager.match_latest_values.length; i++){
|
||||
// types[i] = latest_values[i].getViewValue();
|
||||
try {
|
||||
@@ -347,14 +353,8 @@ public class MatchScoutingFragment extends Fragment {
|
||||
DataManager.match_latest_values[i].setViewValue(DataManager.match_latest_values[i].default_value);
|
||||
}
|
||||
|
||||
titles[i].setEnabled(DataManager.match_latest_values[i].isBlank);
|
||||
|
||||
if(DataManager.match_latest_values[i].isBlank){
|
||||
titles[i].setBackgroundColor(0xffff0000);
|
||||
titles[i].setTextColor(0xff000000);
|
||||
}else{
|
||||
titles[i].setBackgroundColor(0x00000000);
|
||||
titles[i].setTextColor(default_text_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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_2025);
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
+44
-97
@@ -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,18 @@ 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.google.android.material.divider.MaterialDivider;
|
||||
import com.ridgebotics.ridgescout.ui.ToggleTitleView;
|
||||
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 +46,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();
|
||||
@@ -58,7 +61,7 @@ public class PitScoutingFragment extends Fragment {
|
||||
String filename;
|
||||
String username;
|
||||
|
||||
TextView[] titles;
|
||||
ToggleTitleView[] titles;
|
||||
|
||||
AutoSaveManager asm = new AutoSaveManager(this::save);
|
||||
|
||||
@@ -74,9 +77,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 +96,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 +107,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,50 +121,45 @@ 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();
|
||||
|
||||
}
|
||||
|
||||
private int default_text_color = 0;
|
||||
|
||||
|
||||
private void create_fields() {
|
||||
if(asm.isRunning){
|
||||
asm.stop();
|
||||
}
|
||||
|
||||
titles = new TextView[pit_latest_values.length];
|
||||
titles = new ToggleTitleView[pit_latest_values.length];
|
||||
|
||||
for(int i = 0 ; i < pit_latest_values.length; i++) {
|
||||
TextView tv = new TextView(getContext());
|
||||
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
||||
tv.setText(pit_latest_values[i].name);
|
||||
tv.setTextSize(24);
|
||||
tv.setPadding(8,8,8,8);
|
||||
titles[i] = tv;
|
||||
binding.pitScoutArea.addView(tv);
|
||||
binding.pitScoutArea.addView(new MaterialDivider(getContext()));
|
||||
|
||||
ToggleTitleView ttv = new ToggleTitleView(getContext());
|
||||
ttv.setTitle(pit_latest_values[i].name);
|
||||
ttv.setDescription(pit_latest_values[i].description);
|
||||
titles[i] = ttv;
|
||||
binding.pitScoutArea.addView(ttv);
|
||||
|
||||
default_text_color = tv.getCurrentTextColor();
|
||||
|
||||
int fi = i;
|
||||
tv.setOnClickListener(p -> {
|
||||
// boolean blank = !latest_values[fi].getViewValue().isNull();
|
||||
ttv.setOnToggleListener(enabled -> {
|
||||
update_asm();
|
||||
|
||||
// System.out.println(blank);
|
||||
|
||||
asm.update();
|
||||
|
||||
if(!pit_latest_values[fi].isBlank){
|
||||
tv.setBackgroundColor(0xffff0000);
|
||||
tv.setTextColor(0xff000000);
|
||||
if(enabled){
|
||||
pit_latest_values[fi].nullify();
|
||||
}else{
|
||||
tv.setBackgroundColor(0x00000000);
|
||||
tv.setTextColor(default_text_color);
|
||||
pit_latest_values[fi].setViewValue(pit_latest_values[fi].default_value);
|
||||
}
|
||||
});
|
||||
@@ -230,9 +182,7 @@ public class PitScoutingFragment extends Fragment {
|
||||
for(int i = 0; i < pit_latest_values.length; i++){
|
||||
inputType input = pit_latest_values[i];
|
||||
input.setViewValue(input.default_value);
|
||||
|
||||
titles[i].setBackgroundColor(0x00000000);
|
||||
titles[i].setTextColor(default_text_color);
|
||||
titles[i].enable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,15 +192,12 @@ public class PitScoutingFragment extends Fragment {
|
||||
dataType[] types = psdr.data.array;
|
||||
|
||||
for(int i = 0; i < pit_latest_values.length; i++){
|
||||
// types[i] = latest_values[i].getViewValue();
|
||||
pit_latest_values[i].setViewValue(types[i]);
|
||||
|
||||
if(pit_latest_values[i].isBlank){
|
||||
titles[i].setBackgroundColor(0xffff0000);
|
||||
titles[i].setTextColor(0xff000000);
|
||||
titles[i].disable();
|
||||
}else{
|
||||
titles[i].setBackgroundColor(0x00000000);
|
||||
titles[i].setTextColor(default_text_color);
|
||||
titles[i].enable();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package com.ridgebotics.ridgescout.ui.scouting;
|
||||
|
||||
import static android.widget.LinearLayout.VERTICAL;
|
||||
import static androidx.navigation.fragment.FragmentKt.findNavController;
|
||||
|
||||
import static com.ridgebotics.ridgescout.utility.DataManager.event;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.ridgebotics.ridgescout.R;
|
||||
import com.ridgebotics.ridgescout.types.frcEvent;
|
||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
||||
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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ScoutingFragment extends Fragment {
|
||||
|
||||
private FragmentScoutingBinding binding;
|
||||
private boolean is_main_page = true;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
binding = FragmentScoutingBinding.inflate(inflater, container, false);
|
||||
|
||||
binding.buttons.setVisibility(View.VISIBLE);
|
||||
|
||||
DataManager.reload_event();
|
||||
|
||||
if(settingsManager.getCustomEvents()){
|
||||
binding.eventAddButton.setVisibility(View.VISIBLE);
|
||||
binding.eventAddButton.setOnClickListener(view -> {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle("Chose event name");
|
||||
|
||||
LinearLayout layout = new LinearLayout(getContext());
|
||||
layout.setOrientation(VERTICAL);
|
||||
EditText eventName = new EditText(getContext());
|
||||
eventName.setHint("Event Name");
|
||||
EditText eventCode = new EditText(getContext());
|
||||
eventCode.setHint("Event Code");
|
||||
layout.addView(eventName);
|
||||
layout.addView(eventCode);
|
||||
|
||||
|
||||
builder.setPositiveButton("Create", (dialog, which) -> {
|
||||
String name = eventName.getText().toString();
|
||||
String code = eventCode.getText().toString();
|
||||
if(name.isEmpty() || code.isEmpty()) return;
|
||||
|
||||
frcEvent event = new frcEvent();
|
||||
event.name = name;
|
||||
event.eventCode = code;
|
||||
event.teams = new ArrayList<>();
|
||||
event.matches = new ArrayList<>();
|
||||
|
||||
fileEditor.setEvent(event);
|
||||
|
||||
|
||||
});
|
||||
builder.setNeutralButton("Cancel", (dialog, which) -> {});
|
||||
|
||||
builder.setView(layout);
|
||||
builder.create().show();
|
||||
});
|
||||
}
|
||||
|
||||
if(event == null){
|
||||
binding.noEventError.setVisibility(View.VISIBLE);
|
||||
binding.matchScoutingButton.setEnabled(false);
|
||||
binding.pitScoutingButton.setEnabled(false);
|
||||
binding.eventButton.setEnabled(false);
|
||||
is_main_page = false;
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
if(event.matches.isEmpty()){
|
||||
binding.matchScoutingButton.setEnabled(false);
|
||||
}
|
||||
|
||||
if(event.teams.isEmpty()){
|
||||
binding.pitScoutingButton.setEnabled(false);
|
||||
}
|
||||
|
||||
binding.matchScoutingButton.setOnClickListener(v -> {
|
||||
findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_match_scouting);
|
||||
});
|
||||
|
||||
binding.pitScoutingButton.setOnClickListener(v -> {
|
||||
TeamSelectorFragment.setPits_mode(true);
|
||||
TeamSelectorFragment.setOnSelect((self, team) -> {
|
||||
PitScoutingFragment.setTeam(team);
|
||||
findNavController(self).navigate(R.id.action_navigation_team_selector_to_navigation_pit_scouting);
|
||||
});
|
||||
findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_team_selector);
|
||||
});
|
||||
|
||||
binding.eventButton.setOnClickListener(v -> {
|
||||
findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_scouting_event);
|
||||
});
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if(getView() == null){
|
||||
return;
|
||||
}
|
||||
|
||||
getView().setFocusableInTouchMode(true);
|
||||
getView().requestFocus();
|
||||
getView().setOnKeyListener((v, keyCode, event) -> {
|
||||
|
||||
if (event.getAction() == KeyEvent.ACTION_UP
|
||||
&& keyCode == KeyEvent.KEYCODE_BACK
|
||||
&& !is_main_page){
|
||||
|
||||
is_main_page = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -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,349 @@
|
||||
package com.ridgebotics.ridgescout.ui.settings;
|
||||
|
||||
import static com.ridgebotics.ridgescout.utility.settingsManager.AllyPosKey;
|
||||
import static com.ridgebotics.ridgescout.utility.settingsManager.CustomEventsKey;
|
||||
import static com.ridgebotics.ridgescout.utility.settingsManager.SelEVCodeKey;
|
||||
import static com.ridgebotics.ridgescout.utility.settingsManager.UnameKey;
|
||||
import static com.ridgebotics.ridgescout.utility.settingsManager.WifiModeKey;
|
||||
import static com.ridgebotics.ridgescout.utility.settingsManager.YearNumKey;
|
||||
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.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.google.android.material.card.MaterialCardView;
|
||||
import com.google.android.material.checkbox.MaterialCheckBox;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.ridgebotics.ridgescout.databinding.FragmentSettingsBinding;
|
||||
import com.ridgebotics.ridgescout.ui.CustomSpinnerPopup;
|
||||
import com.ridgebotics.ridgescout.ui.CustomSpinnerView;
|
||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
||||
import com.ridgebotics.ridgescout.utility.settingsManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class settingsFragment extends Fragment {
|
||||
private FragmentSettingsBinding binding;
|
||||
|
||||
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"};
|
||||
|
||||
SettingsManager manager = new SettingsManager(getContext());
|
||||
|
||||
|
||||
manager.addItem(new CheckboxSettingsItem(CustomEventsKey, "Custom Events"));
|
||||
|
||||
StringSettingsItem FTPServer = new StringSettingsItem(settingsManager.FTPServer, "FTP Server (Sync)");
|
||||
manager.addItem(FTPServer);
|
||||
CheckboxSettingsItem FTPSendMetaFiles = new CheckboxSettingsItem(settingsManager.FTPSendMetaFiles, "Sync meta files");
|
||||
manager.addItem(FTPSendMetaFiles);
|
||||
CheckboxSettingsItem FTPEnabled = new CheckboxSettingsItem(settingsManager.FTPEnabled, "FTP Enabled", FTPServer, FTPSendMetaFiles);
|
||||
manager.addItem(FTPEnabled);
|
||||
|
||||
manager.addItem(new CheckboxSettingsItem(WifiModeKey, "Wifi Mode", FTPEnabled));
|
||||
|
||||
manager.addItem(new NumberSettingsItem(YearNumKey, "Year", 0, 9999));
|
||||
|
||||
manager.addItem(new DropdownSettingsItem(AllyPosKey, "Alliance Pos", alliance_pos_list));
|
||||
manager.addItem(new DropdownSettingsItem(SelEVCodeKey, "Event Code", fileEditor.getEventList().toArray(new String[0])));
|
||||
manager.addItem(new StringSettingsItem(UnameKey, "Username"));
|
||||
|
||||
manager.getView(binding.SettingsTable);
|
||||
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public abstract class SettingsItem<T> {
|
||||
private String key;
|
||||
private String title;
|
||||
private T defaultValue;
|
||||
|
||||
public SettingsItem(String key, String title, T defaultValue) {
|
||||
this.key = key;
|
||||
this.title = title;
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public abstract View createView(Context context);
|
||||
public abstract T getValue();
|
||||
|
||||
public String getKey() { return key; }
|
||||
public String getTitle() { return title; }
|
||||
public T getDefaultValue() { return defaultValue; }
|
||||
public abstract void setEnabled(boolean enabled);
|
||||
}
|
||||
|
||||
public class StringSettingsItem extends SettingsItem<String> {
|
||||
public StringSettingsItem(String key, String title) {
|
||||
super(key, title, prefs.getString(key, (String) defaults.get(key)));
|
||||
}
|
||||
|
||||
TextInputEditText editText;
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled){
|
||||
editText.setEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createView(Context context) {
|
||||
TextInputLayout textInputLayout = new TextInputLayout(context);
|
||||
textInputLayout.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
|
||||
editText = new TextInputEditText(context);
|
||||
editText.setText(getValue());
|
||||
|
||||
editText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
getEditor().putString(getKey(), s.toString()).apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
});
|
||||
|
||||
textInputLayout.addView(editText);
|
||||
return textInputLayout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return prefs.getString(getKey(), (String) defaults.get(getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
public class NumberSettingsItem extends SettingsItem<Integer> {
|
||||
private int min;
|
||||
private int max;
|
||||
|
||||
public NumberSettingsItem(String key, String title, int min, int max) {
|
||||
super(key, title, prefs.getInt(key, (int) defaults.get(key)));
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
TextInputEditText editText;
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled){
|
||||
editText.setEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createView(Context context) {
|
||||
TextView titleView = new TextView(context);
|
||||
titleView.setText(getTitle());
|
||||
titleView.setTextAppearance(com.google.android.material.R.style.TextAppearance_MaterialComponents_Subtitle1);
|
||||
|
||||
TextInputLayout textInputLayout = new TextInputLayout(context);
|
||||
editText = new TextInputEditText(context);
|
||||
|
||||
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
editText.setText(String.valueOf(getValue()));
|
||||
|
||||
editText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
try {
|
||||
int value = Integer.parseInt(s.toString());
|
||||
if (value >= min && value <= max) {
|
||||
getEditor().putInt(getKey(), value).apply();
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
editText.setText(String.valueOf(getDefaultValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
});
|
||||
|
||||
textInputLayout.addView(editText);
|
||||
textInputLayout.addView(titleView);
|
||||
return textInputLayout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getValue() {
|
||||
return prefs.getInt(getKey(), (int) defaults.get(getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
public class DropdownSettingsItem extends SettingsItem<String> {
|
||||
private String[] options;
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled){
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public DropdownSettingsItem(String key, String title, String[] options) {
|
||||
super(key, title, prefs.getString(key, (String) defaults.get(key)));
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createView(Context context) {
|
||||
CustomSpinnerView dropdown = new CustomSpinnerView(getContext());
|
||||
dropdown.setLayoutParams(new ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
|
||||
|
||||
ArrayList<String> optionsList = new ArrayList<>(Arrays.asList(options));
|
||||
|
||||
dropdown.setTitle(getTitle());
|
||||
dropdown.setOptions(optionsList, getValue());
|
||||
dropdown.setOption(getValue());
|
||||
|
||||
dropdown.setOnClickListener((item, index) -> {
|
||||
getEditor().putString(getKey(), item).apply();
|
||||
});
|
||||
|
||||
return dropdown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return prefs.getString(getKey(), (String) defaults.get(getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
public class CheckboxSettingsItem extends SettingsItem<Boolean> {
|
||||
private List<SettingsItem<?>> controlledItems;
|
||||
|
||||
public CheckboxSettingsItem(String key, String title, SettingsItem<?>... controlledItems) {
|
||||
super(key, title, prefs.getBoolean(key, (Boolean) defaults.get(key)));
|
||||
this.controlledItems = Arrays.asList(controlledItems);
|
||||
}
|
||||
|
||||
MaterialCheckBox checkBox;
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled){
|
||||
checkBox.setEnabled(enabled);
|
||||
for (SettingsItem<?> item : controlledItems) {
|
||||
item.setEnabled(enabled && checkBox.isChecked());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createView(Context context) {
|
||||
checkBox = new MaterialCheckBox(context);
|
||||
checkBox.setText(getTitle());
|
||||
checkBox.setChecked(getValue());
|
||||
checkBox.setTextAppearance(com.google.android.material.R.style.TextAppearance_MaterialComponents_Subtitle1);
|
||||
checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
getEditor().putBoolean(getKey(), isChecked).apply();
|
||||
for (SettingsItem<?> item : controlledItems) {
|
||||
item.setEnabled(isChecked);
|
||||
}
|
||||
});
|
||||
|
||||
for (SettingsItem<?> item : controlledItems) {
|
||||
item.setEnabled(getValue());
|
||||
}
|
||||
|
||||
return checkBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getValue() {
|
||||
return prefs.getBoolean(getKey(), (Boolean) defaults.get(getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
public class SettingsManager {
|
||||
private Context context;
|
||||
private HashMap<String, Object> settings;
|
||||
private List<SettingsItem<?>> items;
|
||||
// private LinearLayout container;
|
||||
|
||||
public SettingsManager(Context context) {
|
||||
this.context = context;
|
||||
this.items = new ArrayList<>();
|
||||
// this.container = new LinearLayout(context);
|
||||
// this.container.setOrientation(LinearLayout.VERTICAL);
|
||||
// this.container.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
// LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
// LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
// ));
|
||||
}
|
||||
|
||||
private final List<View> views = new ArrayList<>();
|
||||
public void addItem(SettingsItem<?> item) {
|
||||
items.add(item);
|
||||
|
||||
LinearLayout itemContainer = new LinearLayout(context);
|
||||
itemContainer.setOrientation(LinearLayout.VERTICAL);
|
||||
itemContainer.setPadding(32, 0, 32, 8);
|
||||
|
||||
itemContainer.addView(item.createView(context));
|
||||
views.add(itemContainer);
|
||||
}
|
||||
|
||||
public void getView(LinearLayout layout) {
|
||||
for(int i = views.size()-1; i >= 0; i--)
|
||||
layout.addView(views.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
+41
-30
@@ -1,32 +1,27 @@
|
||||
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.types.input.inputType;
|
||||
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 +59,18 @@ 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 {
|
||||
String tempData = "";
|
||||
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.match_values, DataManager.match_transferValues);
|
||||
dataType[] matchData = psdr.data.array;
|
||||
inputType[] types = psdr.data.values[psdr.data.values.length-1];
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
tempData += (safeCSV(types[i].toString(matchData[i])) + ",");
|
||||
}
|
||||
data += tempData;
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
data += ("null,".repeat(match_latest_values.length));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -86,7 +89,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 +111,18 @@ 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 {
|
||||
String tempData = "";
|
||||
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.pit_values, DataManager.pit_transferValues);
|
||||
dataType[] teamData = psdr.data.array;
|
||||
inputType[] types = psdr.data.values[psdr.data.values.length-1];
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
tempData += (safeCSV(types[i].toString(teamData[i])) + ",");
|
||||
}
|
||||
data += tempData;
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
data += ("null,".repeat(pit_latest_values.length));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
package com.ridgebotics.ridgescout.ui.transfer;
|
||||
|
||||
//import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
|
||||
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
|
||||
import static com.ridgebotics.ridgescout.utility.fileEditor.baseDir;
|
||||
|
||||
import com.ridgebotics.ridgescout.ui.data.FieldEditorHelper;
|
||||
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 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.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class FTPSync extends Thread {
|
||||
public static final String remoteBasePath = "/RidgeScout/";
|
||||
public static final String timestampsFilename = "timestamps";
|
||||
|
||||
|
||||
|
||||
public static long lastSyncTime = 0;
|
||||
private static Date curSyncTime;
|
||||
private static final long millisTolerance = 1000;
|
||||
|
||||
private boolean after(Date a, Date b){
|
||||
return a.getTime() - b.getTime() > millisTolerance;
|
||||
}
|
||||
|
||||
|
||||
public interface onResult {
|
||||
void onResult(boolean error, int upCount, int downCount);
|
||||
}
|
||||
public interface UpdateIndicator {
|
||||
void onText(String text);
|
||||
}
|
||||
private static UpdateIndicator updateIndicator = text -> {};
|
||||
public static String text = "";
|
||||
private static void setUpdateIndicator(String m_text){
|
||||
text = m_text;
|
||||
updateIndicator.onText(m_text);
|
||||
}
|
||||
public static void setOnUpdateIndicator(UpdateIndicator m_updateIndicator){
|
||||
updateIndicator = m_updateIndicator;
|
||||
}
|
||||
|
||||
private static onResult onResult = (error, upCount, downCount) -> {};
|
||||
public static void setOnResult(onResult result){
|
||||
onResult = result;
|
||||
}
|
||||
|
||||
private static boolean isRunning = false;
|
||||
public static boolean getIsRunning(){return isRunning;}
|
||||
|
||||
public static void sync(){
|
||||
// DataManager.reload_event();
|
||||
FTPSync ftpSync = new FTPSync();
|
||||
|
||||
curSyncTime = new Date();
|
||||
|
||||
ftpSync.start();
|
||||
}
|
||||
|
||||
FTPClient ftpClient;
|
||||
|
||||
private int upCount = 0;
|
||||
private int downCount = 0;
|
||||
|
||||
private void downloadFile(String remoteFile, File localFile) throws IOException {
|
||||
try (FileOutputStream fos = new FileOutputStream(localFile)) {
|
||||
ftpClient.retrieveFile(remoteBasePath + remoteFile, fos);
|
||||
}
|
||||
}
|
||||
|
||||
private void uploadFile(File localFile) throws IOException {
|
||||
try (FileInputStream fis = new FileInputStream(localFile)) {
|
||||
ftpClient.storeFile(remoteBasePath + localFile.getName(), fis);
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
public void run() {
|
||||
isRunning = true;
|
||||
boolean sendMetaFiles = settingsManager.getFTPSendMetaFiles();
|
||||
|
||||
// Meta files
|
||||
List<String> meta_string_array = Arrays.asList(
|
||||
"matches.fields",
|
||||
"pits.fields",
|
||||
evcode+".eventdata"
|
||||
);
|
||||
|
||||
try {
|
||||
// Login to FTP
|
||||
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();
|
||||
Map<String, Date> remoteTimestamps = getTimestamps();
|
||||
|
||||
// Loop through local files and send all that are more recent
|
||||
if (localFiles != null) {
|
||||
for (int i = 0; i < localFiles.length; i++) {
|
||||
File localFile = localFiles[i];
|
||||
setUpdateIndicator("Uploading " + (i+1) + "/" + localFiles.length);
|
||||
|
||||
if(localFile.isDirectory()) continue;
|
||||
// Remove timestamts file
|
||||
if(localFile.getName().equals(timestampsFilename)) continue;
|
||||
// Remove meta files if the option is disabled
|
||||
if(!sendMetaFiles && meta_string_array.contains(localFile.getName())) continue;
|
||||
|
||||
Date remoteTimestamp = remoteTimestamps.get(localFile.getName());
|
||||
|
||||
Date localTimeStamp = getLocalFileUtcTimestamp(localFile);
|
||||
|
||||
if (remoteTimestamp == null || after(localTimeStamp, remoteTimestamp)) {
|
||||
uploadFile(localFile);
|
||||
System.out.println("Uploaded" + localFile.getName());
|
||||
|
||||
setLocalFileTimestamp(localFile, curSyncTime);
|
||||
remoteTimestamps.put(localFile.getName(), curSyncTime);
|
||||
upCount++;
|
||||
}else{
|
||||
System.out.println("Did not upload");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> keySet = remoteTimestamps.keySet();
|
||||
Iterator<String> keyIt = keySet.iterator();
|
||||
for (int i = 0; i < keySet.size(); i++) {
|
||||
String remoteFile = keyIt.next();
|
||||
setUpdateIndicator("Downloading " + (i+1) + "/" + keySet.size());
|
||||
|
||||
File localFile = new File(baseDir, remoteFile);
|
||||
if(remoteFile.equals(timestampsFilename)) continue;
|
||||
// Remove meta files if the option is disabled
|
||||
if(!sendMetaFiles && meta_string_array.contains(remoteFile)) continue;
|
||||
|
||||
// Date t1 = getLocalFileUtcTimestamp(localFile);
|
||||
// Date t2 = getUtcTimestamp(remoteFile);
|
||||
////
|
||||
// System.out.println("- " + t1 + (t1.after(t2) ? ">" : "<") + t2);
|
||||
|
||||
Date localTimeStamp = getLocalFileUtcTimestamp(localFile);
|
||||
Date remoteTimestamp = remoteTimestamps.get(remoteFile);
|
||||
|
||||
|
||||
|
||||
if (!localFile.exists() || (after(remoteTimestamp, localTimeStamp) && !localTimeStamp.equals(remoteTimestamp))) {
|
||||
downloadFile(remoteFile, localFile);
|
||||
|
||||
System.out.println("Downloaded " + localFile.getName());
|
||||
|
||||
if(!localFile.exists()) System.out.println("Not exist");
|
||||
else if(after(remoteTimestamp, localTimeStamp)) System.out.println("Before: " + (localTimeStamp.getTime()-remoteTimestamp.getTime()));
|
||||
|
||||
// Date d = getUtcTimestamp(remoteFile);
|
||||
setLocalFileTimestamp(localFile, remoteTimestamps.get(localFile.getName()));
|
||||
// remoteTimestamps.put(remoteFile, curSyncTime);
|
||||
downCount++;
|
||||
}else{
|
||||
System.out.println("Did not download");
|
||||
}
|
||||
}
|
||||
|
||||
setTimestamps(remoteTimestamps);
|
||||
|
||||
} catch (Exception e) {
|
||||
AlertManager.error(e);
|
||||
onResult.onResult(true, upCount, downCount);
|
||||
setUpdateIndicator("ERROR!");
|
||||
} finally {
|
||||
onResult.onResult(false, upCount, downCount);
|
||||
setUpdateIndicator("Finished");
|
||||
}
|
||||
|
||||
isRunning = false;
|
||||
}
|
||||
|
||||
private boolean setTimestamps(Map<String, Date> timestamps){
|
||||
try {
|
||||
ByteBuilder bb = new ByteBuilder();
|
||||
String[] filenames = timestamps.keySet().toArray(new String[0]);
|
||||
|
||||
for(int i = 0; i < filenames.length; i++){
|
||||
bb.addString(filenames[i]);
|
||||
bb.addLong(timestamps.get(filenames[i]).getTime());
|
||||
}
|
||||
|
||||
fileEditor.writeFile(timestampsFilename, bb.build());
|
||||
|
||||
uploadFile(new File(baseDir + timestampsFilename));
|
||||
return true;
|
||||
} catch (ByteBuilder.buildingException | IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Date> getTimestamps() {
|
||||
try {
|
||||
downloadFile(timestampsFilename, new File(baseDir + timestampsFilename));
|
||||
|
||||
byte[] data = fileEditor.readFile(timestampsFilename);
|
||||
|
||||
if(data == null || data.length == 0)
|
||||
return new HashMap<>();
|
||||
|
||||
BuiltByteParser bbp = new BuiltByteParser(data);
|
||||
List<BuiltByteParser.parsedObject> pa = bbp.parse();
|
||||
|
||||
Map<String, Date> output = new HashMap<>();
|
||||
for(int i = 0; i < pa.size(); i+=2){
|
||||
// System.out.println((long) pa.get(i).get());
|
||||
output.put(
|
||||
(String) pa.get(i).get(),
|
||||
new Date((long) pa.get(i+1).get())
|
||||
);
|
||||
}
|
||||
return output;
|
||||
|
||||
}catch (IOException | BuiltByteParser.byteParsingExeption e){
|
||||
AlertManager.error(e);
|
||||
return new HashMap<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-9
@@ -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;
|
||||
+21
-9
@@ -1,11 +1,12 @@
|
||||
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;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TableRow;
|
||||
@@ -15,11 +16,12 @@ 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.DataManager;
|
||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -41,6 +43,7 @@ public class FileSelectorFragment extends Fragment {
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
binding = FragmentTransferFileSelectorBinding.inflate(inflater, container, false);
|
||||
|
||||
DataManager.reload_event();
|
||||
|
||||
meta_string_array = new String[]{
|
||||
"matches.fields",
|
||||
@@ -66,6 +69,10 @@ public class FileSelectorFragment extends Fragment {
|
||||
|
||||
tr.setBackgroundColor(background_color);
|
||||
|
||||
CheckBox checkBox = new CheckBox(getContext());
|
||||
checkBox.setChecked(true);
|
||||
tr.addView(checkBox);
|
||||
|
||||
TextView tv = new TextView(getContext());
|
||||
tv.setText(String.valueOf(files[i]));
|
||||
tv.setTextSize(20);
|
||||
@@ -77,6 +84,7 @@ public class FileSelectorFragment extends Fragment {
|
||||
selected_arr[fi] = sel;
|
||||
|
||||
tr.setBackgroundColor(sel ? background_color : unselected_background_color);
|
||||
((CheckBox) tr.getChildAt(0)).setChecked(sel);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -88,9 +96,12 @@ public class FileSelectorFragment extends Fragment {
|
||||
Arrays.fill(selected_arr, Boolean.TRUE);
|
||||
|
||||
for(int i = 0; i < files.length; i++){
|
||||
View child = binding.fileSelectorTable.getChildAt(i);
|
||||
TableRow child = (TableRow) binding.fileSelectorTable.getChildAt(i);
|
||||
child.setBackgroundColor(background_color);
|
||||
child.setVisibility(is_in_search_param(files[i], search_param, match_num_nums) ? View.VISIBLE : View.GONE);
|
||||
boolean sel = is_in_search_param(files[i], search_param, match_num_nums);
|
||||
child.setVisibility(sel ? View.VISIBLE : View.GONE);
|
||||
((CheckBox) child.getChildAt(0)).setChecked(sel);
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -103,6 +114,7 @@ public class FileSelectorFragment extends Fragment {
|
||||
View child = binding.fileSelectorTable.getChildAt(i);
|
||||
if(child.getVisibility() == View.VISIBLE && selected_arr[i])
|
||||
filenames.add(files[i]);
|
||||
|
||||
}
|
||||
onSelect.onSelect(get_bytes_of_filenames(filenames));
|
||||
});
|
||||
+17
-12
@@ -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,15 @@ 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 com.ridgebotics.ridgescout.utility.settingsManager;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
@@ -35,13 +36,13 @@ import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
|
||||
public class TBAFragment extends Fragment {
|
||||
private final String TBAAddress = "https://www.thebluealliance.com/api/v3/";
|
||||
private final String TBAHeader = "X-TBA-Auth-Key: tjEKSZojAU2pgbs2mBt06SKyOakVhLutj3NwuxLTxPKQPLih11aCIwRIVFXKzY4e";
|
||||
private static final String TBAAddress = "https://www.thebluealliance.com/api/v3/";
|
||||
private static final String TBAHeader = "X-TBA-Auth-Key: tjEKSZojAU2pgbs2mBt06SKyOakVhLutj3NwuxLTxPKQPLih11aCIwRIVFXKzY4e";
|
||||
|
||||
private android.widget.TableLayout Table;
|
||||
private FragmentTransferTbaBinding binding;
|
||||
|
||||
private static final int year = 2024;
|
||||
private final int year = settingsManager.getYearNum();
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
@@ -58,6 +59,10 @@ public class TBAFragment extends Fragment {
|
||||
|
||||
final RequestTask rq = new RequestTask();
|
||||
rq.onResult(s -> {
|
||||
if(s == null || s.isEmpty()) {
|
||||
AlertManager.error("Could not fetch event!");
|
||||
return null;
|
||||
}
|
||||
eventTable(s);
|
||||
return null;
|
||||
});
|
||||
+48
-43
@@ -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,16 @@ 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 org.apache.commons.net.ftp.FTP;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class TransferFragment extends Fragment {
|
||||
private FragmentTransferBinding binding;
|
||||
@@ -45,32 +50,50 @@ 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();
|
||||
});
|
||||
|
||||
binding.TBAButton.setOnClickListener(v -> {
|
||||
binding.noEventError.setVisibility(View.GONE);
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
|
||||
alert.setTitle("Warning");
|
||||
alert.setMessage("This action requires internet.");
|
||||
alert.setCancelable(true);
|
||||
|
||||
alert.setPositiveButton("Ok", (dialog, which) -> {
|
||||
findNavController(this).navigate(R.id.action_navigation_transfer_to_navigation_tba);
|
||||
});
|
||||
|
||||
alert.setNegativeButton("Cancel", null);
|
||||
alert.create().show();
|
||||
findNavController(this).navigate(R.id.action_navigation_transfer_to_navigation_tba);
|
||||
});
|
||||
|
||||
|
||||
if(!settingsManager.getWifiMode()) {
|
||||
binding.TBAButton.setEnabled(false);
|
||||
binding.SyncButton.setEnabled(false);
|
||||
}
|
||||
|
||||
if(!settingsManager.getFTPEnabled()) {
|
||||
binding.SyncButton.setEnabled(false);
|
||||
}
|
||||
|
||||
binding.SyncButton.setOnClickListener(v -> {
|
||||
binding.SyncButton.setEnabled(false);
|
||||
FTPSync.sync();
|
||||
});
|
||||
|
||||
if(FTPSync.getIsRunning())
|
||||
binding.SyncButton.setEnabled(false);
|
||||
|
||||
FTPSync.setOnResult((error, upcount, downcount) -> {
|
||||
if (getActivity() != null)
|
||||
getActivity().runOnUiThread(() -> {
|
||||
binding.SyncButton.setEnabled(true);
|
||||
AlertManager.toast((!error ? "Synced! " : "Error Syncing. ") + upcount + " Up " + downcount + " Down");
|
||||
});
|
||||
});
|
||||
|
||||
binding.syncIndicator.setText(FTPSync.text);
|
||||
FTPSync.setOnUpdateIndicator(text -> {if(getActivity() != null) getActivity().runOnUiThread(() -> binding.syncIndicator.setText(text));});
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -82,33 +105,15 @@ public class TransferFragment extends Fragment {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle("Chose data");
|
||||
|
||||
builder.setNegativeButton("Pit data", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
CSVExport.exportPits(getContext());
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton("Pit data", (dialog, which) -> CSVExport.exportPits(getContext()));
|
||||
|
||||
builder.setPositiveButton("Match data", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
CSVExport.exportMatches(getContext());
|
||||
}
|
||||
});
|
||||
builder.setPositiveButton("Match data", (dialog, which) -> CSVExport.exportMatches(getContext()));
|
||||
|
||||
builder.setNeutralButton("Cancel", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
builder.setNeutralButton("Cancel", (dialog, which) -> dialog.cancel());
|
||||
|
||||
builder.show();
|
||||
});
|
||||
|
||||
if(!latestSettings.settings.get_wifi_mode())
|
||||
binding.TBAButton.setVisibility(View.GONE);
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
+5
-11
@@ -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 {
|
||||
|
||||
@@ -30,17 +30,11 @@ public class TransferSelectorFragment extends Fragment {
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
binding = FragmentTransferSelectorBinding.inflate(inflater, container, false);
|
||||
|
||||
binding.codesButton.setOnClickListener(view -> {
|
||||
onselect.onSelectCodes(this);
|
||||
});
|
||||
binding.codesButton.setOnClickListener(view -> onselect.onSelectCodes(this));
|
||||
|
||||
binding.bluetoothButton.setOnClickListener(view -> {
|
||||
onselect.onSelectBluetooth(this);
|
||||
});
|
||||
binding.bluetoothButton.setOnClickListener(view -> onselect.onSelectBluetooth(this));
|
||||
|
||||
binding.fileBundleButton.setOnClickListener(view -> {
|
||||
onselect.onSelectFileBundle(this);
|
||||
});
|
||||
binding.fileBundleButton.setOnClickListener(view -> onselect.onSelectFileBundle(this));
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
+9
-10
@@ -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;
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -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;
|
||||
+7
-7
@@ -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;
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -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;
|
||||
+4
-7
@@ -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
-1
@@ -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
-1
@@ -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;
|
||||
+13
-9
@@ -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();
|
||||
+10
-13
@@ -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;
|
||||
@@ -54,19 +53,17 @@ public class AlertManager {
|
||||
|
||||
public static void error(Exception e) {
|
||||
e.printStackTrace();
|
||||
((Activity) context).runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
((Activity) context).runOnUiThread(() -> {
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(context);
|
||||
alert.setMessage(sw.toString());
|
||||
alert.setTitle(e.getMessage());
|
||||
alert.setPositiveButton("OK", null);
|
||||
alert.setCancelable(true);
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(context);
|
||||
alert.setMessage(sw.toString());
|
||||
alert.setTitle(e.getMessage());
|
||||
alert.setPositiveButton("OK", null);
|
||||
alert.setCancelable(true);
|
||||
|
||||
alert.create().show();
|
||||
}
|
||||
alert.create().show();
|
||||
});
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.astatin3.scoutingapp2025.utility;
|
||||
package com.ridgebotics.ridgescout.utility;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
+14
-1
@@ -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;
|
||||
@@ -9,6 +10,7 @@ public class BuiltByteParser {
|
||||
public static final Integer stringType = 2;
|
||||
public static final Integer intArrayType = 3;
|
||||
public static final Integer stringArrayType = 4;
|
||||
public static final Integer longType = 5;
|
||||
|
||||
public class byteParsingExeption extends Exception {
|
||||
public byteParsingExeption() {}
|
||||
@@ -57,6 +59,11 @@ public class BuiltByteParser {
|
||||
public Integer getType(){return stringArrayType;}
|
||||
public Object get(){return arr;}
|
||||
}
|
||||
public class longObject extends parsedObject{
|
||||
long num;
|
||||
public Integer getType(){return longType;}
|
||||
public Object get(){return num;}
|
||||
}
|
||||
|
||||
|
||||
public class rawObject extends parsedObject {
|
||||
@@ -121,6 +128,7 @@ public class BuiltByteParser {
|
||||
|
||||
intArrayObject ia = new intArrayObject();
|
||||
ia.arr = intArr;
|
||||
System.out.println(Arrays.toString(intArr));
|
||||
objects.add(ia);
|
||||
break;
|
||||
case 4:
|
||||
@@ -138,6 +146,11 @@ public class BuiltByteParser {
|
||||
sa.arr = StringArr;
|
||||
objects.add(sa);
|
||||
break;
|
||||
case 5:
|
||||
longObject lo = new longObject();
|
||||
lo.num = fileEditor.fromBytesLong(block, length);
|
||||
objects.add(lo);
|
||||
break;
|
||||
default:
|
||||
rawObject ro = new rawObject(type);
|
||||
ro.bytes = block;
|
||||
+37
-1
@@ -1,4 +1,4 @@
|
||||
package com.astatin3.scoutingapp2025.utility;
|
||||
package com.ridgebotics.ridgescout.utility;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
@@ -9,6 +9,7 @@ public class ByteBuilder {
|
||||
public static final int string_id = 2;
|
||||
public static final int int_arr_id = 3;
|
||||
public static final int string_arr_id = 4;
|
||||
public static final int long_id = 5;
|
||||
|
||||
ArrayList<byteType> bytesToBuild = new ArrayList<>();
|
||||
|
||||
@@ -153,6 +154,41 @@ public class ByteBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
private class longType extends byteType {
|
||||
public int precision;
|
||||
public long num;
|
||||
public byte getType(){return long_id;}
|
||||
public int length(){return precision;}
|
||||
public byte[] build(){
|
||||
return fileEditor.toBytes(num, precision);
|
||||
}
|
||||
}
|
||||
private int getLeastBytePrecision(long num){
|
||||
if(num <= 1){return 1;}
|
||||
return (int) Math.ceil(Math.log(Math.abs(num))/Math.log(8));
|
||||
}
|
||||
public ByteBuilder addLong(long num) throws buildingException {
|
||||
// Get closest number of bytes
|
||||
int precision = getLeastBytePrecision(num);
|
||||
return addLong(num, precision);
|
||||
}
|
||||
public ByteBuilder addLong(long num, int precision) throws buildingException {
|
||||
if(precision <= 0){throw new buildingException("Invalid precision: " + precision);}
|
||||
|
||||
if(precision > 65536){throw new buildingException("Precision too large (greter than 65536)");}
|
||||
if(precision < getLeastBytePrecision(num)){throw new buildingException("Precision too small");}
|
||||
|
||||
if(num > Long.MAX_VALUE){throw new buildingException("Long overflow");}
|
||||
if(num < Long.MIN_VALUE){throw new buildingException("Long overflow");}
|
||||
|
||||
longType longType = new longType();
|
||||
longType.num = num;
|
||||
longType.precision = precision;
|
||||
|
||||
bytesToBuild.add(longType);
|
||||
return this;
|
||||
}
|
||||
|
||||
private class rawType extends byteType {
|
||||
public int type;
|
||||
public byte[] bytes;
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.ridgebotics.ridgescout.utility;
|
||||
|
||||
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;
|
||||
public static frcEvent event;
|
||||
public static void reload_event(){
|
||||
evcode = getevcode();
|
||||
|
||||
if(evcode.equals("unset")) return;
|
||||
|
||||
event = frcEvent.decode(fileEditor.readFile(evcode + ".eventdata"));
|
||||
|
||||
if(event == null) {
|
||||
AlertManager.error("Failed to load event!");
|
||||
settingsManager.setEVCode("unset");
|
||||
evcode = "unset";
|
||||
}
|
||||
}
|
||||
|
||||
public static String getevcode() {
|
||||
return settingsManager.getEVCode();
|
||||
}
|
||||
|
||||
public static inputType[][] match_values;
|
||||
public static inputType[] match_latest_values;
|
||||
public static transferType[][] match_transferValues;
|
||||
public static void reload_match_fields(){
|
||||
try {
|
||||
match_values = fields.load(fields.matchFieldsFilename);
|
||||
match_latest_values = match_values[match_values.length - 1];
|
||||
match_transferValues = transferType.get_transfer_values(match_values);
|
||||
} catch (Exception e){
|
||||
AlertManager.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static inputType[][] pit_values;
|
||||
public static inputType[] pit_latest_values;
|
||||
public static transferType[][] pit_transferValues;
|
||||
public static void reload_pit_fields(){
|
||||
try {
|
||||
pit_values = fields.load(fields.pitsFieldsFilename);
|
||||
pit_latest_values = pit_values[pit_values.length-1];
|
||||
pit_transferValues = transferType.get_transfer_values(pit_values);
|
||||
} catch (Exception e){
|
||||
AlertManager.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -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
-1
@@ -1,4 +1,4 @@
|
||||
package com.astatin3.scoutingapp2025.utility;
|
||||
package com.ridgebotics.ridgescout.utility;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
+1
-2
@@ -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
-1
@@ -1,4 +1,4 @@
|
||||
package com.astatin3.scoutingapp2025.utility;
|
||||
package com.ridgebotics.ridgescout.utility;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.astatin3.scoutingapp2025.utility;
|
||||
package com.ridgebotics.ridgescout.utility;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
+58
-17
@@ -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);
|
||||
}
|
||||
@@ -63,6 +66,17 @@ public final class fileEditor {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static byte[] toBytes(long num, int byteCount){
|
||||
if(num > (Math.pow(2,byteCount*8)-1)){
|
||||
throw new BufferOverflowException();
|
||||
}
|
||||
byte[] bytes = new byte[byteCount];
|
||||
for(int i=0;i<byteCount;i++){
|
||||
bytes[i] = (byte)(num >> (i*8));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static int fromBytes(byte[] bytes, int byteCount){
|
||||
@@ -72,6 +86,13 @@ public final class fileEditor {
|
||||
}
|
||||
return returnInt;
|
||||
}
|
||||
public static long fromBytesLong(byte[] bytes, int byteCount){
|
||||
long returnLong = 0;
|
||||
for(int i=0;i<byteCount;i++){
|
||||
returnLong |= (bytes[i] & 0xFFL) << (i*8);
|
||||
}
|
||||
return returnLong;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -191,7 +212,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 +236,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 +308,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 +383,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,114 @@
|
||||
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 YearNumKey = "year_num";
|
||||
public static final String WifiModeKey = "wifi_mode";
|
||||
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 final String FTPSendMetaFiles = "ftp_send_meta_files";
|
||||
public static final String CustomEventsKey = "enable_custom_event";
|
||||
|
||||
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(YearNumKey, 2025);
|
||||
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");
|
||||
hm.put(FTPSendMetaFiles, false);
|
||||
hm.put(CustomEventsKey, false);
|
||||
|
||||
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(YearNumKey, (int) defaults.get( YearNumKey )).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( FTPServer )).apply();
|
||||
getEditor().putBoolean(FTPSendMetaFiles, (boolean) defaults.get( FTPSendMetaFiles )).apply();
|
||||
|
||||
getEditor().putBoolean(CustomEventsKey, (boolean) defaults.get( CustomEventsKey )).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 getYearNum(){return prefs.getInt( YearNumKey, (int) defaults.get(YearNumKey));}
|
||||
public static void setYearNum(int num){ getEditor().putInt( YearNumKey,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();}
|
||||
|
||||
public static boolean getFTPSendMetaFiles(){return prefs.getBoolean(FTPSendMetaFiles, (boolean) defaults.get(FTPSendMetaFiles));}
|
||||
public static void setFTPSendMetaFiles(boolean bool){getEditor().putBoolean(FTPSendMetaFiles,bool).apply();}
|
||||
|
||||
|
||||
public static boolean getCustomEvents(){return prefs.getBoolean(CustomEventsKey, (boolean) defaults.get(FTPSendMetaFiles));}
|
||||
public static void setCustomEvents(boolean bool){getEditor().putBoolean(CustomEventsKey,bool).apply();}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 997 B |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:src="@drawable/background"
|
||||
android:tileMode="repeat" />
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/transparent"/>
|
||||
<stroke android:width="2dip" android:color="#626262" />
|
||||
<corners android:radius="3dip"/>
|
||||
<padding android:left="0dip"
|
||||
android:top="0dip"
|
||||
android:right="0dip"
|
||||
android:bottom="0dip" />
|
||||
</shape>
|
||||
@@ -0,0 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="12dp" android:viewportHeight="24" android:viewportWidth="24" android:width="12dp">
|
||||
|
||||
<path android:fillColor="#000000" android:fillType="evenOdd" android:pathData="M5,8l7,8l7,-8z" android:strokeColor="#00000000" android:strokeWidth="1"/>
|
||||
|
||||
</vector>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
@@ -4,6 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:background="@drawable/background_repeat"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<fragment
|
||||
|
||||
@@ -44,33 +44,40 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Teams"
|
||||
android:textSize="34sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/compareButton"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/fieldsButton" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/compareButton"
|
||||
android:layout_width="wrap_content"
|
||||
<LinearLayout
|
||||
android:id="@+id/fieldsButtons"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Compare"
|
||||
android:textSize="34sp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/reportButton"
|
||||
android:layout_marginTop="1dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/teamsButton" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/fieldsButton"
|
||||
tools:visibility="visible">
|
||||
|
||||
<Button
|
||||
android:id="@+id/reportButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Report"
|
||||
android:textSize="34sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/compareButton"
|
||||
app:layout_constraintVertical_bias="0.689" />
|
||||
<Button
|
||||
android:id="@+id/fieldsPitsButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="5dp"
|
||||
android:text="Pits"
|
||||
android:textSize="34sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/fieldsMatchesButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="5dp"
|
||||
android:text="Matches"
|
||||
android:textSize="34sp" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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">
|
||||
|
||||
<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>
|
||||
@@ -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 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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">
|
||||
|
||||
<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>
|
||||
@@ -1,24 +1,136 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/teamsMainElem"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
<ScrollView
|
||||
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">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/teamsArea"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="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>
|
||||
<com.ridgebotics.ridgescout.ui.CustomSpinnerView
|
||||
android:id="@+id/data_type_spinner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/team_name2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TextView"
|
||||
android:textAlignment="center"
|
||||
android:textSize="24sp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:layout_editor_absoluteX="0dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/team_description2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TextView"
|
||||
android:textAlignment="center"
|
||||
app:layout_constraintTop_toBottomOf="@+id/team_name2"
|
||||
tools:layout_editor_absoluteX="0dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Pit Data"
|
||||
android:textAlignment="center"
|
||||
android:textSize="24sp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/team_description2"
|
||||
tools:layout_editor_absoluteX="0dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/pitArea"
|
||||
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">
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Match Data"
|
||||
android:textAlignment="center"
|
||||
android:textSize="24sp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/team_description2"
|
||||
tools:layout_editor_absoluteX="0dp" />
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/individual_view_selector"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<Button
|
||||
android:id="@+id/matches_minus_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="0dp"
|
||||
android:text="@string/back"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/match_num"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/match_num"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:text="0"
|
||||
android:textAlignment="gravity"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline4"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:layout_editor_absoluteY="3dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/matches_plus_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="0dp"
|
||||
android:text="next"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/match_num"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/matchArea"
|
||||
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">
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -50,23 +50,35 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/pit_n_scouting"
|
||||
android:textSize="34sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/status_button"
|
||||
app:layout_constraintBottom_toTopOf="@id/event_button"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/matchScoutingButton" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/status_button"
|
||||
android:id="@+id/event_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Status"
|
||||
android:text="event"
|
||||
android:textSize="34sp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/pitScoutingButton"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/pitScoutingButton"
|
||||
app:layout_constraintVertical_bias="0.307" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/event_add_button"
|
||||
android:layout_width="58dp"
|
||||
android:layout_height="63dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:text="+"
|
||||
android:textSize="24sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/event_button"
|
||||
app:layout_constraintTop_toBottomOf="@+id/pitScoutingButton" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user