mirror of
https://github.com/Team4388/RidgeScout.git
synced 2026-06-09 00:37:59 -06:00
Compare commits
95 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 76a1b1ff70 | |||
| 82465f213f | |||
| 3c7a879f51 | |||
| 3157de62ff | |||
| 5ddc032be9 | |||
| e6073ded49 | |||
| 7503cefa09 | |||
| 3b4737e6bc | |||
| 76d28e46cd | |||
| 73308f2acc | |||
| c18a93cb1a | |||
| 3ca601f080 | |||
| 4554db9dc7 | |||
| b5b1100c2c | |||
| 311dfcbd5d | |||
| fa47eb1aff | |||
| 93b58310bf | |||
| 859d3bc773 | |||
| 9136df04df | |||
| f281ff2f0a | |||
| 154e76fbf7 | |||
| ffaec948b4 | |||
| 2d3db09aae | |||
| 05a40e39c3 | |||
| 090a0579b9 | |||
| a30664000c | |||
| 1bae273abd | |||
| 5c2b1fef2e | |||
| dbba56e649 | |||
| 4aa31b620d | |||
| 890b879ef9 | |||
| ef761003c8 | |||
| 5279c085e1 | |||
| 41460fcd7e | |||
| 782fb73050 | |||
| 7e9954d78a | |||
| 65baecac35 | |||
| e278bc10a1 | |||
| 5d727cf359 | |||
| ae147771cb | |||
| 36801e2f9b | |||
| 50419e284c | |||
| c8c278b316 | |||
| e280fc8523 | |||
| e559b4dac9 | |||
| b83d67359e | |||
| 15c503bbb7 | |||
| e2b0eee354 | |||
| ea41c5db24 | |||
| 2210d8d654 | |||
| 9f2ef1b5ed | |||
| 2dfad418e3 | |||
| 465b94ac7e | |||
| 72921a7c11 | |||
| eaa14adbd9 | |||
| a371f2f449 | |||
| 6c38147c6d | |||
| 3f4a2309b3 | |||
| 5447b64857 | |||
| 967dc3c967 | |||
| d2c075da9c | |||
| fbdd2206c0 | |||
| 71ef386075 | |||
| ee3c3b6b9c | |||
| 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 |
@@ -1,3 +1,9 @@
|
|||||||
|
# Python server
|
||||||
|
__pycache__/
|
||||||
|
metadata.json
|
||||||
|
api_key.txt
|
||||||
|
server_data/
|
||||||
|
|
||||||
# Gradle files
|
# Gradle files
|
||||||
.gradle/
|
.gradle/
|
||||||
build/
|
build/
|
||||||
|
|||||||
Binary file not shown.
@@ -11,10 +11,10 @@
|
|||||||
|
|
||||||
#### Here is an overview of the main features currently included in the app:
|
#### 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.
|
- 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.
|
- Similar to ScoutingPASS, many different types of fields can be used to collect data.
|
||||||
- The app is designed to handle updates to the fields on the fly, without loosing any data!
|
- The app is designed to handle updates to the fields on the fly, without losing 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.
|
- 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.
|
- Dynamic displays based on the different fields.
|
||||||
- Data transfer including 2D codes, Bluetooth, and File Bundle.
|
- Data transfer including 2D codes, Bluetooth, and File Bundle.
|
||||||
- Exporting using CSV.
|
- Exporting using CSV.
|
||||||
- Deployment on F-Droid
|
- Deployment on F-Droid
|
||||||
@@ -22,16 +22,13 @@
|
|||||||
|
|
||||||
#### Things that are yet to be implemented:
|
#### Things that are yet to be implemented:
|
||||||
- A page that lets users cross-compare scouting data between teams. (Compare)
|
- 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:
|
#### Things that may or may not be implemented:
|
||||||
- Practice mode
|
- Statbotics integration
|
||||||
- Statbotics intgration
|
|
||||||
- Scout error estimation using OPR-like calculation
|
- Scout error estimation using OPR-like calculation
|
||||||
- - Would most likely require Statbotics
|
- - Would most likely require Statbotics
|
||||||
|
https://www.thebluealliance.com/avatars
|
||||||
### Screenshots
|
### Screenshots
|
||||||
|Match scouting interface|Field editor|Teams data viewer|
|
|Match scouting interface|Field editor|Teams data viewer|
|
||||||
|-|-|-|
|
|-|-|-|
|
||||||
||||
|
||||
|
||||||
|
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
### TODO:
|
|
||||||
##### Scouting:
|
|
||||||
- Make practice mode??
|
|
||||||
##### Data Analysis:
|
|
||||||
- Statbotics intigration???
|
|
||||||
##### Functionality:
|
|
||||||
|
|
||||||
### In Progress:
|
|
||||||
##### Scouting:
|
|
||||||
##### Data Analysis:
|
|
||||||
- AI overview of scouting data for a team???
|
|
||||||
- Make the "Report" menu, A tool that lets users select data to display from the the teams and compare menus.
|
|
||||||
- Make the "Compare" menu, cross comparing team's stats.
|
|
||||||
##### Functionality:
|
|
||||||
|
|
||||||
### Done:
|
|
||||||
##### Scouting:
|
|
||||||
- Add an "unselect" option to all of the scouting fields
|
|
||||||
- When a field is created, make updated scouting data return null values, not the default value
|
|
||||||
- Fix scouting offset bug
|
|
||||||
##### Data Analysis:
|
|
||||||
- Add "history" view type to the teams view menu.
|
|
||||||
- Sentiment analysis of text input type
|
|
||||||
- Add CSV exporting of match scouting data.
|
|
||||||
##### Functionality:
|
|
||||||
- Improve the code scanning progress indicator. It has a rounding error, I think.
|
|
||||||
- Fix navigation crashes.
|
|
||||||
- Make everything use Fragments instead of views that toggle visibility
|
|
||||||
- Make the file browser UI
|
|
||||||
- Bluetooth data sync
|
|
||||||
- Formalize error messages & stacktraces
|
|
||||||
- Make pit and match data field builder UIs. I don't want to have to keep editing a variable
|
|
||||||
- Make the system for blank and unselected fields better.
|
|
||||||
- Write docs
|
|
||||||
- Deploy to F-Droid
|
|
||||||
- Add more types of data fields.
|
|
||||||
- Make server software to allow for easy sync over wifi - FTP
|
|
||||||
- Test the scouting app
|
|
||||||
Vendored
BIN
Binary file not shown.
+11
-14
@@ -1,6 +1,3 @@
|
|||||||
import com.android.build.api.dsl.AaptOptions
|
|
||||||
import com.android.build.api.dsl.AndroidResources
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.androidApplication)
|
alias(libs.plugins.androidApplication)
|
||||||
// id("com.google.gms.google-services")
|
// id("com.google.gms.google-services")
|
||||||
@@ -19,7 +16,7 @@ android {
|
|||||||
dependenciesInfo {
|
dependenciesInfo {
|
||||||
// Disables dependency metadata when building APKs.
|
// Disables dependency metadata when building APKs.
|
||||||
includeInApk = false
|
includeInApk = false
|
||||||
// Disables dependency metadata when building Android App Bundles.
|
// Disables dependency metadata when building Android App Bundles.5
|
||||||
includeInBundle = false
|
includeInBundle = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,8 +25,8 @@ android {
|
|||||||
applicationId = "com.ridgebotics.ridgescout"
|
applicationId = "com.ridgebotics.ridgescout"
|
||||||
minSdk = 24
|
minSdk = 24
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 5
|
versionCode = 15 // **IMPORTANT** Increment this before releasing on github
|
||||||
versionName = "0.5"
|
versionName = "3.1"// **IMPORTANT** Change this before releasing on github (<Year num since 2024>.<Update Version>)
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
@@ -47,8 +44,8 @@ android {
|
|||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding = true
|
viewBinding = true
|
||||||
}
|
}
|
||||||
aaptOptions {
|
androidResources {
|
||||||
noCompress("tflite");
|
noCompress += listOf("tflite")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,10 +53,11 @@ dependencies {
|
|||||||
|
|
||||||
implementation(libs.appcompat)
|
implementation(libs.appcompat)
|
||||||
implementation(libs.material)
|
implementation(libs.material)
|
||||||
|
implementation(libs.material3)
|
||||||
implementation(libs.constraintlayout)
|
implementation(libs.constraintlayout)
|
||||||
implementation(libs.lifecycle.livedata.ktx)
|
implementation(libs.lifecycle.livedata.ktx)
|
||||||
implementation(libs.lifecycle.viewmodel.ktx)
|
implementation(libs.lifecycle.viewmodel.ktx)
|
||||||
implementation(libs.navigation.fragment)
|
implementation("androidx.navigation:navigation-fragment:2.8.9")
|
||||||
implementation(libs.navigation.ui)
|
implementation(libs.navigation.ui)
|
||||||
implementation(libs.preference)
|
implementation(libs.preference)
|
||||||
// implementation(libs.support.annotations)
|
// implementation(libs.support.annotations)
|
||||||
@@ -68,15 +66,14 @@ dependencies {
|
|||||||
androidTestImplementation(libs.espresso.core)
|
androidTestImplementation(libs.espresso.core)
|
||||||
|
|
||||||
|
|
||||||
var camerax_version = "1.3.2"
|
var camerax_version = "1.4.2"
|
||||||
implementation("androidx.camera:camera-core:1.3.2")
|
implementation("androidx.camera:camera-core:${camerax_version}")
|
||||||
implementation("androidx.camera:camera-camera2:1.3.2")
|
implementation("androidx.camera:camera-camera2:${camerax_version}")
|
||||||
implementation("androidx.camera:camera-lifecycle:1.3.2")
|
implementation("androidx.camera:camera-lifecycle:${camerax_version}")
|
||||||
implementation("androidx.camera:camera-view:${camerax_version}")
|
implementation("androidx.camera:camera-view:${camerax_version}")
|
||||||
|
|
||||||
implementation("com.journeyapps:zxing-android-embedded:4.3.0")
|
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.github.PhilJay:MPAndroidChart:v3.1.0")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
@@ -3,16 +3,14 @@ package com.ridgebotics.ridgescout;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.MenuItem;
|
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.databinding.ActivityMainBinding;
|
import com.ridgebotics.ridgescout.databinding.ActivityMainBinding;
|
||||||
import com.ridgebotics.ridgescout.scoutingData.fields;
|
import com.ridgebotics.ridgescout.scoutingData.Fields;
|
||||||
import com.ridgebotics.ridgescout.utility.SentimentAnalysis;
|
import com.ridgebotics.ridgescout.utility.SentimentAnalysis;
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.navigation.NavController;
|
import androidx.navigation.NavController;
|
||||||
import androidx.navigation.NavOptions;
|
import androidx.navigation.NavOptions;
|
||||||
@@ -21,12 +19,14 @@ import androidx.navigation.ui.AppBarConfiguration;
|
|||||||
import androidx.navigation.ui.NavigationUI;
|
import androidx.navigation.ui.NavigationUI;
|
||||||
|
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.utility.settingsManager;
|
import com.ridgebotics.ridgescout.utility.SettingsManager;
|
||||||
import com.google.android.material.navigation.NavigationBarView;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
// Entrypoint for the scouting app.
|
||||||
|
// Configures stuff like the nav menu
|
||||||
|
// Also has some extra functions like a better back stack or a way to suppress the back button.
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
|
||||||
@@ -40,19 +40,23 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
// Load shared prefrences
|
||||||
settingsManager.prefs = this.getSharedPreferences(
|
SettingsManager.prefs = this.getSharedPreferences(
|
||||||
"com.ridgebotics.ridgescout", Context.MODE_PRIVATE);
|
"com.ridgebotics.ridgescout", Context.MODE_PRIVATE);
|
||||||
|
|
||||||
if(!fileEditor.fileExist(fields.matchFieldsFilename)){
|
// Load default match fields
|
||||||
fields.save(fields.matchFieldsFilename, fields.default_match_fields);
|
if(!FileEditor.fileExist(Fields.matchFieldsFilename)){
|
||||||
|
Fields.save(Fields.matchFieldsFilename, Fields.default_match_fields);
|
||||||
|
FileEditor.toTheArchaicPeriod(Fields.matchFieldsFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!fileEditor.fileExist(fields.pitsFieldsFilename)){
|
// Load default pit fields
|
||||||
fields.save(fields.pitsFieldsFilename, fields.default_pit_fields);
|
if(!FileEditor.fileExist(Fields.pitsFieldsFilename)){
|
||||||
|
Fields.save(Fields.pitsFieldsFilename, Fields.default_pit_fields);
|
||||||
|
FileEditor.toTheArchaicPeriod(Fields.pitsFieldsFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get time zone for FTP file transfer
|
||||||
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
|
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
|
||||||
|
|
||||||
AlertManager.init(this);
|
AlertManager.init(this);
|
||||||
@@ -76,7 +80,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
appBarConfiguration = new AppBarConfiguration.Builder(
|
appBarConfiguration = new AppBarConfiguration.Builder(
|
||||||
R.id.navigation_scouting,
|
R.id.navigation_scouting,
|
||||||
R.id.navigation_data,
|
R.id.navigation_data_parent,
|
||||||
R.id.navigation_transfer,
|
R.id.navigation_transfer,
|
||||||
R.id.navigation_settings)
|
R.id.navigation_settings)
|
||||||
.build();
|
.build();
|
||||||
@@ -89,9 +93,8 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
|
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
|
||||||
NavigationUI.setupWithNavController(navView, navController);
|
NavigationUI.setupWithNavController(navView, navController);
|
||||||
|
|
||||||
navView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
|
navView.setOnItemSelectedListener(item -> {
|
||||||
@Override
|
backPressed = null;
|
||||||
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
|
||||||
clearBackStack();
|
clearBackStack();
|
||||||
navController.navigate(item.getItemId(), savedInstanceState, new NavOptions.Builder()
|
navController.navigate(item.getItemId(), savedInstanceState, new NavOptions.Builder()
|
||||||
.setEnterAnim(R.anim.enter_anim)
|
.setEnterAnim(R.anim.enter_anim)
|
||||||
@@ -100,7 +103,6 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
.setPopExitAnim(R.anim.pop_exit_anim).build()
|
.setPopExitAnim(R.anim.pop_exit_anim).build()
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -116,11 +118,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public interface activityResultRelay {
|
public interface activityResultRelay {
|
||||||
void onActivityResult(int requestCode, int resultCode, Intent data);
|
void onActivityResult(int requestCode, int resultCode, Intent data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static activityResultRelay resultRelay = null;
|
public static activityResultRelay resultRelay = null;
|
||||||
public static void setResultRelay(activityResultRelay tmpresultRelay){
|
public static void setResultRelay(activityResultRelay tmpresultRelay){
|
||||||
resultRelay = tmpresultRelay;
|
resultRelay = tmpresultRelay;
|
||||||
@@ -135,4 +135,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();}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
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.FieldType;
|
||||||
|
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;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
||||||
|
// The mechanism to load, save, and create the fields based off of the raw types from ScoutingDataWriter.java
|
||||||
|
public class Fields {
|
||||||
|
// public static ScoutingVersion sv = new ScoutingVersion();
|
||||||
|
|
||||||
|
public static final String matchFieldsFilename = "matches.fields";
|
||||||
|
public static final String pitsFieldsFilename = "pits.fields";
|
||||||
|
|
||||||
|
private static String uuid(){
|
||||||
|
return UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final FieldType[][] default_match_fields = new FieldType[][] {
|
||||||
|
{
|
||||||
|
new FieldposType(uuid(),"Auto start pos", "Where does the robot start its auto?", new int[]{0,0})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static final FieldType[][] default_pit_fields = new FieldType[][] {
|
||||||
|
{
|
||||||
|
new DropdownType(uuid(),"Drivetrain type", "What type of drivetrain does this team have?", new String[]{"Swerve Drive", "Tank Drive (Differential)", "Other, Info in comments"}, 0),
|
||||||
|
new DropdownType(uuid(),"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(uuid(),"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(uuid(),"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(uuid(),"Auto Capability", "What autos does this team have?", ""),
|
||||||
|
new DropdownType(uuid(),"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(uuid(),"Climb type", "What does the robot do to climb?", new String[]{"No Climb", "Only Shallow", "Only Deep", "Both Shallow and Deep"}, 0),
|
||||||
|
new DropdownType(uuid(),"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(uuid(),"Cool Comments", "Is there anything cool about the robot?", ""),
|
||||||
|
|
||||||
|
new TextType(uuid(),"Comments", "Things go here", "Day 1:\n\nDay 2:\n\nDay 3:\n")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean save(String filename, FieldType[][] 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(FieldType[] 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 FieldType[][] load(String filename){
|
||||||
|
byte[] bytes = FileEditor.readFile(filename);
|
||||||
|
|
||||||
|
// System.out.println(bytes);
|
||||||
|
|
||||||
|
try {
|
||||||
|
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
||||||
|
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
||||||
|
FieldType[][] values = new FieldType[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 FieldType[] load_version(byte[] bytes) throws BuiltByteParser.byteParsingExeption{
|
||||||
|
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
||||||
|
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
||||||
|
FieldType[] output = new FieldType[objects.size()];
|
||||||
|
|
||||||
|
for(int i = 0 ; i < objects.size(); i++){
|
||||||
|
BuiltByteParser.parsedObject obj = objects.get(i);
|
||||||
|
FieldType t = null;
|
||||||
|
switch (obj.getType()){
|
||||||
|
case FieldType.slider_type_id:
|
||||||
|
t = new SliderType();
|
||||||
|
break;
|
||||||
|
case FieldType.dropdownType:
|
||||||
|
t = new DropdownType();
|
||||||
|
break;
|
||||||
|
case FieldType.notesType:
|
||||||
|
t = new TextType();
|
||||||
|
break;
|
||||||
|
case FieldType.tallyType:
|
||||||
|
t = new TallyType();
|
||||||
|
break;
|
||||||
|
case FieldType.numberType:
|
||||||
|
t = new NumberType();
|
||||||
|
break;
|
||||||
|
case FieldType.checkboxType:
|
||||||
|
t = new CheckboxType();
|
||||||
|
break;
|
||||||
|
case FieldType.fieldposType:
|
||||||
|
t = new FieldposType();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
t.decode((byte[]) obj.get());
|
||||||
|
output[i] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +1,30 @@
|
|||||||
package com.ridgebotics.ridgescout.scoutingData;
|
package com.ridgebotics.ridgescout.scoutingData;
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.scoutingData.transfer.transferType;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.scoutingData.transfer.TransferType;
|
||||||
import com.ridgebotics.ridgescout.types.ScoutingArray;
|
import com.ridgebotics.ridgescout.types.ScoutingArray;
|
||||||
import com.ridgebotics.ridgescout.types.data.dataType;
|
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||||
import com.ridgebotics.ridgescout.types.data.intArrType;
|
import com.ridgebotics.ridgescout.types.data.IntArrType;
|
||||||
import com.ridgebotics.ridgescout.types.data.stringType;
|
import com.ridgebotics.ridgescout.types.data.StringType;
|
||||||
import com.ridgebotics.ridgescout.types.input.inputType;
|
import com.ridgebotics.ridgescout.types.input.FieldType;
|
||||||
import com.ridgebotics.ridgescout.types.data.intType;
|
import com.ridgebotics.ridgescout.types.data.IntType;
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
// Mostly an extension of Fields.java. Saves the raw data from each Field Type.
|
||||||
public class ScoutingDataWriter {
|
public class ScoutingDataWriter {
|
||||||
// private static final int int_type_id = 255;
|
// private static final int int_type_id = 255;
|
||||||
// private static final int string_type_id = 254;
|
// private static final int string_type_id = 254;
|
||||||
|
|
||||||
public static boolean save(int version, String username, String filename, dataType[] data){
|
public static boolean save(int version, String username, String filename, RawDataType[] data){
|
||||||
ByteBuilder bb = new ByteBuilder();
|
ByteBuilder bb = new ByteBuilder();
|
||||||
try {
|
try {
|
||||||
bb.addInt(version);
|
bb.addInt(version);
|
||||||
@@ -28,19 +33,19 @@ public class ScoutingDataWriter {
|
|||||||
switch (data[i].getValueType()){
|
switch (data[i].getValueType()){
|
||||||
case NUM:
|
case NUM:
|
||||||
bb.addInt((int) data[i].forceGetValue());
|
bb.addInt((int) data[i].forceGetValue());
|
||||||
System.out.println("Saved INT: " + data[i].getName() + ", ("+ data[i].get() +")");
|
Log.i(ScoutingDataWriter.class.toString(),"Saved INT: " + data[i].getUUID() + ", ("+ data[i].get() +")");
|
||||||
break;
|
break;
|
||||||
case STRING:
|
case STRING:
|
||||||
bb.addString((String) data[i].forceGetValue());
|
bb.addString((String) data[i].forceGetValue());
|
||||||
System.out.println("Saved STR: " + data[i].getName() + ", ("+ data[i].get() +")");
|
Log.i(ScoutingDataWriter.class.toString(), "Saved STR: " + data[i].getUUID() + ", ("+ data[i].get() +")");
|
||||||
break;
|
break;
|
||||||
case NUMARR:
|
case NUMARR:
|
||||||
bb.addIntArray((int[]) data[i].forceGetValue());
|
bb.addIntArray((int[]) data[i].forceGetValue());
|
||||||
System.out.println("Saved INT Array: " + data[i].getName() + ", ("+ Arrays.toString((int[]) data[i].get()) +")");
|
Log.i(ScoutingDataWriter.class.toString(), "Saved INT Array: " + data[i].getUUID() + ", ("+ Arrays.toString((int[]) data[i].get()) +")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
byte[] bytes = bb.build();
|
byte[] bytes = bb.build();
|
||||||
fileEditor.writeFile(filename, bytes);
|
FileEditor.writeFile(filename, bytes);
|
||||||
return true;
|
return true;
|
||||||
} catch (ByteBuilder.buildingException e) {
|
} catch (ByteBuilder.buildingException e) {
|
||||||
AlertManager.error(e);
|
AlertManager.error(e);
|
||||||
@@ -55,38 +60,45 @@ public class ScoutingDataWriter {
|
|||||||
public ScoutingArray data;
|
public ScoutingArray data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ParsedScoutingDataResult load(String filename, inputType[][] values , transferType[][] transferValues){
|
public static ParsedScoutingDataResult load(String filename, FieldType[][] values , TransferType[][] transferValues) throws BuiltByteParser.byteParsingExeption{
|
||||||
byte[] bytes = fileEditor.readFile(filename);
|
byte[] bytes = FileEditor.readFile(filename);
|
||||||
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
||||||
try {
|
|
||||||
|
// try {
|
||||||
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
||||||
dataType[] dataTypes = new dataType[objects.size()-2];
|
RawDataType[] rawDataTypes = new RawDataType[objects.size()-2];
|
||||||
|
|
||||||
int version = ((int)objects.get(0).get());
|
int version = ((int)objects.get(0).get());
|
||||||
|
|
||||||
|
if(values.length <= version) {
|
||||||
|
// AlertManager.addSimpleError("Error loading " + filename);
|
||||||
|
throw new BuiltByteParser.byteParsingExeption("Field version (" +version + ") is too recent as compared to latest version (" + (values.length-1) + ")!");
|
||||||
|
}
|
||||||
|
|
||||||
// System.out.println(version);
|
// System.out.println(version);
|
||||||
String username = (String) objects.get(1).get();
|
String username = (String) objects.get(1).get();
|
||||||
|
|
||||||
for(int i = 0; i < values[version].length; i++){
|
for(int i = 0; i < values[version].length; i++){
|
||||||
switch (objects.get(i+2).getType()){
|
switch (objects.get(i+2).getType()){
|
||||||
case 1: // Int
|
case 1: // Int
|
||||||
dataTypes[i] = intType.newNull(values[version][i].name);
|
rawDataTypes[i] = IntType.newNull(values[version][i].UUID);
|
||||||
dataTypes[i].forceSetValue(objects.get(i+2).get());
|
rawDataTypes[i].forceSetValue(objects.get(i+2).get());
|
||||||
System.out.println("Loaded INT: " + values[version][i].name + ", ("+ dataTypes[i].get() +")");
|
Log.i(ParsedScoutingDataResult.class.toString(),"Loaded INT: " + values[version][i].name + " (" + values[version][i].UUID + ") " + ", ("+ rawDataTypes[i].get() +")");
|
||||||
break;
|
break;
|
||||||
case 2: // String
|
case 2: // String
|
||||||
dataTypes[i] = stringType.newNull(values[version][i].name);
|
rawDataTypes[i] = StringType.newNull(values[version][i].UUID);
|
||||||
dataTypes[i].forceSetValue(objects.get(i+2).get());
|
rawDataTypes[i].forceSetValue(objects.get(i+2).get());
|
||||||
System.out.println("Loaded STR: " + values[version][i].name + ", ("+ dataTypes[i].get() +")");
|
Log.i(ParsedScoutingDataResult.class.toString(),"Loaded STR: " + values[version][i].name + " (" + values[version][i].UUID + ") " + ", ("+ rawDataTypes[i].get() +")");
|
||||||
break;
|
break;
|
||||||
case 3: // Int array
|
case 3: // Int array
|
||||||
dataTypes[i] = intArrType.newNull(values[version][i].name);
|
rawDataTypes[i] = IntArrType.newNull(values[version][i].UUID);
|
||||||
dataTypes[i].forceSetValue(objects.get(i+2).get());
|
rawDataTypes[i].forceSetValue(objects.get(i+2).get());
|
||||||
System.out.println("Loaded intARR: " + values[version][i].name + ", ("+ Arrays.toString((int[])dataTypes[i].get()) +")");
|
Log.i(ParsedScoutingDataResult.class.toString(),"Loaded intARR: " + values[version][i].name + " (" + values[version][i].UUID + ") " + ", ("+ Arrays.toString((int[]) rawDataTypes[i].get()) +")");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScoutingArray msa = new ScoutingArray(version, dataTypes, values, transferValues);
|
ScoutingArray msa = new ScoutingArray(version, rawDataTypes, values, transferValues);
|
||||||
msa.update();
|
msa.update();
|
||||||
|
|
||||||
ParsedScoutingDataResult psda = new ParsedScoutingDataResult();
|
ParsedScoutingDataResult psda = new ParsedScoutingDataResult();
|
||||||
@@ -98,10 +110,18 @@ public class ScoutingDataWriter {
|
|||||||
|
|
||||||
return psda;
|
return psda;
|
||||||
|
|
||||||
} catch (BuiltByteParser.byteParsingExeption e){
|
// }
|
||||||
AlertManager.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A function that takes in a list of names seperated by commas, and adds a name if it is not included
|
||||||
|
// This is used for multi-scouter attribution to data.
|
||||||
|
public static String checkAddName(String prevnames, String name){
|
||||||
|
List<String> names = new ArrayList<>(List.of(prevnames.split(", ")));
|
||||||
|
|
||||||
|
if(!names.contains(name))
|
||||||
|
names.add(name);
|
||||||
|
|
||||||
|
return String.join(", ", names);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,158 +0,0 @@
|
|||||||
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", new int[]{0,0}),
|
|
||||||
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 was maybe broken", "Something was broken", "Robot was disabled for part of the match", "Missing robot (Joe Johnson)"}, 0),
|
|
||||||
new textType("Other Comments", "")
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static final inputType[][] default_pit_fields = new inputType[][] {
|
|
||||||
{
|
|
||||||
new sliderType("How good is robot", 5, 0, 10),
|
|
||||||
new 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;
|
|
||||||
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;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package com.ridgebotics.ridgescout.scoutingData.transfer;
|
||||||
|
|
||||||
|
// Transfer type if a field was created
|
||||||
|
public class CreateTransferType extends TransferType {
|
||||||
|
public transferValue getType() {return transferValue.CREATE;}
|
||||||
|
public CreateTransferType(String UUID){
|
||||||
|
super(UUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package com.ridgebotics.ridgescout.scoutingData.transfer;
|
||||||
|
|
||||||
|
// Transfer type if a field directly transfers
|
||||||
|
public class DirectTransferType extends TransferType {
|
||||||
|
public transferValue getType() {return transferValue.DIRECT;}
|
||||||
|
public DirectTransferType(String UUID){
|
||||||
|
super(UUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.ridgebotics.ridgescout.scoutingData.transfer;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.types.input.FieldType;
|
||||||
|
|
||||||
|
|
||||||
|
// The "Transfer Types" system, a component in the loading of scouting data.
|
||||||
|
// Dictates how the
|
||||||
|
// For example, a field can be created in one version, and how the app updates it is by obtaining it's transfer value, in this case being "create".
|
||||||
|
public abstract class TransferType {
|
||||||
|
public enum transferValue {
|
||||||
|
DIRECT,
|
||||||
|
CREATE
|
||||||
|
}
|
||||||
|
public String UUID;
|
||||||
|
public abstract transferValue getType();
|
||||||
|
public TransferType(String UUID){
|
||||||
|
this.UUID = UUID;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static FieldType get_input_type_by_UUID(FieldType[] values, String UUID){
|
||||||
|
for(FieldType it : values){
|
||||||
|
if(it.UUID.equals(UUID)){
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Inputs:
|
||||||
|
public static TransferType[][] get_transfer_values(FieldType[][] values) {
|
||||||
|
TransferType[][] output = new TransferType[values.length][];
|
||||||
|
for(int a = 1; a < values.length; a++){
|
||||||
|
|
||||||
|
TransferType[] v = new TransferType[values[a].length];
|
||||||
|
|
||||||
|
for(int b = 0; b < values[a].length; b++){
|
||||||
|
String UUID = values[a][b].UUID;
|
||||||
|
if(get_input_type_by_UUID(values[a-1], UUID) != null){
|
||||||
|
v[b] = new DirectTransferType(UUID);
|
||||||
|
}else{
|
||||||
|
v[b] = new CreateTransferType(UUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output[a-1] = v;
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
-8
@@ -1,8 +0,0 @@
|
|||||||
package com.ridgebotics.ridgescout.scoutingData.transfer;
|
|
||||||
|
|
||||||
public class createTransferType extends transferType {
|
|
||||||
public transferValue getType() {return transferValue.CREATE;}
|
|
||||||
public createTransferType(String name){
|
|
||||||
super(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-8
@@ -1,8 +0,0 @@
|
|||||||
package com.ridgebotics.ridgescout.scoutingData.transfer;
|
|
||||||
|
|
||||||
public class directTransferType extends transferType {
|
|
||||||
public transferValue getType() {return transferValue.DIRECT;}
|
|
||||||
public directTransferType(String name){
|
|
||||||
super(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package com.ridgebotics.ridgescout.scoutingData.transfer;
|
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.types.input.inputType;
|
|
||||||
|
|
||||||
public abstract class transferType {
|
|
||||||
public enum transferValue {
|
|
||||||
DIRECT,
|
|
||||||
CREATE
|
|
||||||
}
|
|
||||||
public String name;
|
|
||||||
public abstract transferValue getType();
|
|
||||||
public transferType(String name){
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static inputType get_input_type_by_name(inputType[] values, String name){
|
|
||||||
for(inputType it : values){
|
|
||||||
if(it.name.equals(name)){
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static transferType[][] get_transfer_values(inputType[][] values) {
|
|
||||||
transferType[][] output = new transferType[values.length][];
|
|
||||||
for(int a = 1; a < values.length; a++){
|
|
||||||
transferType[] v = new transferType[values[a].length];
|
|
||||||
for(int b = 0; b < values[a].length; b++){
|
|
||||||
String name = values[a][b].name;
|
|
||||||
if(get_input_type_by_name(values[a-1], name) != null){
|
|
||||||
v[b] = new directTransferType(name);
|
|
||||||
}else{
|
|
||||||
v[b] = new createTransferType(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output[a-1] = v;
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
package com.ridgebotics.ridgescout.types;
|
||||||
|
|
||||||
|
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.io.File;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.temporal.TemporalField;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
public class ColabArray {
|
||||||
|
private enum Action {
|
||||||
|
ADD,
|
||||||
|
REMOVE
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Diff> changelog = new ArrayList<>();
|
||||||
|
|
||||||
|
private void addChange(Diff change) {
|
||||||
|
this.changelog.add(change);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Diff> getChangelog() {
|
||||||
|
return changelog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(String item) {
|
||||||
|
Diff diff = new Diff();
|
||||||
|
diff.action = Action.ADD;
|
||||||
|
diff.content = item;
|
||||||
|
diff.time = new Date();
|
||||||
|
addChange(diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(String item) {
|
||||||
|
Diff diff = new Diff();
|
||||||
|
diff.action = Action.REMOVE;
|
||||||
|
diff.content = item;
|
||||||
|
diff.time = new Date();
|
||||||
|
addChange(diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(int index) {
|
||||||
|
remove(get().get(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Diff {
|
||||||
|
public Action action;
|
||||||
|
public String content;
|
||||||
|
public Date time;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.getClass() != this.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Diff other = (Diff) obj;
|
||||||
|
|
||||||
|
return other.action == this.action &&
|
||||||
|
other.time.getTime() == this.time.getTime() &&
|
||||||
|
other.content.equals(this.content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public byte[] encode() throws ByteBuilder.buildingException{
|
||||||
|
ByteBuilder bb = new ByteBuilder();
|
||||||
|
|
||||||
|
for(Diff change : this.changelog){
|
||||||
|
bb.addInt(change.action.ordinal());
|
||||||
|
bb.addString(change.content);
|
||||||
|
bb.addLong(change.time.getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return bb.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ColabArray decode(byte[] bytes) throws BuiltByteParser.byteParsingExeption {
|
||||||
|
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
||||||
|
List<BuiltByteParser.parsedObject> results = bbp.parse();
|
||||||
|
|
||||||
|
if(results.size() % 3 != 0){
|
||||||
|
throw new BuiltByteParser.byteParsingExeption("Wrong amount of elements in ColabArray!");
|
||||||
|
}
|
||||||
|
|
||||||
|
ColabArray arr = new ColabArray();
|
||||||
|
|
||||||
|
for(int i = 0; i < results.size(); i += 3) {
|
||||||
|
Diff diff = new Diff();
|
||||||
|
diff.action = Action.values()[(int) results.get(i).get()];
|
||||||
|
diff.content = (String) results.get(i+1).get();
|
||||||
|
diff.time = new Date((long) results.get(i+2).get());
|
||||||
|
arr.addChange(diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void append(ColabArray other) {
|
||||||
|
|
||||||
|
List<Diff> otherlog = other.getChangelog();
|
||||||
|
|
||||||
|
otherlog.removeIf(diff ->
|
||||||
|
this.changelog.contains(diff)
|
||||||
|
);
|
||||||
|
|
||||||
|
this.changelog.addAll(otherlog);
|
||||||
|
this.changelog = Arrays.asList(sort(this.changelog));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void append(File other) {
|
||||||
|
byte[] bytes = FileEditor.readFile(other);
|
||||||
|
if(bytes == null) return;
|
||||||
|
try {
|
||||||
|
append(decode(bytes));
|
||||||
|
} catch (BuiltByteParser.byteParsingExeption e) {
|
||||||
|
AlertManager.error("Failed to append ColabArray!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Diff[] sort(List<Diff> changelog) {
|
||||||
|
Diff[] sorted = changelog.toArray(new Diff[0]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Arrays.sort(sorted, (o1, o2) -> (int) (o1.time.getTime() - o2.time.getTime()));
|
||||||
|
} catch (Exception e){
|
||||||
|
AlertManager.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sorted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> get() {
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
|
||||||
|
for(Diff change : changelog) {
|
||||||
|
switch (change.action) {
|
||||||
|
case ADD:
|
||||||
|
result.add(change.content);
|
||||||
|
break;
|
||||||
|
case REMOVE:
|
||||||
|
result.remove(change.content);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(String item) {
|
||||||
|
// Diff[] sorted = sort();
|
||||||
|
|
||||||
|
for(int i = changelog.size()-1; i >= 0; i--) {
|
||||||
|
Diff change = changelog.get(i);
|
||||||
|
if(!change.content.equals(item)) continue;
|
||||||
|
return change.action == Action.ADD;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return get().size();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,21 +1,24 @@
|
|||||||
package com.ridgebotics.ridgescout.types;
|
package com.ridgebotics.ridgescout.types;
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.scoutingData.transfer.createTransferType;
|
import android.util.Log;
|
||||||
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;
|
|
||||||
|
|
||||||
|
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.RawDataType;
|
||||||
|
import com.ridgebotics.ridgescout.types.data.IntType;
|
||||||
|
import com.ridgebotics.ridgescout.types.data.StringType;
|
||||||
|
import com.ridgebotics.ridgescout.types.input.FieldType;
|
||||||
|
|
||||||
|
// A wrapper class for the stuff going on in Fields.java and ScoutingDataWriter.java.
|
||||||
public class ScoutingArray {
|
public class ScoutingArray {
|
||||||
public int version;
|
public int version;
|
||||||
public dataType[] array;
|
public RawDataType[] array;
|
||||||
public inputType[][] values;
|
public FieldType[][] values;
|
||||||
public int latest_version_num;
|
public int latest_version_num;
|
||||||
public transferType[][] transfer_values;
|
public TransferType[][] transfer_values;
|
||||||
|
|
||||||
public ScoutingArray(int version, dataType[] array, inputType[][] values, transferType[][] transfer_values){
|
public ScoutingArray(int version, RawDataType[] array, FieldType[][] values, TransferType[][] transfer_values){
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.array = array;
|
this.array = array;
|
||||||
this.values = values;
|
this.values = values;
|
||||||
@@ -23,68 +26,58 @@ public class ScoutingArray {
|
|||||||
this.transfer_values = transfer_values;
|
this.transfer_values = transfer_values;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScoutingArray(int version, dataType[] array, inputType[][] values){
|
public ScoutingArray(int version, RawDataType[] array, FieldType[][] values){
|
||||||
this(version, array, values, transferType.get_transfer_values(values));
|
this(version, array, values, TransferType.get_transfer_values(values));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(){
|
public void update(){
|
||||||
while(version<latest_version_num){
|
while(version<latest_version_num){
|
||||||
dataType[] new_values = new dataType[transfer_values[version].length];
|
RawDataType[] new_values = new RawDataType[transfer_values[version].length];
|
||||||
for(int i = 0; i < transfer_values[version].length; i++){
|
for(int i = 0; i < transfer_values[version].length; i++){
|
||||||
transferType tv = transfer_values[version][i];
|
TransferType tv = transfer_values[version][i];
|
||||||
switch (tv.getType()){
|
switch (tv.getType()){
|
||||||
case DIRECT:
|
case DIRECT:
|
||||||
new_values[i] = direct_transfer((directTransferType) tv);
|
new_values[i] = direct_transfer((DirectTransferType) tv);
|
||||||
continue;
|
continue;
|
||||||
// case RENAME:
|
|
||||||
// new_values[i] = rename_transfer((renameTransferType) tv);
|
|
||||||
// continue;
|
|
||||||
case CREATE:
|
case CREATE:
|
||||||
new_values[i] = create_transfer((createTransferType) tv);
|
new_values[i] = create_transfer((CreateTransferType) tv);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.array = new_values;
|
this.array = new_values;
|
||||||
version++;
|
version++;
|
||||||
System.out.println("Updated to " + version);
|
Log.i(getClass().toString(),"Updated to " + version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inputType get_input_type_by_name(int version, String name){
|
private FieldType get_input_type_by_UUID(int version, String UUID){
|
||||||
for(inputType it : values[version]){
|
for(FieldType it : values[version]){
|
||||||
if(it.name.equals(name)){
|
if(it.UUID.equals(UUID)){
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private dataType get_data_type_by_name(String name){
|
private RawDataType get_data_type_by_UUID(String UUID){
|
||||||
for(dataType dt : array){
|
for(RawDataType dt : array){
|
||||||
if(dt.getName().equals(name)){
|
if(dt.getUUID().equals(UUID)){
|
||||||
return dt;
|
return dt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private dataType direct_transfer(directTransferType tv){
|
private RawDataType direct_transfer(DirectTransferType tv){
|
||||||
return get_data_type_by_name(tv.name);
|
return get_data_type_by_UUID(tv.UUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// private dataType rename_transfer(renameTransferType tv){
|
private RawDataType create_transfer(CreateTransferType tv){
|
||||||
// dataType dt = get_data_type_by_name(tv.name);
|
FieldType it = get_input_type_by_UUID(version+1, tv.UUID);
|
||||||
// dt.name = tv.new_name;
|
|
||||||
// return dt;
|
|
||||||
// }
|
|
||||||
|
|
||||||
private dataType create_transfer(createTransferType tv){
|
|
||||||
inputType it = get_input_type_by_name(version+1, tv.name);
|
|
||||||
switch (it.getValueType()){
|
switch (it.getValueType()){
|
||||||
case NUM:
|
case NUM:
|
||||||
return intType.newNull(it.name);
|
return IntType.newNull(it.UUID);
|
||||||
case STRING:
|
case STRING:
|
||||||
return stringType.newNull(it.name);
|
return StringType.newNull(it.UUID);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-12
@@ -3,24 +3,26 @@ package com.ridgebotics.ridgescout.types;
|
|||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class file {
|
// Basically just holds a byte array and a filename, and then us just encoded.
|
||||||
|
public class ScoutingFile {
|
||||||
public static final int typecode = 255;
|
public static final int typecode = 255;
|
||||||
public String filename;
|
public String filename;
|
||||||
public byte[] data;
|
public byte[] data;
|
||||||
|
|
||||||
|
|
||||||
public file(){}
|
public ScoutingFile(){}
|
||||||
|
|
||||||
public file(String filename){
|
public ScoutingFile(String filename){
|
||||||
this(filename, fileEditor.readFile(filename));
|
this(filename, FileEditor.readFile(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
public file(String filename, byte[] data){
|
public ScoutingFile(String filename, byte[] data){
|
||||||
this.filename = filename;
|
this.filename = filename;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
@@ -28,8 +30,9 @@ public class file {
|
|||||||
public byte[] encode(){
|
public byte[] encode(){
|
||||||
try {
|
try {
|
||||||
ByteBuilder bb = new ByteBuilder()
|
ByteBuilder bb = new ByteBuilder()
|
||||||
.addString(filename)
|
.addString(filename);
|
||||||
.addRaw(255, Objects.requireNonNull(fileEditor.readFile(filename)));
|
|
||||||
|
bb.addRaw(255, Objects.requireNonNull(FileEditor.readFile(filename)));
|
||||||
|
|
||||||
return bb.build();
|
return bb.build();
|
||||||
|
|
||||||
@@ -39,18 +42,18 @@ public class file {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static file decode(byte[] bytes){
|
public static ScoutingFile decode(byte[] bytes){
|
||||||
try{
|
try{
|
||||||
ArrayList<BuiltByteParser.parsedObject> objects = new BuiltByteParser(bytes).parse();
|
ArrayList<BuiltByteParser.parsedObject> objects = new BuiltByteParser(bytes).parse();
|
||||||
|
|
||||||
file f = new file();
|
ScoutingFile f = new ScoutingFile();
|
||||||
|
|
||||||
f.filename = (String) objects.get(0).get();
|
f.filename = (String) objects.get(0).get();
|
||||||
f.data = (byte[]) objects.get(1).get();
|
f.data = (byte[]) objects.get(1).get();
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
|
|
||||||
}catch (BuiltByteParser.byteParsingExeption e){
|
}catch (Exception e){
|
||||||
AlertManager.error(e);
|
AlertManager.error(e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -58,6 +61,6 @@ public class file {
|
|||||||
|
|
||||||
public boolean write(){
|
public boolean write(){
|
||||||
if(data == null || filename == null) return false;
|
if(data == null || filename == null) return false;
|
||||||
return fileEditor.writeFile(filename, data);
|
return FileEditor.writeFile(filename, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+6
-4
@@ -1,6 +1,8 @@
|
|||||||
package com.ridgebotics.ridgescout.types.data;
|
package com.ridgebotics.ridgescout.types.data;
|
||||||
|
|
||||||
public class intArrType extends dataType {
|
|
||||||
|
// Int array raw data type
|
||||||
|
public class IntArrType extends RawDataType {
|
||||||
public static final int[] nullval = new int[]{255, 255};
|
public static final int[] nullval = new int[]{255, 255};
|
||||||
// public static final int unselectedval = 1;
|
// public static final int unselectedval = 1;
|
||||||
|
|
||||||
@@ -23,13 +25,13 @@ public class intArrType extends dataType {
|
|||||||
forceSetValue((int[]) value);
|
forceSetValue((int[]) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public intArrType(String name, int[] value) {
|
public IntArrType(String name, int[] value) {
|
||||||
super(name);
|
super(name);
|
||||||
set(value);
|
set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static intArrType newNull(String name){
|
public static IntArrType newNull(String name){
|
||||||
return new intArrType(name, nullval);
|
return new IntArrType(name, nullval);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public static intType newUnselected(String name){
|
// public static intType newUnselected(String name){
|
||||||
+5
-4
@@ -1,6 +1,7 @@
|
|||||||
package com.ridgebotics.ridgescout.types.data;
|
package com.ridgebotics.ridgescout.types.data;
|
||||||
|
|
||||||
public class intType extends dataType {
|
// Number raw data type
|
||||||
|
public class IntType extends RawDataType {
|
||||||
public static final int nullval = 255;
|
public static final int nullval = 255;
|
||||||
// public static final int unselectedval = 1;
|
// public static final int unselectedval = 1;
|
||||||
|
|
||||||
@@ -23,13 +24,13 @@ public class intType extends dataType {
|
|||||||
forceSetValue((int) value);
|
forceSetValue((int) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public intType(String name, int value) {
|
public IntType(String name, int value) {
|
||||||
super(name);
|
super(name);
|
||||||
set(value);
|
set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static intType newNull(String name){
|
public static IntType newNull(String name){
|
||||||
final intType a = new intType(name, 0);
|
final IntType a = new IntType(name, 0);
|
||||||
a.forceSetValue(nullval);
|
a.forceSetValue(nullval);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
+6
-5
@@ -1,6 +1,7 @@
|
|||||||
package com.ridgebotics.ridgescout.types.data;
|
package com.ridgebotics.ridgescout.types.data;
|
||||||
|
|
||||||
public abstract class dataType {
|
// Abstract class for raw data types for use in fields.
|
||||||
|
public abstract class RawDataType {
|
||||||
public enum valueTypes {
|
public enum valueTypes {
|
||||||
NUM,
|
NUM,
|
||||||
NUMARR,
|
NUMARR,
|
||||||
@@ -8,7 +9,7 @@ public abstract class dataType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Object value;
|
private Object value;
|
||||||
private final String name;
|
private final String UUID;
|
||||||
|
|
||||||
public abstract valueTypes getValueType();
|
public abstract valueTypes getValueType();
|
||||||
|
|
||||||
@@ -24,9 +25,9 @@ public abstract class dataType {
|
|||||||
public abstract boolean isNull();
|
public abstract boolean isNull();
|
||||||
// public abstract boolean isUnselected();
|
// public abstract boolean isUnselected();
|
||||||
|
|
||||||
public String getName() {return name;}
|
public String getUUID() {return UUID;}
|
||||||
|
|
||||||
public dataType(String name){
|
public RawDataType(String UUID){
|
||||||
this.name = name;
|
this.UUID = UUID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+5
-4
@@ -1,6 +1,7 @@
|
|||||||
package com.ridgebotics.ridgescout.types.data;
|
package com.ridgebotics.ridgescout.types.data;
|
||||||
|
|
||||||
public class stringType extends dataType{
|
// String raw data type
|
||||||
|
public class StringType extends RawDataType {
|
||||||
public static final String nullval = "null";
|
public static final String nullval = "null";
|
||||||
// public static final String unselectedval = "■";
|
// public static final String unselectedval = "■";
|
||||||
|
|
||||||
@@ -23,13 +24,13 @@ public class stringType extends dataType{
|
|||||||
forceSetValue(value);
|
forceSetValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public stringType(String name, String value) {
|
public StringType(String name, String value) {
|
||||||
super(name);
|
super(name);
|
||||||
forceSetValue(value);
|
forceSetValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static stringType newNull(String name){
|
public static StringType newNull(String name){
|
||||||
final stringType a = new stringType(name, "");
|
final StringType a = new StringType(name, "");
|
||||||
a.forceSetValue(nullval);
|
a.forceSetValue(nullval);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
@@ -2,25 +2,28 @@ package com.ridgebotics.ridgescout.types;
|
|||||||
|
|
||||||
import static com.ridgebotics.ridgescout.utility.DataManager.event;
|
import static com.ridgebotics.ridgescout.utility.DataManager.event;
|
||||||
|
|
||||||
import android.widget.TableRow;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
||||||
|
import com.ridgebotics.ridgescout.utility.SettingsManager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
// Class to contain data for an entire event.
|
||||||
|
// Easily encoded and decoded to binary format.
|
||||||
public class frcEvent {
|
public class frcEvent {
|
||||||
|
|
||||||
public static final int typecode = 254;
|
// public static final int typecode = 254; Unused, no idea what this is
|
||||||
public String eventCode;
|
public String eventCode; //Current event code
|
||||||
public String name;
|
public String name;
|
||||||
public ArrayList<frcMatch> matches;
|
public ArrayList<frcMatch> matches;
|
||||||
public ArrayList<frcTeam> teams;
|
public ArrayList<frcTeam> teams;
|
||||||
|
|
||||||
|
// Turns frcEvent into raw data
|
||||||
public byte[] encode() {
|
public byte[] encode() {
|
||||||
try {
|
try {
|
||||||
ByteBuilder bb = new ByteBuilder()
|
ByteBuilder bb = new ByteBuilder()
|
||||||
@@ -35,6 +38,10 @@ public class frcEvent {
|
|||||||
bb.addRaw(frcMatch.typecode, match.encode());
|
bb.addRaw(frcMatch.typecode, match.encode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(SettingsManager.getEVCode().equals("unset")){
|
||||||
|
SettingsManager.setEVCode(eventCode);
|
||||||
|
}
|
||||||
|
|
||||||
return bb.build();
|
return bb.build();
|
||||||
} catch (ByteBuilder.buildingException e) {
|
} catch (ByteBuilder.buildingException e) {
|
||||||
AlertManager.error(e);
|
AlertManager.error(e);
|
||||||
@@ -42,6 +49,7 @@ public class frcEvent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Decodes the frcEvent
|
||||||
public static frcEvent decode(byte[] bytes) {
|
public static frcEvent decode(byte[] bytes) {
|
||||||
try {
|
try {
|
||||||
ArrayList<BuiltByteParser.parsedObject> objects =
|
ArrayList<BuiltByteParser.parsedObject> objects =
|
||||||
@@ -70,6 +78,7 @@ public class frcEvent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Generates text
|
||||||
@NonNull
|
@NonNull
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return (
|
return (
|
||||||
@@ -117,28 +126,85 @@ public class frcEvent {
|
|||||||
return maxMatch;
|
return maxMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public
|
public frcMatch getNextTeamMatch(int teamNum, int curMatch){
|
||||||
|
frcMatch[] teamMatches = getTeamMatches(teamNum);
|
||||||
|
|
||||||
|
for(int i = 0; i < teamMatches.length; i++) {
|
||||||
|
if (teamMatches[i].matchIndex > curMatch)
|
||||||
|
return teamMatches[i];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Returns the soonest match that there will be all the possible upcoming data on other teams
|
// Returns the soonest match that there will be all the possible upcoming data on other teams
|
||||||
public void getReportMatches(int ourTeamNum){
|
public int getMostInformedBy(int ourTeamNum, int curMatch){
|
||||||
frcMatch[] teamMatches = event.getTeamMatches(ourTeamNum);
|
frcMatch teamMatch = getNextTeamMatch(ourTeamNum, curMatch);
|
||||||
|
|
||||||
|
int maxMatch = Integer.MIN_VALUE;
|
||||||
|
|
||||||
for(int i = 0; i < teamMatches.length; i++){
|
|
||||||
int maxMatch = -1;
|
|
||||||
for(int a = 0; a < 6; a++){
|
for(int a = 0; a < 6; a++){
|
||||||
int teamNum;
|
int teamNum;
|
||||||
if(a < 3)
|
if(a < 3)
|
||||||
teamNum = teamMatches[i].redAlliance[a];
|
teamNum = teamMatch.redAlliance[a];
|
||||||
else
|
else
|
||||||
teamNum = teamMatches[i].blueAlliance[a-3];
|
teamNum = teamMatch.blueAlliance[a-3];
|
||||||
|
|
||||||
if(teamNum == ourTeamNum)
|
if(teamNum == ourTeamNum)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int matchNum = event.getMostRecentTeamMatch(teamNum, teamMatches[i].matchIndex);
|
int matchNum = event.getMostRecentTeamMatch(teamNum, teamMatch.matchIndex);
|
||||||
if(maxMatch < matchNum)
|
if(maxMatch < matchNum)
|
||||||
maxMatch = matchNum;
|
maxMatch = matchNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return maxMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public frcTeam getTeamByNum(int teamNum){
|
||||||
|
for(int i = 0; i < teams.size(); i++){
|
||||||
|
frcTeam team = teams.get(i);
|
||||||
|
if(team.teamNumber == teamNum)
|
||||||
|
return team;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<frcTeam> getTeamsSorted() {
|
||||||
|
int[] teamNums = new int[teams.size()];
|
||||||
|
|
||||||
|
for(int i = 0 ; i < teams.size(); i++){
|
||||||
|
teamNums[i] = teams.get(i).teamNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
Arrays.sort(teamNums);
|
||||||
|
|
||||||
|
List<frcTeam> list = new ArrayList<>();
|
||||||
|
|
||||||
|
for(int i = 0; i < teams.size(); i++){
|
||||||
|
frcTeam team = getTeamByNum(teamNums[i]);
|
||||||
|
assert team != null;
|
||||||
|
list.add(team);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean getIsBlueAlliance(int teamNum, int matchNum){
|
||||||
|
return getIsBlueAlliance(teamNum, matches.get(matchNum));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getIsBlueAlliance(int teamNum, frcMatch match){
|
||||||
|
|
||||||
|
for(int i = 0; i < match.redAlliance.length; i++)
|
||||||
|
if(match.redAlliance[i] == teamNum) return false;
|
||||||
|
for(int i = 0; i < match.blueAlliance.length; i++)
|
||||||
|
if(match.blueAlliance[i] == teamNum) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
// Class to contain data for the six teams numbers in a single match
|
||||||
|
// Easily encoded and decoded to binary format.
|
||||||
public class frcMatch {
|
public class frcMatch {
|
||||||
public static final int typecode = 253;
|
public static final int typecode = 253;
|
||||||
public frcMatch(){}
|
public frcMatch(){}
|
||||||
@@ -27,7 +29,7 @@ public class frcMatch {
|
|||||||
.addInt(redAlliance[1])
|
.addInt(redAlliance[1])
|
||||||
.addInt(redAlliance[2])
|
.addInt(redAlliance[2])
|
||||||
.build();
|
.build();
|
||||||
} catch (ByteBuilder.buildingException e) {
|
} catch (Exception e) {
|
||||||
AlertManager.error(e);
|
AlertManager.error(e);
|
||||||
return new byte[1];
|
return new byte[1];
|
||||||
}
|
}
|
||||||
@@ -49,7 +51,7 @@ public class frcMatch {
|
|||||||
|
|
||||||
return frc;
|
return frc;
|
||||||
|
|
||||||
} catch (BuiltByteParser.byteParsingExeption e) {
|
} catch (Exception e) {
|
||||||
AlertManager.error(e);
|
AlertManager.error(e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,36 @@
|
|||||||
package com.ridgebotics.ridgescout.types;
|
package com.ridgebotics.ridgescout.types;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Color;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
// Class to contain data for a team, in an event.
|
||||||
|
// Easily encoded and decoded to binary format.
|
||||||
public class frcTeam {
|
public class frcTeam {
|
||||||
public static final int typecode = 252;
|
public static final int typecode = 252;
|
||||||
|
private static final int[] DEFAULT_COLOR_ARR = new int[]{64,64,64};
|
||||||
|
private static final int DEFAULT_COLOR = Color.argb(255, DEFAULT_COLOR_ARR[0],DEFAULT_COLOR_ARR[1],DEFAULT_COLOR_ARR[2]);
|
||||||
|
|
||||||
public int teamNumber = 0;
|
public int teamNumber = 0;
|
||||||
public String teamName = "null";
|
public String teamName = "null";
|
||||||
public String city = "null";
|
public String city = "null";
|
||||||
public String stateOrProv = "null";
|
public String stateOrProv = "null";
|
||||||
public String school = "null";
|
public String school = "null";
|
||||||
public String country = "null";
|
public String country = "null";
|
||||||
|
public Bitmap bitmap = null;
|
||||||
|
public int[] teamColor = DEFAULT_COLOR_ARR;
|
||||||
public int startingYear = 0;
|
public int startingYear = 0;
|
||||||
|
|
||||||
public String getDescription(){
|
public String getDescription(){
|
||||||
@@ -32,6 +47,8 @@ public class frcTeam {
|
|||||||
.addString(school)
|
.addString(school)
|
||||||
.addString(country)
|
.addString(country)
|
||||||
.addInt(startingYear)
|
.addInt(startingYear)
|
||||||
|
.addRaw(127, encodeBitmap(bitmap))
|
||||||
|
.addIntArray(teamColor)
|
||||||
.build();
|
.build();
|
||||||
} catch (ByteBuilder.buildingException e) {
|
} catch (ByteBuilder.buildingException e) {
|
||||||
AlertManager.error(e);
|
AlertManager.error(e);
|
||||||
@@ -52,6 +69,13 @@ public class frcTeam {
|
|||||||
frc.country = (String) objects.get(5).get();
|
frc.country = (String) objects.get(5).get();
|
||||||
frc.startingYear = (int) objects.get(6).get();
|
frc.startingYear = (int) objects.get(6).get();
|
||||||
|
|
||||||
|
if(objects.size() == 9){
|
||||||
|
frc.bitmap = decodeBitmap((BuiltByteParser.rawObject) objects.get(7));
|
||||||
|
frc.teamColor = (int[]) objects.get(8).get();
|
||||||
|
|
||||||
|
// System.out.println(Arrays.toString(frc.teamColor));
|
||||||
|
}
|
||||||
|
|
||||||
return frc;
|
return frc;
|
||||||
|
|
||||||
} catch (BuiltByteParser.byteParsingExeption e) {
|
} catch (BuiltByteParser.byteParsingExeption e) {
|
||||||
@@ -60,6 +84,111 @@ public class frcTeam {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] encodeBitmap(Bitmap bitmap){
|
||||||
|
if(bitmap == null) return new byte[]{0};
|
||||||
|
ByteArrayOutputStream blob = new ByteArrayOutputStream();
|
||||||
|
if(bitmap.compress(Bitmap.CompressFormat.PNG, 0 /* Ignored for PNGs */, blob)){
|
||||||
|
return blob.toByteArray();
|
||||||
|
}else{
|
||||||
|
return new byte[]{0};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bitmap decodeBitmap(BuiltByteParser.rawObject rawObject){
|
||||||
|
if(rawObject.getType() != 127) return null;
|
||||||
|
byte[] bytes = (byte[]) rawObject.get();
|
||||||
|
if(bytes.length <= 1) return null;
|
||||||
|
return BitmapFactory.decodeByteArray(bytes,0,bytes.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] findPrimaryColor(Bitmap bitmap) {
|
||||||
|
if (bitmap == null) {
|
||||||
|
return DEFAULT_COLOR_ARR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 1: Posterize the image (reduce color levels)
|
||||||
|
Bitmap posterizedBitmap = posterize(bitmap, 8); // 8 levels of posterization
|
||||||
|
|
||||||
|
// Step 2: Find the most saturated and frequent color
|
||||||
|
return findMostSaturatedAndFrequentColor(posterizedBitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Posterize the image by reducing color levels
|
||||||
|
private static Bitmap posterize(Bitmap original, int levels) {
|
||||||
|
int width = original.getWidth();
|
||||||
|
int height = original.getHeight();
|
||||||
|
Bitmap posterized = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||||
|
|
||||||
|
int step = 255 / (levels - 1);
|
||||||
|
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
int pixel = original.getPixel(x, y);
|
||||||
|
int r = Color.red(pixel);
|
||||||
|
int g = Color.green(pixel);
|
||||||
|
int b = Color.blue(pixel);
|
||||||
|
|
||||||
|
// Quantize the RGB values
|
||||||
|
r = (r / step) * step;
|
||||||
|
g = (g / step) * step;
|
||||||
|
b = (b / step) * step;
|
||||||
|
|
||||||
|
int newPixel = Color.rgb(r, g, b);
|
||||||
|
posterized.setPixel(x, y, newPixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return posterized;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the most saturated and frequent color
|
||||||
|
private static int[] findMostSaturatedAndFrequentColor(Bitmap bitmap) {
|
||||||
|
int width = bitmap.getWidth();
|
||||||
|
int height = bitmap.getHeight();
|
||||||
|
Map<Integer, Integer> colorFrequency = new HashMap<>();
|
||||||
|
|
||||||
|
// Count the frequency of each color
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
int pixel = bitmap.getPixel(x, y);
|
||||||
|
colorFrequency.put(pixel, colorFrequency.getOrDefault(pixel, 0) + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the most saturated and frequent color
|
||||||
|
int primaryColor = DEFAULT_COLOR; // Default fallback
|
||||||
|
double maxColorness = -1;
|
||||||
|
int maxFrequency = 0;
|
||||||
|
|
||||||
|
for (Map.Entry<Integer, Integer> entry : colorFrequency.entrySet()) {
|
||||||
|
int color = entry.getKey();
|
||||||
|
int frequency = entry.getValue();
|
||||||
|
float[] hsv = new float[3];
|
||||||
|
Color.colorToHSV(color, hsv);
|
||||||
|
double colorness = Math.pow(hsv[1],2)+Math.pow(hsv[2],2);
|
||||||
|
|
||||||
|
// Prioritize saturation, then frequency
|
||||||
|
if ((colorness > maxColorness && frequency > maxFrequency * 0.5) && Color.alpha(color) > 127) { //|| (colorness == maxColorness)
|
||||||
|
maxColorness = colorness;
|
||||||
|
// maxFrequency = frequency;
|
||||||
|
primaryColor = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float[] hsv = new float[3];
|
||||||
|
Color.colorToHSV(primaryColor, hsv);
|
||||||
|
|
||||||
|
primaryColor = Color.HSVToColor(new float[]{hsv[0], Math.max(hsv[1], (float) 0.2), Math.max(hsv[2], (float) 0.3)});
|
||||||
|
|
||||||
|
return new int[]{Color.red(primaryColor),Color.blue(primaryColor),Color.green(primaryColor)};
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTeamColor(){
|
||||||
|
return Color.argb(255,teamColor[0],teamColor[2],teamColor[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return "frcTeam Num: " + teamNumber + ", " + getDescription();
|
return "frcTeam Num: " + teamNumber + ", " + getDescription();
|
||||||
|
|||||||
+42
-51
@@ -1,19 +1,18 @@
|
|||||||
package com.ridgebotics.ridgescout.types.input;
|
package com.ridgebotics.ridgescout.types.input;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.chart_background;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.checkbox_colors;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.checkbox_data_color;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.checkbox_value_text_color;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.CompoundButton;
|
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.TableLayout;
|
||||||
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.LineChart;
|
||||||
import com.github.mikephil.charting.charts.PieChart;
|
import com.github.mikephil.charting.charts.PieChart;
|
||||||
@@ -24,69 +23,55 @@ import com.github.mikephil.charting.data.LineDataSet;
|
|||||||
import com.github.mikephil.charting.data.PieData;
|
import com.github.mikephil.charting.data.PieData;
|
||||||
import com.github.mikephil.charting.data.PieDataSet;
|
import com.github.mikephil.charting.data.PieDataSet;
|
||||||
import com.github.mikephil.charting.data.PieEntry;
|
import com.github.mikephil.charting.data.PieEntry;
|
||||||
import com.ridgebotics.ridgescout.types.data.dataType;
|
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||||
import com.ridgebotics.ridgescout.types.data.intType;
|
import com.ridgebotics.ridgescout.types.data.IntType;
|
||||||
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
||||||
import com.skydoves.powerspinner.IconSpinnerAdapter;
|
|
||||||
import com.skydoves.powerspinner.IconSpinnerItem;
|
|
||||||
import com.skydoves.powerspinner.OnSpinnerItemSelectedListener;
|
|
||||||
import com.skydoves.powerspinner.PowerSpinnerView;
|
|
||||||
import com.skydoves.powerspinner.SpinnerGravity;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class checkboxType extends inputType {
|
public class CheckboxType extends FieldType {
|
||||||
public int get_byte_id() {return checkboxType;}
|
public int get_byte_id() {return checkboxType;}
|
||||||
public inputTypes getInputType(){return inputTypes.CHECKBOX;}
|
public inputTypes getInputType(){return inputTypes.CHECKBOX;}
|
||||||
public dataType.valueTypes getValueType(){return dataType.valueTypes.NUM;}
|
public RawDataType.valueTypes getValueType(){return RawDataType.valueTypes.NUM;}
|
||||||
public Object get_fallback_value(){return 0;}
|
public Object get_fallback_value(){return 0;}
|
||||||
public checkboxType(){};
|
public CheckboxType(){};
|
||||||
public String get_type_name(){return "Checkbox";}
|
public String get_type_name(){return "Checkbox";}
|
||||||
public checkboxType(String name, int isChecked){
|
public CheckboxType(String UUID, String name, String description, int isChecked){
|
||||||
super(name);
|
super(UUID, name, description);
|
||||||
this.default_value = isChecked;
|
this.default_value = isChecked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public byte[] encode() throws ByteBuilder.buildingException {
|
public void encodeData(ByteBuilder bb) throws ByteBuilder.buildingException {
|
||||||
ByteBuilder bb = new ByteBuilder();
|
|
||||||
bb.addString(name);
|
|
||||||
bb.addInt((int)default_value);
|
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();
|
public void decodeData(ArrayList<BuiltByteParser.parsedObject> objects) {
|
||||||
default_value = objects.get(1).get();
|
default_value = objects.get(0).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// public PowerSpinnerView dropdown = null;
|
// public PowerSpinnerView dropdown = null;
|
||||||
|
|
||||||
public CheckBox checkBox = null;
|
public CheckBox checkBox = null;
|
||||||
|
|
||||||
public View createView(Context context, Function<dataType, Integer> onUpdate){
|
public View createView(Context context, Function<RawDataType, Integer> onUpdate){
|
||||||
checkBox = new CheckBox(context);
|
checkBox = new CheckBox(context);
|
||||||
|
checkBox.setTextAppearance(com.google.android.material.R.style.TextAppearance_MaterialComponents_Headline6);
|
||||||
checkBox.setText(name);
|
checkBox.setText(name);
|
||||||
checkBox.setTextSize(24);
|
|
||||||
setViewValue(default_value);
|
setViewValue(default_value);
|
||||||
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> onUpdate.apply(getViewValue()));
|
||||||
@Override
|
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
|
||||||
onUpdate.apply(getViewValue());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return checkBox;
|
return checkBox;
|
||||||
|
|
||||||
}
|
}
|
||||||
public void setViewValue(Object value) {
|
public void setViewValue(Object value) {
|
||||||
if(checkBox == null) return;
|
if(checkBox == null) return;
|
||||||
if(intType.isNull((int) value)){
|
if(IntType.isNull((int) value)){
|
||||||
nullify();
|
nullify();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -100,10 +85,10 @@ public class checkboxType extends inputType {
|
|||||||
isBlank = true;
|
isBlank = true;
|
||||||
checkBox.setVisibility(View.GONE);
|
checkBox.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
public dataType getViewValue(){
|
public RawDataType getViewValue(){
|
||||||
if(checkBox == null) return null;
|
if(checkBox == null) return null;
|
||||||
if(checkBox.getVisibility() == View.GONE) return new intType(name, intType.nullval);
|
if(checkBox.getVisibility() == View.GONE) return new IntType(name, IntType.nullval);
|
||||||
return new intType(name, checkBox.isChecked() ? 1 : 0);
|
return new IntType(name, checkBox.isChecked() ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -111,9 +96,10 @@ public class checkboxType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void add_individual_view(LinearLayout parent, dataType data){
|
public void add_individual_view(LinearLayout parent, RawDataType data){
|
||||||
if(data.isNull()) return;
|
if(data.isNull()) return;
|
||||||
CheckBox cb = new CheckBox(parent.getContext());
|
CheckBox cb = new CheckBox(parent.getContext());
|
||||||
|
cb.setTextAppearance(com.google.android.material.R.style.TextAppearance_MaterialComponents_Headline6);
|
||||||
cb.setText(name);
|
cb.setText(name);
|
||||||
cb.setChecked((int) data.get() == 1);
|
cb.setChecked((int) data.get() == 1);
|
||||||
cb.setEnabled(false);
|
cb.setEnabled(false);
|
||||||
@@ -121,11 +107,7 @@ public class checkboxType extends inputType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void add_compiled_view(LinearLayout parent, RawDataType[] data){
|
||||||
public static int[] colors = {0x7f00ff00, 0x7f7f0000};
|
|
||||||
|
|
||||||
|
|
||||||
public void add_compiled_view(LinearLayout parent, dataType[] data){
|
|
||||||
PieChart chart = new PieChart(parent.getContext());
|
PieChart chart = new PieChart(parent.getContext());
|
||||||
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
@@ -154,7 +136,7 @@ public class checkboxType extends inputType {
|
|||||||
entries.add(new PieEntry((float) numFalse, "False"));
|
entries.add(new PieEntry((float) numFalse, "False"));
|
||||||
|
|
||||||
PieDataSet pieDataSet = new PieDataSet(entries, name);
|
PieDataSet pieDataSet = new PieDataSet(entries, name);
|
||||||
pieDataSet.setColors(colors);
|
pieDataSet.setColors(checkbox_colors);
|
||||||
PieData pieData = new PieData(pieDataSet);
|
PieData pieData = new PieData(pieDataSet);
|
||||||
chart.setDrawHoleEnabled(false);
|
chart.setDrawHoleEnabled(false);
|
||||||
chart.setData(pieData);
|
chart.setData(pieData);
|
||||||
@@ -165,7 +147,7 @@ public class checkboxType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void add_history_view(LinearLayout parent, dataType[] data){
|
public void add_history_view(LinearLayout parent, RawDataType[] data){
|
||||||
LineChart chart = new LineChart(parent.getContext());
|
LineChart chart = new LineChart(parent.getContext());
|
||||||
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
@@ -173,7 +155,7 @@ public class checkboxType extends inputType {
|
|||||||
);
|
);
|
||||||
layout.height = 350;
|
layout.height = 350;
|
||||||
chart.setLayoutParams(layout);
|
chart.setLayoutParams(layout);
|
||||||
chart.setBackgroundColor(0xff252025);
|
chart.setBackgroundColor(chart_background);
|
||||||
|
|
||||||
LineData lineData = new LineData();
|
LineData lineData = new LineData();
|
||||||
|
|
||||||
@@ -189,11 +171,11 @@ public class checkboxType extends inputType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LineDataSet dataSet = new LineDataSet(entries, "is checked");
|
LineDataSet dataSet = new LineDataSet(entries, "is checked");
|
||||||
dataSet.setColor(Color.RED);
|
dataSet.setColor(checkbox_data_color);
|
||||||
dataSet.setValueTextColor(Color.BLACK);
|
dataSet.setValueTextColor(Color.BLACK);
|
||||||
dataSet.setDrawCircles(false);
|
dataSet.setDrawCircles(false);
|
||||||
dataSet.setDrawValues(false);
|
dataSet.setDrawValues(false);
|
||||||
dataSet.setValueTextColor(Color.RED);
|
dataSet.setValueTextColor(checkbox_value_text_color);
|
||||||
lineData.addDataSet(dataSet);
|
lineData.addDataSet(dataSet);
|
||||||
|
|
||||||
|
|
||||||
@@ -224,5 +206,14 @@ public class checkboxType extends inputType {
|
|||||||
chart.invalidate();
|
chart.invalidate();
|
||||||
parent.addView(chart);
|
parent.addView(chart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
public void addDataToTable(TableLayout parent, Map<Integer, List<RawDataType>> data){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString(RawDataType data){
|
||||||
|
return (int) data.get() == 1 ? "true" : "false";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+66
-94
@@ -1,5 +1,10 @@
|
|||||||
package com.ridgebotics.ridgescout.types.input;
|
package com.ridgebotics.ridgescout.types.input;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.chart_background;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.chart_text;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.dropdown_value_text_1;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.dropdown_value_text_2;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
@@ -7,12 +12,12 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TableLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||||
|
import com.ridgebotics.ridgescout.types.data.IntType;
|
||||||
import com.ridgebotics.ridgescout.types.data.dataType;
|
import com.ridgebotics.ridgescout.ui.views.CustomSpinnerView;
|
||||||
import com.ridgebotics.ridgescout.types.data.intType;
|
|
||||||
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
||||||
import com.github.mikephil.charting.charts.LineChart;
|
import com.github.mikephil.charting.charts.LineChart;
|
||||||
@@ -24,98 +29,57 @@ import com.github.mikephil.charting.data.LineDataSet;
|
|||||||
import com.github.mikephil.charting.data.PieData;
|
import com.github.mikephil.charting.data.PieData;
|
||||||
import com.github.mikephil.charting.data.PieDataSet;
|
import com.github.mikephil.charting.data.PieDataSet;
|
||||||
import com.github.mikephil.charting.data.PieEntry;
|
import com.github.mikephil.charting.data.PieEntry;
|
||||||
import com.skydoves.powerspinner.IconSpinnerAdapter;
|
import com.ridgebotics.ridgescout.utility.builders.TextViewBuilder;
|
||||||
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.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class dropdownType extends inputType {
|
public class DropdownType extends FieldType {
|
||||||
public String[] text_options;
|
public String[] text_options;
|
||||||
public int get_byte_id() {return dropdownType;}
|
public int get_byte_id() {return dropdownType;}
|
||||||
public inputTypes getInputType(){return inputTypes.DROPDOWN;}
|
public inputTypes getInputType(){return inputTypes.DROPDOWN;}
|
||||||
public dataType.valueTypes getValueType(){return dataType.valueTypes.NUM;}
|
public RawDataType.valueTypes getValueType(){return RawDataType.valueTypes.NUM;}
|
||||||
public Object get_fallback_value(){return 0;}
|
public Object get_fallback_value(){return 0;}
|
||||||
public dropdownType(){};
|
public DropdownType(){};
|
||||||
public String get_type_name(){return "Dropdown";}
|
public String get_type_name(){return "Dropdown";}
|
||||||
public dropdownType(String name, String[] text_options, int defaultSelIndex){
|
public DropdownType(String UUID, String name, String description, String[] text_options, int defaultSelIndex){
|
||||||
super(name);
|
super(UUID, name, description);
|
||||||
this.text_options = text_options;
|
this.text_options = text_options;
|
||||||
this.default_value = defaultSelIndex;
|
this.default_value = defaultSelIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public byte[] encode() throws ByteBuilder.buildingException {
|
public void encodeData(ByteBuilder bb) throws ByteBuilder.buildingException {
|
||||||
ByteBuilder bb = new ByteBuilder();
|
|
||||||
bb.addString(name);
|
|
||||||
bb.addInt((int)default_value);
|
bb.addInt((int)default_value);
|
||||||
bb.addStringArray(text_options);
|
bb.addStringArray(text_options);
|
||||||
return bb.build();
|
|
||||||
}
|
}
|
||||||
public void decode(byte[] bytes) throws BuiltByteParser.byteParsingExeption {
|
public void decodeData(ArrayList<BuiltByteParser.parsedObject> objects) {
|
||||||
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
default_value = objects.get(0).get();
|
||||||
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
text_options = (String[]) objects.get(1).get();
|
||||||
|
|
||||||
name = (String) objects.get(0).get();
|
|
||||||
default_value = objects.get(1).get();
|
|
||||||
text_options = (String[]) objects.get(2).get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PowerSpinnerView dropdown = null;
|
public CustomSpinnerView dropdown = null;
|
||||||
|
|
||||||
public View createView(Context context, Function<dataType, Integer> onUpdate){
|
public View createView(Context context, Function<RawDataType, Integer> onUpdate){
|
||||||
dropdown = new PowerSpinnerView(context);
|
dropdown = new CustomSpinnerView(context);
|
||||||
|
|
||||||
List<IconSpinnerItem> iconSpinnerItems = new ArrayList<>();
|
ArrayList<String> iconSpinnerItems = new ArrayList<>(Arrays.asList(text_options));
|
||||||
for(int i = 0; i < text_options.length; i++){
|
|
||||||
iconSpinnerItems.add(new IconSpinnerItem(text_options[i]));
|
|
||||||
}
|
|
||||||
IconSpinnerAdapter iconSpinnerAdapter = new IconSpinnerAdapter(dropdown);
|
|
||||||
|
|
||||||
dropdown.setGravity(Gravity.CENTER);
|
dropdown.setTitle(name);
|
||||||
|
dropdown.setOptions(iconSpinnerItems, (int) default_value);
|
||||||
dropdown.setSpinnerAdapter(iconSpinnerAdapter);
|
|
||||||
dropdown.setItems(iconSpinnerItems);
|
|
||||||
|
|
||||||
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());
|
onUpdate.apply(getViewValue());
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// dropdown.setLifecycleOwner(context.life);
|
dropdown.setOnClickListener((item, index) -> onUpdate.apply(getViewValue()));
|
||||||
// slider.addOnChangeListener(new Slider.OnChangeListener() {
|
|
||||||
// @Override
|
|
||||||
// public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
|
|
||||||
// onUpdate.apply(getViewValue());
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
return dropdown;
|
return dropdown;
|
||||||
|
|
||||||
}
|
}
|
||||||
public void setViewValue(Object value) {
|
public void setViewValue(Object value) {
|
||||||
if(dropdown == null) return;
|
if(dropdown == null) return;
|
||||||
if(intType.isNull((int) value)){
|
if(IntType.isNull((int) value)){
|
||||||
nullify();
|
nullify();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -123,35 +87,33 @@ public class dropdownType extends inputType {
|
|||||||
isBlank = false;
|
isBlank = false;
|
||||||
|
|
||||||
dropdown.setVisibility(View.VISIBLE);
|
dropdown.setVisibility(View.VISIBLE);
|
||||||
dropdown.selectItemByIndex((int) value);
|
dropdown.setOption((int) value);
|
||||||
}
|
}
|
||||||
public void nullify(){
|
public void nullify(){
|
||||||
isBlank = true;
|
isBlank = true;
|
||||||
dropdown.setVisibility(View.GONE);
|
dropdown.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
public dataType getViewValue(){
|
public RawDataType getViewValue(){
|
||||||
if(dropdown == null) return null;
|
if(dropdown == null) return null;
|
||||||
if(dropdown.getVisibility() == View.GONE) return new intType(name, intType.nullval);
|
if(dropdown.getVisibility() == View.GONE) return new IntType(name, IntType.nullval);
|
||||||
return new intType(name, dropdown.getSelectedIndex());
|
return new IntType(name, dropdown.getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Dropdown view
|
||||||
public void add_individual_view(LinearLayout parent, dataType data){
|
public void add_individual_view(LinearLayout parent, RawDataType data){
|
||||||
if(data.isNull()) return;
|
if(data.isNull()) return;
|
||||||
TextView tv = new TextView(parent.getContext());
|
|
||||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
parent.addView(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
new TextViewBuilder(parent.getContext(), text_options[(int) data.get()])
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
.layout_match_wrap()
|
||||||
));
|
.padding(20)
|
||||||
tv.setPadding(20,20,20,20);
|
.size(18)
|
||||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
.align_left()
|
||||||
tv.setText(text_options[(int) data.get()]);
|
.build());
|
||||||
tv.setTextSize(18);
|
|
||||||
parent.addView(tv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -160,7 +122,7 @@ public class dropdownType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Generates N amount of colors, all opposite colors
|
||||||
private static int[] generateEquidistantColors(int N) {
|
private static int[] generateEquidistantColors(int N) {
|
||||||
int[] colors = new int[N];
|
int[] colors = new int[N];
|
||||||
float[] hsv = new float[3]; // Hue, Saturation, Value
|
float[] hsv = new float[3]; // Hue, Saturation, Value
|
||||||
@@ -176,7 +138,8 @@ public class dropdownType extends inputType {
|
|||||||
return colors;
|
return colors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add_compiled_view(LinearLayout parent, dataType[] data){
|
// Turns the dropdown into a pie chart in the compiled view
|
||||||
|
public void add_compiled_view(LinearLayout parent, RawDataType[] data){
|
||||||
PieChart chart = new PieChart(parent.getContext());
|
PieChart chart = new PieChart(parent.getContext());
|
||||||
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
@@ -184,7 +147,7 @@ public class dropdownType extends inputType {
|
|||||||
);
|
);
|
||||||
layout.height = 350;
|
layout.height = 350;
|
||||||
chart.setLayoutParams(layout);
|
chart.setLayoutParams(layout);
|
||||||
chart.setBackgroundColor(0xff252025);
|
chart.setBackgroundColor(chart_background);
|
||||||
parent.addView(chart);
|
parent.addView(chart);
|
||||||
|
|
||||||
int[] data_2 = new int[text_options.length];
|
int[] data_2 = new int[text_options.length];
|
||||||
@@ -209,8 +172,8 @@ public class dropdownType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Turns the dropdown into a line chart in the history view
|
||||||
public void add_history_view(LinearLayout parent, dataType[] data){
|
public void add_history_view(LinearLayout parent, RawDataType[] data){
|
||||||
LineChart chart = new LineChart(parent.getContext());
|
LineChart chart = new LineChart(parent.getContext());
|
||||||
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
@@ -218,7 +181,7 @@ public class dropdownType extends inputType {
|
|||||||
);
|
);
|
||||||
layout.height = 350;
|
layout.height = 350;
|
||||||
chart.setLayoutParams(layout);
|
chart.setLayoutParams(layout);
|
||||||
chart.setBackgroundColor(0xff252025);
|
chart.setBackgroundColor(chart_background);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -240,10 +203,10 @@ public class dropdownType extends inputType {
|
|||||||
|
|
||||||
LineDataSet dataSet = new LineDataSet(entries, text_options[i]);
|
LineDataSet dataSet = new LineDataSet(entries, text_options[i]);
|
||||||
dataSet.setColor(colors[i]);
|
dataSet.setColor(colors[i]);
|
||||||
dataSet.setValueTextColor(Color.BLACK);
|
dataSet.setValueTextColor(dropdown_value_text_1);
|
||||||
dataSet.setDrawCircles(false);
|
dataSet.setDrawCircles(false);
|
||||||
dataSet.setDrawValues(false);
|
dataSet.setDrawValues(false);
|
||||||
dataSet.setValueTextColor(Color.RED);
|
dataSet.setValueTextColor(dropdown_value_text_2);
|
||||||
lineData.addDataSet(dataSet);
|
lineData.addDataSet(dataSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,9 +222,9 @@ public class dropdownType extends inputType {
|
|||||||
chart.setScaleEnabled(false);
|
chart.setScaleEnabled(false);
|
||||||
|
|
||||||
|
|
||||||
chart.getXAxis().setTextColor(Color.WHITE);
|
chart.getXAxis().setTextColor(chart_text);
|
||||||
chart.getAxisLeft().setTextColor(Color.WHITE);
|
chart.getAxisLeft().setTextColor(chart_text);
|
||||||
chart.getAxisRight().setTextColor(Color.WHITE);
|
chart.getAxisRight().setTextColor(chart_text);
|
||||||
|
|
||||||
chart.getAxisLeft().setAxisMinimum(0.f);
|
chart.getAxisLeft().setAxisMinimum(0.f);
|
||||||
chart.getAxisLeft().setAxisMaximum(1.f);
|
chart.getAxisLeft().setAxisMaximum(1.f);
|
||||||
@@ -270,10 +233,19 @@ public class dropdownType extends inputType {
|
|||||||
chart.getAxisRight().setAxisMaximum(1.f);
|
chart.getAxisRight().setAxisMaximum(1.f);
|
||||||
|
|
||||||
Legend legend = chart.getLegend();
|
Legend legend = chart.getLegend();
|
||||||
legend.setTextColor(Color.WHITE);
|
legend.setTextColor(chart_text);
|
||||||
|
|
||||||
chart.invalidate();
|
chart.invalidate();
|
||||||
parent.addView(chart);
|
parent.addView(chart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
public void addDataToTable(TableLayout parent, Map<Integer, List<RawDataType>> data){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString(RawDataType data){
|
||||||
|
return text_options[(int) data.get()];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package com.ridgebotics.ridgescout.types.input;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TableLayout;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||||
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
|
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
// Abstract class for fields.
|
||||||
|
public abstract class FieldType {
|
||||||
|
// Define what the IDS are for each type
|
||||||
|
public static final int slider_type_id = 255;
|
||||||
|
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,
|
||||||
|
NUMBER,
|
||||||
|
CHECKBOX,
|
||||||
|
FIELDPOS
|
||||||
|
}
|
||||||
|
public String UUID;
|
||||||
|
public String name;
|
||||||
|
public String description;
|
||||||
|
public Object default_value;
|
||||||
|
public abstract inputTypes getInputType();
|
||||||
|
public abstract RawDataType.valueTypes getValueType();
|
||||||
|
public abstract Object get_fallback_value();
|
||||||
|
public abstract int get_byte_id();
|
||||||
|
public FieldType(){}
|
||||||
|
public FieldType(String UUID, String name, String description){
|
||||||
|
this.UUID = UUID;
|
||||||
|
this.name = name;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String get_type_name();
|
||||||
|
|
||||||
|
public byte[] encode() throws ByteBuilder.buildingException {
|
||||||
|
ByteBuilder bb = new ByteBuilder();
|
||||||
|
bb.addString(UUID);
|
||||||
|
bb.addString(name);
|
||||||
|
bb.addString(description);
|
||||||
|
|
||||||
|
encodeData(bb);
|
||||||
|
|
||||||
|
return bb.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public abstract void encodeData(ByteBuilder byteBuilder) throws ByteBuilder.buildingException;
|
||||||
|
public void decode(byte[] bytes) throws BuiltByteParser.byteParsingExeption {
|
||||||
|
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
||||||
|
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
||||||
|
|
||||||
|
UUID = (String) objects.remove(0).get();
|
||||||
|
name = (String) objects.remove(0).get();
|
||||||
|
|
||||||
|
description = (String) objects.remove(0).get();
|
||||||
|
|
||||||
|
decodeData(objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public abstract void decodeData(ArrayList<BuiltByteParser.parsedObject> objects);
|
||||||
|
|
||||||
|
// public abstract dataType[] getConfig();
|
||||||
|
// public abstract void setConfig(dataType[] config);
|
||||||
|
|
||||||
|
public abstract View createView(Context context, Function<RawDataType, Integer> onUpdate);
|
||||||
|
public boolean isBlank = false;
|
||||||
|
public abstract void nullify();
|
||||||
|
public void setViewValue(RawDataType type){setViewValue(type.get());}
|
||||||
|
public abstract void setViewValue(Object value);
|
||||||
|
public abstract RawDataType getViewValue();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public abstract void add_individual_view(LinearLayout parent, RawDataType data);
|
||||||
|
public abstract void add_compiled_view(LinearLayout parent, RawDataType[] data);
|
||||||
|
public abstract void add_history_view(LinearLayout parent, RawDataType[] data);
|
||||||
|
|
||||||
|
|
||||||
|
public abstract void addDataToTable(TableLayout parent, Map<Integer, List<RawDataType>> data);
|
||||||
|
|
||||||
|
|
||||||
|
public abstract String toString(RawDataType data);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+52
-48
@@ -1,46 +1,44 @@
|
|||||||
package com.ridgebotics.ridgescout.types.input;
|
package com.ridgebotics.ridgescout.types.input;
|
||||||
|
|
||||||
import static android.text.InputType.TYPE_CLASS_NUMBER;
|
import static com.ridgebotics.ridgescout.utility.Colors.chart_background;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.chart_text;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.dropdown_value_text_1;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.dropdown_value_text_2;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.fieldpos_data;
|
||||||
|
|
||||||
import android.content.Context;
|
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.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TableLayout;
|
||||||
|
|
||||||
import com.github.mikephil.charting.charts.LineChart;
|
import com.github.mikephil.charting.charts.LineChart;
|
||||||
import com.github.mikephil.charting.components.Legend;
|
import com.github.mikephil.charting.components.Legend;
|
||||||
import com.github.mikephil.charting.data.Entry;
|
import com.github.mikephil.charting.data.Entry;
|
||||||
import com.github.mikephil.charting.data.LineData;
|
import com.github.mikephil.charting.data.LineData;
|
||||||
import com.github.mikephil.charting.data.LineDataSet;
|
import com.github.mikephil.charting.data.LineDataSet;
|
||||||
import com.ridgebotics.ridgescout.R;
|
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||||
import com.ridgebotics.ridgescout.types.data.dataType;
|
import com.ridgebotics.ridgescout.types.data.IntArrType;
|
||||||
import com.ridgebotics.ridgescout.types.data.intArrType;
|
import com.ridgebotics.ridgescout.ui.views.FieldPosView;
|
||||||
import com.ridgebotics.ridgescout.types.data.intType;
|
import com.ridgebotics.ridgescout.ui.views.MultiFieldPosView;
|
||||||
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.BuiltByteParser;
|
||||||
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class fieldposType extends inputType {
|
public class FieldposType extends FieldType {
|
||||||
public int get_byte_id() {return fieldposType;}
|
public int get_byte_id() {return fieldposType;}
|
||||||
public inputTypes getInputType(){return inputTypes.FIELDPOS;}
|
public inputTypes getInputType(){return inputTypes.FIELDPOS;}
|
||||||
public dataType.valueTypes getValueType(){return dataType.valueTypes.NUM;}
|
public RawDataType.valueTypes getValueType(){return RawDataType.valueTypes.NUM;}
|
||||||
public Object get_fallback_value(){return 0;}
|
public Object get_fallback_value(){return 0;}
|
||||||
public fieldposType(){}
|
public FieldposType(){}
|
||||||
public String get_type_name(){return "Field Pos";}
|
public String get_type_name(){return "Field Pos";}
|
||||||
public fieldposType(String name, int[] default_value){
|
public FieldposType(String UUID, String name, String description, int[] default_value){
|
||||||
super(name);
|
super(UUID, name, description);
|
||||||
this.default_value = default_value;
|
this.default_value = default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,20 +46,12 @@ public class fieldposType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public byte[] encode() throws ByteBuilder.buildingException {
|
public void encodeData(ByteBuilder bb) throws ByteBuilder.buildingException {
|
||||||
ByteBuilder bb = new ByteBuilder();
|
|
||||||
bb.addString(name);
|
|
||||||
bb.addIntArray((int[]) default_value);
|
bb.addIntArray((int[]) default_value);
|
||||||
return bb.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void decode(byte[] bytes) throws BuiltByteParser.byteParsingExeption {
|
public void decodeData(ArrayList<BuiltByteParser.parsedObject> objects) {
|
||||||
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
default_value = objects.get(0).get();
|
||||||
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
|
||||||
|
|
||||||
name = (String) objects.get(0).get();
|
|
||||||
default_value = objects.get(1).get();
|
|
||||||
System.out.println("Defalt value!!!!!" + default_value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -70,9 +60,9 @@ public class fieldposType extends inputType {
|
|||||||
|
|
||||||
public FieldPosView field = null;
|
public FieldPosView field = null;
|
||||||
|
|
||||||
public View createView(Context context, Function<dataType, Integer> onUpdate){
|
public View createView(Context context, Function<RawDataType, Integer> onUpdate){
|
||||||
field = new FieldPosView(context, pos -> {
|
field = new FieldPosView(context, pos -> {
|
||||||
onUpdate.apply(new intArrType(name, pos));
|
onUpdate.apply(new IntArrType(name, pos));
|
||||||
});
|
});
|
||||||
setViewValue(default_value);
|
setViewValue(default_value);
|
||||||
return field;
|
return field;
|
||||||
@@ -81,7 +71,11 @@ public class fieldposType extends inputType {
|
|||||||
|
|
||||||
public void setViewValue(Object value) {
|
public void setViewValue(Object value) {
|
||||||
if(field == null) return;
|
if(field == null) return;
|
||||||
if(intArrType.isNull((int[]) value)){
|
if(IntArrType.isNull((int[]) value)){
|
||||||
|
nullify();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(((int[]) value)[0] == 255 && ((int[]) value)[1] == 255){
|
||||||
nullify();
|
nullify();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -94,15 +88,15 @@ public class fieldposType extends inputType {
|
|||||||
isBlank = true;
|
isBlank = true;
|
||||||
field.setVisibility(View.GONE);
|
field.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
public dataType getViewValue(){
|
public RawDataType getViewValue(){
|
||||||
if(field == null) return null;
|
if(field == null) return null;
|
||||||
if(field.getVisibility() == View.GONE) return intArrType.newNull(name);
|
if(field.getVisibility() == View.GONE) return IntArrType.newNull(name);
|
||||||
return new intArrType(name, field.getPos());
|
return new IntArrType(name, field.getPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void add_individual_view(LinearLayout parent, dataType data){
|
public void add_individual_view(LinearLayout parent, RawDataType data){
|
||||||
if(data.isNull()) return;
|
if(data.isNull()) return;
|
||||||
|
|
||||||
FieldPosView fp = new FieldPosView(parent.getContext());
|
FieldPosView fp = new FieldPosView(parent.getContext());
|
||||||
@@ -145,7 +139,7 @@ public class fieldposType extends inputType {
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int findMin(dataType[] data){
|
private static int findMin(RawDataType[] data){
|
||||||
int min = (int)data[0].get();
|
int min = (int)data[0].get();
|
||||||
for(int i = 1; i < data.length; i++)
|
for(int i = 1; i < data.length; i++)
|
||||||
if((int)data[i].get() < min)
|
if((int)data[i].get() < min)
|
||||||
@@ -153,7 +147,7 @@ public class fieldposType extends inputType {
|
|||||||
return min;
|
return min;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int findMax(dataType[] data){
|
private static int findMax(RawDataType[] data){
|
||||||
int max = (int)data[0].get();
|
int max = (int)data[0].get();
|
||||||
for(int i = 1; i < data.length; i++)
|
for(int i = 1; i < data.length; i++)
|
||||||
if((int)data[i].get() > max)
|
if((int)data[i].get() > max)
|
||||||
@@ -161,7 +155,7 @@ public class fieldposType extends inputType {
|
|||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add_compiled_view(LinearLayout parent, dataType[] data){
|
public void add_compiled_view(LinearLayout parent, RawDataType[] data){
|
||||||
MultiFieldPosView mfp = new MultiFieldPosView(parent.getContext());
|
MultiFieldPosView mfp = new MultiFieldPosView(parent.getContext());
|
||||||
for(int i = 0; i < data.length; i++){
|
for(int i = 0; i < data.length; i++){
|
||||||
if(data[i].isNull()) continue;
|
if(data[i].isNull()) continue;
|
||||||
@@ -170,7 +164,7 @@ public class fieldposType extends inputType {
|
|||||||
parent.addView(mfp);
|
parent.addView(mfp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add_history_view(LinearLayout parent, dataType[] data){
|
public void add_history_view(LinearLayout parent, RawDataType[] data){
|
||||||
LineChart chart = new LineChart(parent.getContext());
|
LineChart chart = new LineChart(parent.getContext());
|
||||||
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
@@ -178,7 +172,7 @@ public class fieldposType extends inputType {
|
|||||||
);
|
);
|
||||||
layout.height = 350;
|
layout.height = 350;
|
||||||
chart.setLayoutParams(layout);
|
chart.setLayoutParams(layout);
|
||||||
chart.setBackgroundColor(0xff252025);
|
chart.setBackgroundColor(chart_background);
|
||||||
|
|
||||||
int min = 0;
|
int min = 0;
|
||||||
int max = 255;
|
int max = 255;
|
||||||
@@ -192,8 +186,8 @@ public class fieldposType extends inputType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LineDataSet dataSet = new LineDataSet(entries, "Field position Y value");
|
LineDataSet dataSet = new LineDataSet(entries, "Field position Y value");
|
||||||
dataSet.setColor(Color.BLUE);
|
dataSet.setColor(fieldpos_data);
|
||||||
dataSet.setValueTextColor(Color.BLACK);
|
dataSet.setValueTextColor(dropdown_value_text_1);
|
||||||
dataSet.setDrawCircles(false);
|
dataSet.setDrawCircles(false);
|
||||||
dataSet.setDrawValues(false);
|
dataSet.setDrawValues(false);
|
||||||
|
|
||||||
@@ -207,14 +201,14 @@ public class fieldposType extends inputType {
|
|||||||
chart.setDragEnabled(false);
|
chart.setDragEnabled(false);
|
||||||
chart.setScaleEnabled(false);
|
chart.setScaleEnabled(false);
|
||||||
|
|
||||||
dataSet.setValueTextColor(Color.RED);
|
dataSet.setValueTextColor(dropdown_value_text_2);
|
||||||
|
|
||||||
chart.getXAxis().setTextColor(Color.WHITE);
|
chart.getXAxis().setTextColor(chart_text);
|
||||||
chart.getAxisLeft().setTextColor(Color.WHITE);
|
chart.getAxisLeft().setTextColor(chart_text);
|
||||||
chart.getAxisRight().setTextColor(Color.WHITE);
|
chart.getAxisRight().setTextColor(chart_text);
|
||||||
|
|
||||||
Legend legend = chart.getLegend();
|
Legend legend = chart.getLegend();
|
||||||
legend.setTextColor(Color.WHITE);
|
legend.setTextColor(chart_text);
|
||||||
|
|
||||||
|
|
||||||
chart.getAxisLeft().setAxisMinimum(min);
|
chart.getAxisLeft().setAxisMinimum(min);
|
||||||
@@ -226,5 +220,15 @@ public class fieldposType extends inputType {
|
|||||||
|
|
||||||
parent.addView(chart);
|
parent.addView(chart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
public void addDataToTable(TableLayout parent, Map<Integer, List<RawDataType>> data){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString(RawDataType data){
|
||||||
|
int[] intarr = (int[]) data.get();
|
||||||
|
return "[" + intarr[0] + "," + intarr[1] + "]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+62
-57
@@ -2,8 +2,13 @@ package com.ridgebotics.ridgescout.types.input;
|
|||||||
|
|
||||||
import static android.text.InputType.TYPE_CLASS_NUMBER;
|
import static android.text.InputType.TYPE_CLASS_NUMBER;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.chart_background;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.chart_text;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.dropdown_value_text_1;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.dropdown_value_text_2;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.number_data;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
@@ -12,6 +17,7 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TableLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.github.mikephil.charting.charts.LineChart;
|
import com.github.mikephil.charting.charts.LineChart;
|
||||||
@@ -19,24 +25,26 @@ import com.github.mikephil.charting.components.Legend;
|
|||||||
import com.github.mikephil.charting.data.Entry;
|
import com.github.mikephil.charting.data.Entry;
|
||||||
import com.github.mikephil.charting.data.LineData;
|
import com.github.mikephil.charting.data.LineData;
|
||||||
import com.github.mikephil.charting.data.LineDataSet;
|
import com.github.mikephil.charting.data.LineDataSet;
|
||||||
import com.ridgebotics.ridgescout.types.data.dataType;
|
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||||
import com.ridgebotics.ridgescout.types.data.intType;
|
import com.ridgebotics.ridgescout.types.data.IntType;
|
||||||
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
||||||
|
import com.ridgebotics.ridgescout.utility.builders.TextViewBuilder;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class numberType extends inputType {
|
public class NumberType extends FieldType {
|
||||||
public int get_byte_id() {return numberType;}
|
public int get_byte_id() {return numberType;}
|
||||||
public inputTypes getInputType(){return inputTypes.NUMBER;}
|
public inputTypes getInputType(){return inputTypes.NUMBER;}
|
||||||
public dataType.valueTypes getValueType(){return dataType.valueTypes.NUM;}
|
public RawDataType.valueTypes getValueType(){return RawDataType.valueTypes.NUM;}
|
||||||
public Object get_fallback_value(){return 0;}
|
public Object get_fallback_value(){return 0;}
|
||||||
public numberType(){}
|
public NumberType(){}
|
||||||
public String get_type_name(){return "Number";}
|
public String get_type_name(){return "Number";}
|
||||||
public numberType(String name, int default_value){
|
public NumberType(String UUID, String name, String description, int default_value){
|
||||||
super(name);
|
super(UUID, name, description);
|
||||||
this.default_value = default_value;
|
this.default_value = default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,18 +52,11 @@ public class numberType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public byte[] encode() throws ByteBuilder.buildingException {
|
public void encodeData(ByteBuilder bb) throws ByteBuilder.buildingException {
|
||||||
ByteBuilder bb = new ByteBuilder();
|
|
||||||
bb.addString(name);
|
|
||||||
bb.addInt((int)default_value);
|
bb.addInt((int)default_value);
|
||||||
return bb.build();
|
|
||||||
}
|
}
|
||||||
public void decode(byte[] bytes) throws BuiltByteParser.byteParsingExeption {
|
public void decodeData(ArrayList<BuiltByteParser.parsedObject> objects) {
|
||||||
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
default_value = objects.get(0).get();
|
||||||
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
|
||||||
|
|
||||||
name = (String) objects.get(0).get();
|
|
||||||
default_value = objects.get(1).get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -64,7 +65,7 @@ public class numberType extends inputType {
|
|||||||
|
|
||||||
public EditText num = null;
|
public EditText num = null;
|
||||||
|
|
||||||
public View createView(Context context, Function<dataType, Integer> onUpdate){
|
public View createView(Context context, Function<RawDataType, Integer> onUpdate){
|
||||||
num = new EditText(context);
|
num = new EditText(context);
|
||||||
num.setInputType(TYPE_CLASS_NUMBER);
|
num.setInputType(TYPE_CLASS_NUMBER);
|
||||||
num.addTextChangedListener(new TextWatcher() {
|
num.addTextChangedListener(new TextWatcher() {
|
||||||
@@ -82,7 +83,7 @@ public class numberType extends inputType {
|
|||||||
|
|
||||||
public void setViewValue(Object value) {
|
public void setViewValue(Object value) {
|
||||||
if(num == null) return;
|
if(num == null) return;
|
||||||
if(intType.isNull((int)value)){
|
if(IntType.isNull((int)value)){
|
||||||
nullify();
|
nullify();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -95,39 +96,34 @@ public class numberType extends inputType {
|
|||||||
isBlank = true;
|
isBlank = true;
|
||||||
num.setVisibility(View.GONE);
|
num.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
public dataType getViewValue(){
|
public RawDataType getViewValue(){
|
||||||
if(num == null) return null;
|
if(num == null) return null;
|
||||||
if(num.getVisibility() == View.GONE) return intType.newNull(name);
|
if(num.getVisibility() == View.GONE) return IntType.newNull(name);
|
||||||
return new intType(name, safeToInt(num.getText().toString()));
|
return new IntType(name, safeToInt(num.getText().toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private int safeToInt(String num){
|
private int safeToInt(String num){
|
||||||
if(num.isEmpty())
|
if(num.isEmpty())
|
||||||
return intType.nullval;
|
return IntType.nullval;
|
||||||
try {
|
try {
|
||||||
return Integer.parseInt(num);
|
return Integer.parseInt(num);
|
||||||
}catch (NumberFormatException e){
|
}catch (NumberFormatException e){
|
||||||
return intType.nullval;
|
return IntType.nullval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void add_individual_view(LinearLayout parent, dataType data){
|
public void add_individual_view(LinearLayout parent, RawDataType data){
|
||||||
if(data.isNull()) return;
|
if(data.isNull()) return;
|
||||||
|
parent.addView(new TextViewBuilder(parent.getContext(), String.valueOf((int) data.get()))
|
||||||
TextView tv = new TextView(parent.getContext());
|
.layout_match_wrap()
|
||||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
.align_left()
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
.size(24)
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
.build());
|
||||||
));
|
|
||||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
|
||||||
tv.setText(String.valueOf((int) data.get()));
|
|
||||||
tv.setTextSize(24);
|
|
||||||
parent.addView(tv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -163,7 +159,7 @@ public class numberType extends inputType {
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int findMin(dataType[] data){
|
private static int findMin(RawDataType[] data){
|
||||||
int min = (int)data[0].get();
|
int min = (int)data[0].get();
|
||||||
for(int i = 1; i < data.length; i++)
|
for(int i = 1; i < data.length; i++)
|
||||||
if((int)data[i].get() < min)
|
if((int)data[i].get() < min)
|
||||||
@@ -171,7 +167,7 @@ public class numberType extends inputType {
|
|||||||
return min;
|
return min;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int findMax(dataType[] data){
|
private static int findMax(RawDataType[] data){
|
||||||
int max = (int)data[0].get();
|
int max = (int)data[0].get();
|
||||||
for(int i = 1; i < data.length; i++)
|
for(int i = 1; i < data.length; i++)
|
||||||
if((int)data[i].get() > max)
|
if((int)data[i].get() > max)
|
||||||
@@ -179,7 +175,7 @@ public class numberType extends inputType {
|
|||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add_compiled_view(LinearLayout parent, dataType[] data){
|
public void add_compiled_view(LinearLayout parent, RawDataType[] data){
|
||||||
LineChart chart = new LineChart(parent.getContext());
|
LineChart chart = new LineChart(parent.getContext());
|
||||||
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
@@ -187,7 +183,7 @@ public class numberType extends inputType {
|
|||||||
);
|
);
|
||||||
layout.height = 350;
|
layout.height = 350;
|
||||||
chart.setLayoutParams(layout);
|
chart.setLayoutParams(layout);
|
||||||
chart.setBackgroundColor(0xff252025);
|
chart.setBackgroundColor(chart_background);
|
||||||
|
|
||||||
int min = findMin(data);
|
int min = findMin(data);
|
||||||
int max = findMax(data);
|
int max = findMax(data);
|
||||||
@@ -212,8 +208,8 @@ public class numberType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
LineDataSet dataSet = new LineDataSet(entries, name);
|
LineDataSet dataSet = new LineDataSet(entries, name);
|
||||||
dataSet.setColor(Color.BLUE);
|
dataSet.setColor(number_data);
|
||||||
dataSet.setValueTextColor(Color.BLACK);
|
dataSet.setValueTextColor(dropdown_value_text_1);
|
||||||
dataSet.setDrawCircles(false);
|
dataSet.setDrawCircles(false);
|
||||||
dataSet.setDrawValues(false);
|
dataSet.setDrawValues(false);
|
||||||
|
|
||||||
@@ -228,7 +224,7 @@ public class numberType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
LineDataSet normalDistSet = new LineDataSet(normalDistEntries, "Normal Distribution");
|
LineDataSet normalDistSet = new LineDataSet(normalDistEntries, "Normal Distribution");
|
||||||
normalDistSet.setColor(Color.RED);
|
normalDistSet.setColor(dropdown_value_text_2);
|
||||||
normalDistSet.setDrawCircles(false);
|
normalDistSet.setDrawCircles(false);
|
||||||
normalDistSet.setDrawValues(false);
|
normalDistSet.setDrawValues(false);
|
||||||
normalDistSet.setLineWidth(2f);
|
normalDistSet.setLineWidth(2f);
|
||||||
@@ -243,14 +239,14 @@ public class numberType extends inputType {
|
|||||||
chart.setDragEnabled(false);
|
chart.setDragEnabled(false);
|
||||||
chart.setScaleEnabled(false);
|
chart.setScaleEnabled(false);
|
||||||
|
|
||||||
dataSet.setValueTextColor(Color.RED);
|
dataSet.setValueTextColor(dropdown_value_text_2);
|
||||||
|
|
||||||
chart.getXAxis().setTextColor(Color.WHITE);
|
chart.getXAxis().setTextColor(chart_text);
|
||||||
chart.getAxisLeft().setTextColor(Color.WHITE);
|
chart.getAxisLeft().setTextColor(chart_text);
|
||||||
chart.getAxisRight().setTextColor(Color.WHITE);
|
chart.getAxisRight().setTextColor(chart_text);
|
||||||
|
|
||||||
Legend legend = chart.getLegend();
|
Legend legend = chart.getLegend();
|
||||||
legend.setTextColor(Color.WHITE);
|
legend.setTextColor(chart_text);
|
||||||
|
|
||||||
parent.addView(chart);
|
parent.addView(chart);
|
||||||
}
|
}
|
||||||
@@ -258,7 +254,7 @@ public class numberType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void add_history_view(LinearLayout parent, dataType[] data){
|
public void add_history_view(LinearLayout parent, RawDataType[] data){
|
||||||
LineChart chart = new LineChart(parent.getContext());
|
LineChart chart = new LineChart(parent.getContext());
|
||||||
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
@@ -266,7 +262,7 @@ public class numberType extends inputType {
|
|||||||
);
|
);
|
||||||
layout.height = 350;
|
layout.height = 350;
|
||||||
chart.setLayoutParams(layout);
|
chart.setLayoutParams(layout);
|
||||||
chart.setBackgroundColor(0xff252025);
|
chart.setBackgroundColor(chart_background);
|
||||||
|
|
||||||
int min = findMin(data);
|
int min = findMin(data);
|
||||||
int max = findMax(data);
|
int max = findMax(data);
|
||||||
@@ -281,8 +277,8 @@ public class numberType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
LineDataSet dataSet = new LineDataSet(entries, name);
|
LineDataSet dataSet = new LineDataSet(entries, name);
|
||||||
dataSet.setColor(Color.BLUE);
|
dataSet.setColor(number_data);
|
||||||
dataSet.setValueTextColor(Color.BLACK);
|
dataSet.setValueTextColor(dropdown_value_text_1);
|
||||||
dataSet.setDrawCircles(false);
|
dataSet.setDrawCircles(false);
|
||||||
dataSet.setDrawValues(false);
|
dataSet.setDrawValues(false);
|
||||||
|
|
||||||
@@ -296,14 +292,14 @@ public class numberType extends inputType {
|
|||||||
chart.setDragEnabled(false);
|
chart.setDragEnabled(false);
|
||||||
chart.setScaleEnabled(false);
|
chart.setScaleEnabled(false);
|
||||||
|
|
||||||
dataSet.setValueTextColor(Color.RED);
|
dataSet.setValueTextColor(dropdown_value_text_2);
|
||||||
|
|
||||||
chart.getXAxis().setTextColor(Color.WHITE);
|
chart.getXAxis().setTextColor(chart_text);
|
||||||
chart.getAxisLeft().setTextColor(Color.WHITE);
|
chart.getAxisLeft().setTextColor(chart_text);
|
||||||
chart.getAxisRight().setTextColor(Color.WHITE);
|
chart.getAxisRight().setTextColor(chart_text);
|
||||||
|
|
||||||
Legend legend = chart.getLegend();
|
Legend legend = chart.getLegend();
|
||||||
legend.setTextColor(Color.WHITE);
|
legend.setTextColor(chart_text);
|
||||||
|
|
||||||
|
|
||||||
chart.getAxisLeft().setAxisMinimum(min);
|
chart.getAxisLeft().setAxisMinimum(min);
|
||||||
@@ -315,5 +311,14 @@ public class numberType extends inputType {
|
|||||||
|
|
||||||
parent.addView(chart);
|
parent.addView(chart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
public void addDataToTable(TableLayout parent, Map<Integer, List<RawDataType>> data){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString(RawDataType data){
|
||||||
|
return String.valueOf((int) data.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+56
-48
@@ -1,16 +1,22 @@
|
|||||||
package com.ridgebotics.ridgescout.types.input;
|
package com.ridgebotics.ridgescout.types.input;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.chart_background;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.chart_text;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.dropdown_value_text_1;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.dropdown_value_text_2;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.slider_data;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TableLayout;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.types.data.dataType;
|
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||||
import com.ridgebotics.ridgescout.types.data.intType;
|
import com.ridgebotics.ridgescout.types.data.IntType;
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
||||||
@@ -23,20 +29,21 @@ import com.google.android.material.slider.Slider;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class sliderType extends inputType {
|
public class SliderType extends FieldType {
|
||||||
// public int defaultValue;
|
// public int defaultValue;
|
||||||
public int min;
|
public int min;
|
||||||
public int max;
|
public int max;
|
||||||
public int get_byte_id() {return slider_type_id;}
|
public int get_byte_id() {return slider_type_id;}
|
||||||
public inputTypes getInputType(){return inputTypes.SLIDER;}
|
public inputTypes getInputType(){return inputTypes.SLIDER;}
|
||||||
public dataType.valueTypes getValueType(){return dataType.valueTypes.NUM;}
|
public RawDataType.valueTypes getValueType(){return RawDataType.valueTypes.NUM;}
|
||||||
public Object get_fallback_value(){return 0;}
|
public Object get_fallback_value(){return 0;}
|
||||||
public sliderType(){};
|
public SliderType(){};
|
||||||
public String get_type_name(){return "Slider";}
|
public String get_type_name(){return "Slider";}
|
||||||
public sliderType(String name, int defaultValue, int min, int max){
|
public SliderType(String UUID, String name, String description, int defaultValue, int min, int max){
|
||||||
super(name);
|
super(UUID, name, description);
|
||||||
this.default_value = defaultValue;
|
this.default_value = defaultValue;
|
||||||
this.min = min;
|
this.min = min;
|
||||||
this.max = max;
|
this.max = max;
|
||||||
@@ -45,22 +52,15 @@ public class sliderType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public byte[] encode() throws ByteBuilder.buildingException {
|
public void encodeData(ByteBuilder bb) throws ByteBuilder.buildingException {
|
||||||
ByteBuilder bb = new ByteBuilder();
|
bb.addInt((int) default_value);
|
||||||
bb.addString(name);
|
|
||||||
bb.addInt((int)default_value);
|
|
||||||
bb.addInt(min);
|
bb.addInt(min);
|
||||||
bb.addInt(max);
|
bb.addInt(max);
|
||||||
return bb.build();
|
|
||||||
}
|
}
|
||||||
public void decode(byte[] bytes) throws BuiltByteParser.byteParsingExeption {
|
public void decodeData(ArrayList<BuiltByteParser.parsedObject> objects) {
|
||||||
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
default_value = objects.get(0).get();
|
||||||
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
min = (int) objects.get(1).get();
|
||||||
|
max = (int) objects.get(2).get();
|
||||||
name = (String) objects.get(0).get();
|
|
||||||
default_value = objects.get(1).get();
|
|
||||||
min = (int) objects.get(2).get();
|
|
||||||
max = (int) objects.get(3).get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ public class sliderType extends inputType {
|
|||||||
|
|
||||||
public Slider slider = null;
|
public Slider slider = null;
|
||||||
|
|
||||||
public View createView(Context context, Function<dataType, Integer> onUpdate){
|
public View createView(Context context, Function<RawDataType, Integer> onUpdate){
|
||||||
slider = new Slider(context);
|
slider = new Slider(context);
|
||||||
setViewValue(default_value);
|
setViewValue(default_value);
|
||||||
slider.setStepSize((float) 1 / (max-min));
|
slider.setStepSize((float) 1 / (max-min));
|
||||||
@@ -83,7 +83,7 @@ public class sliderType extends inputType {
|
|||||||
|
|
||||||
public void setViewValue(Object value) {
|
public void setViewValue(Object value) {
|
||||||
if(slider == null) return;
|
if(slider == null) return;
|
||||||
if(intType.isNull((int) value)){
|
if(IntType.isNull((int) value)){
|
||||||
nullify();
|
nullify();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ public class sliderType extends inputType {
|
|||||||
|
|
||||||
float slidervalue = round_position*step_size;
|
float slidervalue = round_position*step_size;
|
||||||
if(slidervalue > 1 || slidervalue < 0) {
|
if(slidervalue > 1 || slidervalue < 0) {
|
||||||
AlertManager.error("Error loading slider " + name);
|
AlertManager.addSimpleError("Error loading slider " + name);
|
||||||
slider.setValue(0);
|
slider.setValue(0);
|
||||||
}else{
|
}else{
|
||||||
slider.setValue(slidervalue);
|
slider.setValue(slidervalue);
|
||||||
@@ -103,10 +103,10 @@ public class sliderType extends inputType {
|
|||||||
|
|
||||||
slider.setVisibility(View.VISIBLE);
|
slider.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
public dataType getViewValue(){
|
public RawDataType getViewValue(){
|
||||||
if(slider == null) return null;
|
if(slider == null) return null;
|
||||||
if(slider.getVisibility() == View.GONE) return intType.newNull(name);
|
if(slider.getVisibility() == View.GONE) return IntType.newNull(name);
|
||||||
return new intType(name, min + (int) (slider.getValue() * (max-min)));
|
return new IntType(name, min + (int) (slider.getValue() * (max-min)));
|
||||||
}
|
}
|
||||||
public void nullify(){
|
public void nullify(){
|
||||||
isBlank = true;
|
isBlank = true;
|
||||||
@@ -118,7 +118,7 @@ public class sliderType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void add_individual_view(LinearLayout parent, dataType data){
|
public void add_individual_view(LinearLayout parent, RawDataType data){
|
||||||
if(data.isNull()) return;
|
if(data.isNull()) return;
|
||||||
Slider slider = new Slider(parent.getContext());
|
Slider slider = new Slider(parent.getContext());
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ public class sliderType extends inputType {
|
|||||||
int round_position = Math.round(slider_position / step_size);
|
int round_position = Math.round(slider_position / step_size);
|
||||||
float value = round_position*step_size;
|
float value = round_position*step_size;
|
||||||
if(value > 1 || value < 0) {
|
if(value > 1 || value < 0) {
|
||||||
AlertManager.error("Error loading slider " + name);
|
AlertManager.addSimpleError("Error loading slider " + name);
|
||||||
slider.setValue(0);
|
slider.setValue(0);
|
||||||
}else{
|
}else{
|
||||||
slider.setValue(value);
|
slider.setValue(value);
|
||||||
@@ -172,7 +172,7 @@ public class sliderType extends inputType {
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add_compiled_view(LinearLayout parent, dataType[] data){
|
public void add_compiled_view(LinearLayout parent, RawDataType[] data){
|
||||||
LineChart chart = new LineChart(parent.getContext());
|
LineChart chart = new LineChart(parent.getContext());
|
||||||
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
@@ -180,7 +180,7 @@ public class sliderType extends inputType {
|
|||||||
);
|
);
|
||||||
layout.height = 350;
|
layout.height = 350;
|
||||||
chart.setLayoutParams(layout);
|
chart.setLayoutParams(layout);
|
||||||
chart.setBackgroundColor(0xff252025);
|
chart.setBackgroundColor(chart_background);
|
||||||
|
|
||||||
int[] values = new int[max-min+1];
|
int[] values = new int[max-min+1];
|
||||||
|
|
||||||
@@ -202,8 +202,8 @@ public class sliderType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
LineDataSet dataSet = new LineDataSet(entries, name);
|
LineDataSet dataSet = new LineDataSet(entries, name);
|
||||||
dataSet.setColor(Color.BLUE);
|
dataSet.setColor(slider_data);
|
||||||
dataSet.setValueTextColor(Color.BLACK);
|
dataSet.setValueTextColor(dropdown_value_text_1);
|
||||||
dataSet.setDrawCircles(false);
|
dataSet.setDrawCircles(false);
|
||||||
dataSet.setDrawValues(false);
|
dataSet.setDrawValues(false);
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@ public class sliderType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
LineDataSet normalDistSet = new LineDataSet(normalDistEntries, "Normal Distribution");
|
LineDataSet normalDistSet = new LineDataSet(normalDistEntries, "Normal Distribution");
|
||||||
normalDistSet.setColor(Color.RED);
|
normalDistSet.setColor(dropdown_value_text_2);
|
||||||
normalDistSet.setDrawCircles(false);
|
normalDistSet.setDrawCircles(false);
|
||||||
normalDistSet.setDrawValues(false);
|
normalDistSet.setDrawValues(false);
|
||||||
normalDistSet.setLineWidth(2f);
|
normalDistSet.setLineWidth(2f);
|
||||||
@@ -233,14 +233,14 @@ public class sliderType extends inputType {
|
|||||||
chart.setDragEnabled(false);
|
chart.setDragEnabled(false);
|
||||||
chart.setScaleEnabled(false);
|
chart.setScaleEnabled(false);
|
||||||
|
|
||||||
dataSet.setValueTextColor(Color.RED);
|
dataSet.setValueTextColor(dropdown_value_text_2);
|
||||||
|
|
||||||
chart.getXAxis().setTextColor(Color.WHITE);
|
chart.getXAxis().setTextColor(chart_text);
|
||||||
chart.getAxisLeft().setTextColor(Color.WHITE);
|
chart.getAxisLeft().setTextColor(chart_text);
|
||||||
chart.getAxisRight().setTextColor(Color.WHITE);
|
chart.getAxisRight().setTextColor(chart_text);
|
||||||
|
|
||||||
Legend legend = chart.getLegend();
|
Legend legend = chart.getLegend();
|
||||||
legend.setTextColor(Color.WHITE);
|
legend.setTextColor(chart_text);
|
||||||
|
|
||||||
parent.addView(chart);
|
parent.addView(chart);
|
||||||
}
|
}
|
||||||
@@ -248,7 +248,7 @@ public class sliderType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void add_history_view(LinearLayout parent, dataType[] data){
|
public void add_history_view(LinearLayout parent, RawDataType[] data){
|
||||||
LineChart chart = new LineChart(parent.getContext());
|
LineChart chart = new LineChart(parent.getContext());
|
||||||
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
@@ -256,7 +256,7 @@ public class sliderType extends inputType {
|
|||||||
);
|
);
|
||||||
layout.height = 350;
|
layout.height = 350;
|
||||||
chart.setLayoutParams(layout);
|
chart.setLayoutParams(layout);
|
||||||
chart.setBackgroundColor(0xff252025);
|
chart.setBackgroundColor(chart_background);
|
||||||
|
|
||||||
List<Entry> entries = new ArrayList<>();
|
List<Entry> entries = new ArrayList<>();
|
||||||
for (int i = 0; i < data.length; i++){
|
for (int i = 0; i < data.length; i++){
|
||||||
@@ -268,8 +268,8 @@ public class sliderType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
LineDataSet dataSet = new LineDataSet(entries, name);
|
LineDataSet dataSet = new LineDataSet(entries, name);
|
||||||
dataSet.setColor(Color.BLUE);
|
dataSet.setColor(slider_data);
|
||||||
dataSet.setValueTextColor(Color.BLACK);
|
dataSet.setValueTextColor(dropdown_value_text_1);
|
||||||
dataSet.setDrawCircles(false);
|
dataSet.setDrawCircles(false);
|
||||||
dataSet.setDrawValues(false);
|
dataSet.setDrawValues(false);
|
||||||
|
|
||||||
@@ -283,14 +283,14 @@ public class sliderType extends inputType {
|
|||||||
chart.setDragEnabled(false);
|
chart.setDragEnabled(false);
|
||||||
chart.setScaleEnabled(false);
|
chart.setScaleEnabled(false);
|
||||||
|
|
||||||
dataSet.setValueTextColor(Color.RED);
|
dataSet.setValueTextColor(dropdown_value_text_2);
|
||||||
|
|
||||||
chart.getXAxis().setTextColor(Color.WHITE);
|
chart.getXAxis().setTextColor(chart_text);
|
||||||
chart.getAxisLeft().setTextColor(Color.WHITE);
|
chart.getAxisLeft().setTextColor(chart_text);
|
||||||
chart.getAxisRight().setTextColor(Color.WHITE);
|
chart.getAxisRight().setTextColor(chart_text);
|
||||||
|
|
||||||
Legend legend = chart.getLegend();
|
Legend legend = chart.getLegend();
|
||||||
legend.setTextColor(Color.WHITE);
|
legend.setTextColor(chart_text);
|
||||||
|
|
||||||
|
|
||||||
chart.getAxisLeft().setAxisMinimum(min);
|
chart.getAxisLeft().setAxisMinimum(min);
|
||||||
@@ -302,4 +302,12 @@ public class sliderType extends inputType {
|
|||||||
|
|
||||||
parent.addView(chart);
|
parent.addView(chart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addDataToTable(TableLayout parent, Map<Integer, List<RawDataType>> data){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString(RawDataType data){
|
||||||
|
return String.valueOf((int) data.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+116
-57
@@ -1,17 +1,27 @@
|
|||||||
package com.ridgebotics.ridgescout.types.input;
|
package com.ridgebotics.ridgescout.types.input;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.chart_background;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.chart_text;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.dropdown_value_text_1;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.dropdown_value_text_2;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.tally_data;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TableLayout;
|
||||||
|
import android.widget.TableRow;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.types.data.dataType;
|
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||||
import com.ridgebotics.ridgescout.types.data.intType;
|
import com.ridgebotics.ridgescout.types.data.IntType;
|
||||||
import com.ridgebotics.ridgescout.ui.scouting.TallyCounterView;
|
import com.ridgebotics.ridgescout.ui.views.CandlestickHeader;
|
||||||
|
import com.ridgebotics.ridgescout.ui.views.CandlestickView;
|
||||||
|
import com.ridgebotics.ridgescout.ui.data.DataProcessing;
|
||||||
|
import com.ridgebotics.ridgescout.ui.views.TallyCounterView;
|
||||||
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
||||||
import com.github.mikephil.charting.charts.LineChart;
|
import com.github.mikephil.charting.charts.LineChart;
|
||||||
@@ -19,20 +29,23 @@ import com.github.mikephil.charting.components.Legend;
|
|||||||
import com.github.mikephil.charting.data.Entry;
|
import com.github.mikephil.charting.data.Entry;
|
||||||
import com.github.mikephil.charting.data.LineData;
|
import com.github.mikephil.charting.data.LineData;
|
||||||
import com.github.mikephil.charting.data.LineDataSet;
|
import com.github.mikephil.charting.data.LineDataSet;
|
||||||
|
import com.ridgebotics.ridgescout.utility.builders.TextViewBuilder;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class tallyType extends inputType {
|
public class TallyType extends FieldType {
|
||||||
public int get_byte_id() {return tallyType;}
|
public int get_byte_id() {return tallyType;}
|
||||||
public inputTypes getInputType(){return inputTypes.TALLY;}
|
public inputTypes getInputType(){return inputTypes.TALLY;}
|
||||||
public dataType.valueTypes getValueType(){return dataType.valueTypes.NUM;}
|
public RawDataType.valueTypes getValueType(){return RawDataType.valueTypes.NUM;}
|
||||||
public Object get_fallback_value(){return 0;}
|
public Object get_fallback_value(){return 0;}
|
||||||
public tallyType(){}
|
public TallyType(){}
|
||||||
public String get_type_name(){return "Tally";}
|
public String get_type_name(){return "Tally";}
|
||||||
public tallyType(String name, int default_value){
|
public TallyType(String UUID, String name, String description, int default_value){
|
||||||
super(name);
|
super(UUID, name, description);
|
||||||
this.default_value = default_value;
|
this.default_value = default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,18 +53,11 @@ public class tallyType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public byte[] encode() throws ByteBuilder.buildingException {
|
public void encodeData(ByteBuilder bb) throws ByteBuilder.buildingException {
|
||||||
ByteBuilder bb = new ByteBuilder();
|
bb.addInt((int) default_value);
|
||||||
bb.addString(name);
|
|
||||||
bb.addInt((int)default_value);
|
|
||||||
return bb.build();
|
|
||||||
}
|
}
|
||||||
public void decode(byte[] bytes) throws BuiltByteParser.byteParsingExeption {
|
public void decodeData(ArrayList<BuiltByteParser.parsedObject> objects) {
|
||||||
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
default_value = objects.get(0).get();
|
||||||
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
|
||||||
|
|
||||||
name = (String) objects.get(0).get();
|
|
||||||
default_value = objects.get(1).get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -60,7 +66,7 @@ public class tallyType extends inputType {
|
|||||||
|
|
||||||
public TallyCounterView tally = null;
|
public TallyCounterView tally = null;
|
||||||
|
|
||||||
public View createView(Context context, Function<dataType, Integer> onUpdate){
|
public View createView(Context context, Function<RawDataType, Integer> onUpdate){
|
||||||
tally = new TallyCounterView(context);
|
tally = new TallyCounterView(context);
|
||||||
tally.setOnCountChangedListener(n -> onUpdate.apply(getViewValue()));
|
tally.setOnCountChangedListener(n -> onUpdate.apply(getViewValue()));
|
||||||
|
|
||||||
@@ -72,8 +78,7 @@ public class tallyType extends inputType {
|
|||||||
|
|
||||||
public void setViewValue(Object value) {
|
public void setViewValue(Object value) {
|
||||||
if(tally == null) return;
|
if(tally == null) return;
|
||||||
System.out.println(value);
|
if(IntType.isNull((int)value)){
|
||||||
if(intType.isNull((int)value)){
|
|
||||||
nullify();
|
nullify();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -86,10 +91,10 @@ public class tallyType extends inputType {
|
|||||||
isBlank = true;
|
isBlank = true;
|
||||||
tally.setVisibility(View.GONE);
|
tally.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
public dataType getViewValue(){
|
public RawDataType getViewValue(){
|
||||||
if(tally == null) return null;
|
if(tally == null) return null;
|
||||||
if(tally.getVisibility() == View.GONE) return intType.newNull(name);
|
if(tally.getVisibility() == View.GONE) return IntType.newNull(name);
|
||||||
return new intType(name, tally.getValue());
|
return new IntType(name, tally.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -97,18 +102,13 @@ public class tallyType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void add_individual_view(LinearLayout parent, dataType data){
|
public void add_individual_view(LinearLayout parent, RawDataType data){
|
||||||
if(data.isNull()) return;
|
if(data.isNull()) return;
|
||||||
|
parent.addView(new TextViewBuilder(parent.getContext(), String.valueOf((int) data.get()))
|
||||||
TextView tv = new TextView(parent.getContext());
|
.layout_match_wrap()
|
||||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
.align_left()
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
.size(24)
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
.build());
|
||||||
));
|
|
||||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
|
||||||
tv.setText(String.valueOf((int) data.get()));
|
|
||||||
tv.setTextSize(24);
|
|
||||||
parent.addView(tv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ public class tallyType extends inputType {
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int findMin(dataType[] data){
|
private static int findMin(RawDataType[] data){
|
||||||
int min = (int)data[0].get();
|
int min = (int)data[0].get();
|
||||||
for(int i = 1; i < data.length; i++)
|
for(int i = 1; i < data.length; i++)
|
||||||
if((int)data[i].get() < min)
|
if((int)data[i].get() < min)
|
||||||
@@ -152,7 +152,7 @@ public class tallyType extends inputType {
|
|||||||
return min;
|
return min;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int findMax(dataType[] data){
|
private static int findMax(RawDataType[] data){
|
||||||
int max = (int)data[0].get();
|
int max = (int)data[0].get();
|
||||||
for(int i = 1; i < data.length; i++)
|
for(int i = 1; i < data.length; i++)
|
||||||
if((int)data[i].get() > max)
|
if((int)data[i].get() > max)
|
||||||
@@ -160,7 +160,7 @@ public class tallyType extends inputType {
|
|||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add_compiled_view(LinearLayout parent, dataType[] data){
|
public void add_compiled_view(LinearLayout parent, RawDataType[] data){
|
||||||
LineChart chart = new LineChart(parent.getContext());
|
LineChart chart = new LineChart(parent.getContext());
|
||||||
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
@@ -193,8 +193,8 @@ public class tallyType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
LineDataSet dataSet = new LineDataSet(entries, name);
|
LineDataSet dataSet = new LineDataSet(entries, name);
|
||||||
dataSet.setColor(Color.BLUE);
|
dataSet.setColor(tally_data);
|
||||||
dataSet.setValueTextColor(Color.BLACK);
|
dataSet.setValueTextColor(dropdown_value_text_1);
|
||||||
dataSet.setDrawCircles(false);
|
dataSet.setDrawCircles(false);
|
||||||
dataSet.setDrawValues(false);
|
dataSet.setDrawValues(false);
|
||||||
|
|
||||||
@@ -209,7 +209,7 @@ public class tallyType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
LineDataSet normalDistSet = new LineDataSet(normalDistEntries, "Normal Distribution");
|
LineDataSet normalDistSet = new LineDataSet(normalDistEntries, "Normal Distribution");
|
||||||
normalDistSet.setColor(Color.RED);
|
normalDistSet.setColor(dropdown_value_text_2);
|
||||||
normalDistSet.setDrawCircles(false);
|
normalDistSet.setDrawCircles(false);
|
||||||
normalDistSet.setDrawValues(false);
|
normalDistSet.setDrawValues(false);
|
||||||
normalDistSet.setLineWidth(2f);
|
normalDistSet.setLineWidth(2f);
|
||||||
@@ -224,14 +224,14 @@ public class tallyType extends inputType {
|
|||||||
chart.setDragEnabled(false);
|
chart.setDragEnabled(false);
|
||||||
chart.setScaleEnabled(false);
|
chart.setScaleEnabled(false);
|
||||||
|
|
||||||
dataSet.setValueTextColor(Color.RED);
|
dataSet.setValueTextColor(dropdown_value_text_2);
|
||||||
|
|
||||||
chart.getXAxis().setTextColor(Color.WHITE);
|
chart.getXAxis().setTextColor(chart_text);
|
||||||
chart.getAxisLeft().setTextColor(Color.WHITE);
|
chart.getAxisLeft().setTextColor(chart_text);
|
||||||
chart.getAxisRight().setTextColor(Color.WHITE);
|
chart.getAxisRight().setTextColor(chart_text);
|
||||||
|
|
||||||
Legend legend = chart.getLegend();
|
Legend legend = chart.getLegend();
|
||||||
legend.setTextColor(Color.WHITE);
|
legend.setTextColor(chart_text);
|
||||||
|
|
||||||
parent.addView(chart);
|
parent.addView(chart);
|
||||||
}
|
}
|
||||||
@@ -239,7 +239,7 @@ public class tallyType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void add_history_view(LinearLayout parent, dataType[] data){
|
public void add_history_view(LinearLayout parent, RawDataType[] data){
|
||||||
LineChart chart = new LineChart(parent.getContext());
|
LineChart chart = new LineChart(parent.getContext());
|
||||||
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
@@ -247,7 +247,7 @@ public class tallyType extends inputType {
|
|||||||
);
|
);
|
||||||
layout.height = 350;
|
layout.height = 350;
|
||||||
chart.setLayoutParams(layout);
|
chart.setLayoutParams(layout);
|
||||||
chart.setBackgroundColor(0xff252025);
|
chart.setBackgroundColor(chart_background);
|
||||||
|
|
||||||
int min = findMin(data);
|
int min = findMin(data);
|
||||||
int max = findMax(data);
|
int max = findMax(data);
|
||||||
@@ -262,8 +262,8 @@ public class tallyType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
LineDataSet dataSet = new LineDataSet(entries, name);
|
LineDataSet dataSet = new LineDataSet(entries, name);
|
||||||
dataSet.setColor(Color.BLUE);
|
dataSet.setColor(tally_data);
|
||||||
dataSet.setValueTextColor(Color.BLACK);
|
dataSet.setValueTextColor(dropdown_value_text_1);
|
||||||
dataSet.setDrawCircles(false);
|
dataSet.setDrawCircles(false);
|
||||||
dataSet.setDrawValues(false);
|
dataSet.setDrawValues(false);
|
||||||
|
|
||||||
@@ -277,14 +277,14 @@ public class tallyType extends inputType {
|
|||||||
chart.setDragEnabled(false);
|
chart.setDragEnabled(false);
|
||||||
chart.setScaleEnabled(false);
|
chart.setScaleEnabled(false);
|
||||||
|
|
||||||
dataSet.setValueTextColor(Color.RED);
|
dataSet.setValueTextColor(dropdown_value_text_2);
|
||||||
|
|
||||||
chart.getXAxis().setTextColor(Color.WHITE);
|
chart.getXAxis().setTextColor(chart_text);
|
||||||
chart.getAxisLeft().setTextColor(Color.WHITE);
|
chart.getAxisLeft().setTextColor(chart_text);
|
||||||
chart.getAxisRight().setTextColor(Color.WHITE);
|
chart.getAxisRight().setTextColor(chart_text);
|
||||||
|
|
||||||
Legend legend = chart.getLegend();
|
Legend legend = chart.getLegend();
|
||||||
legend.setTextColor(Color.WHITE);
|
legend.setTextColor(chart_text);
|
||||||
|
|
||||||
|
|
||||||
chart.getAxisLeft().setAxisMinimum(min);
|
chart.getAxisLeft().setAxisMinimum(min);
|
||||||
@@ -296,5 +296,64 @@ public class tallyType extends inputType {
|
|||||||
|
|
||||||
parent.addView(chart);
|
parent.addView(chart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addDataToTable(TableLayout parent, Map<Integer, List<RawDataType>> data){
|
||||||
|
int[] tmp_abs_bounds = DataProcessing.getNumberBounds(data);
|
||||||
|
int absmin = tmp_abs_bounds[0];
|
||||||
|
int absmax = tmp_abs_bounds[1];
|
||||||
|
|
||||||
|
//(int[]) teamData.get(i).get())[0];
|
||||||
|
// AlertManager.alert("Results","Min: " + min + " Max: " + max);
|
||||||
|
|
||||||
|
parent.removeAllViews();
|
||||||
|
|
||||||
|
List<CandlestickView> views = new ArrayList<>();
|
||||||
|
|
||||||
|
for(Integer teamNum : data.keySet()){
|
||||||
|
CandlestickView candlestickView = new CandlestickView(parent.getContext());
|
||||||
|
candlestickView.fromTeamData(data.get(teamNum), teamNum, absmin, absmax);
|
||||||
|
views.add(candlestickView);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TableRow row = new TableRow(parent.getContext());
|
||||||
|
|
||||||
|
// Make candlestick chart fill full width
|
||||||
|
parent.setColumnStretchable(1, true);
|
||||||
|
|
||||||
|
// Fill in top left cell
|
||||||
|
row.addView(new View(parent.getContext()));
|
||||||
|
|
||||||
|
CandlestickHeader header = new CandlestickHeader(parent.getContext());
|
||||||
|
header.setScale(absmin, absmax);
|
||||||
|
row.addView(header);
|
||||||
|
|
||||||
|
parent.addView(row);
|
||||||
|
|
||||||
|
// parent.addView(new );
|
||||||
|
|
||||||
|
try {
|
||||||
|
Collections.sort(views, (a, b) -> (int) ((b.average - a.average) * 50.f));
|
||||||
|
}catch (Exception e){}
|
||||||
|
|
||||||
|
for(int i = 0; i < views.size(); i++){
|
||||||
|
row = new TableRow(parent.getContext());
|
||||||
|
CandlestickView view = views.get(i);
|
||||||
|
|
||||||
|
row.addView(new TextViewBuilder(parent.getContext(), String.valueOf(view.teamNum))
|
||||||
|
.align_center()
|
||||||
|
.padding(10)
|
||||||
|
.h6()
|
||||||
|
.build());
|
||||||
|
|
||||||
|
row.addView(view);
|
||||||
|
|
||||||
|
parent.addView(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString(RawDataType data){
|
||||||
|
return String.valueOf((int) data.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+55
-54
@@ -1,7 +1,12 @@
|
|||||||
package com.ridgebotics.ridgescout.types.input;
|
package com.ridgebotics.ridgescout.types.input;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.chart_background;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.chart_text;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.dropdown_value_text_1;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.dropdown_value_text_2;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.text_data;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
@@ -10,10 +15,11 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TableLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.types.data.dataType;
|
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||||
import com.ridgebotics.ridgescout.types.data.stringType;
|
import com.ridgebotics.ridgescout.types.data.StringType;
|
||||||
import com.ridgebotics.ridgescout.utility.SentimentAnalysis;
|
import com.ridgebotics.ridgescout.utility.SentimentAnalysis;
|
||||||
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
||||||
@@ -22,20 +28,22 @@ import com.github.mikephil.charting.components.Legend;
|
|||||||
import com.github.mikephil.charting.data.Entry;
|
import com.github.mikephil.charting.data.Entry;
|
||||||
import com.github.mikephil.charting.data.LineData;
|
import com.github.mikephil.charting.data.LineData;
|
||||||
import com.github.mikephil.charting.data.LineDataSet;
|
import com.github.mikephil.charting.data.LineDataSet;
|
||||||
|
import com.ridgebotics.ridgescout.utility.builders.TextViewBuilder;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class textType extends inputType {
|
public class TextType extends FieldType {
|
||||||
|
|
||||||
public int get_byte_id() {return notesType;}
|
public int get_byte_id() {return notesType;}
|
||||||
public inputTypes getInputType(){return inputTypes.NOTES_INPUT;}
|
public inputTypes getInputType(){return inputTypes.NOTES_INPUT;}
|
||||||
public dataType.valueTypes getValueType(){return dataType.valueTypes.STRING;}
|
public RawDataType.valueTypes getValueType(){return RawDataType.valueTypes.STRING;}
|
||||||
public Object get_fallback_value(){return "<no-notes>";}
|
public Object get_fallback_value(){return "<no-notes>";}
|
||||||
public textType(){}
|
public TextType(){}
|
||||||
public textType(String name, String default_text){
|
public TextType(String UUID, String name, String description, String default_text){
|
||||||
super(name);
|
super(UUID, name, description);
|
||||||
this.default_value = default_text;
|
this.default_value = default_text;
|
||||||
}
|
}
|
||||||
public String get_type_name(){return "Text";}
|
public String get_type_name(){return "Text";}
|
||||||
@@ -46,18 +54,11 @@ public class textType extends inputType {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public byte[] encode() throws ByteBuilder.buildingException {
|
public void encodeData(ByteBuilder bb) throws ByteBuilder.buildingException {
|
||||||
ByteBuilder bb = new ByteBuilder();
|
|
||||||
bb.addString(name);
|
|
||||||
bb.addString((String) default_value);
|
bb.addString((String) default_value);
|
||||||
return bb.build();
|
|
||||||
}
|
}
|
||||||
public void decode(byte[] bytes) throws BuiltByteParser.byteParsingExeption {
|
public void decodeData(ArrayList<BuiltByteParser.parsedObject> objects) {
|
||||||
BuiltByteParser bbp = new BuiltByteParser(bytes);
|
default_value = objects.get(0).get();
|
||||||
ArrayList<BuiltByteParser.parsedObject> objects = bbp.parse();
|
|
||||||
|
|
||||||
name = (String) objects.get(0).get();
|
|
||||||
default_value = objects.get(1).get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -75,7 +76,7 @@ public class textType extends inputType {
|
|||||||
|
|
||||||
public EditText text = null;
|
public EditText text = null;
|
||||||
|
|
||||||
public View createView(Context context, Function<dataType, Integer> onUpdate){
|
public View createView(Context context, Function<RawDataType, Integer> onUpdate){
|
||||||
text = new EditText(context);
|
text = new EditText(context);
|
||||||
text.setText((String)default_value);
|
text.setText((String)default_value);
|
||||||
text.addTextChangedListener(new TextWatcher() {
|
text.addTextChangedListener(new TextWatcher() {
|
||||||
@@ -89,7 +90,7 @@ public class textType extends inputType {
|
|||||||
}
|
}
|
||||||
public void setViewValue(Object value) {
|
public void setViewValue(Object value) {
|
||||||
if(text == null) return;
|
if(text == null) return;
|
||||||
if(stringType.isNull((String) value)){
|
if(StringType.isNull((String) value)){
|
||||||
nullify();
|
nullify();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -101,26 +102,22 @@ public class textType extends inputType {
|
|||||||
isBlank = true;
|
isBlank = true;
|
||||||
text.setVisibility(View.GONE);
|
text.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
public dataType getViewValue(){
|
public RawDataType getViewValue(){
|
||||||
if(text == null) return null;
|
if(text == null) return null;
|
||||||
if(text.getVisibility() == View.GONE) return new stringType(name, stringType.nullval);
|
if(text.getVisibility() == View.GONE) return new StringType(name, StringType.nullval);
|
||||||
return new stringType(name, text.getText().toString());
|
return new StringType(name, text.getText().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void add_individual_view(LinearLayout parent, dataType data){
|
public void add_individual_view(LinearLayout parent, RawDataType data){
|
||||||
if(data.isNull()) return;
|
if(data.isNull()) return;
|
||||||
TextView tv = new TextView(parent.getContext());
|
parent.addView(new TextViewBuilder(parent.getContext(), (String) data.get())
|
||||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
.layout_match_wrap()
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
.align_left()
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
.size(18)
|
||||||
));
|
.build());
|
||||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
|
||||||
tv.setText((String) data.get());
|
|
||||||
tv.setTextSize(18);
|
|
||||||
parent.addView(tv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -140,36 +137,31 @@ public class textType extends inputType {
|
|||||||
|
|
||||||
TextView positive_text;
|
TextView positive_text;
|
||||||
|
|
||||||
public void add_compiled_view(LinearLayout parent, dataType[] data) {
|
public void add_compiled_view(LinearLayout parent, RawDataType[] data) {
|
||||||
positive_mean = 0;
|
positive_mean = 0;
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
||||||
positive_text = new TextView(parent.getContext());
|
positive_text = new TextViewBuilder(parent.getContext())
|
||||||
positive_text.setLayoutParams(new FrameLayout.LayoutParams(
|
.align_center()
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
.size(20)
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
.build();
|
||||||
));
|
|
||||||
positive_text.setGravity(Gravity.CENTER_HORIZONTAL);
|
|
||||||
positive_text.setTextSize(20);
|
|
||||||
parent.addView(positive_text);
|
parent.addView(positive_text);
|
||||||
|
|
||||||
for (int i = 0; i < data.length; i++){
|
for (int i = 0; i < data.length; i++){
|
||||||
if (!data[i].isNull()) {
|
if (!data[i].isNull()) {
|
||||||
SentimentAnalysis.analyse((String) data[i].get(), new SentimentAnalysis.resultCallback() {
|
SentimentAnalysis.analyse((String) data[i].get(), sentiment -> {
|
||||||
@Override
|
|
||||||
public void onFinish(float sentiment) {
|
|
||||||
positive_mean += sentiment;
|
positive_mean += sentiment;
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
positive_text.setText("Sentiment: " + (positive_mean / count));
|
positive_text.setText("Sentiment: " + (positive_mean / count));
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void add_history_view(LinearLayout parent, dataType[] data){
|
public void add_history_view(LinearLayout parent, RawDataType[] data){
|
||||||
LineChart chart = new LineChart(parent.getContext());
|
LineChart chart = new LineChart(parent.getContext());
|
||||||
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
@@ -177,7 +169,7 @@ public class textType extends inputType {
|
|||||||
);
|
);
|
||||||
layout.height = 350;
|
layout.height = 350;
|
||||||
chart.setLayoutParams(layout);
|
chart.setLayoutParams(layout);
|
||||||
chart.setBackgroundColor(0xff252025);
|
chart.setBackgroundColor(chart_background);
|
||||||
|
|
||||||
|
|
||||||
List<Entry> entries = new ArrayList<>();
|
List<Entry> entries = new ArrayList<>();
|
||||||
@@ -192,11 +184,11 @@ public class textType extends inputType {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
LineDataSet dataSet = new LineDataSet(entries, "Sentiment");
|
LineDataSet dataSet = new LineDataSet(entries, "Sentiment");
|
||||||
dataSet.setColor(Color.BLUE);
|
dataSet.setColor(text_data);
|
||||||
dataSet.setValueTextColor(Color.BLACK);
|
dataSet.setValueTextColor(dropdown_value_text_1);
|
||||||
dataSet.setDrawCircles(false);
|
dataSet.setDrawCircles(false);
|
||||||
dataSet.setDrawValues(false);
|
dataSet.setDrawValues(false);
|
||||||
dataSet.setValueTextColor(Color.RED);
|
dataSet.setValueTextColor(dropdown_value_text_2);
|
||||||
|
|
||||||
|
|
||||||
LineData lineData = new LineData(dataSet);
|
LineData lineData = new LineData(dataSet);
|
||||||
@@ -210,9 +202,9 @@ public class textType extends inputType {
|
|||||||
chart.setScaleEnabled(false);
|
chart.setScaleEnabled(false);
|
||||||
|
|
||||||
|
|
||||||
chart.getXAxis().setTextColor(Color.WHITE);
|
chart.getXAxis().setTextColor(chart_text);
|
||||||
chart.getAxisLeft().setTextColor(Color.WHITE);
|
chart.getAxisLeft().setTextColor(chart_text);
|
||||||
chart.getAxisRight().setTextColor(Color.WHITE);
|
chart.getAxisRight().setTextColor(chart_text);
|
||||||
|
|
||||||
chart.getAxisLeft().setAxisMinimum(0.f);
|
chart.getAxisLeft().setAxisMinimum(0.f);
|
||||||
chart.getAxisLeft().setAxisMaximum(1.f);
|
chart.getAxisLeft().setAxisMaximum(1.f);
|
||||||
@@ -221,11 +213,20 @@ public class textType extends inputType {
|
|||||||
chart.getAxisRight().setAxisMaximum(1.f);
|
chart.getAxisRight().setAxisMaximum(1.f);
|
||||||
|
|
||||||
Legend legend = chart.getLegend();
|
Legend legend = chart.getLegend();
|
||||||
legend.setTextColor(Color.WHITE);
|
legend.setTextColor(chart_text);
|
||||||
|
|
||||||
chart.invalidate();
|
chart.invalidate();
|
||||||
parent.addView(chart);
|
parent.addView(chart);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
public void addDataToTable(TableLayout parent, Map<Integer, List<RawDataType>> data){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString(RawDataType data){
|
||||||
|
return String.valueOf(data.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
package com.ridgebotics.ridgescout.types.input;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.types.data.dataType;
|
|
||||||
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
|
||||||
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public abstract class inputType {
|
|
||||||
public static final int slider_type_id = 255;
|
|
||||||
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,
|
|
||||||
NUMBER,
|
|
||||||
CHECKBOX,
|
|
||||||
FIELDPOS
|
|
||||||
}
|
|
||||||
public String name;
|
|
||||||
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){
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract String get_type_name();
|
|
||||||
|
|
||||||
public abstract byte[] encode() throws ByteBuilder.buildingException;
|
|
||||||
public abstract void decode(byte[] bytes) throws BuiltByteParser.byteParsingExeption;
|
|
||||||
|
|
||||||
// public abstract dataType[] getConfig();
|
|
||||||
// public abstract void setConfig(dataType[] config);
|
|
||||||
|
|
||||||
public abstract View createView(Context context, Function<dataType, Integer> onUpdate);
|
|
||||||
public boolean isBlank = false;
|
|
||||||
public abstract void nullify();
|
|
||||||
public void setViewValue(dataType type){setViewValue(type.get());}
|
|
||||||
public abstract void setViewValue(Object value);
|
|
||||||
public abstract dataType getViewValue();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// private enum parameterTypeEnum {
|
|
||||||
// paramNumber,
|
|
||||||
// paramString,
|
|
||||||
// paramStringArray
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public static class parameterType {
|
|
||||||
// public String name;
|
|
||||||
// public parameterTypeEnum id;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public static class paramNumber extends parameterType {
|
|
||||||
// public int val;
|
|
||||||
// public paramNumber(String name, int val){
|
|
||||||
// this.name = name + " (Number)";
|
|
||||||
// this.val = val;
|
|
||||||
// this.id = parameterTypeEnum.paramNumber;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public static class paramString extends parameterType {
|
|
||||||
// public String val;
|
|
||||||
// public paramString(String name, String val){
|
|
||||||
// this.name = name + " (String)";
|
|
||||||
// this.val = val;
|
|
||||||
// this.id = parameterTypeEnum.paramString;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public static class paramStringArray extends parameterType {
|
|
||||||
// public String[] val;
|
|
||||||
// public paramStringArray(String name, String[] val){
|
|
||||||
// this.name = name + " (String array)";
|
|
||||||
// this.val = val;
|
|
||||||
// this.id = parameterTypeEnum.paramStringArray;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public abstract parameterType[] getDefaultParameters();
|
|
||||||
|
|
||||||
|
|
||||||
public abstract void add_individual_view(LinearLayout parent, dataType data);
|
|
||||||
|
|
||||||
|
|
||||||
public abstract void add_compiled_view(LinearLayout parent, dataType[] data);
|
|
||||||
|
|
||||||
|
|
||||||
public abstract void add_history_view(LinearLayout parent, dataType[] data);
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
package com.ridgebotics.ridgescout.ui;
|
|
||||||
|
|
||||||
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
|
|
||||||
import static com.ridgebotics.ridgescout.utility.DataManager.event;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.TableLayout;
|
|
||||||
import android.widget.TableRow;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.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;
|
|
||||||
|
|
||||||
public class TeamSelectorFragment extends Fragment {
|
|
||||||
private FragmentTeamSelectorBinding binding;
|
|
||||||
|
|
||||||
private static boolean pits_mode;
|
|
||||||
public static void setPits_mode(boolean mode){
|
|
||||||
pits_mode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static onTeamSelected onSelect = new onTeamSelected() {@Override public void onSelect(TeamSelectorFragment self, frcTeam team) {}};
|
|
||||||
|
|
||||||
public interface onTeamSelected {
|
|
||||||
void onSelect(TeamSelectorFragment self, frcTeam team);
|
|
||||||
}
|
|
||||||
public static void setOnSelect(onTeamSelected tmponSelect){
|
|
||||||
onSelect = tmponSelect;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
|
||||||
@Nullable Bundle savedInstanceState) {
|
|
||||||
binding = FragmentTeamSelectorBinding.inflate(inflater, container, false);
|
|
||||||
|
|
||||||
// event = fileEditor.g
|
|
||||||
DataManager.reload_event();
|
|
||||||
|
|
||||||
if(evcode == null || evcode.equals("unset")){
|
|
||||||
AlertManager.error("You somehow have not loaded an event!");
|
|
||||||
return binding.getRoot();
|
|
||||||
}
|
|
||||||
|
|
||||||
load_teams();
|
|
||||||
|
|
||||||
|
|
||||||
return binding.getRoot();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load_teams(){
|
|
||||||
// binding.pitFileIndicator.setVisibility(View.GONE);
|
|
||||||
// binding.pitTeamName.setVisibility(View.GONE);
|
|
||||||
// binding.pitTeamDescription.setVisibility(View.GONE);
|
|
||||||
//
|
|
||||||
// clear_fields();
|
|
||||||
|
|
||||||
|
|
||||||
int[] teamNums = new int[event.teams.size()];
|
|
||||||
|
|
||||||
for(int i = 0 ; i < event.teams.size(); i++){
|
|
||||||
teamNums[i] = event.teams.get(i).teamNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
Arrays.sort(teamNums);
|
|
||||||
|
|
||||||
TableLayout table = new TableLayout(getContext());
|
|
||||||
table.setStretchAllColumns(true);
|
|
||||||
binding.teams.addView(table);
|
|
||||||
|
|
||||||
|
|
||||||
for(int i = 0; i < event.teams.size(); i++){
|
|
||||||
frcTeam team = null;
|
|
||||||
for(int a = 0 ; a < event.teams.size(); a++){
|
|
||||||
if(event.teams.get(a).teamNumber == teamNums[i]){
|
|
||||||
team = event.teams.get(a);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TableRow tr = new TableRow(getContext());
|
|
||||||
TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams(
|
|
||||||
FrameLayout.LayoutParams.WRAP_CONTENT,
|
|
||||||
FrameLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
);
|
|
||||||
rowParams.setMargins(20,20,20,20);
|
|
||||||
tr.setLayoutParams(rowParams);
|
|
||||||
tr.setPadding(20,20,20,20);
|
|
||||||
table.addView(tr);
|
|
||||||
|
|
||||||
if(!pits_mode || fileEditor.fileExist(evcode + "-" + team.teamNumber + ".pitscoutdata")){
|
|
||||||
tr.setBackgroundColor(0x3000FF00);
|
|
||||||
}else{
|
|
||||||
tr.setBackgroundColor(0x30FF0000);
|
|
||||||
}
|
|
||||||
|
|
||||||
TextView tv = new TextView(getContext());
|
|
||||||
tv.setText(String.valueOf(team.teamNumber));
|
|
||||||
tv.setTextSize(20);
|
|
||||||
tr.addView(tv);
|
|
||||||
|
|
||||||
tv = new TextView(getContext());
|
|
||||||
tv.setText(team.teamName);
|
|
||||||
tv.setTextSize(16);
|
|
||||||
tr.addView(tv);
|
|
||||||
|
|
||||||
frcTeam finalTeam = team;
|
|
||||||
tr.setOnClickListener(v -> {
|
|
||||||
onSelect.onSelect(this, finalTeam);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package com.ridgebotics.ridgescout.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.ridgebotics.ridgescout.databinding.FragmentDataCompareBinding;
|
|
||||||
|
|
||||||
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,7 +1,14 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.data;
|
package com.ridgebotics.ridgescout.ui.data;
|
||||||
|
|
||||||
|
|
||||||
import static androidx.navigation.fragment.FragmentKt.findNavController;
|
import static android.view.View.GONE;
|
||||||
|
import static android.view.View.VISIBLE;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.datafragment_option_1;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.datafragment_option_2;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.DataManager.event;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.DataManager.match_latest_values;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -13,67 +20,119 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.R;
|
|
||||||
import com.ridgebotics.ridgescout.utility.settingsManager;
|
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentDataBinding;
|
|
||||||
import com.ridgebotics.ridgescout.types.frcTeam;
|
import com.ridgebotics.ridgescout.types.frcTeam;
|
||||||
import com.ridgebotics.ridgescout.ui.TeamSelectorFragment;
|
import com.ridgebotics.ridgescout.ui.views.FieldBorderedRow;
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
import com.ridgebotics.ridgescout.ui.views.TeamListOption;
|
||||||
import com.ridgebotics.ridgescout.types.frcEvent;
|
import com.ridgebotics.ridgescout.utility.DataManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.SettingsManager;
|
||||||
|
import com.ridgebotics.ridgescout.databinding.FragmentDataBinding;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
// Fragment for the menu of the data tab.
|
||||||
|
// Shows either by field type or by team.
|
||||||
|
// This is held in a sub-fragment under DataParentFragment
|
||||||
public class DataFragment extends Fragment {
|
public class DataFragment extends Fragment {
|
||||||
|
|
||||||
private FragmentDataBinding binding;
|
private FragmentDataBinding binding;
|
||||||
|
private int option = 0;
|
||||||
|
|
||||||
|
|
||||||
private boolean submenu = false;
|
|
||||||
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
@Nullable Bundle savedInstanceState) {
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
|
||||||
binding = FragmentDataBinding.inflate(inflater, container, false);
|
binding = FragmentDataBinding.inflate(inflater, container, false);
|
||||||
|
binding.table.setStretchAllColumns(true);
|
||||||
View root = binding.getRoot();
|
View root = binding.getRoot();
|
||||||
|
|
||||||
String evcode = settingsManager.getEVCode();
|
if(evcode == null || evcode.equals("unset") || event == null){
|
||||||
|
binding.noEventError.setVisibility(VISIBLE);
|
||||||
|
binding.dataTypeDropdown.setVisibility(GONE);
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
binding.fieldsButton.setOnClickListener(v -> {
|
option = SettingsManager.getDataMode();
|
||||||
findNavController(this).navigate(R.id.action_navigation_data_to_navigation_data_fields_chooser);
|
|
||||||
|
binding.dataTypeDropdown.setTitle("Data type");
|
||||||
|
binding.dataTypeDropdown.setOptions(List.of(new String[]{
|
||||||
|
"By Team", "By Data Field"
|
||||||
|
}), option);
|
||||||
|
binding.dataTypeDropdown.setOnClickListener((item, index) -> {
|
||||||
|
option = index;
|
||||||
|
SettingsManager.setDataMode(option);
|
||||||
|
reload_views();
|
||||||
});
|
});
|
||||||
|
|
||||||
if(evcode.equals("unset")){
|
reload_views();
|
||||||
binding.noEventError.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
binding.buttons.setVisibility(View.VISIBLE);
|
|
||||||
binding.teamsButton.setEnabled(false);
|
|
||||||
binding.compareButton.setEnabled(false);
|
|
||||||
binding.reportButton.setEnabled(false);
|
|
||||||
binding.fieldsButton.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
frcEvent event = frcEvent.decode(fileEditor.readFile(evcode + ".eventdata"));
|
public void reload_views(){
|
||||||
|
binding.table.removeViews(1, binding.table.getChildCount()-1);
|
||||||
|
|
||||||
binding.teamsButton.setOnClickListener(v -> {
|
switch (option) {
|
||||||
TeamSelectorFragment.setPits_mode(false);
|
case 0:
|
||||||
TeamSelectorFragment.setOnSelect(new TeamSelectorFragment.onTeamSelected() {
|
load_teams();
|
||||||
@Override
|
break;
|
||||||
public void onSelect(TeamSelectorFragment self, frcTeam team) {
|
case 1:
|
||||||
TeamsFragment.setTeam(team);
|
load_fields();
|
||||||
findNavController(self).navigate(R.id.action_navigation_team_selector_to_navigation_data_teams);
|
break;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
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 -> {
|
public void load_teams(){
|
||||||
findNavController(this).navigate(R.id.action_navigation_data_to_navigation_data_report_selector);
|
|
||||||
});
|
|
||||||
|
|
||||||
return root;
|
int[] teamNums = new int[event.teams.size()];
|
||||||
|
|
||||||
|
for(int i = 0 ; i < event.teams.size(); i++){
|
||||||
|
teamNums[i] = event.teams.get(i).teamNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
Arrays.sort(teamNums);
|
||||||
|
|
||||||
|
for(int i = 0; i < event.teams.size(); i++){
|
||||||
|
frcTeam team = null;
|
||||||
|
for(int a = 0 ; a < event.teams.size(); a++){
|
||||||
|
if(event.teams.get(a).teamNumber == teamNums[i]){
|
||||||
|
team = event.teams.get(a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert team != null;
|
||||||
|
|
||||||
|
TeamListOption teamRow = new TeamListOption(getContext());
|
||||||
|
binding.table.addView(teamRow);
|
||||||
|
teamRow.fromTeam(team);
|
||||||
|
|
||||||
|
frcTeam finalTeam = team;
|
||||||
|
teamRow.setOnClickListener(v -> {
|
||||||
|
TeamsFragment.setTeam(finalTeam);
|
||||||
|
((DataParentFragment) getParentFragment()).moveToFragment(new TeamsFragment());
|
||||||
|
// findNavController(this).navigate(R.id.action_navigation_data_parent_to_navigation_data_teams);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void load_fields(){
|
||||||
|
DataManager.reload_match_fields();
|
||||||
|
|
||||||
|
if(match_latest_values == null) return;
|
||||||
|
|
||||||
|
for(int i = 0; i < match_latest_values.length; i++){
|
||||||
|
FieldBorderedRow tr = new FieldBorderedRow(getContext());
|
||||||
|
tr.fromField(match_latest_values[i]);
|
||||||
|
tr.setColor(i % 2 == 0 ? datafragment_option_1 : datafragment_option_2);
|
||||||
|
binding.table.addView(tr);
|
||||||
|
|
||||||
|
final int fi = i;
|
||||||
|
tr.setOnClickListener(v -> {
|
||||||
|
FieldDataFragment.setFieldIndex(fi);
|
||||||
|
((DataParentFragment) getParentFragment()).moveToFragment(new FieldDataFragment());
|
||||||
|
// findNavController(get).navigate(R.id.action_navigation_data_parent_to_navigation_data_field_data);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,183 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.data;
|
||||||
|
|
||||||
|
|
||||||
|
import static android.content.Context.CLIPBOARD_SERVICE;
|
||||||
|
import static android.view.View.GONE;
|
||||||
|
import static android.view.View.VISIBLE;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.DataManager.event;
|
||||||
|
|
||||||
|
import android.content.ClipData;
|
||||||
|
import android.content.ClipboardManager;
|
||||||
|
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 androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.R;
|
||||||
|
import com.ridgebotics.ridgescout.databinding.FragmentDataParentBinding;
|
||||||
|
import com.ridgebotics.ridgescout.types.frcMatch;
|
||||||
|
import com.ridgebotics.ridgescout.types.frcTeam;
|
||||||
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.AutoSaveManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.DataManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.SettingsManager;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
// Holds the scouting data editor aswell as the sub-fragment for the scouting data browser
|
||||||
|
public class DataParentFragment extends Fragment {
|
||||||
|
|
||||||
|
private FragmentDataParentBinding binding;
|
||||||
|
private DataFragment dataFragment;
|
||||||
|
|
||||||
|
|
||||||
|
private boolean editBoxEnabled = true;
|
||||||
|
private int teamNum = SettingsManager.getTeamNum();
|
||||||
|
private frcMatch[] ourMatches;
|
||||||
|
private int matchIndex = 0;
|
||||||
|
|
||||||
|
private AutoSaveManager asm;
|
||||||
|
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
binding = FragmentDataParentBinding.inflate(inflater, container, false);
|
||||||
|
DataManager.reload_event();
|
||||||
|
|
||||||
|
if (savedInstanceState == null && dataFragment == null){
|
||||||
|
dataFragment = new DataFragment();
|
||||||
|
|
||||||
|
//add child fragment
|
||||||
|
getChildFragmentManager()
|
||||||
|
.beginTransaction()
|
||||||
|
.add(R.id.data_subfragment, dataFragment, "Data Subfragment")
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(evcode.equals("unset") || event == null){
|
||||||
|
binding.reportToggleButton.setVisibility(GONE);
|
||||||
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
ourMatches = event.getTeamMatches(SettingsManager.getTeamNum());
|
||||||
|
matchIndex = SettingsManager.getReportMatchIndex(evcode);
|
||||||
|
|
||||||
|
if(ourMatches.length == 0){
|
||||||
|
binding.reportToggleButton.setVisibility(GONE);
|
||||||
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.scoutUpButton.setOnClickListener(v -> {
|
||||||
|
matchIndex++;
|
||||||
|
updateButtons();
|
||||||
|
});
|
||||||
|
|
||||||
|
binding.scoutDownButton.setOnClickListener(v -> {
|
||||||
|
matchIndex--;
|
||||||
|
updateButtons();
|
||||||
|
});
|
||||||
|
|
||||||
|
updateButtons();
|
||||||
|
|
||||||
|
binding.reportToggleButton.setOnClickListener(view -> {
|
||||||
|
editBoxEnabled =! editBoxEnabled;
|
||||||
|
binding.ScoutingEditBox.setVisibility(editBoxEnabled ? GONE : VISIBLE);
|
||||||
|
binding.reportToggleButton.setText(editBoxEnabled ? "▲ report" : "▼ report");
|
||||||
|
});
|
||||||
|
|
||||||
|
binding.reportCopyButton.setOnClickListener(v -> {
|
||||||
|
// ClipData e = new ClipData();
|
||||||
|
ClipboardManager clipboardManager = (ClipboardManager) getContext().getSystemService(CLIPBOARD_SERVICE);
|
||||||
|
ClipData clipData = ClipData.newPlainText(
|
||||||
|
"Scouting report",
|
||||||
|
binding.scoutingReportEdittext.getText().toString()
|
||||||
|
);
|
||||||
|
|
||||||
|
clipboardManager.setPrimaryClip(clipData);
|
||||||
|
AlertManager.toast("Copied report to clipboard!");
|
||||||
|
});
|
||||||
|
|
||||||
|
asm = new AutoSaveManager(() -> SettingsManager.setScoutingReport(evcode, matchIndex, binding.scoutingReportEdittext.getText().toString()), 300);
|
||||||
|
asm.start();
|
||||||
|
|
||||||
|
binding.scoutingReportEdittext.addTextChangedListener(new TextWatcher() {
|
||||||
|
@Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
|
||||||
|
@Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||||
|
asm.update();
|
||||||
|
}
|
||||||
|
@Override public void afterTextChanged(Editable editable) {}
|
||||||
|
});
|
||||||
|
|
||||||
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateButtons(){
|
||||||
|
binding.matchNum.setText(String.valueOf(ourMatches[matchIndex].matchIndex));
|
||||||
|
binding.scoutUpButton.setEnabled(matchIndex < ourMatches.length-1);
|
||||||
|
binding.scoutDownButton.setEnabled(matchIndex > 0);
|
||||||
|
SettingsManager.setReportIndex(matchIndex, evcode);
|
||||||
|
|
||||||
|
String report = SettingsManager.getScoutingReport(evcode, matchIndex);
|
||||||
|
if(report.isEmpty()) report = generateScoutingTemplate(ourMatches[matchIndex]);
|
||||||
|
binding.scoutingReportEdittext.setText(report);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void moveToFragment(Fragment newFragment){
|
||||||
|
// consider using Java coding conventions (upper first char class names!!!)
|
||||||
|
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
|
||||||
|
// Replace whatever is in the fragment_container view with this fragment,
|
||||||
|
// and add the transaction to the back stack
|
||||||
|
transaction.replace(R.id.data_subfragment, newFragment);
|
||||||
|
transaction.addToBackStack(null);
|
||||||
|
// Commit the transaction
|
||||||
|
transaction.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Generate format for scouting data
|
||||||
|
private String generateScoutingTemplate(frcMatch nextMatch){
|
||||||
|
boolean isBlueAlliance = event.getIsBlueAlliance(teamNum, nextMatch);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
List<frcTeam> ourAlliance = new ArrayList<>();
|
||||||
|
List<frcTeam> opposingAlliance = new ArrayList<>();
|
||||||
|
|
||||||
|
for(int a = 0; a < nextMatch.blueAlliance.length; a++)
|
||||||
|
if(nextMatch.blueAlliance[a] != teamNum){
|
||||||
|
(isBlueAlliance ? ourAlliance : opposingAlliance).add(event.getTeamByNum(nextMatch.blueAlliance[a]));
|
||||||
|
}
|
||||||
|
for(int a = 0; a < nextMatch.redAlliance.length; a++)
|
||||||
|
if(nextMatch.redAlliance[a] != teamNum){
|
||||||
|
(!isBlueAlliance ? ourAlliance : opposingAlliance).add(event.getTeamByNum(nextMatch.redAlliance[a]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String output = "Match: " + (nextMatch.matchIndex) + "\n";
|
||||||
|
|
||||||
|
output += "## Our Alliance ##";
|
||||||
|
output += getTeamNameAndNum(ourAlliance.get(0));
|
||||||
|
output += getTeamNameAndNum(ourAlliance.get(1));
|
||||||
|
output += "\n## Opposing Alliance ##";
|
||||||
|
output += getTeamNameAndNum(opposingAlliance.get(0));
|
||||||
|
output += getTeamNameAndNum(opposingAlliance.get(1));
|
||||||
|
output += getTeamNameAndNum(opposingAlliance.get(2));
|
||||||
|
|
||||||
|
|
||||||
|
return output;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getTeamNameAndNum(frcTeam team){
|
||||||
|
return "\n" + team.teamNumber + " " + team.teamName + ": \n";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.data;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
// Helper class for scouting data by fields.
|
||||||
|
public class DataProcessing {
|
||||||
|
public static int[] getNumberBounds(Map<Integer, List<RawDataType>> data){
|
||||||
|
int min = Integer.MAX_VALUE;
|
||||||
|
int max = Integer.MIN_VALUE;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for(Integer teamNum : data.keySet()){
|
||||||
|
List<RawDataType> teamData = data.get(teamNum);
|
||||||
|
|
||||||
|
int[] locBounds = getNumberBounds(teamData);
|
||||||
|
|
||||||
|
if(locBounds[1] > max) max = locBounds[1];
|
||||||
|
if(locBounds[0] < min) min = locBounds[0];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return new int[]{min, max};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] getNumberBounds(List<RawDataType> data){
|
||||||
|
int min = Integer.MAX_VALUE;
|
||||||
|
int max = Integer.MIN_VALUE;
|
||||||
|
|
||||||
|
if(data == null) return new int[]{min, max};
|
||||||
|
for(int i = 0; i < data.size(); i++){
|
||||||
|
RawDataType dataPoint = data.get(i);
|
||||||
|
// if(dataPoint == null) continue;
|
||||||
|
int num = (int) dataPoint.get();
|
||||||
|
if(num > max) max = num;
|
||||||
|
if(num < min) min = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new int[]{min, max};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//https://stackoverflow.com/questions/42381759/finding-first-quartile-and-third-quartile-in-integer-array-using-java#63891545
|
||||||
|
public static float[] getQuartiles(List<RawDataType> data) {
|
||||||
|
float ans[] = new float[3];
|
||||||
|
|
||||||
|
float[] val = new float[data.size()];
|
||||||
|
for(int i = 0; i < val.length; i++){
|
||||||
|
val[i] = (int) data.get(i).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int quartileType = 1; quartileType < 4; quartileType++) {
|
||||||
|
float length = val.length + 1;
|
||||||
|
float quartile;
|
||||||
|
float newArraySize = (length * ((float) (quartileType) * 25 / 100)) - 1;
|
||||||
|
Arrays.sort(val);
|
||||||
|
if (newArraySize % 1 == 0) {
|
||||||
|
quartile = val[(int) (newArraySize)];
|
||||||
|
} else {
|
||||||
|
int newArraySize1 = (int) (newArraySize);
|
||||||
|
quartile = (val[newArraySize1] + val[newArraySize1 + 1]) / 2;
|
||||||
|
}
|
||||||
|
ans[quartileType - 1] = quartile;
|
||||||
|
}
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the specified percentile of a dataset.
|
||||||
|
*
|
||||||
|
* @param data The dataset to analyze
|
||||||
|
* @param percentile The percentile to find (0-100)
|
||||||
|
* @return The value at the specified percentile
|
||||||
|
*/
|
||||||
|
public static float calculatePercentile(float[] data, float percentile) {
|
||||||
|
// Make a copy of the data to avoid modifying the original
|
||||||
|
float[] dataCopy = Arrays.copyOf(data, data.length);
|
||||||
|
|
||||||
|
// Sort the data in ascending order
|
||||||
|
Arrays.sort(dataCopy);
|
||||||
|
|
||||||
|
// Calculate the position as a fraction
|
||||||
|
float position = (percentile / 100.0f) * (dataCopy.length - 1);
|
||||||
|
|
||||||
|
// Get the integer part of the position
|
||||||
|
int lowerIndex = (int) Math.floor(position);
|
||||||
|
int upperIndex = (int) Math.ceil(position);
|
||||||
|
|
||||||
|
// If position is already an integer, return the value at that position
|
||||||
|
if (lowerIndex == upperIndex) {
|
||||||
|
return dataCopy[lowerIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, interpolate between the two adjacent values
|
||||||
|
float fraction = position - lowerIndex;
|
||||||
|
float lowerValue = dataCopy[lowerIndex];
|
||||||
|
float upperValue = dataCopy[upperIndex];
|
||||||
|
|
||||||
|
// Linear interpolation
|
||||||
|
return lowerValue + fraction * (upperValue - lowerValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.data;
|
||||||
|
|
||||||
|
|
||||||
|
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.match_transferValues;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.DataManager.match_values;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.DataManager.rescout_list;
|
||||||
|
|
||||||
|
import android.app.ProgressDialog;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
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.databinding.FragmentDataFieldDataBinding;
|
||||||
|
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
|
||||||
|
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||||
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
// Fragment for viewing the data of a specfic field.
|
||||||
|
public class FieldDataFragment extends Fragment {
|
||||||
|
|
||||||
|
private FragmentDataFieldDataBinding binding;
|
||||||
|
|
||||||
|
private static int fieldIndex = -1;
|
||||||
|
public static void setFieldIndex(int index){
|
||||||
|
fieldIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
binding = FragmentDataFieldDataBinding.inflate(inflater, container, false);
|
||||||
|
binding.table.setStretchAllColumns(true);
|
||||||
|
View root = binding.getRoot();
|
||||||
|
|
||||||
|
if (fieldIndex == -1)
|
||||||
|
return root;
|
||||||
|
|
||||||
|
startLoading("Loading data...");
|
||||||
|
|
||||||
|
Thread t = new Thread(() -> {
|
||||||
|
|
||||||
|
Map<Integer, List<RawDataType>> data = new HashMap<>();
|
||||||
|
for (int teamIndex = 0; teamIndex < event.teams.size(); teamIndex++) {
|
||||||
|
int teamNum = event.teams.get(teamIndex).teamNumber;
|
||||||
|
List<String> filenames = new ArrayList<>(List.of(FileEditor.getMatchesByTeamNum(evcode, event.teams.get(teamIndex).teamNumber)));
|
||||||
|
filenames.removeAll(rescout_list.get());
|
||||||
|
|
||||||
|
ArrayList<RawDataType> teamData = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < filenames.size(); i++) {
|
||||||
|
try {
|
||||||
|
Log.i(getClass().toString(), "Loading: " + filenames.get(i));
|
||||||
|
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(filenames.get(i), match_values, match_transferValues);
|
||||||
|
if (psda.data.array[fieldIndex] != null && psda.data.array[fieldIndex].get() != null && !psda.data.array[fieldIndex].isNull())
|
||||||
|
teamData.add(psda.data.array[fieldIndex]);
|
||||||
|
} catch (Exception e) {
|
||||||
|
AlertManager.error("Failure to load file " + filenames.get(i), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.put(teamNum, teamData);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i(getClass().toString(), "Finished!");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
getActivity().runOnUiThread(() -> {
|
||||||
|
binding.table.setStretchAllColumns(false);
|
||||||
|
match_latest_values[fieldIndex].addDataToTable(binding.table, data);
|
||||||
|
stopLoading();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
t.start();
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ProgressDialog loadingDialog;
|
||||||
|
|
||||||
|
private void startLoading(String title){
|
||||||
|
getActivity().runOnUiThread(() -> {
|
||||||
|
if(loadingDialog != null && loadingDialog.isShowing())
|
||||||
|
loadingDialog.dismiss();
|
||||||
|
loadingDialog = ProgressDialog.show(getActivity(), title, "Please wait...");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopLoading(){
|
||||||
|
getActivity().runOnUiThread(() -> {
|
||||||
|
if (loadingDialog != null)
|
||||||
|
loadingDialog.cancel();
|
||||||
|
loadingDialog = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,322 +0,0 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.data;
|
|
||||||
|
|
||||||
import static android.text.InputType.TYPE_CLASS_NUMBER;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.TableLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
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,
|
|
||||||
paramNumberArray
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class parameterType {
|
|
||||||
public String name;
|
|
||||||
public parameterTypeEnum id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class paramNumber extends parameterType{
|
|
||||||
public int val;
|
|
||||||
public paramNumber(String name, int val){
|
|
||||||
this.name = name + " (Number)";
|
|
||||||
this.val = val;
|
|
||||||
this.id = parameterTypeEnum.paramNumber;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class paramString extends parameterType {
|
|
||||||
public String val;
|
|
||||||
public paramString(String name, String val){
|
|
||||||
this.name = name + " (String)";
|
|
||||||
this.val = val;
|
|
||||||
this.id = parameterTypeEnum.paramString;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class paramStringArray extends parameterType{
|
|
||||||
public String[] val;
|
|
||||||
public paramStringArray(String name, String[] val){
|
|
||||||
this.name = name + " (String array)";
|
|
||||||
this.val = val;
|
|
||||||
this.id = parameterTypeEnum.paramStringArray;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// public static class paramNumberArray extends parameterType{
|
|
||||||
// public int[] val;
|
|
||||||
// public paramNumberArray(String name, int[] val){
|
|
||||||
// this.name = name + " (Number array)";
|
|
||||||
// this.val = val;
|
|
||||||
// this.id = parameterTypeEnum.paramNumberArray;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
public static final parameterType[] defaultSliderParams = new parameterType[]{
|
|
||||||
new paramNumber("Min", 0),
|
|
||||||
new paramNumber("Max", 10),
|
|
||||||
new paramNumber("Default Value", 5)
|
|
||||||
};
|
|
||||||
public static final parameterType[] defaultDropdownParams = new parameterType[]{
|
|
||||||
new paramStringArray("Default Value", new String[]{"Zero","One","Two","Three"}),
|
|
||||||
new paramNumber("Default Option", 0),
|
|
||||||
};
|
|
||||||
public static final parameterType[] defaultTextParams = new parameterType[]{
|
|
||||||
new paramString("Default Value", "")
|
|
||||||
};
|
|
||||||
public static final parameterType[] defaultTallyParams = new parameterType[]{
|
|
||||||
new paramNumber("Default Value", 0)
|
|
||||||
};
|
|
||||||
public static final parameterType[] defaultNumberParams = new parameterType[]{
|
|
||||||
new paramNumber("Default Value", 0)
|
|
||||||
};
|
|
||||||
public static final parameterType[] defaultCheckboxParam = new parameterType[]{
|
|
||||||
new paramNumber("Default Value ( 1 or 0 )", 0)
|
|
||||||
};
|
|
||||||
public static final parameterType[] defaultFieldPosParam = new parameterType[]{
|
|
||||||
new paramNumber("Default X", 0),
|
|
||||||
new paramNumber("Default Y", 0)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
private static parameterType[] getSliderParams(sliderType s){
|
|
||||||
return new parameterType[]{
|
|
||||||
new paramNumber("Min", s.min),
|
|
||||||
new paramNumber("Max", s.max),
|
|
||||||
new paramNumber("Default Value", (int) s.default_value)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static parameterType[] getDropdownParams(dropdownType s){
|
|
||||||
return new parameterType[]{
|
|
||||||
new paramStringArray("Default Value",s.text_options),
|
|
||||||
new paramNumber("Default Option", (int) s.default_value),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static parameterType[] getTextParams(textType s){
|
|
||||||
return new parameterType[]{
|
|
||||||
new paramString("Default Value", (String) s.default_value)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static parameterType[] getTallyParams(tallyType s){
|
|
||||||
return new parameterType[]{
|
|
||||||
new paramNumber("Default Value", (int) s.default_value)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static parameterType[] getNumberParams(numberType s){
|
|
||||||
return new parameterType[]{
|
|
||||||
new paramNumber("Default Value", (int) s.default_value)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static parameterType[] getCheckboxParam(checkboxType s){
|
|
||||||
return new parameterType[]{
|
|
||||||
new paramNumber("Default Value ( 1 or 0 )", (int) s.default_value)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static parameterType[] getFieldPosParam(fieldposType s){
|
|
||||||
return new parameterType[]{
|
|
||||||
new paramNumber("Default X", ((int[]) s.default_value)[0]),
|
|
||||||
new paramNumber("Default Y", ((int[]) s.default_value)[1])
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static void setSliderParams(sliderType s, parameterType[] types){
|
|
||||||
s.min = ((paramNumber) types[0]).val;
|
|
||||||
s.max = ((paramNumber) types[1]).val;
|
|
||||||
s.default_value = ((paramNumber) types[2]).val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setDropdownParams(dropdownType s, parameterType[] types){
|
|
||||||
s.text_options = ((paramStringArray) types[0]).val;
|
|
||||||
s.default_value = ((paramNumber) types[1]).val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setTextParams(textType s, parameterType[] types){
|
|
||||||
s.default_value = ((paramString) types[0]).val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setTallyParams(tallyType s, parameterType[] types){
|
|
||||||
s.default_value = ((paramNumber) types[0]).val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setNumberParams(numberType s, parameterType[] types){
|
|
||||||
s.default_value = ((paramNumber) types[0]).val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setCheckboxParam(checkboxType s, parameterType[] types){
|
|
||||||
s.default_value = ((paramNumber) types[0]).val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setFieldPosParam(fieldposType s, parameterType[] types){
|
|
||||||
s.default_value = new int[]{
|
|
||||||
((paramNumber) types[0]).val,
|
|
||||||
((paramNumber) types[1]).val
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static void setInputParameter(inputType t, parameterType[] types){
|
|
||||||
switch (t.getInputType()){
|
|
||||||
case TALLY:
|
|
||||||
setTallyParams((tallyType) t, types);
|
|
||||||
break;
|
|
||||||
case SLIDER:
|
|
||||||
setSliderParams((sliderType) t, types);
|
|
||||||
break;
|
|
||||||
case DROPDOWN:
|
|
||||||
setDropdownParams((dropdownType) t, types);
|
|
||||||
break;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static parameterType[] getParamsFromInputType(inputType t){
|
|
||||||
switch (t.getInputType()){
|
|
||||||
case TALLY:
|
|
||||||
return getTallyParams((tallyType) t);
|
|
||||||
case SLIDER:
|
|
||||||
return getSliderParams((sliderType) t);
|
|
||||||
case DROPDOWN:
|
|
||||||
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[]{};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static View createNumberEdit(Context c, int value){
|
|
||||||
EditText text = new EditText(c);
|
|
||||||
text.setInputType(TYPE_CLASS_NUMBER);
|
|
||||||
text.setText(String.valueOf(value));
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static View createStringEdit(Context c, String value){
|
|
||||||
EditText text = new EditText(c);
|
|
||||||
text.setText(value);
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static View createStringArrayEdit(Context c, String[] value){
|
|
||||||
EditText text = new EditText(c);
|
|
||||||
text.setText(String.join("\n", value));
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static View createEdit(Context c, parameterType t){
|
|
||||||
switch (t.id){
|
|
||||||
case paramNumber:
|
|
||||||
return createNumberEdit(c, ((paramNumber) t).val);
|
|
||||||
case paramString:
|
|
||||||
return createStringEdit(c, ((paramString) t).val);
|
|
||||||
case paramStringArray:
|
|
||||||
return createStringArrayEdit(c, ((paramStringArray) t).val);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static boolean readEdit(View v, parameterType t){
|
|
||||||
try{
|
|
||||||
String val;
|
|
||||||
switch (t.id) {
|
|
||||||
case paramNumber:
|
|
||||||
val = ((EditText) v).getText().toString();
|
|
||||||
if(val.isEmpty() || val.isBlank()) return false;
|
|
||||||
((paramNumber) t).val = Integer.parseInt(val);
|
|
||||||
break;
|
|
||||||
case paramString:
|
|
||||||
val = ((EditText) v).getText().toString();
|
|
||||||
//if(val.isEmpty() || val.isBlank()) return false;
|
|
||||||
((paramString) t).val = val;
|
|
||||||
break;
|
|
||||||
case paramStringArray:
|
|
||||||
val = ((EditText) v).getText().toString();
|
|
||||||
if(val.isEmpty() || val.isBlank()) return false;
|
|
||||||
((paramStringArray) t).val = val.split("\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
AlertManager.error(e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private parameterType[] types;
|
|
||||||
private View[] views;
|
|
||||||
private inputType t;
|
|
||||||
public FieldEditorHelper(Context c, inputType t, TableLayout parentView, parameterType[] tmptypes){
|
|
||||||
this.types = tmptypes;
|
|
||||||
this.t = t;
|
|
||||||
views = new View[types.length];
|
|
||||||
for(int i = 0; i < types.length; i++){
|
|
||||||
TextView tv = new TextView(c);
|
|
||||||
tv.setText(types[i].name);
|
|
||||||
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
|
||||||
tv.setTextSize(20);
|
|
||||||
parentView.addView(tv);
|
|
||||||
|
|
||||||
views[i] = createEdit(c, types[i]);
|
|
||||||
parentView.addView(views[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public FieldEditorHelper(Context c, inputType t, TableLayout parentView){
|
|
||||||
this(c,t,parentView,getParamsFromInputType(t));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean save(){
|
|
||||||
for(int i = 0; i < types.length; i++){
|
|
||||||
if(!readEdit(views[i], types[i]))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
setInputParameter(t, types);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package com.ridgebotics.ridgescout.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.ridgebotics.ridgescout.R;
|
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentDataFieldsChooserBinding;
|
|
||||||
import com.ridgebotics.ridgescout.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,562 +0,0 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.data;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Activity;
|
|
||||||
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.EditText;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.TableLayout;
|
|
||||||
import android.widget.TableRow;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import androidx.navigation.Navigation;
|
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.R;
|
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentDataFieldsBinding;
|
|
||||||
import com.ridgebotics.ridgescout.scoutingData.fields;
|
|
||||||
import com.ridgebotics.ridgescout.types.input.checkboxType;
|
|
||||||
import com.ridgebotics.ridgescout.types.input.dropdownType;
|
|
||||||
import com.ridgebotics.ridgescout.types.input.fieldposType;
|
|
||||||
import com.ridgebotics.ridgescout.types.input.inputType;
|
|
||||||
import com.ridgebotics.ridgescout.types.input.numberType;
|
|
||||||
import com.ridgebotics.ridgescout.types.input.sliderType;
|
|
||||||
import com.ridgebotics.ridgescout.types.input.tallyType;
|
|
||||||
import com.ridgebotics.ridgescout.types.input.textType;
|
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
|
||||||
import com.skydoves.powerspinner.IconSpinnerAdapter;
|
|
||||||
import com.skydoves.powerspinner.IconSpinnerItem;
|
|
||||||
import com.skydoves.powerspinner.PowerSpinnerView;
|
|
||||||
import com.skydoves.powerspinner.SpinnerGravity;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class FieldsFragment extends Fragment {
|
|
||||||
FragmentDataFieldsBinding binding;
|
|
||||||
|
|
||||||
private static String filename;
|
|
||||||
public static void set_filename(String tmpfilename){
|
|
||||||
filename = tmpfilename;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
|
||||||
@Nullable Bundle savedInstanceState) {
|
|
||||||
binding = FragmentDataFieldsBinding.inflate(inflater, container, false);
|
|
||||||
|
|
||||||
binding.valueEditScrollview.setOnTouchListener((v, event) -> true);
|
|
||||||
|
|
||||||
binding.saveButton.setVisibility(View.GONE);
|
|
||||||
binding.cancelEditButton.setVisibility(View.GONE);
|
|
||||||
binding.editButton.setVisibility(View.GONE);
|
|
||||||
binding.upButton.setVisibility(View.GONE);
|
|
||||||
binding.addButton.setVisibility(View.GONE);
|
|
||||||
binding.downButton.setVisibility(View.GONE);
|
|
||||||
binding.deleteButton.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
binding.valueEditContainer.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
load_field_menu();
|
|
||||||
|
|
||||||
return binding.getRoot();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final int background_color = 0x5000ff00;
|
|
||||||
private static final int unfocused_background_color = 0x2000ff00;
|
|
||||||
|
|
||||||
inputType[][] values;
|
|
||||||
|
|
||||||
private void load_field_menu() {
|
|
||||||
|
|
||||||
values = fields.load(filename);
|
|
||||||
|
|
||||||
binding.fieldsArea.bringToFront();
|
|
||||||
binding.fieldsArea.setStretchAllColumns(true);
|
|
||||||
binding.fieldsArea.removeAllViews();
|
|
||||||
binding.fieldsArea.setReorderingEnabled(false);
|
|
||||||
|
|
||||||
if(values == null) return;
|
|
||||||
|
|
||||||
for(int i = 0; i < values.length; i++){
|
|
||||||
|
|
||||||
TableRow tr = new TableRow(getContext());
|
|
||||||
TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams(
|
|
||||||
FrameLayout.LayoutParams.WRAP_CONTENT,
|
|
||||||
FrameLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
);
|
|
||||||
|
|
||||||
rowParams.setMargins(20,20,20,20);
|
|
||||||
tr.setLayoutParams(rowParams);
|
|
||||||
tr.setPadding(20,20,20,20);
|
|
||||||
|
|
||||||
TextView tv = new TextView(getContext());
|
|
||||||
tv.setText("v" + i);
|
|
||||||
tv.setTextSize(20);
|
|
||||||
tr.addView(tv);
|
|
||||||
|
|
||||||
tv = new TextView(getContext());
|
|
||||||
tv.setText(values[i].length + " Fields");
|
|
||||||
tv.setTextSize(16);
|
|
||||||
tr.addView(tv);
|
|
||||||
|
|
||||||
binding.fieldsArea.addView(tr);
|
|
||||||
|
|
||||||
if(i == values.length-1) {
|
|
||||||
tr.setBackgroundColor(background_color);
|
|
||||||
int fi = i;
|
|
||||||
tr.setOnClickListener(v -> {
|
|
||||||
display_fields(values[fi]);
|
|
||||||
});
|
|
||||||
}else{
|
|
||||||
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) {
|
|
||||||
binding.fieldsArea.removeAllViews();
|
|
||||||
binding.fieldsArea.setReorderingEnabled(false);
|
|
||||||
|
|
||||||
binding.revertVersionButton.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
binding.saveButton.setVisibility(View.GONE);
|
|
||||||
binding.editButton.setVisibility(View.GONE);
|
|
||||||
binding.upButton.setVisibility(View.VISIBLE);
|
|
||||||
binding.addButton.setVisibility(View.VISIBLE);
|
|
||||||
binding.downButton.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
binding.valueEditContainer.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
for(int i = 0; i < version_values.length; i++){
|
|
||||||
addRow(version_values[i]);
|
|
||||||
}
|
|
||||||
selindex = -1;
|
|
||||||
|
|
||||||
|
|
||||||
binding.addButton.setOnClickListener(this::addField);
|
|
||||||
binding.saveButton.setOnClickListener(this::buttonfunc);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addRow(inputType field){
|
|
||||||
TableRow tr = getTableRow(field);
|
|
||||||
|
|
||||||
binding.fieldsArea.addView(tr);
|
|
||||||
|
|
||||||
tr.setOnClickListener(v -> {
|
|
||||||
binding.editButton.setVisibility(View.VISIBLE);
|
|
||||||
trOnClick(values[values.length-1], tr);
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.upButton.setOnClickListener(v -> {
|
|
||||||
if(selindex != 0) {
|
|
||||||
binding.saveButton.setVisibility(View.VISIBLE);
|
|
||||||
binding.fieldsArea.updateRowOrder(selindex, selindex - 1);
|
|
||||||
selindex -= 1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.downButton.setOnClickListener(v -> {
|
|
||||||
if(selindex != values[values.length-1].length-1) {
|
|
||||||
binding.saveButton.setVisibility(View.VISIBLE);
|
|
||||||
binding.fieldsArea.updateRowOrder(selindex, selindex + 1);
|
|
||||||
selindex += 1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void buttonfunc(View v){
|
|
||||||
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", (dialog, which) -> {
|
|
||||||
inputType[][] currentValues = fields.load(filename);
|
|
||||||
assert currentValues != null;
|
|
||||||
inputType[][] newValues = new inputType[currentValues.length+1][];
|
|
||||||
System.arraycopy(currentValues, 0, newValues, 0, currentValues.length);
|
|
||||||
|
|
||||||
newValues[newValues.length-1] = new inputType[values[values.length-1].length];
|
|
||||||
|
|
||||||
for(int i = 0; i < values[values.length-1].length; i++){
|
|
||||||
newValues[newValues.length-1][i] = values[values.length-1][binding.fieldsArea.getReorderedIndexes().get(i)];
|
|
||||||
}
|
|
||||||
// newValues[newValues.length-1] = values[values.length-1];
|
|
||||||
|
|
||||||
if(fields.save(filename, newValues))
|
|
||||||
AlertManager.toast("Saved");
|
|
||||||
|
|
||||||
Navigation.findNavController((Activity) getContext(), R.id.nav_host_fragment_activity_main).navigate(R.id.action_navigation_data_fields_to_navigation_data_fields_chooser);
|
|
||||||
});
|
|
||||||
alert.setNegativeButton("Cancel", null);
|
|
||||||
alert.setCancelable(true);
|
|
||||||
alert.create().show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int selindex = -1;
|
|
||||||
|
|
||||||
private void trOnClick(inputType[] version_values, TableRow tr){
|
|
||||||
selindex = -1;
|
|
||||||
for(int i = 0; i < binding.fieldsArea.getChildCount(); i++){
|
|
||||||
View v = binding.fieldsArea.getChildAt(i);
|
|
||||||
|
|
||||||
if(v.equals(tr)) {
|
|
||||||
tr.setBackgroundColor(background_color);
|
|
||||||
selindex = i;
|
|
||||||
} else
|
|
||||||
binding.fieldsArea.getChildAt(i).setBackgroundColor(unfocused_background_color);
|
|
||||||
}
|
|
||||||
|
|
||||||
onFieldSelect(version_values[binding.fieldsArea.getReorderedIndexes().get(selindex)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onFieldSelect(inputType field){
|
|
||||||
//System.out.println(field.name);
|
|
||||||
|
|
||||||
binding.editButton.setOnClickListener(v -> {
|
|
||||||
binding.editButton.setVisibility(View.GONE);
|
|
||||||
binding.addButton.setVisibility(View.GONE);
|
|
||||||
binding.upButton.setVisibility(View.GONE);
|
|
||||||
binding.downButton.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
binding.ValueEditTable.removeAllViews();
|
|
||||||
binding.valueEditContainer.setVisibility(View.VISIBLE);
|
|
||||||
TextView tv = new TextView(getContext());
|
|
||||||
|
|
||||||
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
|
||||||
tv.setText(field.name);
|
|
||||||
tv.setPadding(8,8,8,8);
|
|
||||||
tv.setTextSize(24);
|
|
||||||
|
|
||||||
binding.ValueEditTable.addView(tv);
|
|
||||||
|
|
||||||
final FieldEditorHelper fe = new FieldEditorHelper(
|
|
||||||
getContext(),
|
|
||||||
field,
|
|
||||||
binding.ValueEditTable
|
|
||||||
);
|
|
||||||
|
|
||||||
binding.saveButton.setVisibility(View.VISIBLE);
|
|
||||||
binding.saveButton.setOnClickListener(a -> {
|
|
||||||
System.out.println(fe.save());
|
|
||||||
defaultVisibility();
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.cancelEditButton.setVisibility(View.VISIBLE);
|
|
||||||
binding.cancelEditButton.setOnClickListener(a -> {
|
|
||||||
defaultVisibility();
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.deleteButton.setVisibility(View.VISIBLE);
|
|
||||||
binding.deleteButton.setOnClickListener(a -> {
|
|
||||||
deleteField(field);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteField(inputType field){
|
|
||||||
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
|
|
||||||
alert.setTitle("Warning!");
|
|
||||||
alert.setMessage("Removing a value will result in data being deleted in subsequent field versions!");
|
|
||||||
alert.setNegativeButton("Cancel", null);
|
|
||||||
alert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
defaultVisibility();
|
|
||||||
|
|
||||||
int oldindex = -1;
|
|
||||||
for(int i = 0; i < values[values.length - 1].length; i++){
|
|
||||||
if(values[values.length - 1][i].equals(field)){
|
|
||||||
oldindex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(oldindex != -1) {
|
|
||||||
System.out.println(Arrays.toString(values[values.length - 1]));
|
|
||||||
binding.fieldsArea.removeViewAt(selindex);
|
|
||||||
binding.fieldsArea.removeElement(oldindex);
|
|
||||||
values[values.length - 1] = removeElement(values[values.length - 1], oldindex);
|
|
||||||
selindex = -1;
|
|
||||||
AlertManager.toast("Removed!");
|
|
||||||
binding.editButton.setVisibility(View.GONE);
|
|
||||||
System.out.println(Arrays.toString(values[values.length - 1]));
|
|
||||||
//System.out.println(values[values.length-1].length);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
alert.setCancelable(true);
|
|
||||||
alert.create().show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public inputType[] removeElement(inputType[] src, int i) {
|
|
||||||
inputType[] newArray = new inputType[src.length - 1];
|
|
||||||
if (i > 0){
|
|
||||||
System.arraycopy(src, 0, newArray, 0, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newArray.length > i){
|
|
||||||
System.arraycopy(src, i + 1, newArray, i, newArray.length - i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return newArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void defaultVisibility() {
|
|
||||||
binding.editButton.setVisibility(View.VISIBLE);
|
|
||||||
binding.addButton.setVisibility(View.VISIBLE);
|
|
||||||
binding.upButton.setVisibility(View.VISIBLE);
|
|
||||||
binding.downButton.setVisibility(View.VISIBLE);
|
|
||||||
binding.ValueEditTable.removeAllViews();
|
|
||||||
binding.valueEditContainer.setVisibility(View.GONE);
|
|
||||||
binding.cancelEditButton.setVisibility(View.GONE);
|
|
||||||
binding.deleteButton.setVisibility(View.GONE);
|
|
||||||
binding.saveButton.setOnClickListener(this::buttonfunc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void addField(View v) {
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
|
||||||
builder.setTitle("Title");
|
|
||||||
|
|
||||||
final EditText input = new EditText(getContext());
|
|
||||||
input.setInputType(InputType.TYPE_CLASS_TEXT);
|
|
||||||
|
|
||||||
builder.setView(input);
|
|
||||||
|
|
||||||
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) {
|
|
||||||
String title = input.getText().toString();
|
|
||||||
if(title.isEmpty() || title.isBlank()) {
|
|
||||||
AlertManager.error("Title cannot be blank!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
addField_Part_2(title);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addField_Part_2(String title) {
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
|
||||||
builder.setTitle("Title");
|
|
||||||
|
|
||||||
final PowerSpinnerView dropdown = new PowerSpinnerView(getContext());
|
|
||||||
|
|
||||||
List<IconSpinnerItem> iconSpinnerItems = new ArrayList<>();
|
|
||||||
|
|
||||||
iconSpinnerItems.add(new IconSpinnerItem("Slider"));
|
|
||||||
iconSpinnerItems.add(new IconSpinnerItem("Text"));
|
|
||||||
iconSpinnerItems.add(new IconSpinnerItem("Dropdown"));
|
|
||||||
iconSpinnerItems.add(new IconSpinnerItem("Tally"));
|
|
||||||
iconSpinnerItems.add(new IconSpinnerItem("Number"));
|
|
||||||
iconSpinnerItems.add(new IconSpinnerItem("Checkbox"));
|
|
||||||
iconSpinnerItems.add(new IconSpinnerItem("Field Position"));
|
|
||||||
|
|
||||||
IconSpinnerAdapter iconSpinnerAdapter = new IconSpinnerAdapter(dropdown);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addField_Part_3(String title, int typeIndex) {
|
|
||||||
switch (typeIndex){
|
|
||||||
case 0:
|
|
||||||
sliderType slider = new sliderType();
|
|
||||||
slider.name = title;
|
|
||||||
FieldEditorHelper.setSliderParams(slider, FieldEditorHelper.defaultSliderParams);
|
|
||||||
addField_Part_4(slider);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
textType text = new textType();
|
|
||||||
text.name = title;
|
|
||||||
FieldEditorHelper.setTextParams(text, FieldEditorHelper.defaultTextParams);
|
|
||||||
addField_Part_4(text);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
dropdownType dropdown = new dropdownType();
|
|
||||||
dropdown.name = title;
|
|
||||||
FieldEditorHelper.setDropdownParams(dropdown, FieldEditorHelper.defaultDropdownParams);
|
|
||||||
addField_Part_4(dropdown);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
tallyType tally = new tallyType();
|
|
||||||
tally.name = title;
|
|
||||||
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;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
private void addField_Part_4(inputType field) {
|
|
||||||
binding.editButton.setVisibility(View.GONE);
|
|
||||||
binding.addButton.setVisibility(View.GONE);
|
|
||||||
binding.upButton.setVisibility(View.GONE);
|
|
||||||
binding.downButton.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
binding.ValueEditTable.removeAllViews();
|
|
||||||
binding.valueEditContainer.setVisibility(View.VISIBLE);
|
|
||||||
TextView tv = new TextView(getContext());
|
|
||||||
|
|
||||||
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
|
||||||
tv.setText(field.name);
|
|
||||||
tv.setPadding(8,8,8,8);
|
|
||||||
tv.setTextSize(24);
|
|
||||||
|
|
||||||
binding.ValueEditTable.addView(tv);
|
|
||||||
|
|
||||||
final FieldEditorHelper fe = new FieldEditorHelper(
|
|
||||||
getContext(),
|
|
||||||
field,
|
|
||||||
binding.ValueEditTable
|
|
||||||
);
|
|
||||||
|
|
||||||
binding.saveButton.setVisibility(View.VISIBLE);
|
|
||||||
binding.saveButton.setOnClickListener(a -> {
|
|
||||||
inputType[] newValues = new inputType[values[values.length-1].length+1];
|
|
||||||
System.arraycopy(values[values.length-1], 0, newValues, 0, values[values.length-1].length);
|
|
||||||
newValues[newValues.length-1] = field;
|
|
||||||
values[values.length-1] = newValues;
|
|
||||||
|
|
||||||
// AlertManager.alert("Test", String.valueOf(binding.fieldsArea.getReorderedIndexes()));
|
|
||||||
|
|
||||||
//TableRow tr = getTableRow(field);
|
|
||||||
//binding.fieldsArea.addView(tr);
|
|
||||||
addRow(field);
|
|
||||||
|
|
||||||
System.out.println(fe.save());
|
|
||||||
defaultVisibility();
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.cancelEditButton.setVisibility(View.VISIBLE);
|
|
||||||
binding.cancelEditButton.setOnClickListener(a -> {
|
|
||||||
defaultVisibility();
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private @NonNull TableRow getTableRow(inputType field) {
|
|
||||||
TableRow tr = new TableRow(getContext());
|
|
||||||
TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams(
|
|
||||||
FrameLayout.LayoutParams.WRAP_CONTENT,
|
|
||||||
FrameLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
);
|
|
||||||
|
|
||||||
rowParams.setMargins(20,20,20,20);
|
|
||||||
tr.setLayoutParams(rowParams);
|
|
||||||
tr.setPadding(20,20,20,20);
|
|
||||||
tr.setBackgroundColor(unfocused_background_color);
|
|
||||||
|
|
||||||
TextView tv = new TextView(getContext());
|
|
||||||
tv.setText(field.get_type_name());
|
|
||||||
tv.setTextSize(12);
|
|
||||||
tr.addView(tv);
|
|
||||||
|
|
||||||
tv = new TextView(getContext());
|
|
||||||
tv.setText(field.name);
|
|
||||||
tv.setTextSize(20);
|
|
||||||
tr.addView(tv);
|
|
||||||
return tr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.data;
|
|
||||||
|
|
||||||
import static com.ridgebotics.ridgescout.utility.DataManager.event;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.TableRow;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentDataReportBinding;
|
|
||||||
import com.ridgebotics.ridgescout.types.frcMatch;
|
|
||||||
import com.ridgebotics.ridgescout.utility.DataManager;
|
|
||||||
import com.ridgebotics.ridgescout.utility.ollama.OllamaClient;
|
|
||||||
import com.ridgebotics.ridgescout.utility.ollama.PromptCreator;
|
|
||||||
import com.ridgebotics.ridgescout.utility.settingsManager;
|
|
||||||
|
|
||||||
public class ReportFragment extends Fragment {
|
|
||||||
FragmentDataReportBinding binding;
|
|
||||||
|
|
||||||
private static frcMatch match;
|
|
||||||
public static void setMatch(frcMatch m){
|
|
||||||
match = m;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final int ourTeamNum = settingsManager.getTeamNum();
|
|
||||||
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
|
||||||
@Nullable Bundle savedInstanceState) {
|
|
||||||
|
|
||||||
binding = FragmentDataReportBinding.inflate(inflater, container, false);
|
|
||||||
|
|
||||||
binding.teamNumber.setText(String.valueOf(ourTeamNum));
|
|
||||||
|
|
||||||
binding.AyEyeBox.setVisibility(View.VISIBLE);
|
|
||||||
binding.AyEyeButton.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
DataManager.reload_event();
|
|
||||||
DataManager.reload_pit_fields();
|
|
||||||
DataManager.reload_match_fields();
|
|
||||||
|
|
||||||
binding.AyEyeBox.setText("TBD!\n This is meant to be a tool that lets scouters more easily write reports to the drive team before matches. There are some plans for LLM integration into this menu ");
|
|
||||||
|
|
||||||
// binding.AyEyeButton.setText("Create Prompt");
|
|
||||||
// binding.AyEyeButton.setOnClickListener(a ->{
|
|
||||||
// getPrompt();
|
|
||||||
// binding.AyEyeButton.setText("Generate Overview");
|
|
||||||
// binding.AyEyeButton.setOnClickListener(b ->{
|
|
||||||
// AIDataOverview();
|
|
||||||
// binding.AyEyeButton.setVisibility(View.GONE);
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
return binding.getRoot();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void getPrompt(){
|
|
||||||
binding.AyEyeBox.setVisibility(View.VISIBLE);
|
|
||||||
String prompt = PromptCreator.genMatchPrompt(0);
|
|
||||||
binding.AyEyeBox.setText(prompt);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AIDataOverview(){
|
|
||||||
String prompt = binding.AyEyeBox.getText().toString();
|
|
||||||
binding.AyEyeBox.setText("");
|
|
||||||
OllamaClient.run(prompt, new OllamaClient.ollamaListener() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(String response) {
|
|
||||||
// System.out.println(response);
|
|
||||||
getActivity().runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
binding.AyEyeBox.setText(binding.AyEyeBox.getText()+response);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onComplete() {
|
|
||||||
System.out.println(binding.AyEyeBox.getText());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.data;
|
|
||||||
|
|
||||||
import static androidx.navigation.fragment.FragmentKt.findNavController;
|
|
||||||
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
|
|
||||||
import static com.ridgebotics.ridgescout.utility.DataManager.event;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.TableLayout;
|
|
||||||
import android.widget.TableRow;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.R;
|
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentDataReportSelectorBinding;
|
|
||||||
import com.ridgebotics.ridgescout.types.frcMatch;
|
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
|
||||||
import com.ridgebotics.ridgescout.utility.DataManager;
|
|
||||||
import com.ridgebotics.ridgescout.utility.settingsManager;
|
|
||||||
|
|
||||||
public class ReportSelectorFragment extends Fragment {
|
|
||||||
FragmentDataReportSelectorBinding binding;
|
|
||||||
|
|
||||||
private final int teamNum = settingsManager.getTeamNum();
|
|
||||||
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
|
||||||
@Nullable Bundle savedInstanceState) {
|
|
||||||
binding = FragmentDataReportSelectorBinding.inflate(inflater, container, false);
|
|
||||||
binding.matchTable.setStretchAllColumns(true);
|
|
||||||
|
|
||||||
DataManager.reload_event();
|
|
||||||
frcMatch[] teamMatches = event.getTeamMatches(teamNum);
|
|
||||||
|
|
||||||
if(teamMatches.length == 0){
|
|
||||||
AlertManager.error("Team number " + teamNum + " could not be found in event " + evcode);
|
|
||||||
findNavController(this).navigate(R.id.action_navigation_data_report_selector_to_navigation_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < teamMatches.length; i++){
|
|
||||||
addTableRow(teamMatches[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return binding.getRoot();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
private void addTableRow(frcMatch match){
|
|
||||||
TableRow tr = new TableRow(getContext());
|
|
||||||
TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams(
|
|
||||||
FrameLayout.LayoutParams.WRAP_CONTENT,
|
|
||||||
FrameLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
);
|
|
||||||
rowParams.setMargins(20,20,20,20);
|
|
||||||
tr.setLayoutParams(rowParams);
|
|
||||||
tr.setPadding(20,20,20,20);
|
|
||||||
tr.setBackgroundColor(0x5000ff00);
|
|
||||||
binding.matchTable.addView(tr);
|
|
||||||
|
|
||||||
TextView tv = new TextView(getContext());
|
|
||||||
tv.setText("Match " + match.matchIndex);
|
|
||||||
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
|
||||||
tr.addView(tv);
|
|
||||||
|
|
||||||
tv = new TextView(getContext());
|
|
||||||
tv.setText("Pos " + match.getTeamAlliance(teamNum));
|
|
||||||
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
|
||||||
tr.addView(tv);
|
|
||||||
|
|
||||||
tr.setOnClickListener(v -> {
|
|
||||||
ReportFragment.setMatch(match);
|
|
||||||
findNavController(this).navigate(R.id.action_navigation_data_report_selector_to_navigation_data_report);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.data;
|
package com.ridgebotics.ridgescout.ui.data;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.toggletitle_black_background;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.toggletitle_unselected;
|
||||||
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
|
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_latest_values;
|
||||||
import static com.ridgebotics.ridgescout.utility.DataManager.match_transferValues;
|
import static com.ridgebotics.ridgescout.utility.DataManager.match_transferValues;
|
||||||
@@ -8,37 +10,36 @@ 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_transferValues;
|
||||||
import static com.ridgebotics.ridgescout.utility.DataManager.pit_values;
|
import static com.ridgebotics.ridgescout.utility.DataManager.pit_values;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TableLayout;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.utility.settingsManager;
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
|
import com.ridgebotics.ridgescout.utility.SettingsManager;
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentDataTeamsBinding;
|
import com.ridgebotics.ridgescout.databinding.FragmentDataTeamsBinding;
|
||||||
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
|
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
|
||||||
import com.ridgebotics.ridgescout.types.data.dataType;
|
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||||
import com.ridgebotics.ridgescout.types.frcTeam;
|
import com.ridgebotics.ridgescout.types.frcTeam;
|
||||||
import com.ridgebotics.ridgescout.utility.DataManager;
|
import com.ridgebotics.ridgescout.utility.DataManager;
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
import com.google.android.material.divider.MaterialDivider;
|
import com.ridgebotics.ridgescout.utility.builders.TextViewBuilder;
|
||||||
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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
// Fragment for viewing the data of a team.
|
||||||
public class TeamsFragment extends Fragment {
|
public class TeamsFragment extends Fragment {
|
||||||
FragmentDataTeamsBinding binding;
|
FragmentDataTeamsBinding binding;
|
||||||
|
|
||||||
@@ -47,232 +48,139 @@ public class TeamsFragment extends Fragment {
|
|||||||
team = 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,
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
@Nullable Bundle savedInstanceState) {
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
|
||||||
binding = FragmentDataTeamsBinding.inflate(inflater, container, false);
|
binding = FragmentDataTeamsBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
binding.teamsArea.removeAllViews();
|
|
||||||
|
|
||||||
DataManager.reload_match_fields();
|
DataManager.reload_match_fields();
|
||||||
DataManager.reload_pit_fields();
|
DataManager.reload_pit_fields();
|
||||||
|
|
||||||
TableLayout table = new TableLayout(getContext());
|
binding.dataTypeSpinner.setTitle("Data Mode");
|
||||||
table.setStretchAllColumns(true);
|
|
||||||
binding.teamsArea.addView(table);
|
|
||||||
|
|
||||||
loadTeam(settingsManager.getDataMode());
|
List<String> options = new ArrayList<>();
|
||||||
|
options.add("Individual");
|
||||||
|
options.add("Compiled");
|
||||||
|
options.add("History");
|
||||||
|
|
||||||
|
binding.dataTypeSpinner.setOptions(options, SettingsManager.getTeamsDataMode());
|
||||||
|
|
||||||
|
binding.dataTypeSpinner.setOnClickListener((item, index) -> {
|
||||||
|
SettingsManager.setTeamsDataMode(index);
|
||||||
|
loadTeam(index);
|
||||||
|
});
|
||||||
|
|
||||||
|
binding.tbaButton.setOnClickListener(v -> openWebPage(
|
||||||
|
"https://www.thebluealliance.com/team/"+team.teamNumber+"/"+SettingsManager.getYearNum()
|
||||||
|
));
|
||||||
|
|
||||||
|
binding.statboticsButton.setOnClickListener(v -> openWebPage(
|
||||||
|
"https://www.statbotics.io/team/"+team.teamNumber+"/"+SettingsManager.getYearNum()
|
||||||
|
));
|
||||||
|
|
||||||
|
loadTeam(SettingsManager.getTeamsDataMode());
|
||||||
|
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void openWebPage(String url) {
|
||||||
|
Uri webpage = Uri.parse(url);
|
||||||
|
Intent intent = new Intent(Intent.ACTION_VIEW, webpage);
|
||||||
|
// if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
|
||||||
|
startActivity(intent);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
public void loadTeam(int mode) {
|
public void loadTeam(int mode) {
|
||||||
binding.teamsArea.removeAllViews();
|
binding.dataTeamCard.fromTeam(team);
|
||||||
|
|
||||||
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());
|
try {add_pit_data(team);}catch(Exception e){AlertManager.error(e);}
|
||||||
|
try {add_match_data(team, mode);}catch(Exception e){AlertManager.error(e);}
|
||||||
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) {
|
|
||||||
|
|
||||||
settingsManager.setDataMode(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){
|
public void add_pit_data(frcTeam team) throws BuiltByteParser.byteParsingExeption {
|
||||||
|
binding.pitArea.removeAllViews();
|
||||||
final String filename = evcode+"-"+team.teamNumber+".pitscoutdata";
|
final String filename = evcode+"-"+team.teamNumber+".pitscoutdata";
|
||||||
|
|
||||||
ll.addView(new MaterialDivider(getContext()));
|
// ll.addView(new MaterialDivider(getContext()));
|
||||||
|
|
||||||
TextView tv = new TextView(getContext());
|
// TextView tv = new TextView(getContext());
|
||||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
// tv.setLayoutParams(new FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
// ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
// ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
));
|
// ));
|
||||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
// tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||||
tv.setPadding(0,10,0,10);
|
// tv.setPadding(0,10,0,10);
|
||||||
tv.setText("----- Pit data -----");
|
// tv.setText("----- Pit data -----");
|
||||||
tv.setTextSize(30);
|
// tv.setTextSize(30);
|
||||||
ll.addView(tv);
|
// ll.addView(tv);
|
||||||
|
|
||||||
ll.addView(new MaterialDivider(getContext()));
|
// ll.addView(new MaterialDivider(getContext()));
|
||||||
|
|
||||||
if(!fileEditor.fileExist(filename)){
|
if(!FileEditor.fileExist(filename)){
|
||||||
tv = new TextView(getContext());
|
binding.pitArea.addView(new TextViewBuilder(getContext(), "No pit data has been collected!")
|
||||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
.layout_match_wrap().align_center().size(23).build());
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(filename, pit_values, pit_transferValues);
|
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(filename, pit_values, pit_transferValues);
|
||||||
|
|
||||||
tv = new TextView(getContext());
|
|
||||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
binding.pitArea.addView(new TextViewBuilder(getContext(), "Pit scouting by " + psda.username)
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
.layout_match_wrap()
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
.padding(0, 20, 0, 5)
|
||||||
));
|
.align_center()
|
||||||
tv.setPadding(0, 20, 0, 5);
|
.size(30)
|
||||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
.build()
|
||||||
tv.setText("Pit scouting by " + psda.username);
|
);
|
||||||
tv.setTextSize(30);
|
|
||||||
ll.addView(tv);
|
|
||||||
|
|
||||||
for (int a = 0; a < psda.data.array.length; a++) {
|
for (int a = 0; a < psda.data.array.length; a++) {
|
||||||
tv = new TextView(getContext());
|
TextViewBuilder tvb = new TextViewBuilder(getContext(), pit_latest_values[a].name)
|
||||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
.align_center()
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
.layout_match_wrap()
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
.size(25);
|
||||||
));
|
|
||||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
|
||||||
tv.setText(psda.data.array[a].getName());
|
|
||||||
tv.setTextSize(25);
|
|
||||||
|
|
||||||
if(psda.data.array[a].isNull()){
|
if(psda.data.array[a].isNull()){
|
||||||
tv.setBackgroundColor(0xffff0000);
|
tvb.tv.setBackgroundColor(toggletitle_unselected);
|
||||||
tv.setTextColor(0xff000000);
|
tvb.tv.setTextColor(toggletitle_black_background);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.pitArea.addView(tvb.build());
|
||||||
ll.addView(tv);
|
|
||||||
|
|
||||||
|
|
||||||
pit_latest_values[a].add_individual_view(ll, psda.data.array[a]);
|
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){
|
||||||
public void add_match_data(LinearLayout ll, frcTeam team, int mode){
|
binding.matchArea.removeAllViews();
|
||||||
String[] files = fileEditor.getMatchesByTeamNum(evcode, team.teamNumber);
|
binding.individualViewSelector.setVisibility(View.GONE);
|
||||||
|
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){
|
if(files.length == 0){
|
||||||
tv = new TextView(getContext());
|
binding.matchArea.addView(new TextViewBuilder(getContext(), "No match data has been collected!")
|
||||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
.layout_match_wrap()
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
.align_center()
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
.size(23)
|
||||||
));
|
.build());
|
||||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
|
||||||
tv.setText("No match data has been collected!");
|
|
||||||
tv.setTextSize(23);
|
|
||||||
ll.addView(tv);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mode){
|
switch (mode){
|
||||||
case 0:
|
case 0:
|
||||||
add_individual_views(ll,files);
|
add_individual_views(files);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
add_compiled_views(ll,files);
|
add_compiled_views(files);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
add_history_views(ll,files);
|
add_history_views(files);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -280,45 +188,69 @@ public class TeamsFragment extends Fragment {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void add_individual_views(LinearLayout ll, String[] files) {
|
public void add_individual_views(String[] files) {
|
||||||
for (int i = 0; i < files.length; i++) {
|
|
||||||
String[] split = files[i].split("-");
|
|
||||||
|
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]);
|
int match_num = Integer.parseInt(split[1]);
|
||||||
|
binding.matchNum.setText(split[1]);
|
||||||
|
|
||||||
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[i], match_values, match_transferValues);
|
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);
|
|
||||||
ll.addView(tv);
|
|
||||||
|
|
||||||
for (int a = 0; a < psda.data.array.length; a++) {
|
TextView title = new TextViewBuilder(getContext(),
|
||||||
tv = new TextView(getContext());
|
"M" + (match_num) + " " + split[2] + "-" + split[3] + " by " + psda.username)
|
||||||
tv.setLayoutParams(new FrameLayout.LayoutParams(
|
.align_center()
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
.size(30)
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
.padding(0, 0, 40, 5)
|
||||||
));
|
.build();
|
||||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
title.setPaintFlags(title.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
|
||||||
tv.setText(psda.data.array[a].getName());
|
binding.matchArea.addView(title);
|
||||||
tv.setTextSize(25);
|
|
||||||
|
|
||||||
if (psda.data.array[a].isNull()) {
|
for (int i = 0; i < psda.data.array.length; i++) {
|
||||||
tv.setBackgroundColor(0xffff0000);
|
TextViewBuilder tv = new TextViewBuilder(getContext(), match_latest_values[i].name)
|
||||||
tv.setTextColor(0xff000000);
|
.align_left()
|
||||||
|
.size(25);
|
||||||
|
|
||||||
|
if (psda.data.array[i].isNull()) {
|
||||||
|
tv.tv.setBackgroundColor(toggletitle_unselected);
|
||||||
|
tv.tv.setTextColor(toggletitle_black_background);
|
||||||
}
|
}
|
||||||
|
|
||||||
ll.addView(tv);
|
binding.matchArea.addView(tv.build());
|
||||||
|
|
||||||
|
|
||||||
match_latest_values[a].add_individual_view(ll, psda.data.array[a]);
|
if(psda.data.array[i] != null)
|
||||||
|
match_latest_values[i].add_individual_view(binding.matchArea, psda.data.array[i]);
|
||||||
}
|
}
|
||||||
|
}catch (Exception e){
|
||||||
|
AlertManager.error("Failure to load file " + files[matchIndex], e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -326,29 +258,33 @@ public class TeamsFragment extends Fragment {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void add_compiled_views(LinearLayout ll, String[] files){
|
public void add_compiled_views(String[] files){
|
||||||
dataType[][] data = new dataType[match_latest_values.length][files.length];
|
RawDataType[][] data = new RawDataType[match_latest_values.length][files.length];
|
||||||
for (int i = 0; i < files.length; i++) {
|
for (int i = 0; i < files.length; i++) {
|
||||||
|
try {
|
||||||
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[i], match_values, match_transferValues);
|
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[i], match_values, match_transferValues);
|
||||||
for (int a = 0; a < data.length; a++) {
|
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];
|
data[a][i] = psda.data.array[a];
|
||||||
}
|
}
|
||||||
|
} catch (Exception e){
|
||||||
|
AlertManager.error("Failure to load file " + files[i], e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < match_latest_values.length; 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);
|
|
||||||
ll.addView(tv);
|
|
||||||
|
|
||||||
match_latest_values[i].add_compiled_view(ll, data[i]);
|
binding.matchArea.addView(
|
||||||
|
new TextViewBuilder(getContext(), match_latest_values[i].name)
|
||||||
|
.align_center()
|
||||||
|
.padding(0, 0, 20, 5)
|
||||||
|
.size(30)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
if(data[i] != null)
|
||||||
|
match_latest_values[i].add_compiled_view(binding.matchArea, data[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,29 +292,33 @@ public class TeamsFragment extends Fragment {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void add_history_views(LinearLayout ll, String[] files){
|
public void add_history_views(String[] files){
|
||||||
dataType[][] data = new dataType[match_latest_values.length][files.length];
|
RawDataType[][] data = new RawDataType[match_latest_values.length][files.length];
|
||||||
for (int i = 0; i < files.length; i++) {
|
for (int i = 0; i < files.length; i++) {
|
||||||
|
try {
|
||||||
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[i], match_values, match_transferValues);
|
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[i], match_values, match_transferValues);
|
||||||
for (int a = 0; a < data.length; a++) {
|
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];
|
data[a][i] = psda.data.array[a];
|
||||||
}
|
}
|
||||||
|
}catch (Exception e){
|
||||||
|
AlertManager.error("Failure to load file " + files[i], e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < match_latest_values.length; 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);
|
|
||||||
ll.addView(tv);
|
|
||||||
|
|
||||||
match_latest_values[i].add_history_view(ll, data[i]);
|
TextView tv = new TextViewBuilder(getContext(), match_latest_values[i].name)
|
||||||
|
.align_center()
|
||||||
|
.size(30)
|
||||||
|
.padding(0,0,20,5)
|
||||||
|
.build();
|
||||||
|
tv.setPaintFlags(tv.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
|
||||||
|
binding.matchArea.addView(tv);
|
||||||
|
|
||||||
|
if(data[i] != null)
|
||||||
|
match_latest_values[i].add_history_view(binding.matchArea, data[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,409 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.scouting;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.color_found;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.color_not_found;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.color_rescout;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.DataManager.event;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.InputType;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
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.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.databinding.FragmentScoutingEventBinding;
|
||||||
|
import com.ridgebotics.ridgescout.types.frcTeam;
|
||||||
|
import com.ridgebotics.ridgescout.ui.views.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 com.ridgebotics.ridgescout.utility.builders.TextViewBuilder;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
// Fragment to show the status of scouting, aswell as adding or removing matches and teams manually.
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
private void addTableText(TableRow tr, String textStr){
|
||||||
|
tr.addView(new TextViewBuilder(getContext(), textStr)
|
||||||
|
.align_center()
|
||||||
|
.size(18)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
TextViewBuilder text = new TextViewBuilder(getContext(), String.valueOf(num))
|
||||||
|
.size(18)
|
||||||
|
.align_center();
|
||||||
|
|
||||||
|
final String filename = event.eventCode + "-" + num + ".pitscoutdata";
|
||||||
|
if(FileEditor.fileExist(filename)){
|
||||||
|
final boolean[] rescout = {DataManager.rescout_list.contains(filename)};
|
||||||
|
|
||||||
|
text.tv.setBackgroundColor(rescout[0] ? color_rescout : color_found);
|
||||||
|
|
||||||
|
text.tv.setOnLongClickListener(view -> {
|
||||||
|
rescout[0] = !rescout[0];
|
||||||
|
if(rescout[0]) {
|
||||||
|
text.tv.setBackgroundColor(color_rescout);
|
||||||
|
DataManager.rescout_list.add(filename);
|
||||||
|
}else{
|
||||||
|
text.tv.setBackgroundColor(color_found);
|
||||||
|
DataManager.rescout_list.remove(filename);
|
||||||
|
}
|
||||||
|
DataManager.save_rescout_list();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
text.tv.setBackgroundColor(color_not_found);
|
||||||
|
}
|
||||||
|
tr.addView(text.build());
|
||||||
|
}
|
||||||
|
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++){
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextViewBuilder text = new TextViewBuilder(getContext(), String.valueOf(team_num))
|
||||||
|
.size(18)
|
||||||
|
.align_center();
|
||||||
|
|
||||||
|
final String filename = event.eventCode + "-" + match.matchIndex + "-" + alliance_position + "-" + team_num + ".matchscoutdata";
|
||||||
|
if(FileEditor.fileExist(filename)){
|
||||||
|
final boolean[] rescout = {DataManager.rescout_list.contains(filename)};
|
||||||
|
|
||||||
|
text.tv.setBackgroundColor(rescout[0] ? color_rescout : color_found);
|
||||||
|
|
||||||
|
text.tv.setOnLongClickListener(view -> {
|
||||||
|
rescout[0] = !rescout[0];
|
||||||
|
if(rescout[0]) {
|
||||||
|
text.tv.setBackgroundColor(color_rescout);
|
||||||
|
DataManager.rescout_list.add(filename);
|
||||||
|
}else{
|
||||||
|
text.tv.setBackgroundColor(color_found);
|
||||||
|
DataManager.rescout_list.remove(filename);
|
||||||
|
}
|
||||||
|
DataManager.save_rescout_list();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
}else{
|
||||||
|
text.tv.setBackgroundColor(color_not_found);
|
||||||
|
}
|
||||||
|
tr.addView(text.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
Log.i(getClass().toString(), String.valueOf(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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+128
-97
@@ -1,10 +1,15 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.scouting;
|
package com.ridgebotics.ridgescout.ui.scouting;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.AutoSaveManager.AUTO_SAVE_DELAY;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.rescout_color;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.saved_color;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.unsaved_color;
|
||||||
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
|
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
|
||||||
import static com.ridgebotics.ridgescout.utility.DataManager.event;
|
import static com.ridgebotics.ridgescout.utility.DataManager.event;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -14,21 +19,23 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.utility.settingsManager;
|
import com.google.android.material.divider.MaterialDivider;
|
||||||
|
import com.ridgebotics.ridgescout.ui.views.ToggleTitleView;
|
||||||
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
|
import com.ridgebotics.ridgescout.utility.SettingsManager;
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentScoutingMatchBinding;
|
import com.ridgebotics.ridgescout.databinding.FragmentScoutingMatchBinding;
|
||||||
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
|
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
|
||||||
import com.ridgebotics.ridgescout.types.data.dataType;
|
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||||
import com.ridgebotics.ridgescout.types.frcMatch;
|
import com.ridgebotics.ridgescout.types.frcMatch;
|
||||||
import com.ridgebotics.ridgescout.types.frcTeam;
|
import com.ridgebotics.ridgescout.types.frcTeam;
|
||||||
import com.ridgebotics.ridgescout.types.input.inputType;
|
import com.ridgebotics.ridgescout.types.input.FieldType;
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
import com.ridgebotics.ridgescout.utility.AutoSaveManager;
|
import com.ridgebotics.ridgescout.utility.AutoSaveManager;
|
||||||
import com.ridgebotics.ridgescout.utility.DataManager;
|
import com.ridgebotics.ridgescout.utility.DataManager;
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
|
import com.ridgebotics.ridgescout.utility.builders.TextViewBuilder;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
|
// Fragment for match scouting data editing.
|
||||||
public class MatchScoutingFragment extends Fragment {
|
public class MatchScoutingFragment extends Fragment {
|
||||||
|
|
||||||
private FragmentScoutingMatchBinding binding;
|
private FragmentScoutingMatchBinding binding;
|
||||||
@@ -41,59 +48,55 @@ public class MatchScoutingFragment extends Fragment {
|
|||||||
|
|
||||||
DataManager.reload_match_fields();
|
DataManager.reload_match_fields();
|
||||||
|
|
||||||
alliance_position = settingsManager.getAllyPos();
|
alliance_position = SettingsManager.getAllyPos();
|
||||||
username = settingsManager.getUsername();
|
username = SettingsManager.getUsername();
|
||||||
|
|
||||||
binding.username.setText(username);
|
binding.bindicator.setUsername(username);
|
||||||
binding.alliancePosText.setText(alliance_position);
|
binding.bindicator.setAlliancePos(alliance_position);
|
||||||
|
binding.bindicator.bringToFront();
|
||||||
|
|
||||||
binding.teamDescription.setVisibility(View.GONE);
|
binding.matchTeamCard.setVisibility(View.GONE);
|
||||||
binding.teamName.setVisibility(View.GONE);
|
|
||||||
clear_fields();
|
clear_fields();
|
||||||
binding.teamDescription.setVisibility(View.VISIBLE);
|
binding.matchTeamCard.setVisibility(View.VISIBLE);
|
||||||
binding.teamName.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
if(DataManager.match_values == null || DataManager.match_values.length == 0){
|
if(DataManager.match_values == null || DataManager.match_values.length == 0){
|
||||||
TextView tv = new TextView(getContext());
|
|
||||||
tv.setText("Failed to load fields.\nTry to either download or create match scouting fields.");
|
binding.MatchScoutArea.addView(
|
||||||
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
new TextViewBuilder(getContext(), "Failed to load fields.\nTry to either download or create match scouting fields.")
|
||||||
binding.MatchScoutArea.addView(tv);
|
.align_center()
|
||||||
|
.build());
|
||||||
|
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
binding.bindicator.match_indicator_next_button.setOnClickListener(v -> {
|
||||||
cur_match_num = settingsManager.getMatchNum();
|
|
||||||
update_match_num();
|
|
||||||
|
|
||||||
binding.nextButton.setOnClickListener(v -> {
|
|
||||||
if(edited) save();
|
if(edited) save();
|
||||||
settingsManager.setMatchNum(cur_match_num+1);
|
SettingsManager.setMatchNum(cur_match_num+1);
|
||||||
cur_match_num += 1;
|
cur_match_num += 1;
|
||||||
update_match_num();
|
update_match_num();
|
||||||
update_scouting_data();
|
update_scouting_data();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(SettingsManager.getEnableQuickAlliancePosChange())
|
||||||
boolean fileIndicatorTapped = false;
|
binding.bindicator.setOnClickListener(v -> {
|
||||||
binding.fileIndicator.setOnClickListener(v -> {
|
// if(e.getAction() != MotionEvent.ACTION_MOVE) return true;
|
||||||
// if(e.getAction() != MotionEvent.ACTION_MOVE) return true;
|
// System.out.println(e.getAxisValue(0));
|
||||||
// System.out.println(e.getAxisValue(0));
|
|
||||||
if(edited) save();
|
if(edited) save();
|
||||||
|
|
||||||
alliance_position = incrementMatchPos(alliance_position);
|
alliance_position = incrementMatchPos(alliance_position);
|
||||||
settingsManager.setAllyPos(alliance_position);
|
SettingsManager.setAllyPos(alliance_position);
|
||||||
binding.alliancePosText.setText(alliance_position);
|
binding.bindicator.setAlliancePos(alliance_position);
|
||||||
|
|
||||||
update_match_num();
|
update_match_num();
|
||||||
update_scouting_data();
|
update_scouting_data();
|
||||||
// return true;
|
// return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
binding.backButton.setOnClickListener(v -> {
|
binding.bindicator.match_indicator_back_button.setOnClickListener(v -> {
|
||||||
if(edited) save();
|
if(edited) save();
|
||||||
settingsManager.setMatchNum(cur_match_num-1);
|
SettingsManager.setMatchNum(cur_match_num-1);
|
||||||
cur_match_num -= 1;
|
cur_match_num -= 1;
|
||||||
update_match_num();
|
update_match_num();
|
||||||
update_scouting_data();
|
update_scouting_data();
|
||||||
@@ -103,9 +106,22 @@ public class MatchScoutingFragment extends Fragment {
|
|||||||
// if(edited) save();
|
// 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();
|
create_fields();
|
||||||
update_scouting_data();
|
update_scouting_data();
|
||||||
|
|
||||||
|
if(DataManager.scoutNotice.isEmpty())
|
||||||
|
binding.scoutingNoticeBox.setVisibility(View.GONE);
|
||||||
|
else
|
||||||
|
binding.scoutingNoticeText.setText(DataManager.scoutNotice);
|
||||||
|
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,40 +143,35 @@ public class MatchScoutingFragment extends Fragment {
|
|||||||
return "red-1";
|
return "red-1";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int unsaved_color = 0x60ff0000;
|
|
||||||
private static final int saved_color = 0x6000ff00;
|
|
||||||
|
|
||||||
String alliance_position;
|
String alliance_position;
|
||||||
int cur_match_num;
|
int cur_match_num;
|
||||||
String username;
|
String username;
|
||||||
|
String fileUsernames = "";
|
||||||
String filename;
|
String filename;
|
||||||
|
|
||||||
boolean edited = false;
|
boolean edited = false;
|
||||||
|
boolean rescout = false;
|
||||||
TextView[] titles;
|
ToggleTitleView[] titles;
|
||||||
|
AutoSaveManager asm = new AutoSaveManager(this::save, AUTO_SAVE_DELAY);
|
||||||
AutoSaveManager asm = new AutoSaveManager(this::save);
|
|
||||||
|
|
||||||
ArrayList<dataType> dataTypes;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void save(){
|
public void save(){
|
||||||
System.out.println("Saved!");
|
Log.i(this.getClass().toString(), "Saved!");
|
||||||
edited = false;
|
edited = false;
|
||||||
set_indicator_color(saved_color);
|
enableRescoutButton();
|
||||||
AlertManager.toast("Saved " + filename);
|
AlertManager.toast("Saved " + filename);
|
||||||
save_fields();
|
save_fields();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set_indicator_color(int color){
|
public void set_indicator_color(int color){
|
||||||
binding.fileIndicator.setBackgroundColor(color);
|
binding.bindicator.setColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update_asm(){
|
public void update_asm(){
|
||||||
// v.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
|
// v.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
|
||||||
edited = true;
|
edited = true;
|
||||||
set_indicator_color(unsaved_color);
|
set_indicator_color(unsaved_color);
|
||||||
|
disableRescoutButton();
|
||||||
asm.update();
|
asm.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,48 +197,41 @@ public class MatchScoutingFragment extends Fragment {
|
|||||||
asm.stop();
|
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++) {
|
for(int i = 0 ; i < DataManager.match_latest_values.length; i++) {
|
||||||
final TextView tv = new TextView(getContext());
|
binding.MatchScoutArea.addView(new MaterialDivider(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;
|
|
||||||
|
|
||||||
default_text_color = tv.getCurrentTextColor();
|
|
||||||
|
|
||||||
final View v = DataManager.match_latest_values[i].createView(getContext(), new Function<dataType, Integer>() {
|
final ToggleTitleView ttv = new ToggleTitleView(getContext());
|
||||||
@Override
|
ttv.setTitle(DataManager.match_latest_values[i].name);
|
||||||
public Integer apply(dataType dataType) {
|
ttv.setDescription(DataManager.match_latest_values[i].description);
|
||||||
|
titles[i] = ttv;
|
||||||
|
|
||||||
|
|
||||||
|
final View v = DataManager.match_latest_values[i].createView(getContext(), dataType -> {
|
||||||
// edited = true;
|
// edited = true;
|
||||||
if(asm.isRunning)
|
if(asm.isRunning)
|
||||||
update_asm();
|
update_asm();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
binding.MatchScoutArea.addView(tv);
|
binding.MatchScoutArea.addView(ttv);
|
||||||
int fi = i;
|
int fi = i;
|
||||||
tv.setOnClickListener(p -> {
|
|
||||||
// boolean blank = !latest_values[fi].getViewValue().isNull();
|
|
||||||
|
|
||||||
// System.out.println(blank);
|
ttv.setOnToggleListener(enabled -> {
|
||||||
if(asm.isRunning)
|
if(asm.isRunning)
|
||||||
update_asm();
|
update_asm();
|
||||||
|
|
||||||
if(!DataManager.match_latest_values[fi].isBlank){
|
// System.out.println("Checked!");
|
||||||
tv.setBackgroundColor(0xffff0000);
|
|
||||||
tv.setTextColor(0xff000000);
|
if(enabled){
|
||||||
DataManager.match_latest_values[fi].nullify();
|
DataManager.match_latest_values[fi].nullify();
|
||||||
}else{
|
}else
|
||||||
tv.setBackgroundColor(0x00000000);
|
|
||||||
tv.setTextColor(default_text_color);
|
|
||||||
DataManager.match_latest_values[fi].setViewValue(DataManager.match_latest_values[fi].default_value);
|
DataManager.match_latest_values[fi].setViewValue(DataManager.match_latest_values[fi].default_value);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
binding.MatchScoutArea.addView(v);
|
binding.MatchScoutArea.addView(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,18 +244,18 @@ public class MatchScoutingFragment extends Fragment {
|
|||||||
|
|
||||||
edited = false;
|
edited = false;
|
||||||
|
|
||||||
binding.matchnum.setText(String.valueOf(cur_match_num+1));
|
binding.bindicator.setMatchNum(String.valueOf(cur_match_num+1));
|
||||||
|
|
||||||
if(cur_match_num <= 0){
|
if(cur_match_num <= 0){
|
||||||
binding.backButton.setVisibility(View.GONE);
|
binding.bindicator.match_indicator_back_button.setVisibility(View.GONE);
|
||||||
}else{
|
}else{
|
||||||
binding.backButton.setVisibility(View.VISIBLE);
|
binding.bindicator.match_indicator_back_button.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cur_match_num >= event.matches.size()-1){
|
if(cur_match_num >= event.matches.size()-1){
|
||||||
binding.nextButton.setVisibility(View.GONE);
|
binding.bindicator.match_indicator_next_button.setVisibility(View.GONE);
|
||||||
}else{
|
}else{
|
||||||
binding.nextButton.setVisibility(View.VISIBLE);
|
binding.bindicator.match_indicator_next_button.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,7 +277,7 @@ public class MatchScoutingFragment extends Fragment {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.barTeamNum.setText(String.valueOf(team_num));
|
binding.bindicator.setTeamNum(String.valueOf(team_num));
|
||||||
|
|
||||||
frcTeam team = null;
|
frcTeam team = null;
|
||||||
for(int i=0; i < event.teams.size(); i++){
|
for(int i=0; i < event.teams.size(); i++){
|
||||||
@@ -286,6 +290,8 @@ public class MatchScoutingFragment extends Fragment {
|
|||||||
|
|
||||||
filename = evcode + "-" + (cur_match_num+1) + "-" + alliance_position + "-" + team_num + ".matchscoutdata";
|
filename = evcode + "-" + (cur_match_num+1) + "-" + alliance_position + "-" + team_num + ".matchscoutdata";
|
||||||
|
|
||||||
|
rescout = DataManager.rescout_list.contains(filename);
|
||||||
|
|
||||||
return team;
|
return team;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,10 +303,16 @@ public class MatchScoutingFragment extends Fragment {
|
|||||||
frcMatch match = event.matches.get(cur_match_num);
|
frcMatch match = event.matches.get(cur_match_num);
|
||||||
frcTeam team = get_team(match);
|
frcTeam team = get_team(match);
|
||||||
|
|
||||||
binding.teamName.setText(team.teamName);
|
if(team == null) {
|
||||||
binding.teamDescription.setText(team.getDescription());
|
AlertManager.addSimpleError("This team does not exist!");
|
||||||
|
binding.matchTeamCard.setTeamName("Error!");
|
||||||
|
binding.matchTeamCard.setTeamDescription("Error!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
boolean new_file = !fileEditor.fileExist(filename);
|
binding.matchTeamCard.fromTeam(team);
|
||||||
|
|
||||||
|
boolean new_file = !FileEditor.fileExist(filename);
|
||||||
|
|
||||||
if(asm.isRunning){
|
if(asm.isRunning){
|
||||||
asm.stop();
|
asm.stop();
|
||||||
@@ -309,14 +321,16 @@ public class MatchScoutingFragment extends Fragment {
|
|||||||
if(new_file){
|
if(new_file){
|
||||||
default_fields();
|
default_fields();
|
||||||
set_indicator_color(unsaved_color);
|
set_indicator_color(unsaved_color);
|
||||||
|
disableRescoutButton();
|
||||||
}else{
|
}else{
|
||||||
try {
|
try {
|
||||||
get_fields();
|
get_fields();
|
||||||
set_indicator_color(saved_color);
|
enableRescoutButton();
|
||||||
} catch (Exception e){
|
} catch (Exception e){
|
||||||
AlertManager.error(e);
|
AlertManager.error(e);
|
||||||
default_fields();
|
default_fields();
|
||||||
set_indicator_color(unsaved_color);
|
set_indicator_color(unsaved_color);
|
||||||
|
disableRescoutButton();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,20 +342,21 @@ public class MatchScoutingFragment extends Fragment {
|
|||||||
|
|
||||||
public void default_fields(){
|
public void default_fields(){
|
||||||
for(int i = 0; i < DataManager.match_latest_values.length; i++){
|
for(int i = 0; i < DataManager.match_latest_values.length; i++){
|
||||||
inputType input = DataManager.match_latest_values[i];
|
FieldType input = DataManager.match_latest_values[i];
|
||||||
input.setViewValue(input.default_value);
|
input.setViewValue(input.default_value);
|
||||||
|
|
||||||
titles[i].setBackgroundColor(0x00000000);
|
titles[i].enable();
|
||||||
titles[i].setTextColor(default_text_color);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void get_fields(){
|
public void get_fields() throws BuiltByteParser.byteParsingExeption{
|
||||||
|
|
||||||
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.match_values, DataManager.match_transferValues);
|
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.match_values, DataManager.match_transferValues);
|
||||||
dataType[] types = psdr.data.array;
|
RawDataType[] types = psdr.data.array;
|
||||||
|
fileUsernames = psdr.username;
|
||||||
|
|
||||||
|
|
||||||
for(int i = 0; i < DataManager.match_latest_values.length; i++){
|
for(int i = 0; i < DataManager.match_latest_values.length; i++){
|
||||||
// types[i] = latest_values[i].getViewValue();
|
// types[i] = latest_values[i].getViewValue();
|
||||||
@@ -352,14 +367,8 @@ public class MatchScoutingFragment extends Fragment {
|
|||||||
DataManager.match_latest_values[i].setViewValue(DataManager.match_latest_values[i].default_value);
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,15 +376,37 @@ public class MatchScoutingFragment extends Fragment {
|
|||||||
|
|
||||||
public void save_fields(){
|
public void save_fields(){
|
||||||
|
|
||||||
dataType[] types = new dataType[DataManager.match_latest_values.length];
|
RawDataType[] types = new RawDataType[DataManager.match_latest_values.length];
|
||||||
|
|
||||||
for(int i = 0; i < DataManager.match_latest_values.length; i++){
|
for(int i = 0; i < DataManager.match_latest_values.length; i++){
|
||||||
types[i] = DataManager.match_latest_values[i].getViewValue();
|
types[i] = DataManager.match_latest_values[i].getViewValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ScoutingDataWriter.save(DataManager.match_values.length-1, username, filename, types))
|
if(ScoutingDataWriter.save(DataManager.match_values.length-1, ScoutingDataWriter.checkAddName(fileUsernames, username), filename, types))
|
||||||
System.out.println("Saved!");
|
Log.i(getClass().toString(), "Saved!");
|
||||||
else
|
else
|
||||||
System.out.println("Error saving");
|
Log.i(getClass().toString(), "Error saving");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enableRescoutButton(){
|
||||||
|
set_indicator_color(rescout ? rescout_color : saved_color);
|
||||||
|
binding.bindicator.setOnLongClickListener(v -> {
|
||||||
|
rescout = !rescout;
|
||||||
|
if(rescout){
|
||||||
|
set_indicator_color(rescout_color);
|
||||||
|
DataManager.rescout_list.add(filename);
|
||||||
|
DataManager.save_rescout_list();
|
||||||
|
}else{
|
||||||
|
set_indicator_color(saved_color);
|
||||||
|
DataManager.rescout_list.remove(filename);
|
||||||
|
DataManager.save_rescout_list();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void disableRescoutButton(){
|
||||||
|
binding.bindicator.setOnLongClickListener(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,43 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.scouting;
|
package com.ridgebotics.ridgescout.ui.scouting;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.AutoSaveManager.AUTO_SAVE_DELAY;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.rescout_color;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.saved_color;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.unsaved_color;
|
||||||
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
|
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_latest_values;
|
||||||
import static com.ridgebotics.ridgescout.utility.DataManager.pit_transferValues;
|
import static com.ridgebotics.ridgescout.utility.DataManager.pit_transferValues;
|
||||||
import static com.ridgebotics.ridgescout.utility.DataManager.pit_values;
|
import static com.ridgebotics.ridgescout.utility.DataManager.pit_values;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import com.google.android.material.divider.MaterialDivider;
|
||||||
|
import com.ridgebotics.ridgescout.ui.views.PitScoutingIndicator;
|
||||||
|
import com.ridgebotics.ridgescout.ui.views.ToggleTitleView;
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
import com.ridgebotics.ridgescout.utility.settingsManager;
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
|
import com.ridgebotics.ridgescout.utility.SettingsManager;
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentScoutingPitBinding;
|
import com.ridgebotics.ridgescout.databinding.FragmentScoutingPitBinding;
|
||||||
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
|
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
|
||||||
import com.ridgebotics.ridgescout.types.data.dataType;
|
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||||
import com.ridgebotics.ridgescout.types.frcTeam;
|
import com.ridgebotics.ridgescout.types.frcTeam;
|
||||||
import com.ridgebotics.ridgescout.types.input.inputType;
|
import com.ridgebotics.ridgescout.types.input.FieldType;
|
||||||
import com.ridgebotics.ridgescout.utility.AutoSaveManager;
|
import com.ridgebotics.ridgescout.utility.AutoSaveManager;
|
||||||
import com.ridgebotics.ridgescout.utility.DataManager;
|
import com.ridgebotics.ridgescout.utility.DataManager;
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
// Fragment for pit scouting data editing
|
||||||
public class PitScoutingFragment extends Fragment {
|
public class PitScoutingFragment extends Fragment {
|
||||||
|
|
||||||
FragmentScoutingPitBinding binding;
|
FragmentScoutingPitBinding binding;
|
||||||
@@ -44,52 +53,61 @@ public class PitScoutingFragment extends Fragment {
|
|||||||
|
|
||||||
binding = FragmentScoutingPitBinding.inflate(inflater, container, false);
|
binding = FragmentScoutingPitBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
username = settingsManager.getUsername();
|
username = SettingsManager.getUsername();
|
||||||
DataManager.reload_pit_fields();
|
DataManager.reload_pit_fields();
|
||||||
|
|
||||||
|
if(pit_latest_values == null) {
|
||||||
|
AlertManager.addSimpleError("Error loading pit fields!");
|
||||||
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(DataManager.scoutNotice.isEmpty())
|
||||||
|
binding.scoutingNoticeBox.setVisibility(View.GONE);
|
||||||
|
else
|
||||||
|
binding.scoutingNoticeText.setText(DataManager.scoutNotice);
|
||||||
|
|
||||||
loadTeam();
|
loadTeam();
|
||||||
|
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
private static final int unsaved_color = 0x60ff0000;
|
|
||||||
private static final int saved_color = 0x6000ff00;
|
|
||||||
|
|
||||||
boolean edited = false;
|
boolean edited = false;
|
||||||
|
boolean rescout = false;
|
||||||
|
|
||||||
String filename;
|
String filename;
|
||||||
String username;
|
String username;
|
||||||
|
|
||||||
TextView[] titles;
|
String fileUsernames = "";
|
||||||
|
ToggleTitleView[] titles;
|
||||||
|
AutoSaveManager asm = new AutoSaveManager(this::save, AUTO_SAVE_DELAY);
|
||||||
|
|
||||||
AutoSaveManager asm = new AutoSaveManager(this::save);
|
ArrayList<RawDataType> rawDataTypes;
|
||||||
|
|
||||||
ArrayList<dataType> dataTypes;
|
|
||||||
|
|
||||||
public void save(){
|
public void save(){
|
||||||
edited = false;
|
edited = false;
|
||||||
set_indicator_color(saved_color);
|
enableRescoutButton();
|
||||||
|
|
||||||
dataType[] types = new dataType[pit_latest_values.length];
|
RawDataType[] types = new RawDataType[pit_latest_values.length];
|
||||||
|
|
||||||
for(int i = 0; i < pit_latest_values.length; i++){
|
for(int i = 0; i < pit_latest_values.length; i++){
|
||||||
types[i] = pit_latest_values[i].getViewValue();
|
types[i] = pit_latest_values[i].getViewValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ScoutingDataWriter.save(pit_values.length-1, username, filename, types)) {
|
if(ScoutingDataWriter.save(pit_values.length-1, ScoutingDataWriter.checkAddName(fileUsernames, username), filename, types)) {
|
||||||
System.out.println("Saved!");
|
Log.i(getClass().toString(), "Saved!");
|
||||||
AlertManager.toast("Saved " + filename);
|
Log.i(getClass().toString(), "Saved " + filename);
|
||||||
}else
|
}else
|
||||||
System.out.println("Error saving");
|
Log.i(getClass().toString(), "Error saving");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set_indicator_color(int color){
|
public void set_indicator_color(int color){
|
||||||
binding.pitFileIndicator.setBackgroundColor(color);
|
binding.pitIndicator.setColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update_asm(){
|
public void update_asm(){
|
||||||
// v.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
|
// v.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
|
||||||
edited = true;
|
edited = true;
|
||||||
set_indicator_color(unsaved_color);
|
set_indicator_color(unsaved_color);
|
||||||
|
disableRescoutButton();
|
||||||
asm.update();
|
asm.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,17 +115,13 @@ public class PitScoutingFragment extends Fragment {
|
|||||||
public void loadTeam(){
|
public void loadTeam(){
|
||||||
// clear_fields();
|
// clear_fields();
|
||||||
|
|
||||||
binding.pitFileIndicator.setVisibility(View.VISIBLE);
|
binding.pitsTeamCard.setVisibility(View.VISIBLE);
|
||||||
binding.pitTeamName.setVisibility(View.VISIBLE);
|
binding.pitIndicator.setTeamNum(team.teamNumber);
|
||||||
binding.pitTeamDescription.setVisibility(View.VISIBLE);
|
binding.pitIndicator.setUsername(SettingsManager.getUsername());
|
||||||
|
binding.pitsTeamCard.fromTeam(team);
|
||||||
binding.pitTeamName.setText(team.teamName);
|
|
||||||
binding.pitTeamDescription.setText(team.getDescription());
|
|
||||||
binding.pitBarTeamNum.setText(String.valueOf(team.teamNumber));
|
|
||||||
|
|
||||||
filename = evcode + "-" + team.teamNumber + ".pitscoutdata";
|
filename = evcode + "-" + team.teamNumber + ".pitscoutdata";
|
||||||
|
rescout = DataManager.rescout_list.contains(filename);
|
||||||
boolean new_file = !fileEditor.fileExist(filename);
|
|
||||||
|
|
||||||
if(asm.isRunning){
|
if(asm.isRunning){
|
||||||
asm.stop();
|
asm.stop();
|
||||||
@@ -115,13 +129,16 @@ public class PitScoutingFragment extends Fragment {
|
|||||||
|
|
||||||
create_fields();
|
create_fields();
|
||||||
|
|
||||||
if(new_file){
|
if(!FileEditor.fileExist(filename)){
|
||||||
default_fields();
|
default_fields();
|
||||||
set_indicator_color(unsaved_color);
|
set_indicator_color(unsaved_color);
|
||||||
|
disableRescoutButton();
|
||||||
}else{
|
}else{
|
||||||
try {
|
try {
|
||||||
get_fields();
|
get_fields();
|
||||||
set_indicator_color(saved_color);
|
|
||||||
|
enableRescoutButton();
|
||||||
|
|
||||||
} catch (Exception e){
|
} catch (Exception e){
|
||||||
AlertManager.error(e);
|
AlertManager.error(e);
|
||||||
default_fields();
|
default_fields();
|
||||||
@@ -129,11 +146,33 @@ public class PitScoutingFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.pitIndicator.bringToFront();
|
||||||
|
|
||||||
asm.start();
|
asm.start();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int default_text_color = 0;
|
private void enableRescoutButton(){
|
||||||
|
set_indicator_color(rescout ? rescout_color : saved_color);
|
||||||
|
binding.pitIndicator.setOnLongClickListener(v -> {
|
||||||
|
rescout = !rescout;
|
||||||
|
if(rescout){
|
||||||
|
set_indicator_color(rescout_color);
|
||||||
|
DataManager.rescout_list.add(filename);
|
||||||
|
DataManager.save_rescout_list();
|
||||||
|
}else{
|
||||||
|
set_indicator_color(saved_color);
|
||||||
|
DataManager.rescout_list.remove(filename);
|
||||||
|
DataManager.save_rescout_list();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void disableRescoutButton(){
|
||||||
|
binding.pitIndicator.setOnLongClickListener(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void create_fields() {
|
private void create_fields() {
|
||||||
@@ -141,37 +180,32 @@ public class PitScoutingFragment extends Fragment {
|
|||||||
asm.stop();
|
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++) {
|
for(int i = 0 ; i < pit_latest_values.length; i++) {
|
||||||
TextView tv = new TextView(getContext());
|
binding.pitScoutArea.addView(new MaterialDivider(getContext()));
|
||||||
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
|
||||||
tv.setText(pit_latest_values[i].name);
|
ToggleTitleView ttv = new ToggleTitleView(getContext());
|
||||||
tv.setTextSize(24);
|
ttv.setTitle(pit_latest_values[i].name);
|
||||||
tv.setPadding(8,8,8,8);
|
ttv.setDescription(pit_latest_values[i].description);
|
||||||
titles[i] = tv;
|
titles[i] = ttv;
|
||||||
binding.pitScoutArea.addView(tv);
|
binding.pitScoutArea.addView(ttv);
|
||||||
|
|
||||||
default_text_color = tv.getCurrentTextColor();
|
|
||||||
|
|
||||||
int fi = i;
|
int fi = i;
|
||||||
tv.setOnClickListener(p -> {
|
ttv.setOnToggleListener(enabled -> {
|
||||||
update_asm();
|
update_asm();
|
||||||
|
|
||||||
if(!pit_latest_values[fi].isBlank){
|
if(enabled){
|
||||||
tv.setBackgroundColor(0xffff0000);
|
|
||||||
tv.setTextColor(0xff000000);
|
|
||||||
pit_latest_values[fi].nullify();
|
pit_latest_values[fi].nullify();
|
||||||
}else{
|
}else{
|
||||||
tv.setBackgroundColor(0x00000000);
|
|
||||||
tv.setTextColor(default_text_color);
|
|
||||||
pit_latest_values[fi].setViewValue(pit_latest_values[fi].default_value);
|
pit_latest_values[fi].setViewValue(pit_latest_values[fi].default_value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
View v = pit_latest_values[i].createView(getContext(), new Function<dataType, Integer>() {
|
View v = pit_latest_values[i].createView(getContext(), new Function<RawDataType, Integer>() {
|
||||||
@Override
|
@Override
|
||||||
public Integer apply(dataType dataType) {
|
public Integer apply(RawDataType dataType) {
|
||||||
// edited = true;
|
// edited = true;
|
||||||
if(asm.isRunning)
|
if(asm.isRunning)
|
||||||
update_asm();
|
update_asm();
|
||||||
@@ -185,29 +219,26 @@ public class PitScoutingFragment extends Fragment {
|
|||||||
|
|
||||||
public void default_fields(){
|
public void default_fields(){
|
||||||
for(int i = 0; i < pit_latest_values.length; i++){
|
for(int i = 0; i < pit_latest_values.length; i++){
|
||||||
inputType input = pit_latest_values[i];
|
FieldType input = pit_latest_values[i];
|
||||||
input.setViewValue(input.default_value);
|
input.setViewValue(input.default_value);
|
||||||
|
titles[i].enable();
|
||||||
titles[i].setBackgroundColor(0x00000000);
|
|
||||||
titles[i].setTextColor(default_text_color);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void get_fields(){
|
public void get_fields() throws BuiltByteParser.byteParsingExeption{
|
||||||
|
|
||||||
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, pit_values, pit_transferValues);
|
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, pit_values, pit_transferValues);
|
||||||
dataType[] types = psdr.data.array;
|
RawDataType[] types = psdr.data.array;
|
||||||
|
fileUsernames = psdr.username;
|
||||||
|
|
||||||
|
|
||||||
for(int i = 0; i < pit_latest_values.length; i++){
|
for(int i = 0; i < pit_latest_values.length; i++){
|
||||||
// types[i] = latest_values[i].getViewValue();
|
|
||||||
pit_latest_values[i].setViewValue(types[i]);
|
pit_latest_values[i].setViewValue(types[i]);
|
||||||
|
|
||||||
if(pit_latest_values[i].isBlank){
|
if(pit_latest_values[i].isBlank){
|
||||||
titles[i].setBackgroundColor(0xffff0000);
|
titles[i].disable();
|
||||||
titles[i].setTextColor(0xff000000);
|
|
||||||
}else{
|
}else{
|
||||||
titles[i].setBackgroundColor(0x00000000);
|
titles[i].enable();
|
||||||
titles[i].setTextColor(default_text_color);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,139 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.scouting;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.color_found;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.color_not_found;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.color_rescout;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.DataManager.event;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TableLayout;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.databinding.FragmentTeamSelectorBinding;
|
||||||
|
import com.ridgebotics.ridgescout.types.frcTeam;
|
||||||
|
import com.ridgebotics.ridgescout.ui.views.TeamListOption;
|
||||||
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.DataManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
// Fragment for choosing which team to pit scout
|
||||||
|
public class PitSelectorFragment extends Fragment {
|
||||||
|
private FragmentTeamSelectorBinding binding;
|
||||||
|
|
||||||
|
private static onTeamSelected onSelect = new onTeamSelected() {@Override public void onSelect(PitSelectorFragment self, frcTeam team) {}};
|
||||||
|
|
||||||
|
public interface onTeamSelected {
|
||||||
|
void onSelect(PitSelectorFragment self, frcTeam team);
|
||||||
|
}
|
||||||
|
public static void setOnSelect(onTeamSelected tmponSelect){
|
||||||
|
onSelect = tmponSelect;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
binding = FragmentTeamSelectorBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
|
// event = fileEditor.g
|
||||||
|
DataManager.reload_event();
|
||||||
|
|
||||||
|
if(evcode == null || evcode.equals("unset")){
|
||||||
|
AlertManager.addSimpleError("You somehow have not loaded an event!");
|
||||||
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
load_teams();
|
||||||
|
|
||||||
|
|
||||||
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load_teams(){
|
||||||
|
// binding.pitFileIndicator.setVisibility(View.GONE);
|
||||||
|
// binding.pitTeamName.setVisibility(View.GONE);
|
||||||
|
// binding.pitTeamDescription.setVisibility(View.GONE);
|
||||||
|
//
|
||||||
|
// clear_fields();
|
||||||
|
|
||||||
|
|
||||||
|
int[] teamNums = new int[event.teams.size()];
|
||||||
|
|
||||||
|
for(int i = 0 ; i < event.teams.size(); i++){
|
||||||
|
teamNums[i] = event.teams.get(i).teamNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
Arrays.sort(teamNums);
|
||||||
|
|
||||||
|
TableLayout table = new TableLayout(getContext());
|
||||||
|
table.setStretchAllColumns(true);
|
||||||
|
binding.teams.addView(table);
|
||||||
|
|
||||||
|
|
||||||
|
for(int i = 0; i < event.teams.size(); i++){
|
||||||
|
frcTeam team = null;
|
||||||
|
for(int a = 0 ; a < event.teams.size(); a++){
|
||||||
|
if(event.teams.get(a).teamNumber == teamNums[i]){
|
||||||
|
team = event.teams.get(a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert team != null;
|
||||||
|
|
||||||
|
// TableRow tr = new TableRow(getContext());
|
||||||
|
// TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams(
|
||||||
|
// FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
// FrameLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
// );
|
||||||
|
// rowParams.setMargins(20,20,20,20);
|
||||||
|
// tr.setLayoutParams(rowParams);
|
||||||
|
// tr.setPadding(20,20,20,20);
|
||||||
|
// table.addView(tr);
|
||||||
|
|
||||||
|
TeamListOption teamRow = new TeamListOption(getContext());
|
||||||
|
table.addView(teamRow);
|
||||||
|
teamRow.fromTeam(team);
|
||||||
|
|
||||||
|
|
||||||
|
String filename = evcode + "-" + team.teamNumber + ".pitscoutdata";
|
||||||
|
|
||||||
|
if (FileEditor.fileExist(filename)) {
|
||||||
|
final boolean[] rescout = {DataManager.rescout_list.contains(filename)};
|
||||||
|
|
||||||
|
teamRow.setColor(DataManager.rescout_list.contains(filename) ? color_rescout : color_found);
|
||||||
|
|
||||||
|
teamRow.setOnLongClickListener(v -> {
|
||||||
|
rescout[0] = !rescout[0];
|
||||||
|
if(rescout[0]){
|
||||||
|
DataManager.rescout_list.add(filename);
|
||||||
|
teamRow.setColor(color_rescout);
|
||||||
|
DataManager.save_rescout_list();
|
||||||
|
}else{
|
||||||
|
DataManager.rescout_list.remove(filename);
|
||||||
|
teamRow.setColor(color_found);
|
||||||
|
DataManager.save_rescout_list();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
teamRow.setColor(color_not_found);
|
||||||
|
teamRow.setOnLongClickListener(v -> true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
frcTeam finalTeam = team;
|
||||||
|
teamRow.setOnClickListener(v -> onSelect.onSelect(this, finalTeam));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,27 +1,39 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.scouting;
|
package com.ridgebotics.ridgescout.ui.scouting;
|
||||||
|
|
||||||
|
import static android.widget.LinearLayout.VERTICAL;
|
||||||
import static androidx.navigation.fragment.FragmentKt.findNavController;
|
import static androidx.navigation.fragment.FragmentKt.findNavController;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
|
||||||
import static com.ridgebotics.ridgescout.utility.DataManager.event;
|
import static com.ridgebotics.ridgescout.utility.DataManager.event;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.R;
|
import com.ridgebotics.ridgescout.R;
|
||||||
import com.ridgebotics.ridgescout.utility.settingsManager;
|
import com.ridgebotics.ridgescout.types.frcEvent;
|
||||||
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
|
import com.ridgebotics.ridgescout.utility.SettingsManager;
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentScoutingBinding;
|
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 com.ridgebotics.ridgescout.utility.DataManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.builders.TextViewBuilder;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
// Main dashbord page
|
||||||
public class ScoutingFragment extends Fragment {
|
public class ScoutingFragment extends Fragment {
|
||||||
|
|
||||||
private FragmentScoutingBinding binding;
|
private FragmentScoutingBinding binding;
|
||||||
@@ -34,42 +46,87 @@ public class ScoutingFragment extends Fragment {
|
|||||||
|
|
||||||
binding.buttons.setVisibility(View.VISIBLE);
|
binding.buttons.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
String evcode = settingsManager.getEVCode();
|
DataManager.reload_event();
|
||||||
|
|
||||||
if(evcode.equals("unset")){
|
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.noEventError.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
binding.textMatchAlliance.setVisibility(View.GONE);
|
||||||
|
binding.textName.setVisibility(View.GONE);
|
||||||
|
binding.infoBox.setVisibility(View.GONE);
|
||||||
|
binding.textRescoutIndicator.setVisibility(View.GONE);
|
||||||
|
|
||||||
binding.matchScoutingButton.setEnabled(false);
|
binding.matchScoutingButton.setEnabled(false);
|
||||||
binding.pitScoutingButton.setEnabled(false);
|
binding.pitScoutingButton.setEnabled(false);
|
||||||
binding.statusButton.setEnabled(false);
|
binding.eventButton.setEnabled(false);
|
||||||
is_main_page = false;
|
is_main_page = false;
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
DataManager.reload_event();
|
if(event.matches.isEmpty()){
|
||||||
|
binding.matchScoutingButton.setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
if(event.matches.isEmpty())
|
if(event.teams.isEmpty()){
|
||||||
binding.matchScoutingButton.setVisibility(View.GONE);
|
binding.pitScoutingButton.setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
binding.matchScoutingButton.setOnClickListener(v -> {
|
binding.matchScoutingButton.setOnClickListener(v -> {
|
||||||
findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_match_scouting);
|
findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_match_scouting);
|
||||||
});
|
});
|
||||||
|
|
||||||
binding.pitScoutingButton.setOnClickListener(v -> {
|
binding.pitScoutingButton.setOnClickListener(v -> {
|
||||||
TeamSelectorFragment.setPits_mode(true);
|
PitSelectorFragment.setOnSelect((self, team) -> {
|
||||||
TeamSelectorFragment.setOnSelect(new TeamSelectorFragment.onTeamSelected() {
|
|
||||||
@Override
|
|
||||||
public void onSelect(TeamSelectorFragment self, frcTeam team) {
|
|
||||||
PitScoutingFragment.setTeam(team);
|
PitScoutingFragment.setTeam(team);
|
||||||
findNavController(self).navigate(R.id.action_navigation_team_selector_to_navigation_pit_scouting);
|
findNavController(self).navigate(R.id.action_navigation_scouting_pit_selector_to_navigation_pit_scouting);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_team_selector);
|
findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_scouting_pit_selector);
|
||||||
});
|
});
|
||||||
|
|
||||||
binding.statusButton.setOnClickListener(v -> {
|
binding.eventButton.setOnClickListener(v -> {
|
||||||
findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_scouting_status);
|
findNavController(this).navigate(R.id.action_navigation_scouting_to_navigation_scouting_event);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateDashboard();
|
||||||
|
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,24 +140,52 @@ public class ScoutingFragment extends Fragment {
|
|||||||
|
|
||||||
getView().setFocusableInTouchMode(true);
|
getView().setFocusableInTouchMode(true);
|
||||||
getView().requestFocus();
|
getView().requestFocus();
|
||||||
getView().setOnKeyListener(new View.OnKeyListener() {
|
getView().setOnKeyListener((v, keyCode, event) -> {
|
||||||
@Override
|
|
||||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
|
||||||
|
|
||||||
if (event.getAction() == KeyEvent.ACTION_UP
|
if (event.getAction() == KeyEvent.ACTION_UP
|
||||||
&& keyCode == KeyEvent.KEYCODE_BACK
|
&& keyCode == KeyEvent.KEYCODE_BACK
|
||||||
&& !is_main_page){
|
&& !is_main_page){
|
||||||
|
|
||||||
// binding.buttons.setVisibility(View.VISIBLE);
|
|
||||||
// binding.matchScoutingView.setVisibility(View.GONE);
|
|
||||||
// binding.pitScoutingView.setVisibility(View.GONE);
|
|
||||||
is_main_page = true;
|
is_main_page = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateDashboard() {
|
||||||
|
binding.textName.setText("Welcome, " + SettingsManager.getUsername() + "!");
|
||||||
|
|
||||||
|
binding.textRescoutIndicator.setText("Things to rescout: " + DataManager.rescout_list.size());
|
||||||
|
|
||||||
|
if(event.matches.size() == 0) {
|
||||||
|
binding.textMatchAlliance.setText("No Matches!");
|
||||||
|
} else {
|
||||||
|
int teamNum = SettingsManager.getTeamNum();
|
||||||
|
int curMatchNum = SettingsManager.getMatchNum();
|
||||||
|
|
||||||
|
binding.textMatchAlliance.setText("Match: " + (curMatchNum+1) + ", " + SettingsManager.getAllyPos());
|
||||||
|
|
||||||
|
int nextMatch;
|
||||||
|
try {
|
||||||
|
nextMatch = event.getNextTeamMatch(teamNum, curMatchNum).matchIndex;
|
||||||
|
} catch (Exception e){
|
||||||
|
AlertManager.error("Sorry, in event ("+evcode+"), your team number ("+teamNum+") wasn't found!", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
binding.infoBox.addView(new TextViewBuilder(getContext(), "Our next match: Match " + nextMatch)
|
||||||
|
.body1()
|
||||||
|
.build());
|
||||||
|
|
||||||
|
int informedBy = event.getMostInformedBy(teamNum, curMatchNum);
|
||||||
|
|
||||||
|
|
||||||
|
binding.infoBox.addView(new TextViewBuilder(getContext(), "Most informed by: Match " + informedBy)
|
||||||
|
.body1()
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.scouting;
|
|
||||||
|
|
||||||
import static com.ridgebotics.ridgescout.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.ridgebotics.ridgescout.databinding.FragmentScoutingStatusBinding;
|
|
||||||
import com.ridgebotics.ridgescout.utility.DataManager;
|
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
|
||||||
import com.ridgebotics.ridgescout.types.frcEvent;
|
|
||||||
import com.ridgebotics.ridgescout.types.frcMatch;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,424 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.settings;
|
||||||
|
|
||||||
|
import static android.text.InputType.TYPE_CLASS_NUMBER;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TableLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
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.FieldType;
|
||||||
|
import com.ridgebotics.ridgescout.types.input.NumberType;
|
||||||
|
import com.ridgebotics.ridgescout.types.input.SliderType;
|
||||||
|
import com.ridgebotics.ridgescout.types.input.TallyType;
|
||||||
|
import com.ridgebotics.ridgescout.types.input.TextType;
|
||||||
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.builders.TextViewBuilder;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
// Class to help with fields editor fragment, containing the defaults for each field.
|
||||||
|
public class FieldEditorHelper {
|
||||||
|
private enum parameterTypeEnum {
|
||||||
|
paramNumber,
|
||||||
|
paramString,
|
||||||
|
paramStringArray,
|
||||||
|
paramNumberArray
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class parameterType {
|
||||||
|
public String name;
|
||||||
|
public parameterTypeEnum id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class paramNumber extends parameterType{
|
||||||
|
public int val;
|
||||||
|
public paramNumber(String name, int val){
|
||||||
|
this.name = name + " (Number)";
|
||||||
|
this.val = val;
|
||||||
|
this.id = parameterTypeEnum.paramNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class paramString extends parameterType {
|
||||||
|
public String val;
|
||||||
|
public paramString(String name, String val){
|
||||||
|
this.name = name + " (String)";
|
||||||
|
this.val = val;
|
||||||
|
this.id = parameterTypeEnum.paramString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class paramStringArray extends parameterType{
|
||||||
|
public String[] val;
|
||||||
|
public paramStringArray(String name, String[] val){
|
||||||
|
this.name = name + " (String array)";
|
||||||
|
this.val = val;
|
||||||
|
this.id = parameterTypeEnum.paramStringArray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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("Name", "New Slider"),
|
||||||
|
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("Name", "New Dropdown"),
|
||||||
|
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("Name", "New Text"),
|
||||||
|
new paramString("Description", ""),
|
||||||
|
new paramString("Default Value", "")
|
||||||
|
};
|
||||||
|
public static final parameterType[] defaultTallyParams = new parameterType[]{
|
||||||
|
new paramString("Name", "New Tally"),
|
||||||
|
new paramString("Description", ""),
|
||||||
|
new paramNumber("Default Value", 0)
|
||||||
|
};
|
||||||
|
public static final parameterType[] defaultNumberParams = new parameterType[]{
|
||||||
|
new paramString("Name", "New Number"),
|
||||||
|
new paramString("Description", ""),
|
||||||
|
new paramNumber("Default Value", 0)
|
||||||
|
};
|
||||||
|
public static final parameterType[] defaultCheckboxParam = new parameterType[]{
|
||||||
|
new paramString("Name", "New Checkbox"),
|
||||||
|
new paramString("Description", ""),
|
||||||
|
new paramNumber("Default Value ( 1 or 0 )", 0)
|
||||||
|
};
|
||||||
|
public static final parameterType[] defaultFieldPosParam = new parameterType[]{
|
||||||
|
new paramString("Name", "New Field Position"),
|
||||||
|
new paramString("Description", ""),
|
||||||
|
new paramNumber("Default X", 0),
|
||||||
|
new paramNumber("Default Y", 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private static parameterType[] getSliderParams(SliderType s){
|
||||||
|
return new parameterType[]{
|
||||||
|
new paramString("Name", s.name),
|
||||||
|
new paramString("Description", s.description),
|
||||||
|
new paramNumber("Min", s.min),
|
||||||
|
new paramNumber("Max", s.max),
|
||||||
|
new paramNumber("Default Value", (int) s.default_value)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static parameterType[] getDropdownParams(DropdownType s){
|
||||||
|
return new parameterType[]{
|
||||||
|
new paramString("Name", s.name),
|
||||||
|
new paramString("Description", s.description),
|
||||||
|
new paramStringArray("Default Value",s.text_options),
|
||||||
|
new paramNumber("Default Option", (int) s.default_value),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static parameterType[] getTextParams(TextType s){
|
||||||
|
return new parameterType[]{
|
||||||
|
new paramString("Name", s.name),
|
||||||
|
new paramString("Description", s.description),
|
||||||
|
new paramString("Default Value", (String) s.default_value)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static parameterType[] getTallyParams(TallyType s){
|
||||||
|
return new parameterType[]{
|
||||||
|
new paramString("Name", s.name),
|
||||||
|
new paramString("Description", s.description),
|
||||||
|
new paramNumber("Default Value", (int) s.default_value)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static parameterType[] getNumberParams(NumberType s){
|
||||||
|
return new parameterType[]{
|
||||||
|
new paramString("Name", s.name),
|
||||||
|
new paramString("Description", s.description),
|
||||||
|
new paramNumber("Default Value", (int) s.default_value)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static parameterType[] getCheckboxParam(CheckboxType s){
|
||||||
|
return new parameterType[]{
|
||||||
|
new paramString("Name", s.name),
|
||||||
|
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("Name", s.name),
|
||||||
|
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.name = ((paramString) types[0]).val;
|
||||||
|
s.description = ((paramString) types[1]).val;
|
||||||
|
s.min = ((paramNumber) types[2]).val;
|
||||||
|
s.max = ((paramNumber) types[3]).val;
|
||||||
|
s.default_value = ((paramNumber) types[4]).val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDropdownParams(DropdownType s, parameterType[] types){
|
||||||
|
s.name = ((paramString) types[0]).val;
|
||||||
|
s.description = ((paramString) types[1]).val;
|
||||||
|
s.text_options = ((paramStringArray) types[2]).val;
|
||||||
|
s.default_value = ((paramNumber) types[3]).val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setTextParams(TextType s, parameterType[] types){
|
||||||
|
s.name = ((paramString) types[0]).val;
|
||||||
|
s.description = ((paramString) types[1]).val;
|
||||||
|
s.default_value = ((paramString) types[2]).val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setTallyParams(TallyType s, parameterType[] types){
|
||||||
|
s.name = ((paramString) types[0]).val;
|
||||||
|
s.description = ((paramString) types[1]).val;
|
||||||
|
s.default_value = ((paramNumber) types[2]).val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setNumberParams(NumberType s, parameterType[] types){
|
||||||
|
s.name = ((paramString) types[0]).val;
|
||||||
|
s.description = ((paramString) types[1]).val;
|
||||||
|
s.default_value = ((paramNumber) types[2]).val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setCheckboxParam(CheckboxType s, parameterType[] types){
|
||||||
|
s.name = ((paramString) types[0]).val;
|
||||||
|
s.description = ((paramString) types[1]).val;
|
||||||
|
s.default_value = ((paramNumber) types[2]).val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setFieldPosParam(FieldposType s, parameterType[] types){
|
||||||
|
s.name = ((paramString) types[0]).val;
|
||||||
|
s.description = ((paramString) types[1]).val;
|
||||||
|
s.default_value = new int[]{
|
||||||
|
((paramNumber) types[2]).val,
|
||||||
|
((paramNumber) types[3]).val
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void setInputParameter(FieldType t, parameterType[] types){
|
||||||
|
switch (t.getInputType()){
|
||||||
|
case TALLY:
|
||||||
|
setTallyParams((TallyType) t, types);
|
||||||
|
break;
|
||||||
|
case SLIDER:
|
||||||
|
setSliderParams((SliderType) t, types);
|
||||||
|
break;
|
||||||
|
case DROPDOWN:
|
||||||
|
setDropdownParams((DropdownType) t, types);
|
||||||
|
break;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static parameterType[] getParamsFromInputType(FieldType t){
|
||||||
|
switch (t.getInputType()){
|
||||||
|
case TALLY:
|
||||||
|
return getTallyParams((TallyType) t);
|
||||||
|
case SLIDER:
|
||||||
|
return getSliderParams((SliderType) t);
|
||||||
|
case DROPDOWN:
|
||||||
|
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[]{};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static View createNumberEdit(Context c, int value){
|
||||||
|
EditText text = new EditText(c);
|
||||||
|
text.setInputType(TYPE_CLASS_NUMBER);
|
||||||
|
text.setText(String.valueOf(value));
|
||||||
|
text.setLayoutParams(new LinearLayout.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
));
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static View createStringEdit(Context c, String value){
|
||||||
|
EditText text = new EditText(c);
|
||||||
|
text.setText(value);
|
||||||
|
text.setLayoutParams(new LinearLayout.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
));
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static View createStringArrayEdit(Context c, String[] value){
|
||||||
|
EditText text = new EditText(c);
|
||||||
|
text.setText(String.join("\n", value));
|
||||||
|
text.setLayoutParams(new LinearLayout.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
));
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static View createEdit(Context c, parameterType t){
|
||||||
|
switch (t.id){
|
||||||
|
case paramNumber:
|
||||||
|
return createNumberEdit(c, ((paramNumber) t).val);
|
||||||
|
case paramString:
|
||||||
|
return createStringEdit(c, ((paramString) t).val);
|
||||||
|
case paramStringArray:
|
||||||
|
return createStringArrayEdit(c, ((paramStringArray) t).val);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static boolean readEdit(View v, parameterType t){
|
||||||
|
try{
|
||||||
|
String val;
|
||||||
|
switch (t.id) {
|
||||||
|
case paramNumber:
|
||||||
|
val = ((EditText) v).getText().toString();
|
||||||
|
if(val.isEmpty() || val.isBlank()) return false;
|
||||||
|
((paramNumber) t).val = Integer.parseInt(val);
|
||||||
|
break;
|
||||||
|
case paramString:
|
||||||
|
val = ((EditText) v).getText().toString();
|
||||||
|
//if(val.isEmpty() || val.isBlank()) return false;
|
||||||
|
((paramString) t).val = val;
|
||||||
|
break;
|
||||||
|
case paramStringArray:
|
||||||
|
val = ((EditText) v).getText().toString();
|
||||||
|
if(val.isEmpty() || val.isBlank()) return false;
|
||||||
|
((paramStringArray) t).val = val.split("\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
AlertManager.error(e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FieldType createNewFieldType(int n){
|
||||||
|
switch(n){
|
||||||
|
case 0:
|
||||||
|
SliderType slider = new SliderType();
|
||||||
|
slider.UUID = UUID.randomUUID().toString();
|
||||||
|
setSliderParams(slider, defaultSliderParams);
|
||||||
|
return slider;
|
||||||
|
case 1:
|
||||||
|
TextType textType = new TextType();
|
||||||
|
textType.UUID = UUID.randomUUID().toString();
|
||||||
|
setTextParams(textType, defaultTextParams);
|
||||||
|
return textType;
|
||||||
|
case 2:
|
||||||
|
DropdownType dropdownType = new DropdownType();
|
||||||
|
dropdownType.UUID = UUID.randomUUID().toString();
|
||||||
|
setDropdownParams(dropdownType, defaultDropdownParams);
|
||||||
|
return dropdownType;
|
||||||
|
case 3:
|
||||||
|
TallyType tallyType = new TallyType();
|
||||||
|
tallyType.UUID = UUID.randomUUID().toString();
|
||||||
|
setTallyParams(tallyType, defaultTallyParams);
|
||||||
|
return tallyType;
|
||||||
|
case 4:
|
||||||
|
NumberType numberType = new NumberType();
|
||||||
|
numberType.UUID = UUID.randomUUID().toString();
|
||||||
|
setNumberParams(numberType, defaultNumberParams);
|
||||||
|
return numberType;
|
||||||
|
case 5:
|
||||||
|
CheckboxType checkboxType = new CheckboxType();
|
||||||
|
checkboxType.UUID = UUID.randomUUID().toString();
|
||||||
|
setCheckboxParam(checkboxType, defaultCheckboxParam);
|
||||||
|
return checkboxType;
|
||||||
|
case 6:
|
||||||
|
FieldposType fieldposType = new FieldposType();
|
||||||
|
fieldposType.UUID = UUID.randomUUID().toString();
|
||||||
|
setFieldPosParam(fieldposType, defaultFieldPosParam);
|
||||||
|
return fieldposType;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private parameterType[] types;
|
||||||
|
private View[] views;
|
||||||
|
private FieldType t;
|
||||||
|
public FieldEditorHelper(Context c, FieldType t, TableLayout parentView, parameterType[] tmptypes){
|
||||||
|
this.types = tmptypes;
|
||||||
|
this.t = t;
|
||||||
|
views = new View[types.length];
|
||||||
|
for(int i = 0; i < types.length; i++){
|
||||||
|
|
||||||
|
parentView.addView(new TextViewBuilder(c, types[i].name)
|
||||||
|
.align_center()
|
||||||
|
.size(20)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
views[i] = createEdit(c, types[i]);
|
||||||
|
parentView.addView(views[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public FieldEditorHelper(Context c, FieldType t, TableLayout parentView){
|
||||||
|
this(c,t,parentView,getParamsFromInputType(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean save(){
|
||||||
|
for(int i = 0; i < types.length; i++){
|
||||||
|
if(!readEdit(views[i], types[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
setInputParameter(t, types);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,313 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.settings;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.background_color;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.unfocused_background_color;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ScrollView;
|
||||||
|
import android.widget.TableLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.navigation.Navigation;
|
||||||
|
|
||||||
|
import com.google.android.material.button.MaterialButton;
|
||||||
|
import com.ridgebotics.ridgescout.MainActivity;
|
||||||
|
import com.ridgebotics.ridgescout.R;
|
||||||
|
import com.ridgebotics.ridgescout.databinding.FragmentSettingsFieldsBinding;
|
||||||
|
import com.ridgebotics.ridgescout.scoutingData.Fields;
|
||||||
|
import com.ridgebotics.ridgescout.types.input.FieldType;
|
||||||
|
import com.ridgebotics.ridgescout.ui.views.CustomSpinnerView;
|
||||||
|
import com.ridgebotics.ridgescout.ui.views.FieldDisplay;
|
||||||
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.builders.TextViewBuilder;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
// Fragment that shows the field editor.
|
||||||
|
public class FieldsFragment extends Fragment {
|
||||||
|
FragmentSettingsFieldsBinding binding;
|
||||||
|
|
||||||
|
private static String filename;
|
||||||
|
public static void set_filename(String tmpfilename){
|
||||||
|
filename = tmpfilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int index = -1;
|
||||||
|
|
||||||
|
private boolean edited = false;
|
||||||
|
|
||||||
|
List<FieldType> values;
|
||||||
|
List<FieldDisplay> views;
|
||||||
|
|
||||||
|
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
binding = FragmentSettingsFieldsBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
|
binding.upButton.setEnabled(false);
|
||||||
|
binding.downButton.setEnabled(false);
|
||||||
|
binding.saveButton.setEnabled(false);
|
||||||
|
|
||||||
|
FieldType[][] tmp_values = Fields.load(filename);
|
||||||
|
if(tmp_values == null || tmp_values.length == 0) return binding.getRoot();
|
||||||
|
|
||||||
|
values = new ArrayList(List.of(tmp_values[tmp_values.length-1]));
|
||||||
|
views = new ArrayList<>();
|
||||||
|
|
||||||
|
for(int i = 0; i < values.size(); i++){
|
||||||
|
createFieldDisplay(values.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Up and down buttons
|
||||||
|
binding.upButton.setOnClickListener(v -> {
|
||||||
|
if(index <= 0) return;
|
||||||
|
Collections.swap(values, index, index-1);
|
||||||
|
Collections.swap(views, index, index-1);
|
||||||
|
index--;
|
||||||
|
updateRowOrder();
|
||||||
|
});
|
||||||
|
binding.downButton.setOnClickListener(v -> {
|
||||||
|
if(index >= values.size()-1) return;
|
||||||
|
Collections.swap(values, index, index+1);
|
||||||
|
Collections.swap(views, index, index+1);
|
||||||
|
index++;
|
||||||
|
updateRowOrder();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add Field button
|
||||||
|
binding.addButton.setOnClickListener(v -> {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||||
|
builder.setTitle("Select Type");
|
||||||
|
|
||||||
|
final CustomSpinnerView dropdown = new CustomSpinnerView(getContext());
|
||||||
|
List<String> options = new ArrayList<>();
|
||||||
|
|
||||||
|
options.add("Slider");
|
||||||
|
options.add("Text");
|
||||||
|
options.add("Dropdown");
|
||||||
|
options.add("Tally");
|
||||||
|
options.add("Number");
|
||||||
|
options.add("Checkbox");
|
||||||
|
options.add("Field Position");
|
||||||
|
|
||||||
|
dropdown.setOptions(options, 0);
|
||||||
|
dropdown.setTitle("Type");
|
||||||
|
|
||||||
|
builder.setView(dropdown);
|
||||||
|
|
||||||
|
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
|
||||||
|
builder.setPositiveButton("OK", (dialog, which) -> addField(dropdown.getIndex()));
|
||||||
|
|
||||||
|
builder.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Back button listener
|
||||||
|
((MainActivity) getActivity()).setOnBackPressed(() -> {
|
||||||
|
if(!edited) 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) -> {
|
||||||
|
edited = false;
|
||||||
|
if(getActivity() != null)
|
||||||
|
getActivity().onBackPressed();
|
||||||
|
});
|
||||||
|
alert.setCancelable(true);
|
||||||
|
|
||||||
|
alert.create().show();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
binding.saveButton.setOnClickListener(l -> save());
|
||||||
|
|
||||||
|
if(tmp_values.length > 1)
|
||||||
|
binding.revertButton.setOnClickListener(v -> revertPopup());
|
||||||
|
else
|
||||||
|
binding.revertButton.setEnabled(false);
|
||||||
|
|
||||||
|
|
||||||
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
private void createFieldDisplay(FieldType field){
|
||||||
|
final FieldDisplay fd = new FieldDisplay(getContext());
|
||||||
|
views.add(fd);
|
||||||
|
|
||||||
|
fd.setField(field);
|
||||||
|
fd.setColor(unfocused_background_color);
|
||||||
|
fd.coloredBackground.setOnTouchListener((view, motionEvent) -> {
|
||||||
|
FieldsFragment.this.setFocus(fd, false);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
fd.editButton.setOnClickListener(v -> openEditor(fd));
|
||||||
|
|
||||||
|
binding.fieldsArea.addView(fd);
|
||||||
|
}
|
||||||
|
private void updateRowOrder(){
|
||||||
|
enableSaving();
|
||||||
|
binding.fieldsArea.removeAllViews();
|
||||||
|
for(int i = 0; i < views.size(); i++){
|
||||||
|
binding.fieldsArea.addView(views.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.upButton.setEnabled(index != -1 && index > 0);
|
||||||
|
binding.downButton.setEnabled(index != -1 && index < views.size()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setFocus(FieldDisplay fd, boolean scroll){
|
||||||
|
index = views.indexOf(fd);
|
||||||
|
for(int a = 0; a < values.size(); a++) {
|
||||||
|
views.get(a).setColor(unfocused_background_color);
|
||||||
|
views.get(a).hideButtons();
|
||||||
|
}
|
||||||
|
fd.setColor(background_color);
|
||||||
|
fd.showButtons();
|
||||||
|
|
||||||
|
binding.upButton.setEnabled(index != -1 && index > 0);
|
||||||
|
binding.downButton.setEnabled(index != -1 && index < views.size()-1);
|
||||||
|
if(scroll)
|
||||||
|
binding.scrollView.post(() -> binding.scrollView.scrollTo(0, fd.getTop()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openEditor(FieldDisplay fd){
|
||||||
|
FieldType field = fd.getField();
|
||||||
|
|
||||||
|
ScrollView sv = new ScrollView(getContext());
|
||||||
|
TableLayout table = new TableLayout(getContext());
|
||||||
|
table.setStretchAllColumns(true);
|
||||||
|
table.setPadding(10, 10, 10, 10);
|
||||||
|
|
||||||
|
sv.addView(table);
|
||||||
|
|
||||||
|
|
||||||
|
table.addView(new TextViewBuilder(getContext(), "Type: " + field.get_type_name() + "\nUUID: " + field.UUID)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
FieldEditorHelper f = new FieldEditorHelper(getContext(), field, table);
|
||||||
|
|
||||||
|
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
|
||||||
|
alert.setTitle("Edit " + field.name);
|
||||||
|
alert.setView(sv);
|
||||||
|
alert.setCancelable(false);
|
||||||
|
alert.setNeutralButton("Cancel", (dialogInterface, i) -> {});
|
||||||
|
alert.setPositiveButton("Save", (dialogInterface, i) -> {
|
||||||
|
f.save();
|
||||||
|
fd.setField(field);
|
||||||
|
enableSaving();
|
||||||
|
});
|
||||||
|
|
||||||
|
AlertDialog dialog = alert.create();
|
||||||
|
dialog.show();
|
||||||
|
|
||||||
|
MaterialButton deleteButton = new MaterialButton(getContext());
|
||||||
|
deleteButton.setText("DELETE");
|
||||||
|
deleteButton.setOnClickListener(l -> {
|
||||||
|
AlertDialog.Builder alert2 = new AlertDialog.Builder(getContext());
|
||||||
|
alert2.setTitle("Warning!");
|
||||||
|
alert2.setMessage("This may destroy any data after being saved!");
|
||||||
|
alert2.setPositiveButton("Return", (dialogInterface, i) -> {});
|
||||||
|
alert2.setNeutralButton("DELETE", (dialogInterface, i) -> {
|
||||||
|
removeField(field);
|
||||||
|
dialog.cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
alert2.setCancelable(true);
|
||||||
|
alert2.create().show();
|
||||||
|
});
|
||||||
|
|
||||||
|
table.addView(deleteButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enableSaving(){
|
||||||
|
edited = true;
|
||||||
|
binding.saveButton.setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addField(int n){
|
||||||
|
FieldType field = FieldEditorHelper.createNewFieldType(n);
|
||||||
|
|
||||||
|
values.add(field);
|
||||||
|
createFieldDisplay(field);
|
||||||
|
setFocus(views.get(views.size()-1), true);
|
||||||
|
enableSaving();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeField(FieldType field){
|
||||||
|
int fieldIndex = values.indexOf(field);
|
||||||
|
|
||||||
|
views.remove(fieldIndex);
|
||||||
|
values.remove(fieldIndex);
|
||||||
|
|
||||||
|
index = -1;
|
||||||
|
|
||||||
|
updateRowOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void save(){
|
||||||
|
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
|
||||||
|
alert.setTitle("Warning!");
|
||||||
|
alert.setMessage("Changing or removing some values will result in lost data! but you can revert at any time.");
|
||||||
|
alert.setNeutralButton("Save", (dialog, which) -> {
|
||||||
|
FieldType[][] currentValues = Fields.load(filename);
|
||||||
|
assert currentValues != null;
|
||||||
|
FieldType[][] newValues = new FieldType[currentValues.length+1][];
|
||||||
|
|
||||||
|
System.arraycopy(currentValues, 0, newValues, 0, currentValues.length);
|
||||||
|
|
||||||
|
Log.i(getClass().toString(), "Length: " + values.size());
|
||||||
|
|
||||||
|
newValues[currentValues.length] = new FieldType[values.size()];
|
||||||
|
for(int i = 0; i < values.size(); i++) {
|
||||||
|
FieldType value = values.get(i);
|
||||||
|
newValues[currentValues.length][i] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_settings);
|
||||||
|
});
|
||||||
|
alert.setNegativeButton("Cancel", null);
|
||||||
|
alert.setCancelable(true);
|
||||||
|
alert.create().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void revertPopup(){
|
||||||
|
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
|
||||||
|
alert.setTitle("Warning!");
|
||||||
|
alert.setMessage("If there is any data scouted with this version of the fields, it will cause conflicts!\nYou should know what you are doing");
|
||||||
|
alert.setNeutralButton("Revert and delete version", (dialog, which) -> {
|
||||||
|
FieldType[][] currentValues = Fields.load(filename);
|
||||||
|
assert currentValues != null;
|
||||||
|
FieldType[][] newValues = new FieldType[currentValues.length-1][];
|
||||||
|
|
||||||
|
System.arraycopy(currentValues, 0, newValues, 0, currentValues.length - 1);
|
||||||
|
|
||||||
|
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_settings);
|
||||||
|
});
|
||||||
|
alert.setNegativeButton("Cancel", null);
|
||||||
|
alert.setCancelable(true);
|
||||||
|
alert.create().show();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,713 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.settings;
|
||||||
|
|
||||||
|
import static android.widget.LinearLayout.HORIZONTAL;
|
||||||
|
import static android.widget.LinearLayout.VERTICAL;
|
||||||
|
import static androidx.navigation.fragment.FragmentKt.findNavController;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.SettingsManager.AllyPosKey;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.SettingsManager.CustomEventsKey;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.SettingsManager.EnableQuickAllianceChangeKey;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.SettingsManager.FieldImageKey;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.SettingsManager.MatchNumKey;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.SettingsManager.SelEVCodeKey;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.SettingsManager.TeamNumKey;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.SettingsManager.UnameKey;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.SettingsManager.WifiModeKey;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.SettingsManager.YearNumKey;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.SettingsManager.defaults;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.SettingsManager.getEVCode;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.SettingsManager.getEditor;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.SettingsManager.prefs;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.InputType;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ScrollView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import com.google.android.material.button.MaterialButton;
|
||||||
|
import com.google.android.material.checkbox.MaterialCheckBox;
|
||||||
|
import com.google.android.material.divider.MaterialDivider;
|
||||||
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
import com.google.android.material.textfield.TextInputLayout;
|
||||||
|
import com.ridgebotics.ridgescout.R;
|
||||||
|
import com.ridgebotics.ridgescout.databinding.FragmentSettingsBinding;
|
||||||
|
import com.ridgebotics.ridgescout.scoutingData.Fields;
|
||||||
|
import com.ridgebotics.ridgescout.ui.views.CustomSpinnerView;
|
||||||
|
import com.ridgebotics.ridgescout.ui.views.TallyCounterView;
|
||||||
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.DataManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
|
import com.ridgebotics.ridgescout.utility.ToDelete;
|
||||||
|
import com.ridgebotics.ridgescout.utility.builders.TextViewBuilder;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
// Fragment to edit settings, aswell as redirect to the fields editor.
|
||||||
|
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();
|
||||||
|
|
||||||
|
reloadSettings();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reloadSettings(){
|
||||||
|
String[] alliance_pos_list = new String[]{"red-1", "red-2", "red-3",
|
||||||
|
"blue-1", "blue-2", "blue-3"};
|
||||||
|
|
||||||
|
SettingsManager manager = new SettingsManager(getContext());
|
||||||
|
|
||||||
|
|
||||||
|
ButtonSettingsItem appInfoButton = new ButtonSettingsItem();
|
||||||
|
appInfoButton.addButton("App info", v -> showAppInfo());
|
||||||
|
manager.addItem(appInfoButton);
|
||||||
|
|
||||||
|
|
||||||
|
ButtonSettingsItem corruptButton = new ButtonSettingsItem();
|
||||||
|
corruptButton.addButton("find corrupted files", view -> {
|
||||||
|
ToDelete.findCorruptedFiles(getContext());
|
||||||
|
});
|
||||||
|
corruptButton.addButton("delete files", view -> {
|
||||||
|
ToDelete.deleteFiles(getContext(), Arrays.asList(FileEditor.getFiles()), false);
|
||||||
|
});
|
||||||
|
// corruptButton.setEnabled(!getEVCode().equals("unset"));
|
||||||
|
|
||||||
|
manager.addItem(corruptButton);
|
||||||
|
manager.addItem(new HeaderSettingsItem("Advanced"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ButtonSettingsItem fieldsButtons = new ButtonSettingsItem();
|
||||||
|
fieldsButtons.addButton("Edit pit fields", v -> {
|
||||||
|
FieldsFragment.set_filename(Fields.pitsFieldsFilename);
|
||||||
|
findNavController(this).navigate(R.id.action_navigation_settings_to_navigation_data_fields);
|
||||||
|
});
|
||||||
|
fieldsButtons.addButton("Edit match fields", v -> {
|
||||||
|
FieldsFragment.set_filename(Fields.matchFieldsFilename);
|
||||||
|
findNavController(this).navigate(R.id.action_navigation_settings_to_navigation_data_fields);
|
||||||
|
});
|
||||||
|
manager.addItem(fieldsButtons);
|
||||||
|
|
||||||
|
ButtonSettingsItem noticeButton = new ButtonSettingsItem();
|
||||||
|
noticeButton.addButton("Edit scout notice", v->editNotice());
|
||||||
|
noticeButton.setEnabled(!getEVCode().equals("unset"));
|
||||||
|
manager.addItem(noticeButton);
|
||||||
|
|
||||||
|
|
||||||
|
manager.addItem(new CheckboxSettingsItem(CustomEventsKey, "Custom Events"));
|
||||||
|
|
||||||
|
CheckboxSettingsItem FTPSendMetaFiles = new CheckboxSettingsItem(com.ridgebotics.ridgescout.utility.SettingsManager.FTPSendMetaFiles, "[⚠] Send meta files");
|
||||||
|
manager.addItem(FTPSendMetaFiles);
|
||||||
|
|
||||||
|
manager.addItem(new HeaderSettingsItem("Admin"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
StringSettingsItem FTPKey = new StringSettingsItem(com.ridgebotics.ridgescout.utility.SettingsManager.FTPKey, "Sync Key");
|
||||||
|
manager.addItem(FTPKey);
|
||||||
|
StringSettingsItem FTPServer = new StringSettingsItem(com.ridgebotics.ridgescout.utility.SettingsManager.FTPServer, "Sync Server (Sync)");
|
||||||
|
manager.addItem(FTPServer);
|
||||||
|
CheckboxSettingsItem FTPEnabled = new CheckboxSettingsItem(com.ridgebotics.ridgescout.utility.SettingsManager.FTPEnabled, "Sync Enabled", FTPServer, FTPKey, FTPSendMetaFiles);
|
||||||
|
manager.addItem(FTPEnabled);
|
||||||
|
|
||||||
|
manager.addItem(new CheckboxSettingsItem(WifiModeKey, "Wifi Mode", FTPEnabled));
|
||||||
|
|
||||||
|
|
||||||
|
manager.addItem(new NumberSettingsItem(YearNumKey, "Year", 0, 9999));
|
||||||
|
|
||||||
|
manager.addItem(new HeaderSettingsItem("Connection"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
manager.addItem(new CheckboxSettingsItem(EnableQuickAllianceChangeKey, "Enable quick alliance swap", null));
|
||||||
|
manager.addItem(new DropdownSettingsItem(FieldImageKey, "Field Image", new String[]{
|
||||||
|
"2026",
|
||||||
|
"2026 (Flipped)",
|
||||||
|
"2025",
|
||||||
|
"2025 (Flipped)"
|
||||||
|
}));
|
||||||
|
|
||||||
|
manager.addItem(new DropdownSettingsItem(AllyPosKey, "Alliance Pos", alliance_pos_list));
|
||||||
|
|
||||||
|
int max = 0;
|
||||||
|
boolean hasEvent = false;
|
||||||
|
|
||||||
|
if(!DataManager.getevcode().equals("unset")){
|
||||||
|
DataManager.reload_event();
|
||||||
|
max = DataManager.event.matches.size();
|
||||||
|
hasEvent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TallySettingsItem matchNum = new TallySettingsItem(MatchNumKey, "Match Number", max);
|
||||||
|
matchNum.setEnabled(hasEvent);
|
||||||
|
manager.addItem(matchNum);
|
||||||
|
|
||||||
|
DropdownSettingsItem eventCode = new DropdownSettingsItem(SelEVCodeKey, "Event Code", FileEditor.getEventList().toArray(new String[0]));
|
||||||
|
eventCode.reloadOnChange(true);
|
||||||
|
manager.addItem(eventCode);
|
||||||
|
|
||||||
|
manager.addItem(new StringSettingsItem(UnameKey, "Username"));
|
||||||
|
manager.addItem(new NumberSettingsItem(TeamNumKey, "Team Number", 0, 99999));
|
||||||
|
manager.addItem(new HeaderSettingsItem("Scouting"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
binding.SettingsTable.removeAllViews();
|
||||||
|
|
||||||
|
manager.getView(binding.SettingsTable);
|
||||||
|
|
||||||
|
|
||||||
|
// Add "Edit scout notice" button to the bottom of the page=
|
||||||
|
|
||||||
|
|
||||||
|
// Add "Field edit" buttons to the bottom of the page
|
||||||
|
// LinearLayout fieldButtons = new LinearLayout(getContext());
|
||||||
|
// fieldButtons.setLayoutParams(new LinearLayout.LayoutParams(
|
||||||
|
// LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
// LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
// ));
|
||||||
|
// fieldButtons.setOrientation(HORIZONTAL);
|
||||||
|
//
|
||||||
|
// Button editMatchFieldsButton = new Button(getContext());
|
||||||
|
// editMatchFieldsButton.setText("Edit Match Fields");
|
||||||
|
// editMatchFieldsButton.setOnClickListener(v -> {
|
||||||
|
// FieldsFragment.set_filename(Fields.matchFieldsFilename);
|
||||||
|
// findNavController(this).navigate(R.id.action_navigation_settings_to_navigation_data_fields);
|
||||||
|
// });
|
||||||
|
// fieldButtons.addView(editMatchFieldsButton);
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Button editPitsFieldsButton = new Button(getContext());
|
||||||
|
// editPitsFieldsButton.setText("Edit pits Fields");
|
||||||
|
// editPitsFieldsButton.setOnClickListener(v -> {
|
||||||
|
// FieldsFragment.set_filename(Fields.pitsFieldsFilename);
|
||||||
|
// findNavController(this).navigate(R.id.action_navigation_settings_to_navigation_data_fields);
|
||||||
|
// });
|
||||||
|
// fieldButtons.addView(editPitsFieldsButton);
|
||||||
|
|
||||||
|
|
||||||
|
// binding.SettingsTable.addView(fieldButtons);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void editNotice(){
|
||||||
|
ScrollView sv = new ScrollView(getContext());
|
||||||
|
EditText editText = new EditText(getContext());
|
||||||
|
editText.setText(DataManager.scoutNotice);
|
||||||
|
sv.addView(editText);
|
||||||
|
|
||||||
|
|
||||||
|
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
|
||||||
|
alert.setTitle("Edit Notice");
|
||||||
|
alert.setView(sv);
|
||||||
|
alert.setNeutralButton("Cancel", null);
|
||||||
|
alert.setPositiveButton("Save", (dialogInterface, i) -> {
|
||||||
|
DataManager.scoutNotice = editText.getText().toString();
|
||||||
|
DataManager.save_scout_notice();
|
||||||
|
});
|
||||||
|
alert.setCancelable(false);
|
||||||
|
|
||||||
|
alert.create().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private TextView createText(String title) {
|
||||||
|
return new TextViewBuilder(getContext(), title)
|
||||||
|
.body1().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showAppInfo() {
|
||||||
|
LinearLayout ll = new LinearLayout(getContext());
|
||||||
|
ll.setOrientation(VERTICAL);
|
||||||
|
ll.setPadding(10, 10, 10, 10);
|
||||||
|
|
||||||
|
try {
|
||||||
|
PackageInfo pInfo = getContext().getPackageManager().getPackageInfo(getContext().getPackageName(), 0);
|
||||||
|
ll.addView(createText("Package: " + pInfo.packageName));
|
||||||
|
ll.addView(createText("Version: " + pInfo.versionName));
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
|
ll.addView(createText("Signature: " + (pInfo.signingInfo != null ? "True" : "False")));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
AlertManager.error("Failed to get version info", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
|
||||||
|
alert.setTitle("App info");
|
||||||
|
alert.setView(ll);
|
||||||
|
alert.setNeutralButton("Ok", null);
|
||||||
|
alert.setCancelable(true);
|
||||||
|
|
||||||
|
alert.create().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public abstract class SettingsItem<T> {
|
||||||
|
private String key;
|
||||||
|
private String title;
|
||||||
|
private T defaultValue;
|
||||||
|
public View view;
|
||||||
|
|
||||||
|
public SettingsItem(String key, String title, T defaultValue) {
|
||||||
|
this.key = key;
|
||||||
|
this.title = title;
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean reloadOnChange = false;
|
||||||
|
public void reloadOnChange(boolean enabled){
|
||||||
|
reloadOnChange = enabled;
|
||||||
|
}
|
||||||
|
public boolean isReloadOnChange(){
|
||||||
|
return reloadOnChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
if(isReloadOnChange()) reloadSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 TextViewBuilder(context, getTitle())
|
||||||
|
.sub1().build();
|
||||||
|
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
if(isReloadOnChange()) reloadSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 TallySettingsItem extends SettingsItem<Integer> {
|
||||||
|
private int max;
|
||||||
|
|
||||||
|
public TallySettingsItem(String key, String title, int max) {
|
||||||
|
super(key, title, prefs.getInt(key, (int) defaults.get(key)));
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
TallyCounterView tally;
|
||||||
|
private boolean enabled;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(boolean enabled){
|
||||||
|
this.enabled = enabled;
|
||||||
|
if(tally != null)
|
||||||
|
tally.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View createView(Context context) {
|
||||||
|
LinearLayout ll = new LinearLayout(getContext());
|
||||||
|
ll.setOrientation(VERTICAL);
|
||||||
|
|
||||||
|
tally = new TallyCounterView(getContext());
|
||||||
|
|
||||||
|
int value = getValue()+1;
|
||||||
|
if(value >= max){
|
||||||
|
value = max;
|
||||||
|
getEditor().putInt(getKey(), Math.max(0,max-1)).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
tally.setValue(value);
|
||||||
|
tally.setBounds(1, max);
|
||||||
|
|
||||||
|
tally.setOnCountChangedListener(count -> {
|
||||||
|
getEditor().putInt(getKey(), Math.max(0,count-1)).apply();
|
||||||
|
if(isReloadOnChange()) reloadSettings();
|
||||||
|
});
|
||||||
|
tally.setEnabled(enabled);
|
||||||
|
|
||||||
|
|
||||||
|
ll.addView(new TextViewBuilder(getContext(), getTitle())
|
||||||
|
.h6()
|
||||||
|
.build());
|
||||||
|
|
||||||
|
ll.addView(tally);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return ll;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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();
|
||||||
|
if(isReloadOnChange()) reloadSettings();
|
||||||
|
});
|
||||||
|
|
||||||
|
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, @Nullable SettingsItem<?>... controlledItems) {
|
||||||
|
super(key, title, prefs.getBoolean(key, (Boolean) defaults.get(key)));
|
||||||
|
this.controlledItems = (controlledItems != null) ? Arrays.asList(controlledItems) : new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
if(isReloadOnChange()) reloadSettings();
|
||||||
|
});
|
||||||
|
|
||||||
|
for (SettingsItem<?> item : controlledItems) {
|
||||||
|
item.setEnabled(getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return checkBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean getValue() {
|
||||||
|
return prefs.getBoolean(getKey(), (Boolean) defaults.get(getKey()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HeaderSettingsItem extends SettingsItem<Void> {
|
||||||
|
String title;
|
||||||
|
|
||||||
|
public HeaderSettingsItem(String title) {
|
||||||
|
super("", title, null);
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(boolean enabled){
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View createView(Context context) {
|
||||||
|
LinearLayout ll = new LinearLayout(context);
|
||||||
|
ll.setOrientation(VERTICAL);
|
||||||
|
ll.setPadding(0, 20,0,0);
|
||||||
|
|
||||||
|
ll.addView(new TextViewBuilder(context, title)
|
||||||
|
.h4()
|
||||||
|
.build());
|
||||||
|
|
||||||
|
ll.addView(new MaterialDivider(context));
|
||||||
|
|
||||||
|
return ll;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void getValue() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ButtonSettingsItem extends SettingsItem<Void> {
|
||||||
|
List<MaterialButton> buttons = new ArrayList<>();
|
||||||
|
List<String> titles = new ArrayList<>();
|
||||||
|
List<View.OnClickListener> callbacks = new ArrayList<>();
|
||||||
|
|
||||||
|
boolean enabled = true;
|
||||||
|
|
||||||
|
public ButtonSettingsItem() {
|
||||||
|
super("", "", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(boolean enabled){
|
||||||
|
this.enabled = enabled;
|
||||||
|
for(int i = 0; i < buttons.size(); i++){
|
||||||
|
buttons.get(i).setEnabled(enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addButton(String text, View.OnClickListener onClickListener) {
|
||||||
|
titles.add(text);
|
||||||
|
callbacks.add(onClickListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View createView(Context context) {
|
||||||
|
LinearLayout ll = new LinearLayout(context);
|
||||||
|
ll.setOrientation(HORIZONTAL);
|
||||||
|
|
||||||
|
for(int i = 0; i < titles.size(); i++){
|
||||||
|
MaterialButton button = new MaterialButton(context);
|
||||||
|
button.setText(titles.get(i));
|
||||||
|
button.setOnClickListener(callbacks.get(i));
|
||||||
|
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f);
|
||||||
|
layoutParams.setMargins(3, 0, 3, 0);
|
||||||
|
// layoutParams.weight
|
||||||
|
button.setLayoutParams(layoutParams);
|
||||||
|
button.setEnabled(enabled);
|
||||||
|
// button.weight
|
||||||
|
buttons.add(button);
|
||||||
|
|
||||||
|
ll.addView(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ll;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void getValue() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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(VERTICAL);
|
||||||
|
itemContainer.setPadding(32, 0, 32, 8);
|
||||||
|
|
||||||
|
View view = item.createView(context);
|
||||||
|
itemContainer.addView(view);
|
||||||
|
|
||||||
|
item.view = view;
|
||||||
|
|
||||||
|
views.add(itemContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getView(LinearLayout layout) {
|
||||||
|
for(int i = views.size()-1; i >= 0; i--)
|
||||||
|
layout.addView(views.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,256 +0,0 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.settings;
|
|
||||||
|
|
||||||
import static android.text.InputType.TYPE_CLASS_NUMBER;
|
|
||||||
import static com.ridgebotics.ridgescout.utility.settingsManager.AllyPosKey;
|
|
||||||
import static com.ridgebotics.ridgescout.utility.settingsManager.FTPEnabled;
|
|
||||||
import static com.ridgebotics.ridgescout.utility.settingsManager.FTPServer;
|
|
||||||
import static com.ridgebotics.ridgescout.utility.settingsManager.SelEVCodeKey;
|
|
||||||
import static com.ridgebotics.ridgescout.utility.settingsManager.TeamNumKey;
|
|
||||||
import static com.ridgebotics.ridgescout.utility.settingsManager.UnameKey;
|
|
||||||
import static com.ridgebotics.ridgescout.utility.settingsManager.WifiModeKey;
|
|
||||||
import static com.ridgebotics.ridgescout.utility.settingsManager.defaults;
|
|
||||||
import static com.ridgebotics.ridgescout.utility.settingsManager.getEditor;
|
|
||||||
import static com.ridgebotics.ridgescout.utility.settingsManager.prefs;
|
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.TextWatcher;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.CheckBox;
|
|
||||||
import android.widget.CompoundButton;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.Spinner;
|
|
||||||
import android.widget.TableRow;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
|
|
||||||
import com.google.android.material.divider.MaterialDivider;
|
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentSettingsBinding;
|
|
||||||
import com.ridgebotics.ridgescout.types.data.intType;
|
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
|
||||||
import com.ridgebotics.ridgescout.utility.settingsManager;
|
|
||||||
|
|
||||||
import com.skydoves.powerspinner.IconSpinnerAdapter;
|
|
||||||
import com.skydoves.powerspinner.IconSpinnerItem;
|
|
||||||
import com.skydoves.powerspinner.OnSpinnerItemSelectedListener;
|
|
||||||
import com.skydoves.powerspinner.PowerSpinnerView;
|
|
||||||
import com.skydoves.powerspinner.SpinnerGravity;
|
|
||||||
|
|
||||||
import org.checkerframework.checker.units.qual.C;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
|
|
||||||
public class settingsFragment extends Fragment {
|
|
||||||
private FragmentSettingsBinding binding;
|
|
||||||
private android.widget.ScrollView ScrollArea;
|
|
||||||
private android.widget.TableLayout Table;
|
|
||||||
|
|
||||||
// private void setDropdownItems(Spinner dropdown, String[] items){
|
|
||||||
// ArrayAdapter<String> adapter = new ArrayAdapter<>(requireActivity(), android.R.layout.simple_spinner_item, items);
|
|
||||||
// dropdown.setAdapter(adapter);
|
|
||||||
// }
|
|
||||||
|
|
||||||
private View[] concatArrays(View[] a, View[] b){
|
|
||||||
return Stream.of(a, b).flatMap(Stream::of).toArray(View[]::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private View[] addViews(View[] a){
|
|
||||||
for(int i = 0; i < a.length; i++){
|
|
||||||
binding.SettingsTable.addView(a[i]);
|
|
||||||
}
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int safeToInt(String num){
|
|
||||||
if(num.isEmpty())
|
|
||||||
return 0;
|
|
||||||
try {
|
|
||||||
return Integer.parseInt(num);
|
|
||||||
}catch (NumberFormatException e){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private View[] createHeading(String name){
|
|
||||||
TextView tv = new TextView(getContext());
|
|
||||||
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
|
||||||
TableRow.LayoutParams params = new TableRow.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
||||||
);
|
|
||||||
params.topMargin = 100;
|
|
||||||
tv.setLayoutParams(params);
|
|
||||||
tv.setTextSize(20);
|
|
||||||
tv.setText(name);
|
|
||||||
|
|
||||||
View divider = new MaterialDivider(getContext());
|
|
||||||
|
|
||||||
return new View[]{tv, divider};
|
|
||||||
}
|
|
||||||
|
|
||||||
private View[] addStringEdit(String name, String key){
|
|
||||||
View[] heading = createHeading(name);
|
|
||||||
EditText et = new EditText(getContext());
|
|
||||||
et.setText(prefs.getString(key, (String) defaults.get(key)));
|
|
||||||
|
|
||||||
et.addTextChangedListener(new TextWatcher() {
|
|
||||||
|
|
||||||
public void afterTextChanged(Editable s) {
|
|
||||||
getEditor().putString(key, s.toString()).apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
|
||||||
});
|
|
||||||
return concatArrays(heading, new View[]{et});
|
|
||||||
}
|
|
||||||
|
|
||||||
private View[] addNumberEdit(String name, String key){
|
|
||||||
View[] heading = createHeading(name);
|
|
||||||
EditText et = new EditText(getContext());
|
|
||||||
et.setText(String.valueOf(prefs.getInt(key, (Integer) defaults.get(key))));
|
|
||||||
et.setInputType(TYPE_CLASS_NUMBER);
|
|
||||||
|
|
||||||
et.addTextChangedListener(new TextWatcher() {
|
|
||||||
|
|
||||||
public void afterTextChanged(Editable s) {
|
|
||||||
getEditor().putInt(key, safeToInt(s.toString())).apply();
|
|
||||||
}
|
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
|
||||||
});
|
|
||||||
return concatArrays(heading, new View[]{et});
|
|
||||||
}
|
|
||||||
|
|
||||||
private PowerSpinnerView addDropdownEdit(String name, String[] options, String key){
|
|
||||||
PowerSpinnerView dropdown = new PowerSpinnerView(getContext());
|
|
||||||
|
|
||||||
List<IconSpinnerItem> iconSpinnerItems = new ArrayList<>();
|
|
||||||
for(int i = 0; i < options.length; i++){
|
|
||||||
iconSpinnerItems.add(new IconSpinnerItem(options[i]));
|
|
||||||
}
|
|
||||||
IconSpinnerAdapter iconSpinnerAdapter = new IconSpinnerAdapter(dropdown);
|
|
||||||
|
|
||||||
dropdown.setGravity(Gravity.CENTER);
|
|
||||||
|
|
||||||
dropdown.setSpinnerAdapter(iconSpinnerAdapter);
|
|
||||||
dropdown.setItems(iconSpinnerItems);
|
|
||||||
dropdown.setHint("Unselected");
|
|
||||||
|
|
||||||
dropdown.setPadding(10,20,10,20);
|
|
||||||
dropdown.setBackgroundColor(0xf0000000);
|
|
||||||
dropdown.setTextColor(0xff00ff00);
|
|
||||||
dropdown.setTextSize(14.5f);
|
|
||||||
dropdown.setArrowGravity(SpinnerGravity.END);
|
|
||||||
dropdown.setArrowPadding(8);
|
|
||||||
dropdown.setSpinnerPopupElevation(14);
|
|
||||||
|
|
||||||
return dropdown;
|
|
||||||
}
|
|
||||||
|
|
||||||
private View[] addDropdownByString(String name, String[] options, String key){
|
|
||||||
View[] heading = createHeading(name);
|
|
||||||
PowerSpinnerView dropdown = addDropdownEdit(name, options, key);
|
|
||||||
int index = Arrays.asList(options).indexOf(prefs.getString(key, (String) defaults.get(key)));
|
|
||||||
System.out.println(index);
|
|
||||||
|
|
||||||
if(options.length != 0 && index != -1){
|
|
||||||
dropdown.selectItemByIndex(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
dropdown.setOnSpinnerItemSelectedListener(
|
|
||||||
(OnSpinnerItemSelectedListener<IconSpinnerItem>)
|
|
||||||
(oldIndex, oldItem, newIndex, newItem) -> getEditor().putString(key, newItem.getText().toString()).apply()
|
|
||||||
);
|
|
||||||
|
|
||||||
return concatArrays(heading, new View[]{dropdown});
|
|
||||||
}
|
|
||||||
|
|
||||||
private View[] addDropdownByIndex(String name, String[] options, String key){
|
|
||||||
View[] heading = createHeading(name);
|
|
||||||
PowerSpinnerView dropdown = addDropdownEdit(name, options, key);
|
|
||||||
|
|
||||||
int index = prefs.getInt(key, (Integer) defaults.get(key));
|
|
||||||
|
|
||||||
if(dropdown.length() != 0 && index != -1){
|
|
||||||
dropdown.selectItemByIndex(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
dropdown.setOnSpinnerItemSelectedListener(
|
|
||||||
(OnSpinnerItemSelectedListener<IconSpinnerItem>)
|
|
||||||
(oldIndex, oldItem, newIndex, newItem) -> getEditor().putInt(key, newIndex).apply()
|
|
||||||
);
|
|
||||||
|
|
||||||
return concatArrays(heading, new View[]{dropdown});
|
|
||||||
}
|
|
||||||
|
|
||||||
private View[] addCheckbox(String name, String key, View[] dependency){
|
|
||||||
CheckBox cb = new CheckBox(getContext());
|
|
||||||
cb.setText(name);
|
|
||||||
cb.setTextSize(22);
|
|
||||||
boolean checked = prefs.getBoolean(key, (Boolean) defaults.get(key));
|
|
||||||
cb.setChecked(checked);
|
|
||||||
|
|
||||||
if(dependency != null && !checked){
|
|
||||||
for(int i = 0; i < dependency.length; i++){
|
|
||||||
dependency[i].setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cb.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
|
||||||
getEditor().putBoolean(key, isChecked).apply();
|
|
||||||
if(dependency != null){
|
|
||||||
for(int i = 0; i < dependency.length; i++){
|
|
||||||
dependency[i].setVisibility(isChecked ? View.VISIBLE : View.GONE);
|
|
||||||
System.out.println(dependency[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return new View[]{new MaterialDivider(getContext()), cb};
|
|
||||||
}
|
|
||||||
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
|
||||||
ViewGroup container, Bundle savedInstanceState) {
|
|
||||||
|
|
||||||
binding = FragmentSettingsBinding.inflate(inflater, container, false);
|
|
||||||
View root = binding.getRoot();
|
|
||||||
|
|
||||||
String[] alliance_pos_list = new String[]{"red-1", "red-2", "red-3",
|
|
||||||
"blue-1", "blue-2", "blue-3"};
|
|
||||||
|
|
||||||
addViews(addStringEdit("Username", UnameKey));
|
|
||||||
addViews(addDropdownByString("Event Code", fileEditor.getEventList().toArray(new String[0]), SelEVCodeKey));
|
|
||||||
addViews(addDropdownByString("Alliance Position", alliance_pos_list, AllyPosKey));
|
|
||||||
addViews(addNumberEdit("Team Number", TeamNumKey));
|
|
||||||
|
|
||||||
View[] FTPDependency = addStringEdit("FTP Server", FTPServer);
|
|
||||||
View[] WifiDependency = addCheckbox("FTP Enabled", FTPEnabled, FTPDependency);
|
|
||||||
addViews(addCheckbox("Wifi Mode", WifiModeKey, concatArrays(FTPDependency, WifiDependency)));
|
|
||||||
addViews(WifiDependency);
|
|
||||||
addViews(FTPDependency);
|
|
||||||
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyView() {
|
|
||||||
super.onDestroyView();
|
|
||||||
binding = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,15 +9,20 @@ import static com.ridgebotics.ridgescout.utility.SharePrompt.shareContent;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
|
import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter;
|
||||||
import com.ridgebotics.ridgescout.types.data.dataType;
|
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||||
import com.ridgebotics.ridgescout.types.frcMatch;
|
import com.ridgebotics.ridgescout.types.frcMatch;
|
||||||
import com.ridgebotics.ridgescout.types.frcTeam;
|
import com.ridgebotics.ridgescout.types.frcTeam;
|
||||||
|
import com.ridgebotics.ridgescout.types.input.FieldType;
|
||||||
import com.ridgebotics.ridgescout.utility.DataManager;
|
import com.ridgebotics.ridgescout.utility.DataManager;
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
|
|
||||||
|
// Static class to export matches to a string.
|
||||||
public class CSVExport {
|
public class CSVExport {
|
||||||
private static String[] alliances = {"red", "blue"};
|
private static String[] alliances = {"red", "blue"};
|
||||||
|
|
||||||
|
private static String safeCSV(String input){
|
||||||
|
return input.replace("\n", "").replace(",", ".").replace(";", ".");
|
||||||
|
}
|
||||||
|
|
||||||
public static void exportMatches(Context c){
|
public static void exportMatches(Context c){
|
||||||
DataManager.reload_event();
|
DataManager.reload_event();
|
||||||
@@ -52,13 +57,21 @@ public class CSVExport {
|
|||||||
data += (teamNum + ",");
|
data += (teamNum + ",");
|
||||||
|
|
||||||
String filename = evcode+"-"+matchNum+"-"+alliance+"-"+alliancePos+"-"+teamNum+".matchscoutdata";
|
String filename = evcode+"-"+matchNum+"-"+alliance+"-"+alliancePos+"-"+teamNum+".matchscoutdata";
|
||||||
if(!fileEditor.fileExist(filename)){
|
if(!FileEditor.fileExist(filename)){
|
||||||
data += ("null,".repeat(match_latest_values.length));
|
data += ("null,".repeat(match_latest_values.length));
|
||||||
}else{
|
}else{
|
||||||
|
try {
|
||||||
|
String tempData = "";
|
||||||
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.match_values, DataManager.match_transferValues);
|
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.match_values, DataManager.match_transferValues);
|
||||||
dataType[] types = psdr.data.array;
|
RawDataType[] matchData = psdr.data.array;
|
||||||
for(int i = 0; i < types.length; i++) {
|
FieldType[] types = psdr.data.values[psdr.data.values.length-1];
|
||||||
data += (types[i].get() + ",");
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -77,7 +90,7 @@ public class CSVExport {
|
|||||||
|
|
||||||
String data = "";
|
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++){
|
for(int i = 0; i < pit_latest_values.length; i++){
|
||||||
data += (pit_latest_values[i].name + ",");
|
data += (pit_latest_values[i].name + ",");
|
||||||
}
|
}
|
||||||
@@ -96,13 +109,21 @@ public class CSVExport {
|
|||||||
data += (team.startingYear + ",");
|
data += (team.startingYear + ",");
|
||||||
|
|
||||||
String filename = evcode+"-"+team.teamNumber+".pitscoutdata";
|
String filename = evcode+"-"+team.teamNumber+".pitscoutdata";
|
||||||
if(!fileEditor.fileExist(filename)){
|
if(!FileEditor.fileExist(filename)){
|
||||||
data += ("null,".repeat(pit_latest_values.length));
|
data += ("null,".repeat(pit_latest_values.length));
|
||||||
}else{
|
}else{
|
||||||
|
try {
|
||||||
|
String tempData = "";
|
||||||
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.pit_values, DataManager.pit_transferValues);
|
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.pit_values, DataManager.pit_transferValues);
|
||||||
dataType[] types = psdr.data.array;
|
RawDataType[] teamData = psdr.data.array;
|
||||||
for(int i = 0; i < types.length; i++) {
|
FieldType[] types = psdr.data.values[psdr.data.values.length-1];
|
||||||
data += (types[i].get() + ",");
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,163 +0,0 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.transfer;
|
|
||||||
|
|
||||||
//import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
|
|
||||||
import static com.ridgebotics.ridgescout.utility.fileEditor.baseDir;
|
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
|
||||||
import com.ridgebotics.ridgescout.utility.settingsManager;
|
|
||||||
|
|
||||||
import org.apache.commons.net.ftp.FTP;
|
|
||||||
import org.apache.commons.net.ftp.FTPClient;
|
|
||||||
import org.apache.commons.net.ftp.FTPCmd;
|
|
||||||
import org.apache.commons.net.ftp.FTPFile;
|
|
||||||
import org.apache.commons.net.ftp.FTPReply;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
|
|
||||||
public class FTPSync extends Thread {
|
|
||||||
public static final String remoteBasePath = "/RidgeScout/";
|
|
||||||
public static final long timeTolerance = 60000; // One min
|
|
||||||
public static long lastSyncTime = 0;
|
|
||||||
|
|
||||||
public interface onResult {
|
|
||||||
void onResult(boolean error, int upCount, int downCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
public onResult onResult;
|
|
||||||
|
|
||||||
public static void sync(onResult onResult){
|
|
||||||
// DataManager.reload_event();
|
|
||||||
FTPSync ftpSync = new FTPSync();
|
|
||||||
ftpSync.onResult = onResult;
|
|
||||||
ftpSync.start();
|
|
||||||
|
|
||||||
lastSyncTime = new Date().getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
FTPClient ftpClient;
|
|
||||||
|
|
||||||
// private class FileDate {
|
|
||||||
// public String filename;
|
|
||||||
// public Calendar lastModified;
|
|
||||||
// }
|
|
||||||
|
|
||||||
private int upCount = 0;
|
|
||||||
private int downCount = 0;
|
|
||||||
|
|
||||||
private void downloadFile(FTPFile remoteFile, File localFile) throws IOException {
|
|
||||||
try (FileOutputStream fos = new FileOutputStream(localFile)) {
|
|
||||||
ftpClient.retrieveFile(remoteBasePath + remoteFile.getName(), fos);
|
|
||||||
}
|
|
||||||
Date d = getUtcTimestamp(remoteFile);
|
|
||||||
System.out.println(d);
|
|
||||||
setLocalFileTimestamp(localFile, d);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void uploadFile(File localFile) throws IOException {
|
|
||||||
try (FileInputStream fis = new FileInputStream(localFile)) {
|
|
||||||
ftpClient.storeFile(remoteBasePath + localFile.getName(), fis);
|
|
||||||
}
|
|
||||||
setLocalFileTimestamp(localFile, new Date());
|
|
||||||
}
|
|
||||||
|
|
||||||
private FTPFile findRemoteFile(FTPFile[] remoteFiles, String fileName) {
|
|
||||||
for (FTPFile file : remoteFiles) {
|
|
||||||
if (file.getName().equals(fileName)) {
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Date getUtcTimestamp(FTPFile file) {
|
|
||||||
return file.getTimestamp().getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Date getLocalFileUtcTimestamp(File file) {
|
|
||||||
return new Date(file.lastModified());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setLocalFileTimestamp(File file, Date date) {
|
|
||||||
file.setLastModified(date.getTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
// private long longAbs(long n){
|
|
||||||
// return n>0 ? n : -n;
|
|
||||||
// }
|
|
||||||
|
|
||||||
private boolean toleranceCompareAfter(Date d1, Date d2){
|
|
||||||
long diff = d1.getTime() - d2.getTime();
|
|
||||||
System.out.println(diff);
|
|
||||||
return diff > timeTolerance;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
// localTimeZone = TimeZone.getDefault();
|
|
||||||
ftpClient = new FTPClient();
|
|
||||||
InetAddress address = InetAddress.getByName(settingsManager.getFTPServer());
|
|
||||||
ftpClient.connect(address);
|
|
||||||
ftpClient.login("anonymous", null);
|
|
||||||
ftpClient.enterLocalPassiveMode();
|
|
||||||
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
|
|
||||||
|
|
||||||
File localDir = new File(baseDir);
|
|
||||||
File[] localFiles = localDir.listFiles();
|
|
||||||
FTPFile[] remoteFiles = ftpClient.listFiles(remoteBasePath);
|
|
||||||
|
|
||||||
if (localFiles != null) {
|
|
||||||
for (File localFile : localFiles) {
|
|
||||||
if (localFile.isFile()) {
|
|
||||||
FTPFile remoteFile = findRemoteFile(remoteFiles, localFile.getName());
|
|
||||||
//
|
|
||||||
// Date t1 = getLocalFileUtcTimestamp(localFile);
|
|
||||||
// Date t2 = getUtcTimestamp(remoteFile);
|
|
||||||
////
|
|
||||||
// System.out.println("- " + t1.getTime() + (t1.after(t2) ? ">" : "<") + t2.getTime());
|
|
||||||
|
|
||||||
if (remoteFile == null || toleranceCompareAfter(getLocalFileUtcTimestamp(localFile), (getUtcTimestamp(remoteFile)))) {
|
|
||||||
uploadFile(localFile);
|
|
||||||
System.out.println("Uploaded " + localFile.getName());
|
|
||||||
upCount++;
|
|
||||||
}else{
|
|
||||||
System.out.println("Did not upload " + localFile.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (FTPFile remoteFile : remoteFiles) {
|
|
||||||
if (!remoteFile.isDirectory()) {
|
|
||||||
File localFile = new File(baseDir, remoteFile.getName());
|
|
||||||
|
|
||||||
// Date t1 = getLocalFileUtcTimestamp(localFile);
|
|
||||||
// Date t2 = getUtcTimestamp(remoteFile);
|
|
||||||
////
|
|
||||||
// System.out.println("- " + t1 + (t1.after(t2) ? ">" : "<") + t2);
|
|
||||||
|
|
||||||
if (!localFile.exists() || toleranceCompareAfter(getUtcTimestamp(remoteFile), (getLocalFileUtcTimestamp(localFile)))) {
|
|
||||||
downloadFile(remoteFile, localFile);
|
|
||||||
System.out.println("Downloaded " + localFile.getName());
|
|
||||||
downCount++;
|
|
||||||
}else{
|
|
||||||
System.out.println("Did not download " + remoteFile.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
AlertManager.error(e);
|
|
||||||
onResult.onResult(true, upCount, downCount);
|
|
||||||
} finally {
|
|
||||||
onResult.onResult(false, upCount, downCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,13 +6,13 @@ import android.content.Intent;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.MainActivity;
|
import com.ridgebotics.ridgescout.MainActivity;
|
||||||
import com.ridgebotics.ridgescout.types.file;
|
import com.ridgebotics.ridgescout.types.ScoutingFile;
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
||||||
import com.ridgebotics.ridgescout.utility.DataManager;
|
import com.ridgebotics.ridgescout.utility.DataManager;
|
||||||
import com.ridgebotics.ridgescout.utility.SharePrompt;
|
import com.ridgebotics.ridgescout.utility.SharePrompt;
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -20,28 +20,8 @@ import java.io.InputStream;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
// Class to create the share and receive popups to transfer scouting data.
|
||||||
public class FileBundle {
|
public class FileBundle {
|
||||||
private static final Intent FILE_SELECT_CODE = new Intent();
|
|
||||||
|
|
||||||
public static void send(String[] files, Context c){
|
|
||||||
try {
|
|
||||||
ByteBuilder b = new ByteBuilder();
|
|
||||||
|
|
||||||
for(int i = 0; i < files.length; i++){
|
|
||||||
if(!fileEditor.fileExist(files[i])) continue;
|
|
||||||
// byte[] data = fileEditor.readFile(files[i]);
|
|
||||||
file f = new file(files[i]);
|
|
||||||
b.addRaw(file.typecode, f.encode());
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] data = b.build();
|
|
||||||
send(data, c);
|
|
||||||
|
|
||||||
} catch (ByteBuilder.buildingException e) {
|
|
||||||
AlertManager.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void send(byte[] data, Context c){
|
public static void send(byte[] data, Context c){
|
||||||
String filename = DataManager.getevcode() + "-" + System.currentTimeMillis() + ".scoutbundle";
|
String filename = DataManager.getevcode() + "-" + System.currentTimeMillis() + ".scoutbundle";
|
||||||
SharePrompt.shareContent(c, filename, data, "application/ridgescout");
|
SharePrompt.shareContent(c, filename, data, "application/ridgescout");
|
||||||
@@ -58,6 +38,7 @@ public class FileBundle {
|
|||||||
MainActivity.setResultRelay(new MainActivity.activityResultRelay() {
|
MainActivity.setResultRelay(new MainActivity.activityResultRelay() {
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
if(data == null) return;
|
||||||
Uri uri = data.getData();
|
Uri uri = data.getData();
|
||||||
if(uri == null) return;
|
if(uri == null) return;
|
||||||
|
|
||||||
@@ -90,18 +71,18 @@ public class FileBundle {
|
|||||||
|
|
||||||
for(int i = 0; i < parsedObjectList.size(); i++){
|
for(int i = 0; i < parsedObjectList.size(); i++){
|
||||||
BuiltByteParser.parsedObject pa = parsedObjectList.get(i);
|
BuiltByteParser.parsedObject pa = parsedObjectList.get(i);
|
||||||
if(pa.getType() != file.typecode) continue;
|
if(pa.getType() != ScoutingFile.typecode) continue;
|
||||||
file f = file.decode((byte[]) pa.get());
|
ScoutingFile f = ScoutingFile.decode((byte[]) pa.get());
|
||||||
if(f == null) continue;
|
if(f == null) continue;
|
||||||
filenames.add(f.filename);
|
filenames.add(f.filename);
|
||||||
fileEditor.writeFile(f.filename, f.data);
|
FileEditor.writeFile(f.filename, f.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
AlertManager.alert("Saved",
|
AlertManager.alert("Saved",
|
||||||
String.join("\n", filenames));
|
String.join("\n", filenames));
|
||||||
|
|
||||||
}catch (BuiltByteParser.byteParsingExeption e){
|
}catch (Exception e){
|
||||||
AlertManager.error(e);
|
AlertManager.error("Failed saving files!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+56
-17
@@ -1,11 +1,14 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.transfer;
|
package com.ridgebotics.ridgescout.ui.transfer;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.fileselector_selected_color;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.fileselector_unselected_color;
|
||||||
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
|
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.CheckBox;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.TableLayout;
|
import android.widget.TableLayout;
|
||||||
import android.widget.TableRow;
|
import android.widget.TableRow;
|
||||||
@@ -16,18 +19,19 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentTransferFileSelectorBinding;
|
import com.ridgebotics.ridgescout.databinding.FragmentTransferFileSelectorBinding;
|
||||||
import com.ridgebotics.ridgescout.types.file;
|
import com.ridgebotics.ridgescout.types.ScoutingFile;
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
import com.ridgebotics.ridgescout.utility.ByteBuilder;
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
import com.ridgebotics.ridgescout.utility.DataManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
|
import com.ridgebotics.ridgescout.utility.builders.TextViewBuilder;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
// Class to show a file browseer
|
||||||
public class FileSelectorFragment extends Fragment {
|
public class FileSelectorFragment extends Fragment {
|
||||||
private static final int background_color = 0x5000ff00;
|
|
||||||
private static final int unselected_background_color = 0x2000ff00;
|
|
||||||
|
|
||||||
private static on_file_select onSelect = files -> {};
|
private static on_file_select onSelect = files -> {};
|
||||||
|
|
||||||
@@ -41,14 +45,18 @@ public class FileSelectorFragment extends Fragment {
|
|||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
binding = FragmentTransferFileSelectorBinding.inflate(inflater, container, false);
|
binding = FragmentTransferFileSelectorBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
|
DataManager.reload_event();
|
||||||
|
|
||||||
meta_string_array = new String[]{
|
meta_string_array = new String[]{
|
||||||
"matches.fields",
|
"matches.fields",
|
||||||
"pits.fields",
|
"pits.fields",
|
||||||
evcode+".eventdata"
|
evcode+".eventdata",
|
||||||
|
evcode+".rescout",
|
||||||
|
evcode+".scoutnotice",
|
||||||
|
"todelete.colabarray",
|
||||||
};
|
};
|
||||||
|
|
||||||
String[] files = fileEditor.getEventFiles(evcode);
|
String[] files = FileEditor.getEventFiles(evcode);
|
||||||
|
|
||||||
Boolean[] selected_arr = new Boolean[files.length];
|
Boolean[] selected_arr = new Boolean[files.length];
|
||||||
Arrays.fill(selected_arr, Boolean.TRUE);
|
Arrays.fill(selected_arr, Boolean.TRUE);
|
||||||
@@ -64,19 +72,33 @@ public class FileSelectorFragment extends Fragment {
|
|||||||
tr.setPadding(20,20,20,20);
|
tr.setPadding(20,20,20,20);
|
||||||
binding.fileSelectorTable.addView(tr);
|
binding.fileSelectorTable.addView(tr);
|
||||||
|
|
||||||
tr.setBackgroundColor(background_color);
|
tr.setBackgroundColor(fileselector_selected_color);
|
||||||
|
|
||||||
TextView tv = new TextView(getContext());
|
CheckBox checkBox = new CheckBox(getContext());
|
||||||
tv.setText(String.valueOf(files[i]));
|
checkBox.setChecked(true);
|
||||||
tv.setTextSize(20);
|
tr.addView(checkBox);
|
||||||
tr.addView(tv);
|
|
||||||
|
// Filename
|
||||||
|
tr.addView(
|
||||||
|
new TextViewBuilder(getContext(), files[i])
|
||||||
|
.size(20)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
|
||||||
final int fi = i;
|
final int fi = i;
|
||||||
tr.setOnClickListener(view -> {
|
tr.setOnClickListener(view -> {
|
||||||
boolean sel = !selected_arr[fi];
|
boolean sel = !selected_arr[fi];
|
||||||
selected_arr[fi] = sel;
|
selected_arr[fi] = sel;
|
||||||
|
|
||||||
tr.setBackgroundColor(sel ? background_color : unselected_background_color);
|
tr.setBackgroundColor(sel ? fileselector_selected_color : fileselector_unselected_color);
|
||||||
|
((CheckBox) tr.getChildAt(0)).setChecked(sel);
|
||||||
|
});
|
||||||
|
checkBox.setOnClickListener(view -> {
|
||||||
|
boolean sel = !selected_arr[fi];
|
||||||
|
selected_arr[fi] = sel;
|
||||||
|
|
||||||
|
tr.setBackgroundColor(sel ? fileselector_selected_color : fileselector_unselected_color);
|
||||||
|
((CheckBox) tr.getChildAt(0)).setChecked(sel);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,9 +110,12 @@ public class FileSelectorFragment extends Fragment {
|
|||||||
Arrays.fill(selected_arr, Boolean.TRUE);
|
Arrays.fill(selected_arr, Boolean.TRUE);
|
||||||
|
|
||||||
for(int i = 0; i < files.length; i++){
|
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.setBackgroundColor(fileselector_selected_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;
|
return false;
|
||||||
@@ -103,6 +128,7 @@ public class FileSelectorFragment extends Fragment {
|
|||||||
View child = binding.fileSelectorTable.getChildAt(i);
|
View child = binding.fileSelectorTable.getChildAt(i);
|
||||||
if(child.getVisibility() == View.VISIBLE && selected_arr[i])
|
if(child.getVisibility() == View.VISIBLE && selected_arr[i])
|
||||||
filenames.add(files[i]);
|
filenames.add(files[i]);
|
||||||
|
|
||||||
}
|
}
|
||||||
onSelect.onSelect(get_bytes_of_filenames(filenames));
|
onSelect.onSelect(get_bytes_of_filenames(filenames));
|
||||||
});
|
});
|
||||||
@@ -176,8 +202,21 @@ public class FileSelectorFragment extends Fragment {
|
|||||||
ByteBuilder b = new ByteBuilder();
|
ByteBuilder b = new ByteBuilder();
|
||||||
|
|
||||||
for(int i = 0; i < filenames.size(); i++){
|
for(int i = 0; i < filenames.size(); i++){
|
||||||
file f = new file(filenames.get(i));
|
ScoutingFile f = new ScoutingFile(filenames.get(i));
|
||||||
b.addRaw(file.typecode, f.encode());
|
|
||||||
|
if(!FileEditor.fileExist(f.filename)) {
|
||||||
|
AlertManager.addSimpleError("File " + f.filename + " Does not exist!");
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
byte[] bytes = f.encode();
|
||||||
|
|
||||||
|
if(bytes == null || bytes.length == 0) {
|
||||||
|
AlertManager.addSimpleError("File " + f.filename + " Has no data!");
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
b.addRaw(ScoutingFile.typecode, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.build();
|
return b.build();
|
||||||
|
|||||||
@@ -0,0 +1,386 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.transfer;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.FileEditor.baseDir;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.types.ColabArray;
|
||||||
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
|
import com.ridgebotics.ridgescout.utility.HttpGetFile;
|
||||||
|
import com.ridgebotics.ridgescout.utility.HttpPutFile;
|
||||||
|
import com.ridgebotics.ridgescout.utility.RequestTask;
|
||||||
|
import com.ridgebotics.ridgescout.utility.SettingsManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.ToDelete;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
// Class to synchronise data over HTTP.
|
||||||
|
public class HttpSync extends Thread {
|
||||||
|
public static final String timestampsFilename = "timestamps";
|
||||||
|
|
||||||
|
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();
|
||||||
|
HttpSync sync = new HttpSync();
|
||||||
|
|
||||||
|
sync.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int upCount = 0;
|
||||||
|
private int downCount = 0;
|
||||||
|
|
||||||
|
private class TransferFile {
|
||||||
|
public String filename;
|
||||||
|
public Date updated;
|
||||||
|
public String checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TransferFile> localFiles = new ArrayList<>();
|
||||||
|
private List<TransferFile> remoteFiles = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void await() {
|
||||||
|
while(!runningRequest.get()) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (InterruptedException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AtomicBoolean runningRequest = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
isRunning = true;
|
||||||
|
boolean sendMetaFiles = SettingsManager.getFTPSendMetaFiles();
|
||||||
|
|
||||||
|
ToDelete.reload_todelete_list();
|
||||||
|
List<String> removeFiles = ToDelete.todelete_list.get();
|
||||||
|
|
||||||
|
String serverIP = SettingsManager.getFTPServer();
|
||||||
|
String serverKey = SettingsManager.getFTPKey();
|
||||||
|
|
||||||
|
setUpdateIndicator("Getting Metadata...");
|
||||||
|
|
||||||
|
// Load metadata from server
|
||||||
|
getRemoteFileMetadata(serverIP, serverKey);
|
||||||
|
|
||||||
|
if(!isRunning){
|
||||||
|
setUpdateIndicator("Error Connecting");
|
||||||
|
onResult.onResult(true, upCount, downCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getLocalFileMetadata();
|
||||||
|
|
||||||
|
localFiles.removeIf(localFile -> removeFiles.contains(localFile.filename+","+localFile.checksum));
|
||||||
|
remoteFiles.removeIf(remoteFile -> removeFiles.contains(remoteFile.filename+","+remoteFile.checksum));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Wait for metadata request to finish
|
||||||
|
|
||||||
|
setUpdateIndicator("Uploading 0%");
|
||||||
|
|
||||||
|
for(int i = 0; i < localFiles.size(); i++){
|
||||||
|
TransferFile localFile = localFiles.get(i);
|
||||||
|
|
||||||
|
TransferFile remoteFile = findInFileArray(remoteFiles, localFile.filename);
|
||||||
|
|
||||||
|
// Check if the file is a meta file, and uploads it based off of the setting
|
||||||
|
boolean sendField = (sendMetaFiles || !(localFile.filename.endsWith(".fields")));
|
||||||
|
|
||||||
|
boolean shouldUpload;
|
||||||
|
boolean special;
|
||||||
|
|
||||||
|
// If there is no file on the sever, upload.
|
||||||
|
if(remoteFile == null) {
|
||||||
|
shouldUpload = true;
|
||||||
|
special = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// If the remote file is the same as the local one, do nothing.
|
||||||
|
boolean checksumsEqual = Objects.equals(localFile.checksum, remoteFile.checksum);
|
||||||
|
// If the local file is a colabarray, give it a special propreties
|
||||||
|
special = FileEditor.requiresSpecialInteraction(remoteFile.filename);
|
||||||
|
// If the local file is updated after the remote file
|
||||||
|
boolean after = after(localFile.updated, remoteFile.updated);
|
||||||
|
|
||||||
|
shouldUpload = !checksumsEqual && (special || after);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sendField && shouldUpload) {
|
||||||
|
uploadFile(localFile, serverIP, serverKey, special);
|
||||||
|
Log.d(getClass().toString(), "LocalFile: " + localFile.filename + ", " + localFile.checksum + ", " + localFile.updated + ": Uploaded");
|
||||||
|
upCount++;
|
||||||
|
}else {
|
||||||
|
Log.d(getClass().toString(), "LocalFile: " + localFile.filename + ", " + localFile.checksum + ", " + localFile.updated + ": Not uploaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
setUpdateIndicator("Uploading " + (Math.floor((double) (i * 1000) / localFiles.size()) / 10) + "%");
|
||||||
|
}
|
||||||
|
|
||||||
|
setUpdateIndicator("Downloading 0%");
|
||||||
|
|
||||||
|
for(int i = 0; i < remoteFiles.size(); i++){
|
||||||
|
TransferFile remoteFile = remoteFiles.get(i);
|
||||||
|
|
||||||
|
TransferFile localFile = findInFileArray(localFiles, remoteFile.filename);
|
||||||
|
|
||||||
|
boolean shouldDownload;
|
||||||
|
|
||||||
|
// If there is no file on the sever, upload.
|
||||||
|
if(localFile == null) {
|
||||||
|
shouldDownload = true;
|
||||||
|
} else {
|
||||||
|
// If the remote file is the same as the local one, do nothing.
|
||||||
|
|
||||||
|
boolean checksumsNotEqual = !Objects.equals(localFile.checksum, remoteFile.checksum);
|
||||||
|
// If the local file is updated after the remote file
|
||||||
|
boolean after = after(remoteFile.updated, localFile.updated);
|
||||||
|
// If the local file and remote file's upload dates are exactly the same
|
||||||
|
boolean datesNotEqual = !localFile.updated.equals(remoteFile.updated);
|
||||||
|
|
||||||
|
shouldDownload = checksumsNotEqual && after;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(shouldDownload) {
|
||||||
|
downloadFile(remoteFile, serverIP);
|
||||||
|
// await();
|
||||||
|
Log.d(getClass().toString(), "RemoteFile: " + remoteFile.filename + ", " + remoteFile.checksum + ", " + remoteFile.updated + ": Downloaded");
|
||||||
|
downCount++;
|
||||||
|
} else {
|
||||||
|
Log.d(getClass().toString(), "RemoteFile: " + remoteFile.filename + ", " + remoteFile.checksum + ", " + remoteFile.updated + ": Not downloaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
setUpdateIndicator("Downloading " + (Math.floor((double) (i * 1000) / remoteFiles.size()) / 10) + "%");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove files marked for deletion
|
||||||
|
ToDelete.deleteFiles();
|
||||||
|
|
||||||
|
setUpdateIndicator("Finished, " + upCount + " Up, " + downCount + " Down");
|
||||||
|
|
||||||
|
|
||||||
|
onResult.onResult(false, upCount, downCount);
|
||||||
|
isRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Find file based off of filename
|
||||||
|
private TransferFile findInFileArray(List<TransferFile> files, String filename){
|
||||||
|
for(TransferFile file : files) {
|
||||||
|
if(file.filename.equals(filename))
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get teh last modified date of a file
|
||||||
|
private Date getLocalFileUtcTimestamp(File file) {
|
||||||
|
return new Date(file.lastModified());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the local metadata of files
|
||||||
|
private void getLocalFileMetadata() {
|
||||||
|
File localDir = new File(baseDir);
|
||||||
|
File[] localFileNames = localDir.listFiles();
|
||||||
|
|
||||||
|
assert localFileNames != null;
|
||||||
|
for (int i = 0; i < localFileNames.length; i++) {
|
||||||
|
File file = localFileNames[i];
|
||||||
|
|
||||||
|
if(file.isDirectory()) continue;
|
||||||
|
// Remove timestamts file
|
||||||
|
if(file.getName().equals(timestampsFilename)) continue;
|
||||||
|
|
||||||
|
TransferFile tf = new TransferFile();
|
||||||
|
tf.filename = file.getName();
|
||||||
|
tf.updated = getLocalFileUtcTimestamp(file);
|
||||||
|
try {
|
||||||
|
tf.checksum = FileEditor.getSHA256Hash(file.getName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
AlertManager.error("Failed to get hash of: " + file.getName(), e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
localFiles.add(tf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send request to server and retrieve metadata
|
||||||
|
private void getRemoteFileMetadata(String serverURL, String serverKey) {
|
||||||
|
final RequestTask rq = new RequestTask();
|
||||||
|
runningRequest.set(false);
|
||||||
|
rq.onResult(metadata -> {
|
||||||
|
try {
|
||||||
|
JSONObject j = new JSONObject(metadata);
|
||||||
|
for (Iterator<String> it = j.keys(); it.hasNext(); ) {
|
||||||
|
String key = it.next();
|
||||||
|
|
||||||
|
JSONObject obj = j.getJSONObject(key);
|
||||||
|
|
||||||
|
TransferFile tf = new TransferFile();
|
||||||
|
tf.filename = key;
|
||||||
|
tf.updated = new Date(Long.parseLong(obj.getString("modified")));
|
||||||
|
tf.checksum = obj.getString("sha256");
|
||||||
|
|
||||||
|
remoteFiles.add(tf);
|
||||||
|
}
|
||||||
|
}catch(JSONException | NullPointerException e ) {
|
||||||
|
AlertManager.error(e);
|
||||||
|
isRunning = false;
|
||||||
|
}
|
||||||
|
runningRequest.set(true);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
rq.execute((serverURL + "/api/metadata"), "api_key: " + serverKey);
|
||||||
|
await();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create HTTP request to upload file
|
||||||
|
void uploadFile(TransferFile tf, String serverURL, String apiKey, boolean special) {
|
||||||
|
runningRequest.set(false);
|
||||||
|
|
||||||
|
|
||||||
|
// If the file is "special", download the server copy and merge the local and remote ColabArrays
|
||||||
|
if(special) {
|
||||||
|
HttpGetFile getTask = new HttpGetFile(serverURL + "/api/" + tf.filename, new File(baseDir + tf.filename), (stream, error) -> {
|
||||||
|
if(error != null) {
|
||||||
|
AlertManager.error(error);
|
||||||
|
return;
|
||||||
|
} else if (stream == null) {
|
||||||
|
AlertManager.error("Output stream from download was null!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] bytes = stream.toByteArray();
|
||||||
|
|
||||||
|
FileEditor.syncColabArray(
|
||||||
|
tf.filename,
|
||||||
|
FileEditor.readFile(tf.filename),
|
||||||
|
bytes
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
HttpPutFile uploadTask = new HttpPutFile(serverURL + "/api/" + tf.filename, new File(baseDir + tf.filename), error2 -> {
|
||||||
|
if (error2 != null)
|
||||||
|
AlertManager.error(error2);
|
||||||
|
runningRequest.set(true);
|
||||||
|
}, new String[]{
|
||||||
|
"api_key: " + apiKey,
|
||||||
|
("modified: " + tf.updated.getTime())
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadTask.execute();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
getTask.execute();
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Upload the file
|
||||||
|
HttpPutFile uploadTask = new HttpPutFile(serverURL + "/api/" + tf.filename, new File(baseDir + tf.filename), error -> {
|
||||||
|
if (error != null)
|
||||||
|
AlertManager.error(error);
|
||||||
|
runningRequest.set(true);
|
||||||
|
}, new String[]{
|
||||||
|
"api_key: " + apiKey,
|
||||||
|
("modified: " + tf.updated.getTime())
|
||||||
|
}); // Pass auth token if needed
|
||||||
|
|
||||||
|
uploadTask.execute();
|
||||||
|
await();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void setLocalFileTimestamp(File file, Date date) {
|
||||||
|
file.setLastModified(date.getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download a file from the remote server
|
||||||
|
void downloadFile(TransferFile tf, String serverURL) {
|
||||||
|
runningRequest.set(false);
|
||||||
|
File f = new File(baseDir + tf.filename);
|
||||||
|
HttpGetFile uploadTask = new HttpGetFile(serverURL + "/api/" + tf.filename, f, (stream, error) -> {
|
||||||
|
if(error != null) {
|
||||||
|
AlertManager.error(error);
|
||||||
|
return;
|
||||||
|
} else if (stream == null) {
|
||||||
|
AlertManager.error("Output stream from download was null!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] bytes = stream.toByteArray();
|
||||||
|
|
||||||
|
if(FileEditor.requiresSpecialInteraction(tf.filename)) {
|
||||||
|
FileEditor.syncColabArray(
|
||||||
|
tf.filename,
|
||||||
|
FileEditor.readFile(tf.filename),
|
||||||
|
bytes
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
FileEditor.writeFile(tf.filename, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
setLocalFileTimestamp(f, tf.updated);
|
||||||
|
|
||||||
|
runningRequest.set(true);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadTask.execute();
|
||||||
|
await();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,413 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.transfer;
|
||||||
|
|
||||||
|
import static androidx.navigation.fragment.FragmentKt.findNavController;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.tba_blue;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.tba_red;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.tba_toggle_background;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.FileEditor.TBAAddress;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.FileEditor.TBAHeader;
|
||||||
|
|
||||||
|
import android.app.ProgressDialog;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Base64;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TableLayout;
|
||||||
|
import android.widget.TableRow;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import com.google.android.material.button.MaterialButton;
|
||||||
|
import com.ridgebotics.ridgescout.R;
|
||||||
|
import com.ridgebotics.ridgescout.databinding.FragmentTransferTbaBinding;
|
||||||
|
import com.ridgebotics.ridgescout.types.frcEvent;
|
||||||
|
import com.ridgebotics.ridgescout.types.frcMatch;
|
||||||
|
import com.ridgebotics.ridgescout.types.frcTeam;
|
||||||
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.ImageRequestTask;
|
||||||
|
import com.ridgebotics.ridgescout.utility.JSONUtil;
|
||||||
|
import com.ridgebotics.ridgescout.utility.RequestTask;
|
||||||
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
|
import com.ridgebotics.ridgescout.utility.SettingsManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.builders.TextViewBuilder;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
// Class to download data from a specific event and encode it.
|
||||||
|
public class TBAEventFragment extends Fragment {
|
||||||
|
|
||||||
|
private TableLayout Table;
|
||||||
|
private FragmentTransferTbaBinding binding;
|
||||||
|
|
||||||
|
private final int year = SettingsManager.getYearNum();
|
||||||
|
|
||||||
|
private static JSONObject eventData = null;
|
||||||
|
public static void setEventData(JSONObject j){
|
||||||
|
eventData = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
binding = FragmentTransferTbaBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
|
final String matchKey;
|
||||||
|
try {
|
||||||
|
matchKey = eventData.getString("key");
|
||||||
|
} catch (JSONException e) {
|
||||||
|
AlertManager.error("Failed loading event key!", e);
|
||||||
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
Table = binding.matchTable;
|
||||||
|
|
||||||
|
AlertManager.startLoading("Loading Teams and Matches...");
|
||||||
|
|
||||||
|
// Table.removeAllViews();
|
||||||
|
Table.setStretchAllColumns(true);
|
||||||
|
Table.bringToFront();
|
||||||
|
|
||||||
|
final RequestTask rq = new RequestTask();
|
||||||
|
rq.onResult(teamsStr -> {
|
||||||
|
final RequestTask rq1 = new RequestTask();
|
||||||
|
rq1.onResult(matchesStr -> {
|
||||||
|
matchTable(matchesStr, teamsStr, eventData);
|
||||||
|
AlertManager.stopLoading();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
rq1.execute((TBAAddress + "event/" + matchKey + "/matches"), TBAHeader);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
rq.execute((TBAAddress + "event/" + matchKey + "/teams"), TBAHeader);
|
||||||
|
|
||||||
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addTableText(TableRow tr, String textStr){
|
||||||
|
tr.addView(new TextViewBuilder(getContext(), textStr)
|
||||||
|
.size(18)
|
||||||
|
// .align_center()
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void matchTable(String matchesString, String teamsString, JSONObject eventData){
|
||||||
|
try {
|
||||||
|
final JSONArray matchData = new JSONArray(matchesString);
|
||||||
|
// final JSONArray matchData = new JSONArray();
|
||||||
|
final JSONArray teamData = new JSONArray(teamsString);
|
||||||
|
|
||||||
|
String matchKey = eventData.getString("key");
|
||||||
|
String matchName = eventData.getString("short_name");
|
||||||
|
|
||||||
|
// Sometimes, a short name is not present on TBA Events
|
||||||
|
if(matchName.isEmpty()){
|
||||||
|
matchName = eventData.getString("name");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event code at top
|
||||||
|
Table.addView(new TextViewBuilder(getContext(), matchKey)
|
||||||
|
.align_center()
|
||||||
|
.size(18)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
// Event Name
|
||||||
|
Table.addView(new TextViewBuilder(getContext(), matchName)
|
||||||
|
.align_center()
|
||||||
|
.size(28)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
// Save button
|
||||||
|
MaterialButton btn = new MaterialButton(getContext());
|
||||||
|
btn.setText("Save");
|
||||||
|
btn.setTextSize(18);
|
||||||
|
btn.setLayoutParams(new TableRow.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
));
|
||||||
|
Table.addView(btn);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// If there are no matches, add the error.
|
||||||
|
// If there are no teams, don't allow the user to save the event and set the button to be invisible
|
||||||
|
if(teamData.length() == 0){
|
||||||
|
Table.addView(new TextViewBuilder(getContext(), "This event has no teams released yet...")
|
||||||
|
.align_center()
|
||||||
|
.size(18)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
btn.setVisibility(View.GONE);
|
||||||
|
return;
|
||||||
|
}else if(matchData.length() == 0){
|
||||||
|
Table.addView(new TextViewBuilder(getContext(), "This event has no matches released yet...")
|
||||||
|
.align_center()
|
||||||
|
.size(18)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
Table.addView(new TextViewBuilder(getContext(), "Try manually adding practice matches.")
|
||||||
|
.align_center()
|
||||||
|
.size(18)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Table.addView(
|
||||||
|
new TextViewBuilder(getContext(), "Teams")
|
||||||
|
.align_center()
|
||||||
|
.size(28)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Sort the teams into numerical order
|
||||||
|
int[] teams = new int[teamData.length()];
|
||||||
|
|
||||||
|
for(int i = 0 ; i < teamData.length(); i++){
|
||||||
|
teams[i] = teamData.getJSONObject(i).getInt("team_number");
|
||||||
|
}
|
||||||
|
|
||||||
|
Arrays.sort(teams);
|
||||||
|
|
||||||
|
|
||||||
|
// Loop through each match
|
||||||
|
TableRow tr = null;
|
||||||
|
for(int i=0; i < teamData.length(); i++){
|
||||||
|
int num = teams[i];
|
||||||
|
|
||||||
|
// If this is every 7th row, add the new row.
|
||||||
|
if(i % 7 == 0){
|
||||||
|
if(i != 0)
|
||||||
|
Table.addView(tr);
|
||||||
|
tr = new TableRow(getContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tr.addView(
|
||||||
|
new TextViewBuilder(getContext(), String.valueOf(num))
|
||||||
|
.align_center()
|
||||||
|
.size(18)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if(tr != null)
|
||||||
|
Table.addView(tr);
|
||||||
|
|
||||||
|
final ArrayList<frcMatch> matchesOBJ = new ArrayList<>();
|
||||||
|
|
||||||
|
btn.setOnClickListener(v -> {
|
||||||
|
saveData(matchesOBJ, teamData, eventData);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Table.addView(
|
||||||
|
new TextViewBuilder(getContext(), "Matches")
|
||||||
|
.align_center()
|
||||||
|
.size(28)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
|
||||||
|
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");
|
||||||
|
Table.addView(tr);
|
||||||
|
|
||||||
|
|
||||||
|
if(matchData.length() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
final JSONArray sortedMatchData = JSONUtil.sort(matchData, (a, b) -> {
|
||||||
|
JSONObject ja = (JSONObject)a;
|
||||||
|
JSONObject jb = (JSONObject)b;
|
||||||
|
try {
|
||||||
|
return ja.getInt("match_number") - jb.getInt("match_number");
|
||||||
|
}catch (JSONException j){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
boolean toggle = false;
|
||||||
|
int matchCount = 1;
|
||||||
|
|
||||||
|
for(int a=0;a<sortedMatchData.length();a++){
|
||||||
|
final JSONObject match = sortedMatchData.getJSONObject(a);
|
||||||
|
|
||||||
|
if(!match.getString("comp_level").equals("qm")){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final JSONObject alliances = match.getJSONObject("alliances");
|
||||||
|
final JSONArray redAlliance = alliances.getJSONObject("red").getJSONArray("team_keys");
|
||||||
|
final JSONArray blueAlliance = alliances.getJSONObject("blue").getJSONArray("team_keys");
|
||||||
|
|
||||||
|
tr = new TableRow(getContext());
|
||||||
|
|
||||||
|
if (toggle) {
|
||||||
|
tr.setBackgroundColor(tba_toggle_background);
|
||||||
|
}
|
||||||
|
|
||||||
|
addTableText(tr, String.valueOf(matchCount));
|
||||||
|
// addTableText(tr, match.getString("key"));
|
||||||
|
|
||||||
|
int[] blueKeys = new int[3];
|
||||||
|
int[] redKeys = new int[3];
|
||||||
|
|
||||||
|
for(int b=0;b<6;b++){
|
||||||
|
TextViewBuilder text = new TextViewBuilder(getContext())
|
||||||
|
.size(18)
|
||||||
|
.align_center();
|
||||||
|
|
||||||
|
if(b < 3){
|
||||||
|
String str = redAlliance.getString(b).substring(3);
|
||||||
|
redKeys[b] = Integer.parseInt(str);
|
||||||
|
text.text(str);
|
||||||
|
text.tv.setBackgroundColor(tba_red);
|
||||||
|
}else{
|
||||||
|
String str = blueAlliance.getString(b-3).substring(3);
|
||||||
|
blueKeys[b-3] = Integer.parseInt(str);
|
||||||
|
text.text(str);
|
||||||
|
text.tv.setBackgroundColor(tba_blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tr.addView(text.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
Table.addView(tr);
|
||||||
|
|
||||||
|
frcMatch matchOBJ = new frcMatch();
|
||||||
|
matchOBJ.matchIndex = matchCount;
|
||||||
|
matchOBJ.blueAlliance = blueKeys;
|
||||||
|
matchOBJ.redAlliance = redKeys;
|
||||||
|
matchesOBJ.add(matchOBJ);
|
||||||
|
|
||||||
|
matchCount += 1;
|
||||||
|
toggle = !toggle;
|
||||||
|
}
|
||||||
|
|
||||||
|
}catch (JSONException j){
|
||||||
|
AlertManager.error("Failed Downloading", j);
|
||||||
|
AlertManager.stopLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean saveData(ArrayList<frcMatch> matchData, JSONArray teamData, JSONObject eventData){
|
||||||
|
AlertManager.startLoading("Downloading team data...");
|
||||||
|
|
||||||
|
Thread t = new Thread(() -> {
|
||||||
|
try {
|
||||||
|
final String matchKey = eventData.getString("key");
|
||||||
|
String matchName = eventData.getString("short_name");
|
||||||
|
|
||||||
|
// Sometimes, a short name is not present on TBA Events
|
||||||
|
if (matchName.isEmpty()) {
|
||||||
|
matchName = eventData.getString("name");
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<frcTeam> teams = new ArrayList<>();
|
||||||
|
for (int i = 0; i < teamData.length(); i++) {
|
||||||
|
frcTeam teamObj = new frcTeam();
|
||||||
|
JSONObject team = teamData.getJSONObject(i);
|
||||||
|
|
||||||
|
teamObj.teamNumber = team.getInt("team_number");
|
||||||
|
teamObj.teamName = team.getString("nickname");
|
||||||
|
teamObj.city = team.getString("city");
|
||||||
|
teamObj.stateOrProv = team.getString("state_prov");
|
||||||
|
teamObj.school = team.getString("school_name");
|
||||||
|
teamObj.country = team.getString("country");
|
||||||
|
teamObj.startingYear = team.getInt("rookie_year");
|
||||||
|
|
||||||
|
|
||||||
|
RequestTask rq = new RequestTask();
|
||||||
|
rq.onResult(s -> {
|
||||||
|
try {
|
||||||
|
JSONArray jsonArray = new JSONArray(s);
|
||||||
|
JSONObject jsonObject = jsonArray.getJSONObject(0);
|
||||||
|
String base64 = jsonObject.getJSONObject("details").getString("base64Image");
|
||||||
|
|
||||||
|
byte[] decodedData = Base64.decode(base64, Base64.DEFAULT);
|
||||||
|
Bitmap bitmap = BitmapFactory.decodeByteArray(decodedData, 0, decodedData.length);
|
||||||
|
|
||||||
|
// System.out.println(base64);
|
||||||
|
|
||||||
|
teamObj.bitmap = bitmap;
|
||||||
|
teamObj.teamColor = frcTeam.findPrimaryColor(bitmap);
|
||||||
|
|
||||||
|
Log.i("TBA", "Got icon for team " + teamObj.teamNumber);
|
||||||
|
|
||||||
|
|
||||||
|
} catch (Exception e){
|
||||||
|
Log.i("TBA", "Failed to icon for team " + teamObj.teamNumber);
|
||||||
|
} finally {
|
||||||
|
teams.add(teamObj);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
rq.execute((TBAAddress + "team/frc" + teamObj.teamNumber + "/media/" + year), TBAHeader);
|
||||||
|
|
||||||
|
// ImageRequestTask imageRequestTask = new ImageRequestTask();
|
||||||
|
//
|
||||||
|
// imageRequestTask.onResult(bitmap -> {
|
||||||
|
// teamObj.bitmap = bitmap;
|
||||||
|
// teamObj.teamColor = frcTeam.findPrimaryColor(bitmap);
|
||||||
|
// teams.add(teamObj);
|
||||||
|
//
|
||||||
|
// return null;
|
||||||
|
// });
|
||||||
|
// imageRequestTask.execute("https://www.thebluealliance.com/avatar/" + year + "/frc" + teamObj.teamNumber + ".png");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (teams.size() != teamData.length()) {
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
frcEvent event = new frcEvent();
|
||||||
|
event.name = matchName;
|
||||||
|
event.eventCode = matchKey;
|
||||||
|
event.teams = teams;
|
||||||
|
event.matches = matchData;
|
||||||
|
|
||||||
|
FileEditor.setEvent(event);
|
||||||
|
AlertManager.toast("Saved!");
|
||||||
|
|
||||||
|
getActivity().runOnUiThread(() -> findNavController(this).navigate(R.id.action_navigation_tba_event_to_navigation_transfer));
|
||||||
|
AlertManager.stopLoading();
|
||||||
|
|
||||||
|
}catch(Exception j) {
|
||||||
|
AlertManager.error(j);
|
||||||
|
AlertManager.stopLoading();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
t.start();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,504 +0,0 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.transfer;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.TableLayout;
|
|
||||||
import android.widget.TableRow;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentTransferTbaBinding;
|
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
|
||||||
import com.ridgebotics.ridgescout.utility.RequestTask;
|
|
||||||
import com.ridgebotics.ridgescout.types.frcEvent;
|
|
||||||
import com.ridgebotics.ridgescout.types.frcMatch;
|
|
||||||
import com.ridgebotics.ridgescout.types.frcTeam;
|
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
|
||||||
import com.ridgebotics.ridgescout.utility.JSONUtil;
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Calendar;
|
|
||||||
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 android.widget.TableLayout Table;
|
|
||||||
private FragmentTransferTbaBinding binding;
|
|
||||||
|
|
||||||
private static final int year = 2024;
|
|
||||||
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
|
||||||
@Nullable Bundle savedInstanceState) {
|
|
||||||
|
|
||||||
binding = FragmentTransferTbaBinding.inflate(inflater, container, false);
|
|
||||||
|
|
||||||
Table = binding.matchTable;
|
|
||||||
|
|
||||||
Table.setStretchAllColumns(true);
|
|
||||||
|
|
||||||
TableRow tr = new TableRow(getContext());
|
|
||||||
addTableText(tr, "Loading Events...");
|
|
||||||
Table.addView(tr);
|
|
||||||
|
|
||||||
final RequestTask rq = new RequestTask();
|
|
||||||
rq.onResult(s -> {
|
|
||||||
eventTable(s);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
rq.execute(TBAAddress + "events/"+year, TBAHeader);
|
|
||||||
|
|
||||||
return binding.getRoot();
|
|
||||||
}
|
|
||||||
|
|
||||||
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 eventTable(String dataString){
|
|
||||||
Table.removeAllViews();
|
|
||||||
Table.setStretchAllColumns(true);
|
|
||||||
Table.bringToFront();
|
|
||||||
|
|
||||||
Date currentTime = Calendar.getInstance().getTime();
|
|
||||||
|
|
||||||
try {
|
|
||||||
JSONArray data = new JSONArray(dataString);
|
|
||||||
|
|
||||||
Table.setStretchAllColumns(true);
|
|
||||||
Table.bringToFront();
|
|
||||||
|
|
||||||
boolean toggle = false;
|
|
||||||
|
|
||||||
for(int i=0;i<data.length();i++){
|
|
||||||
TableRow tr = new TableRow(getContext());
|
|
||||||
TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams(
|
|
||||||
TableRow.LayoutParams.WRAP_CONTENT,
|
|
||||||
TableRow.LayoutParams.WRAP_CONTENT
|
|
||||||
);
|
|
||||||
rowParams.setMargins(20,20,20,20);
|
|
||||||
tr.setLayoutParams(rowParams);
|
|
||||||
tr.setPadding(20,20,20,20);
|
|
||||||
tr.setBackgroundColor(0x30000000);
|
|
||||||
|
|
||||||
|
|
||||||
JSONObject j = data.getJSONObject(i);
|
|
||||||
|
|
||||||
String matchKey = j.getString("key");
|
|
||||||
String name = j.getString("short_name");
|
|
||||||
|
|
||||||
// Sometimes, a short name is not present on TBA Events
|
|
||||||
if(name.isEmpty()){
|
|
||||||
name = j.getString("name");
|
|
||||||
}
|
|
||||||
|
|
||||||
TextView tv = new TextView(getContext());
|
|
||||||
tv.setGravity(Gravity.CENTER_VERTICAL);
|
|
||||||
tv.setTextSize(12);
|
|
||||||
tv.setText(j.getString("key"));
|
|
||||||
tr.addView(tv);
|
|
||||||
|
|
||||||
tv = new TextView(getContext());
|
|
||||||
tv.setTextSize(18);
|
|
||||||
tv.setText(name);
|
|
||||||
tr.addView(tv);
|
|
||||||
|
|
||||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
|
|
||||||
try {
|
|
||||||
Date startDate = format.parse(j.getString("start_date"));
|
|
||||||
Date endDate = format.parse(j.getString("end_date"));
|
|
||||||
if(currentTime.after(endDate)){
|
|
||||||
tr.setBackgroundColor(0x30FF0000);
|
|
||||||
}else if(currentTime.before(startDate)){
|
|
||||||
tr.setBackgroundColor(0x3000FF00);
|
|
||||||
}else if(currentTime.after(startDate) && currentTime.before(endDate)){
|
|
||||||
tr.setBackgroundColor(0x30FFFF00);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
AlertManager.error(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
tr.setOnClickListener(v -> {
|
|
||||||
Table.removeAllViews();
|
|
||||||
Table.setStretchAllColumns(true);
|
|
||||||
Table.bringToFront();
|
|
||||||
|
|
||||||
TableRow tr1 = new TableRow(getContext());
|
|
||||||
addTableText(tr1, "Downloading Teams...");
|
|
||||||
Table.addView(tr1);
|
|
||||||
|
|
||||||
final RequestTask rq = new RequestTask();
|
|
||||||
rq.onResult(teamsStr -> {
|
|
||||||
TableRow tr11 = new TableRow(getContext());
|
|
||||||
addTableText(tr11, "Downloading Matches...");
|
|
||||||
Table.addView(tr11);
|
|
||||||
|
|
||||||
final RequestTask rq1 = new RequestTask();
|
|
||||||
rq1.onResult(matchesStr -> {
|
|
||||||
matchTable(matchesStr, teamsStr, j);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
rq1.execute((TBAAddress + "event/" + matchKey + "/matches"), TBAHeader);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
rq.execute((TBAAddress + "event/" + matchKey + "/teams"), TBAHeader);
|
|
||||||
});
|
|
||||||
|
|
||||||
// tr.addView(cl);
|
|
||||||
Table.addView(tr, rowParams);
|
|
||||||
|
|
||||||
toggle = !toggle;
|
|
||||||
}
|
|
||||||
}catch (JSONException j){
|
|
||||||
AlertManager.alert("Error", "Invalid JSON");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class matchComparator implements Comparator<JSONObject>
|
|
||||||
{
|
|
||||||
|
|
||||||
public int compare(JSONObject a, JSONObject b)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return a.getInt("match_number") - b.getInt("match_number");
|
|
||||||
}catch (JSONException j){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void matchTable(String matchesString, String teamsString, JSONObject eventData){
|
|
||||||
Table.removeAllViews();
|
|
||||||
Table.setStretchAllColumns(true);
|
|
||||||
Table.bringToFront();
|
|
||||||
|
|
||||||
try {
|
|
||||||
final JSONArray matchData = new JSONArray(matchesString);
|
|
||||||
// final JSONArray matchData = new JSONArray();
|
|
||||||
final JSONArray teamData = new JSONArray(teamsString);
|
|
||||||
|
|
||||||
String matchKey = eventData.getString("key");
|
|
||||||
String matchName = eventData.getString("short_name");
|
|
||||||
|
|
||||||
// Sometimes, a short name is not present on TBA Events
|
|
||||||
if(matchName.isEmpty()){
|
|
||||||
matchName = eventData.getString("name");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Event code at top
|
|
||||||
TextView tv = new TextView(getContext());
|
|
||||||
tv.setLayoutParams(new TableRow.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
||||||
));
|
|
||||||
tv.setText(matchKey);
|
|
||||||
tv.setTextSize(18);
|
|
||||||
Table.addView(tv);
|
|
||||||
|
|
||||||
// Event Name
|
|
||||||
tv = new TextView(getContext());
|
|
||||||
tv.setLayoutParams(new TableRow.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
||||||
));
|
|
||||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
|
||||||
tv.setText(matchName);
|
|
||||||
tv.setTextSize(28);
|
|
||||||
Table.addView(tv);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Save button
|
|
||||||
Button btn = new Button(getContext());
|
|
||||||
btn.setText("Save");
|
|
||||||
btn.setTextSize(18);
|
|
||||||
btn.setLayoutParams(new TableRow.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
||||||
));
|
|
||||||
Table.addView(btn);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(teamData.length() == 0){
|
|
||||||
tv = new TextView(getContext());
|
|
||||||
tv.setLayoutParams(new TableRow.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
||||||
));
|
|
||||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
|
||||||
tv.setText("This event has no teams released yet...");
|
|
||||||
tv.setTextSize(18);
|
|
||||||
Table.addView(tv);
|
|
||||||
|
|
||||||
tv = new TextView(getContext());
|
|
||||||
tv.setLayoutParams(new TableRow.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
||||||
));
|
|
||||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
|
||||||
tv.setText("This event has no teams released yet...");
|
|
||||||
tv.setTextSize(18);
|
|
||||||
Table.addView(tv);
|
|
||||||
|
|
||||||
btn.setVisibility(View.GONE);
|
|
||||||
return;
|
|
||||||
}else if(matchData.length() == 0){
|
|
||||||
tv = new TextView(getContext());
|
|
||||||
tv.setLayoutParams(new TableRow.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
||||||
));
|
|
||||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
|
||||||
tv.setText("This event has no matches released yet...");
|
|
||||||
tv.setTextSize(18);
|
|
||||||
Table.addView(tv);
|
|
||||||
|
|
||||||
tv = new TextView(getContext());
|
|
||||||
tv.setLayoutParams(new TableRow.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
||||||
));
|
|
||||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
|
||||||
tv.setText("Try manually adding practice matches.");
|
|
||||||
tv.setTextSize(18);
|
|
||||||
Table.addView(tv);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tv = new TextView(getContext());
|
|
||||||
tv.setLayoutParams(new TableRow.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
||||||
));
|
|
||||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
|
||||||
tv.setText("Teams");
|
|
||||||
tv.setTextSize(28);
|
|
||||||
Table.addView(tv);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int[] teams = new int[teamData.length()];
|
|
||||||
|
|
||||||
for(int i = 0 ; i < teamData.length(); i++){
|
|
||||||
teams[i] = teamData.getJSONObject(i).getInt("team_number");
|
|
||||||
}
|
|
||||||
|
|
||||||
Arrays.sort(teams);
|
|
||||||
|
|
||||||
TableRow tr = null;
|
|
||||||
for(int i=0; i < teamData.length(); i++){
|
|
||||||
// frcTeam team = event.teams.get(i);
|
|
||||||
int num = teams[i];
|
|
||||||
|
|
||||||
if(i % 7 == 0){
|
|
||||||
if(i != 0)
|
|
||||||
Table.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(0x3000FF00);
|
|
||||||
// }else{
|
|
||||||
// text.setBackgroundColor(0x30FF0000);
|
|
||||||
// }
|
|
||||||
tr.addView(text);
|
|
||||||
}
|
|
||||||
if(tr != null)
|
|
||||||
Table.addView(tr);
|
|
||||||
|
|
||||||
final ArrayList<frcMatch> matchesOBJ = new ArrayList<>();
|
|
||||||
|
|
||||||
btn.setOnClickListener(v -> {
|
|
||||||
if(saveData(matchesOBJ, teamData, eventData)){
|
|
||||||
AlertManager.alert("Info", "Saved!");
|
|
||||||
}else{
|
|
||||||
AlertManager.alert("Error", "Error saving files.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tv = new TextView(getContext());
|
|
||||||
tv.setLayoutParams(new TableRow.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
||||||
));
|
|
||||||
tv.setGravity(Gravity.CENTER_HORIZONTAL);
|
|
||||||
tv.setText("Matches");
|
|
||||||
tv.setTextSize(28);
|
|
||||||
Table.addView(tv);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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");
|
|
||||||
Table.addView(tr);
|
|
||||||
|
|
||||||
|
|
||||||
if(matchData.length() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
final JSONArray sortedMatchData = JSONUtil.sort(matchData, (a, b) -> {
|
|
||||||
JSONObject ja = (JSONObject)a;
|
|
||||||
JSONObject jb = (JSONObject)b;
|
|
||||||
try {
|
|
||||||
return ja.getInt("match_number") - jb.getInt("match_number");
|
|
||||||
}catch (JSONException j){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
boolean toggle = false;
|
|
||||||
int matchCount = 1;
|
|
||||||
|
|
||||||
for(int a=0;a<sortedMatchData.length();a++){
|
|
||||||
final JSONObject match = sortedMatchData.getJSONObject(a);
|
|
||||||
|
|
||||||
if(!match.getString("comp_level").equals("qm")){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final JSONObject alliances = match.getJSONObject("alliances");
|
|
||||||
final JSONArray redAlliance = alliances.getJSONObject("red").getJSONArray("team_keys");
|
|
||||||
final JSONArray blueAlliance = alliances.getJSONObject("blue").getJSONArray("team_keys");
|
|
||||||
|
|
||||||
tr = new TableRow(getContext());
|
|
||||||
|
|
||||||
if (toggle) {
|
|
||||||
tr.setBackgroundColor(0x30000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
addTableText(tr, String.valueOf(matchCount));
|
|
||||||
// addTableText(tr, match.getString("key"));
|
|
||||||
|
|
||||||
int[] blueKeys = new int[3];
|
|
||||||
int[] redKeys = new int[3];
|
|
||||||
|
|
||||||
for(int b=0;b<6;b++){
|
|
||||||
TextView text = new TextView(getContext());
|
|
||||||
text.setTextSize(18);
|
|
||||||
text.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); // Text align center
|
|
||||||
tr.addView(text);
|
|
||||||
|
|
||||||
if(b < 3){
|
|
||||||
String str = redAlliance.getString(b).substring(3);
|
|
||||||
redKeys[b] = Integer.parseInt(str);
|
|
||||||
text.setText(str);
|
|
||||||
text.setBackgroundColor(0x50ff0000);
|
|
||||||
}else{
|
|
||||||
String str = blueAlliance.getString(b-3).substring(3);
|
|
||||||
blueKeys[b-3] = Integer.parseInt(str);
|
|
||||||
text.setText(str);
|
|
||||||
text.setBackgroundColor(0x500000ff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Table.addView(tr);
|
|
||||||
|
|
||||||
frcMatch matchOBJ = new frcMatch();
|
|
||||||
matchOBJ.matchIndex = matchCount;
|
|
||||||
matchOBJ.blueAlliance = blueKeys;
|
|
||||||
matchOBJ.redAlliance = redKeys;
|
|
||||||
matchesOBJ.add(matchOBJ);
|
|
||||||
|
|
||||||
matchCount += 1;
|
|
||||||
toggle = !toggle;
|
|
||||||
}
|
|
||||||
|
|
||||||
// btn.setOnClickListener(v -> {
|
|
||||||
// if(saveData(matchesOBJ, teamData, eventData)){
|
|
||||||
// alert("Info", "Saved!");
|
|
||||||
// }else{
|
|
||||||
// alert("Error", "Error saving files.");
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
}catch (JSONException j){
|
|
||||||
AlertManager.error(j);
|
|
||||||
AlertManager.alert("Error", "Invalid JSON");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean saveData(ArrayList<frcMatch> matchData, JSONArray teamData, JSONObject eventData){
|
|
||||||
try {
|
|
||||||
final String matchKey = eventData.getString("key");
|
|
||||||
String matchName = eventData.getString("short_name");
|
|
||||||
|
|
||||||
// Sometimes, a short name is not present on TBA Events
|
|
||||||
if(matchName.isEmpty()){
|
|
||||||
matchName = eventData.getString("name");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ArrayList<frcTeam> teams = new ArrayList<>();
|
|
||||||
for(int i=0;i<teamData.length();i++){
|
|
||||||
frcTeam teamObj = new frcTeam();
|
|
||||||
JSONObject team = teamData.getJSONObject(i);
|
|
||||||
|
|
||||||
teamObj.teamNumber = team.getInt("team_number");
|
|
||||||
teamObj.teamName = team.getString("nickname");
|
|
||||||
teamObj.city = team.getString("city");
|
|
||||||
teamObj.stateOrProv = team.getString("state_prov");
|
|
||||||
teamObj.school = team.getString("school_name");
|
|
||||||
teamObj.country = team.getString("country");
|
|
||||||
teamObj.startingYear = team.getInt("rookie_year");
|
|
||||||
|
|
||||||
teams.add(teamObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
frcEvent event = new frcEvent();
|
|
||||||
event.name = matchName;
|
|
||||||
event.eventCode = matchKey;
|
|
||||||
event.teams = teams;
|
|
||||||
event.matches = matchData;
|
|
||||||
|
|
||||||
return fileEditor.setEvent(event);
|
|
||||||
}catch (JSONException j){
|
|
||||||
AlertManager.error(j);
|
|
||||||
AlertManager.alert("Error", "Invalid JSON");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.transfer;
|
||||||
|
|
||||||
|
import static androidx.navigation.fragment.FragmentKt.findNavController;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.tba_current;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.tba_next;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.tba_previous;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.FileEditor.TBAAddress;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.FileEditor.TBAHeader;
|
||||||
|
|
||||||
|
import android.app.ProgressDialog;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TableRow;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.R;
|
||||||
|
import com.ridgebotics.ridgescout.databinding.FragmentTransferTbaBinding;
|
||||||
|
import com.ridgebotics.ridgescout.ui.views.TBAEventOption;
|
||||||
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.RequestTask;
|
||||||
|
import com.ridgebotics.ridgescout.utility.SettingsManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.builders.TextViewBuilder;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
// Class to select an event from TBA and redirect to TBAEventFragment.java.
|
||||||
|
public class TBASelectorFragment extends Fragment {
|
||||||
|
|
||||||
|
private android.widget.TableLayout Table;
|
||||||
|
private FragmentTransferTbaBinding binding;
|
||||||
|
|
||||||
|
private final int year = SettingsManager.getYearNum();
|
||||||
|
|
||||||
|
private ProgressDialog loadingDialog;
|
||||||
|
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
binding = FragmentTransferTbaBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
|
Table = binding.matchTable;
|
||||||
|
|
||||||
|
startLoading("Loading Events...");
|
||||||
|
|
||||||
|
final RequestTask rq = new RequestTask();
|
||||||
|
rq.onResult(s -> {
|
||||||
|
if(s == null || s.isEmpty()) {
|
||||||
|
AlertManager.error("Could not fetch event!");
|
||||||
|
stopLoading();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
eventTable(s);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
rq.execute(TBAAddress + "events/"+year, TBAHeader);
|
||||||
|
|
||||||
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getEventTypeWeight(String type){
|
||||||
|
switch(type){
|
||||||
|
case "Preseason": return -3;
|
||||||
|
case "District": return -2;
|
||||||
|
case "Regional": return -1;
|
||||||
|
case "District Championship Division": return 0;
|
||||||
|
case "District Championship": return 1;
|
||||||
|
case "Championship Divison": return 2;
|
||||||
|
case "Championship Finals": return 3;
|
||||||
|
case "Offseason": return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void eventTable(String dataString){
|
||||||
|
|
||||||
|
Table.removeAllViews();
|
||||||
|
// Table.setStretchAllColumns(true);
|
||||||
|
Table.bringToFront();
|
||||||
|
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
Date currentTime = Calendar.getInstance().getTime();
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONArray events = new JSONArray(dataString);
|
||||||
|
|
||||||
|
List<JSONObject> data = new ArrayList<>();
|
||||||
|
for(int i = 0; i < events.length(); i++){
|
||||||
|
data.add(events.getJSONObject(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort events by date, and then type
|
||||||
|
data.sort((a, b) -> {
|
||||||
|
try {
|
||||||
|
// return (int) (currentTime.getTime() - format.parse(a.getString("start_date")).getTime())
|
||||||
|
// -
|
||||||
|
// (int) (currentTime.getTime() - format.parse(b.getString("start_date")).getTime());
|
||||||
|
|
||||||
|
int diff = format.parse(a.getString("start_date")).compareTo(format.parse(b.getString("start_date"))) * 10;
|
||||||
|
|
||||||
|
if(diff == 0){
|
||||||
|
diff = getEventTypeWeight(a.getString("event_type_string")) - getEventTypeWeight(b.getString("event_type_string"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(diff == 0){
|
||||||
|
diff = a.getString("key").compareTo(b.getString("key"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return diff;
|
||||||
|
} catch (ParseException | JSONException e) {
|
||||||
|
AlertManager.error(e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
boolean toggle = false;
|
||||||
|
|
||||||
|
for(int i=0;i<data.size();i++){
|
||||||
|
JSONObject j = data.get(i);
|
||||||
|
|
||||||
|
TBAEventOption row = new TBAEventOption(getContext());
|
||||||
|
|
||||||
|
|
||||||
|
// TableRow tr = new TableRow(getContext());
|
||||||
|
// TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams(
|
||||||
|
// TableRow.LayoutParams.WRAP_CONTENT,
|
||||||
|
// TableRow.LayoutParams.WRAP_CONTENT
|
||||||
|
// );
|
||||||
|
// rowParams.setMargins(20,20,20,20);
|
||||||
|
// tr.setLayoutParams(rowParams);
|
||||||
|
// tr.setPadding(20,20,20,20);
|
||||||
|
row.setBackgroundColor(0x30000000);
|
||||||
|
|
||||||
|
String name = j.getString("short_name");
|
||||||
|
|
||||||
|
// Sometimes, a short name is not present on TBA Events
|
||||||
|
if(name.isEmpty()){
|
||||||
|
name = j.getString("name");
|
||||||
|
}
|
||||||
|
|
||||||
|
String eventType = j.getString("event_type_string");
|
||||||
|
if(eventType.equals("District") || eventType.equals("Regional"))
|
||||||
|
eventType = "Week " + (j.getInt("week")+1) + " " + eventType;
|
||||||
|
|
||||||
|
row.setName(name);
|
||||||
|
row.setCode(j.getString("key"));
|
||||||
|
row.setType(eventType);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Date startDate = format.parse(j.getString("start_date"));
|
||||||
|
Date endDate = format.parse(j.getString("end_date"));
|
||||||
|
if(currentTime.after(startDate) && currentTime.before(endDate)) {
|
||||||
|
row.setColor(tba_current);
|
||||||
|
} else if(currentTime.after(endDate)){
|
||||||
|
row.setColor(tba_previous);
|
||||||
|
}else if(currentTime.before(startDate)){
|
||||||
|
row.setColor(tba_next);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
AlertManager.error("Failed finding start and end dates!", e);
|
||||||
|
stopLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
row.setOnClickListener(v -> {
|
||||||
|
TBAEventFragment.setEventData(j);
|
||||||
|
findNavController(this).navigate(R.id.action_navigation_tba_selector_to_navigation_tba_event);
|
||||||
|
});
|
||||||
|
|
||||||
|
// tr.addView(cl);
|
||||||
|
Table.addView(row);
|
||||||
|
|
||||||
|
|
||||||
|
toggle = !toggle;
|
||||||
|
}
|
||||||
|
|
||||||
|
stopLoading();
|
||||||
|
}catch (JSONException j){
|
||||||
|
AlertManager.error("Failed Downloading", j);
|
||||||
|
stopLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void startLoading(String title){
|
||||||
|
getActivity().runOnUiThread(() -> {
|
||||||
|
if(loadingDialog != null && loadingDialog.isShowing())
|
||||||
|
loadingDialog.dismiss();
|
||||||
|
loadingDialog = ProgressDialog.show(getActivity(), title, "Please wait...");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopLoading(){
|
||||||
|
getActivity().runOnUiThread(() -> {
|
||||||
|
if (loadingDialog != null)
|
||||||
|
loadingDialog.cancel();
|
||||||
|
loadingDialog = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ package com.ridgebotics.ridgescout.ui.transfer;
|
|||||||
import static androidx.navigation.fragment.FragmentKt.findNavController;
|
import static androidx.navigation.fragment.FragmentKt.findNavController;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -15,13 +14,12 @@ import androidx.fragment.app.Fragment;
|
|||||||
|
|
||||||
import com.ridgebotics.ridgescout.R;
|
import com.ridgebotics.ridgescout.R;
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
import com.ridgebotics.ridgescout.utility.settingsManager;
|
import com.ridgebotics.ridgescout.utility.SettingsManager;
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentTransferBinding;
|
import com.ridgebotics.ridgescout.databinding.FragmentTransferBinding;
|
||||||
import com.ridgebotics.ridgescout.ui.transfer.bluetooth.BluetoothSenderFragment;
|
import com.ridgebotics.ridgescout.ui.transfer.bluetooth.BluetoothSenderFragment;
|
||||||
import com.ridgebotics.ridgescout.ui.transfer.codes.CodeGeneratorView;
|
import com.ridgebotics.ridgescout.ui.transfer.codes.CodeGeneratorView;
|
||||||
|
|
||||||
import java.util.Date;
|
// Class to do transference.
|
||||||
|
|
||||||
public class TransferFragment extends Fragment {
|
public class TransferFragment extends Fragment {
|
||||||
private FragmentTransferBinding binding;
|
private FragmentTransferBinding binding;
|
||||||
|
|
||||||
@@ -34,9 +32,6 @@ public class TransferFragment extends Fragment {
|
|||||||
|
|
||||||
String evcode;
|
String evcode;
|
||||||
|
|
||||||
private static final int background_color = 0x5000ff00;
|
|
||||||
private static final int unselected_background_color = 0x2000ff00;
|
|
||||||
|
|
||||||
// private Bundle b;
|
// private Bundle b;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -48,46 +43,44 @@ public class TransferFragment extends Fragment {
|
|||||||
|
|
||||||
binding = FragmentTransferBinding.inflate(inflater, container, false);
|
binding = FragmentTransferBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
evcode = settingsManager.getEVCode();
|
evcode = SettingsManager.getEVCode();
|
||||||
|
|
||||||
binding.downloadButton.setOnClickListener(v -> {
|
binding.downloadButton.setOnClickListener(v -> {
|
||||||
start_download();
|
start_download();
|
||||||
});
|
});
|
||||||
|
|
||||||
binding.TBAButton.setOnClickListener(v -> {
|
binding.TBAButton.setOnClickListener(v -> {
|
||||||
binding.noEventError.setVisibility(View.GONE);
|
findNavController(this).navigate(R.id.action_navigation_transfer_to_navigation_tba_selector);
|
||||||
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();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
if(!settingsManager.getWifiMode()) {
|
if(!SettingsManager.getWifiMode()) {
|
||||||
binding.TBAButton.setEnabled(false);
|
binding.TBAButton.setEnabled(false);
|
||||||
binding.SyncButton.setEnabled(false);
|
binding.SyncButton.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!settingsManager.getFTPEnabled() ||
|
if(!SettingsManager.getFTPEnabled()) {
|
||||||
new Date().getTime()-FTPSync.lastSyncTime < FTPSync.timeTolerance) {
|
|
||||||
binding.SyncButton.setEnabled(false);
|
binding.SyncButton.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.SyncButton.setOnClickListener(v -> {
|
binding.SyncButton.setOnClickListener(v -> {
|
||||||
binding.SyncButton.setEnabled(false);
|
binding.SyncButton.setEnabled(false);
|
||||||
FTPSync.sync((error, upcount, downcount) -> getActivity().runOnUiThread(() -> {
|
HttpSync.sync();
|
||||||
// binding.SyncButton.setEnabled(true);
|
|
||||||
AlertManager.toast((!error ? "Synced! " : "Error Syncing. ") + upcount + " Up " + downcount + " Down");
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(HttpSync.getIsRunning())
|
||||||
|
binding.SyncButton.setEnabled(false);
|
||||||
|
|
||||||
|
HttpSync.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(HttpSync.text);
|
||||||
|
HttpSync.setOnUpdateIndicator(text -> {if(getActivity() != null) getActivity().runOnUiThread(() -> binding.syncIndicator.setText(text));});
|
||||||
|
|
||||||
if(evcode.equals("unset")){
|
if(evcode.equals("unset")){
|
||||||
binding.noEventError.setVisibility(View.VISIBLE);
|
binding.noEventError.setVisibility(View.VISIBLE);
|
||||||
@@ -105,26 +98,11 @@ public class TransferFragment extends Fragment {
|
|||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||||
builder.setTitle("Chose data");
|
builder.setTitle("Chose data");
|
||||||
|
|
||||||
builder.setNegativeButton("Pit data", new DialogInterface.OnClickListener() {
|
builder.setNegativeButton("Pit data", (dialog, which) -> CSVExport.exportPits(getContext()));
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
CSVExport.exportPits(getContext());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.setPositiveButton("Match data", new DialogInterface.OnClickListener() {
|
builder.setPositiveButton("Match data", (dialog, which) -> CSVExport.exportMatches(getContext()));
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
CSVExport.exportMatches(getContext());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.setNeutralButton("Cancel", new DialogInterface.OnClickListener() {
|
builder.setNeutralButton("Cancel", (dialog, which) -> dialog.cancel());
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
dialog.cancel();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.show();
|
builder.show();
|
||||||
});
|
});
|
||||||
|
|||||||
+4
-9
@@ -11,6 +11,7 @@ import androidx.fragment.app.Fragment;
|
|||||||
|
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentTransferSelectorBinding;
|
import com.ridgebotics.ridgescout.databinding.FragmentTransferSelectorBinding;
|
||||||
|
|
||||||
|
// The transfer method selector
|
||||||
public class TransferSelectorFragment extends Fragment {
|
public class TransferSelectorFragment extends Fragment {
|
||||||
|
|
||||||
// Declaring three blank funcs in one line lol
|
// Declaring three blank funcs in one line lol
|
||||||
@@ -30,17 +31,11 @@ public class TransferSelectorFragment extends Fragment {
|
|||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
binding = FragmentTransferSelectorBinding.inflate(inflater, container, false);
|
binding = FragmentTransferSelectorBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
binding.codesButton.setOnClickListener(view -> {
|
binding.codesButton.setOnClickListener(view -> onselect.onSelectCodes(this));
|
||||||
onselect.onSelectCodes(this);
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.bluetoothButton.setOnClickListener(view -> {
|
binding.bluetoothButton.setOnClickListener(view -> onselect.onSelectBluetooth(this));
|
||||||
onselect.onSelectBluetooth(this);
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.fileBundleButton.setOnClickListener(view -> {
|
binding.fileBundleButton.setOnClickListener(view -> onselect.onSelectFileBundle(this));
|
||||||
onselect.onSelectFileBundle(this);
|
|
||||||
});
|
|
||||||
|
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -8,6 +8,7 @@ import android.bluetooth.BluetoothSocket;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
@@ -20,11 +21,10 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
// Helper class for bluetooth reciever.
|
||||||
public class BluetoothReceiver {
|
public class BluetoothReceiver {
|
||||||
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
|
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
|
||||||
private static final String NAME = "BluetoothReceiverApp";
|
private static final String NAME = "BluetoothReceiverApp";
|
||||||
private static final int REQUEST_ENABLE_BT = 1;
|
|
||||||
private static final int REQUEST_PERMISSIONS = 2;
|
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
private BluetoothAdapter bluetoothAdapter;
|
private BluetoothAdapter bluetoothAdapter;
|
||||||
@@ -140,7 +140,7 @@ public class BluetoothReceiver {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (e.getMessage() != null && e.getMessage().contains("bt socket closed, read return: -1")) {
|
if (e.getMessage() != null && e.getMessage().contains("bt socket closed, read return: -1")) {
|
||||||
receiveddata.onConnectionStop();
|
receiveddata.onConnectionStop();
|
||||||
System.out.println("Bluetooth socket closed, treating as end of stream");
|
Log.i(getClass().toString(), "Bluetooth socket closed, treating as end of stream");
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-13
@@ -1,6 +1,7 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.transfer.bluetooth;
|
package com.ridgebotics.ridgescout.ui.transfer.bluetooth;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -12,16 +13,17 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentTransferBluetoothReceiverBinding;
|
import com.ridgebotics.ridgescout.databinding.FragmentTransferBluetoothReceiverBinding;
|
||||||
import com.ridgebotics.ridgescout.types.file;
|
import com.ridgebotics.ridgescout.types.ScoutingFile;
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.zip.DataFormatException;
|
import java.util.zip.DataFormatException;
|
||||||
|
|
||||||
|
// Class to receive bluetooth transmissions from other devices
|
||||||
public class BluetoothReceiverFragment extends Fragment {
|
public class BluetoothReceiverFragment extends Fragment {
|
||||||
private BluetoothReceiver bluetoothReceiver;
|
private BluetoothReceiver bluetoothReceiver;
|
||||||
private Button startListeningButton;
|
private Button startListeningButton;
|
||||||
@@ -68,12 +70,12 @@ public class BluetoothReceiverFragment extends Fragment {
|
|||||||
statusTextView = binding.statusTextView;
|
statusTextView = binding.statusTextView;
|
||||||
|
|
||||||
if (!bluetoothReceiver.isBluetoothSupported()) {
|
if (!bluetoothReceiver.isBluetoothSupported()) {
|
||||||
AlertManager.error("Bluetooth is not supported on this device");
|
AlertManager.addSimpleError("Bluetooth is not supported on this device");
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bluetoothReceiver.isBluetoothEnabled()) {
|
if (!bluetoothReceiver.isBluetoothEnabled()) {
|
||||||
AlertManager.error("Please enable Bluetooth");
|
AlertManager.addSimpleError("Please enable Bluetooth");
|
||||||
}
|
}
|
||||||
|
|
||||||
startListeningButton.setOnClickListener(v -> {
|
startListeningButton.setOnClickListener(v -> {
|
||||||
@@ -97,7 +99,7 @@ public class BluetoothReceiverFragment extends Fragment {
|
|||||||
recievedBytes = new ArrayList<>();
|
recievedBytes = new ArrayList<>();
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
AlertManager.error("Failed to start listening: " + e.getMessage());
|
AlertManager.error("Failed to start listening", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,15 +110,15 @@ public class BluetoothReceiverFragment extends Fragment {
|
|||||||
startListeningButton.setEnabled(true);
|
startListeningButton.setEnabled(true);
|
||||||
stopListeningButton.setEnabled(false);
|
stopListeningButton.setEnabled(false);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
AlertManager.error("Failed to stop listening: " + e.getMessage());
|
AlertManager.error("Failed to stop listening: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<byte[]> recievedBytes;
|
private List<byte[]> recievedBytes;
|
||||||
|
|
||||||
private void receiveData(byte[] data, int bytes) {
|
private void receiveData(byte[] data, int bytes) {
|
||||||
byte[] newBytes = fileEditor.getByteBlock(data, 0, bytes);
|
byte[] newBytes = FileEditor.getByteBlock(data, 0, bytes);
|
||||||
System.out.println("Recieved " + bytes + " Bytes over bluetooth!");
|
Log.i(getClass().toString(), "Recieved " + bytes + " Bytes over bluetooth!");
|
||||||
recievedBytes.add(newBytes);
|
recievedBytes.add(newBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,19 +127,19 @@ public class BluetoothReceiverFragment extends Fragment {
|
|||||||
String result_filenames = "";
|
String result_filenames = "";
|
||||||
try {
|
try {
|
||||||
|
|
||||||
byte[] resultBytes = fileEditor.combineByteArrays(recievedBytes);
|
byte[] resultBytes = FileEditor.combineByteArrays(recievedBytes);
|
||||||
resultBytes = fileEditor.blockUncompress(resultBytes);
|
resultBytes = FileEditor.blockUncompress(resultBytes);
|
||||||
|
|
||||||
|
|
||||||
BuiltByteParser bbp = new BuiltByteParser(resultBytes);
|
BuiltByteParser bbp = new BuiltByteParser(resultBytes);
|
||||||
ArrayList<BuiltByteParser.parsedObject> result = bbp.parse();
|
ArrayList<BuiltByteParser.parsedObject> result = bbp.parse();
|
||||||
|
|
||||||
for (int i = 0; i < result.size(); i++) {
|
for (int i = 0; i < result.size(); i++) {
|
||||||
if (result.get(i).getType() != file.typecode) continue;
|
if (result.get(i).getType() != ScoutingFile.typecode) continue;
|
||||||
file f = file.decode((byte[]) result.get(i).get());
|
ScoutingFile f = ScoutingFile.decode((byte[]) result.get(i).get());
|
||||||
|
|
||||||
if (f != null) {
|
if (f != null) {
|
||||||
System.out.println(f.filename);
|
Log.i(getClass().toString(), f.filename);
|
||||||
if (f.write())
|
if (f.write())
|
||||||
result_filenames += f.filename + "\n";
|
result_filenames += f.filename + "\n";
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -21,10 +21,9 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
// Helper class with sending bluetooth scouting data
|
||||||
public class BluetoothSender {
|
public class BluetoothSender {
|
||||||
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
|
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
|
||||||
private static final int REQUEST_ENABLE_BT = 1;
|
|
||||||
private static final int REQUEST_PERMISSIONS = 2;
|
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
private BluetoothAdapter bluetoothAdapter;
|
private BluetoothAdapter bluetoothAdapter;
|
||||||
|
|||||||
+4
-3
@@ -17,12 +17,13 @@ import androidx.fragment.app.Fragment;
|
|||||||
|
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentTransferBluetoothSenderBinding;
|
import com.ridgebotics.ridgescout.databinding.FragmentTransferBluetoothSenderBinding;
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
// Class to send scouting data over bluetooth.
|
||||||
public class BluetoothSenderFragment extends Fragment {
|
public class BluetoothSenderFragment extends Fragment {
|
||||||
private BluetoothSender bluetoothSender;
|
private BluetoothSender bluetoothSender;
|
||||||
private ListView deviceListView;
|
private ListView deviceListView;
|
||||||
@@ -101,10 +102,10 @@ public class BluetoothSenderFragment extends Fragment {
|
|||||||
|
|
||||||
private void sendData() {
|
private void sendData() {
|
||||||
try {
|
try {
|
||||||
byte[] compressed = fileEditor.blockCompress(data_to_send);
|
byte[] compressed = FileEditor.blockCompress(data_to_send, FileEditor.lengthHeaderBytes);
|
||||||
|
|
||||||
for(int i = 0; i < Math.ceil((double) compressed.length/1024); i++){
|
for(int i = 0; i < Math.ceil((double) compressed.length/1024); i++){
|
||||||
bluetoothSender.sendData(fileEditor.getByteBlock(compressed, i*1024, (i+1)*1024));
|
bluetoothSender.sendData(FileEditor.getByteBlock(compressed, i*1024, (i+1)*1024));
|
||||||
}
|
}
|
||||||
|
|
||||||
bluetoothSender.close();
|
bluetoothSender.close();
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.transfer.codes;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import com.google.zxing.BarcodeFormat;
|
||||||
|
import com.google.zxing.EncodeHintType;
|
||||||
|
import com.google.zxing.MultiFormatWriter;
|
||||||
|
import com.google.zxing.WriterException;
|
||||||
|
import com.google.zxing.common.BitMatrix;
|
||||||
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
|
import com.ridgebotics.ridgescout.utility.TaskRunner;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class CodeGenTask implements Callable<List<Bitmap>> {
|
||||||
|
// private Function<List<Bitmap>, String> resultFunction = null;
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// protected List<Bitmap> doInBackground(String... strings) {
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// return new ArrayList<>();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// public void onResult(Function<List<Bitmap>, String> func) {
|
||||||
|
// this.resultFunction = func;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// protected void onPostExecute(List<Bitmap> result) {
|
||||||
|
// super.onPostExecute(result);
|
||||||
|
// if(resultFunction != null){
|
||||||
|
// resultFunction.apply(result);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
private final String data;
|
||||||
|
private final int randID;
|
||||||
|
private final int qrSize;
|
||||||
|
private final int qrCount;
|
||||||
|
private final int imageSize;
|
||||||
|
|
||||||
|
public CodeGenTask(String data, int randID, int qrSize, int qrCount, int imageSize) {
|
||||||
|
this.data = data;
|
||||||
|
this.randID = randID;
|
||||||
|
this.qrSize = qrSize;
|
||||||
|
this.qrCount = qrCount;
|
||||||
|
this.imageSize = imageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Bitmap> call() {
|
||||||
|
List<Bitmap> qrBitmaps = new ArrayList<>();
|
||||||
|
|
||||||
|
for(int i=0;i<=((data.length()+1)/qrSize);i++){
|
||||||
|
final int start = i*qrSize;
|
||||||
|
int end = (i+1)*qrSize;
|
||||||
|
if(end >= data.length()){
|
||||||
|
end = data.length();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Bitmap unscaledBitmap = generateQrCode(
|
||||||
|
FileEditor.byteToChar(FileEditor.internalDataVersion, FileEditor.lengthHeaderBytes) +
|
||||||
|
String.valueOf(FileEditor.byteToChar(randID, FileEditor.lengthHeaderBytes)) +
|
||||||
|
FileEditor.byteToChar(i, FileEditor.lengthHeaderBytes) +
|
||||||
|
FileEditor.byteToChar(qrCount - 1, FileEditor.lengthHeaderBytes) +
|
||||||
|
data.substring(start, end)
|
||||||
|
);
|
||||||
|
if(unscaledBitmap == null) {
|
||||||
|
AlertManager.error("Generated image was null!");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
qrBitmaps.add(Bitmap.createScaledBitmap(unscaledBitmap, imageSize, imageSize, false));
|
||||||
|
// alert("title", ""+(qrCount-1));
|
||||||
|
}catch (WriterException e){
|
||||||
|
AlertManager.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return qrBitmaps;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bitmap generateQrCode(String contents) throws WriterException {
|
||||||
|
|
||||||
|
final int size = 512;
|
||||||
|
|
||||||
|
if (contents == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
|
||||||
|
|
||||||
|
// The Charset must be UTF-8, Or data will not be transferred properly. IDK why.
|
||||||
|
hints.put(EncodeHintType.CHARACTER_SET, "ISO-8859-1");
|
||||||
|
// hints.put(EncodeHintType.);
|
||||||
|
hints.put(EncodeHintType.MARGIN, 0); /* default = 4 */
|
||||||
|
MultiFormatWriter writer = new MultiFormatWriter();
|
||||||
|
|
||||||
|
BitMatrix result;
|
||||||
|
try {
|
||||||
|
result = writer.encode(contents, BarcodeFormat.DATA_MATRIX, size, size, hints);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// Unsupported format
|
||||||
|
AlertManager.error(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = result.getWidth();
|
||||||
|
int height = result.getHeight();
|
||||||
|
int[] pixels = new int[width * height];
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
int offset = y * width;
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.WHITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(width, height,
|
||||||
|
Bitmap.Config.ARGB_8888);
|
||||||
|
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
|
||||||
|
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
+76
-109
@@ -1,9 +1,10 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.transfer.codes;
|
package com.ridgebotics.ridgescout.ui.transfer.codes;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.CountDownTimer;
|
import android.os.CountDownTimer;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -17,19 +18,15 @@ import androidx.fragment.app.Fragment;
|
|||||||
|
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentTransferCodeSenderBinding;
|
import com.ridgebotics.ridgescout.databinding.FragmentTransferCodeSenderBinding;
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
import com.google.zxing.BarcodeFormat;
|
import com.ridgebotics.ridgescout.utility.TaskRunner;
|
||||||
import com.google.zxing.EncodeHintType;
|
|
||||||
import com.google.zxing.MultiFormatWriter;
|
|
||||||
import com.google.zxing.WriterException;
|
|
||||||
import com.google.zxing.common.BitMatrix;
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.EnumMap;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
// Class to show the code transfer thing.
|
||||||
public class CodeGeneratorView extends Fragment {
|
public class CodeGeneratorView extends Fragment {
|
||||||
private ImageView qrImage;
|
private ImageView qrImage;
|
||||||
private SeekBar qrSpeedSlider;
|
private SeekBar qrSpeedSlider;
|
||||||
@@ -37,23 +34,28 @@ public class CodeGeneratorView extends Fragment {
|
|||||||
private TextView qrIndexN;
|
private TextView qrIndexN;
|
||||||
private TextView qrIndexD;
|
private TextView qrIndexD;
|
||||||
|
|
||||||
private final int maxQrCount = 256; //The max number that can be stored in a byte
|
private static final int maxQrCount = 256; //The max number that can be stored in a byte
|
||||||
|
|
||||||
private final int maxQrSpeed = 5;
|
private static final int maxQrSize = 800;
|
||||||
private final int minQrSpeed = 300 + maxQrSpeed - 1;
|
|
||||||
|
|
||||||
|
private static final int maxQrSpeed = 50;
|
||||||
|
private static final int minQrSpeed = 1000;
|
||||||
|
private static final int defaultQrDelay = 12;
|
||||||
|
|
||||||
|
|
||||||
|
private int imageSize;
|
||||||
|
|
||||||
private int minQrSize = 0;
|
private int minQrSize = 0;
|
||||||
private final int maxQrSize = 800;
|
|
||||||
private int qrSize = 200;
|
private int qrSize = 200;
|
||||||
|
|
||||||
private final int defaultQrDelay = 419;
|
private double qrDelay = 0;
|
||||||
private int qrDelay = 0;
|
|
||||||
private int qrIndex = 0;
|
private int qrIndex = 0;
|
||||||
|
|
||||||
private CountDownTimer timer;
|
private CountDownTimer timer;
|
||||||
private int qrCount = 0;
|
private int qrCount = 0;
|
||||||
|
|
||||||
private ArrayList<Bitmap> qrBitmaps;
|
private List<Bitmap> qrBitmaps = new ArrayList<>();
|
||||||
|
|
||||||
private FragmentTransferCodeSenderBinding binding;
|
private FragmentTransferCodeSenderBinding binding;
|
||||||
|
|
||||||
@@ -76,7 +78,13 @@ public class CodeGeneratorView extends Fragment {
|
|||||||
qrIndexN = binding.qrIndexN;
|
qrIndexN = binding.qrIndexN;
|
||||||
qrIndexD = binding.qrIndexD;
|
qrIndexD = binding.qrIndexD;
|
||||||
|
|
||||||
String compressed = new String(fileEditor.blockCompress(data), StandardCharsets.ISO_8859_1);
|
DisplayMetrics displaymetrics = new DisplayMetrics();
|
||||||
|
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
|
||||||
|
// int height = displaymetrics.heightPixels;
|
||||||
|
imageSize = displaymetrics.widthPixels;
|
||||||
|
// = 800;
|
||||||
|
|
||||||
|
String compressed = new String(FileEditor.blockCompress(data, FileEditor.lengthHeaderBytes), StandardCharsets.ISO_8859_1);
|
||||||
|
|
||||||
if(compressed.isEmpty()){
|
if(compressed.isEmpty()){
|
||||||
AlertManager.alert("Error!", "Empty data!");
|
AlertManager.alert("Error!", "Empty data!");
|
||||||
@@ -84,75 +92,30 @@ public class CodeGeneratorView extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
minQrSize = Math.round((float)compressed.length() / maxQrCount)+1;
|
minQrSize = Math.round((float)compressed.length() / maxQrCount)+1;
|
||||||
|
qrSize += minQrSize;
|
||||||
qrSizeSlider.setMax(maxQrSize-minQrSize);
|
|
||||||
qrSpeedSlider.setMax((minQrSpeed-maxQrSpeed)*2);
|
|
||||||
|
|
||||||
qrSizeSlider.setProgress(minQrSize+qrSize);
|
|
||||||
qrSpeedSlider.setProgress(defaultQrDelay+5);
|
|
||||||
|
|
||||||
sendData(compressed);
|
sendData(compressed);
|
||||||
|
|
||||||
|
qrSpeedSlider.setMax(maxQrSpeed*2);
|
||||||
|
qrSpeedSlider.setProgress(maxQrSpeed + defaultQrDelay);
|
||||||
|
|
||||||
|
qrSizeSlider.setMax(maxQrSize-minQrSize);
|
||||||
|
qrSizeSlider.setProgress(qrSize-minQrSize);
|
||||||
|
|
||||||
|
startLoop();
|
||||||
|
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Bitmap generateQrCode(String contents) throws WriterException {
|
|
||||||
|
|
||||||
final int size = 512;
|
|
||||||
|
|
||||||
if (contents == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
|
|
||||||
|
|
||||||
// The Charset must be UTF-8, Or data will not be transferred properly. IDK why.
|
|
||||||
hints.put(EncodeHintType.CHARACTER_SET, "ISO-8859-1");
|
|
||||||
// hints.put(EncodeHintType.);
|
|
||||||
hints.put(EncodeHintType.MARGIN, 0); /* default = 4 */
|
|
||||||
MultiFormatWriter writer = new MultiFormatWriter();
|
|
||||||
|
|
||||||
BitMatrix result;
|
|
||||||
try {
|
|
||||||
result = writer.encode(contents, BarcodeFormat.DATA_MATRIX, size, size, hints);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
// Unsupported format
|
|
||||||
AlertManager.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
int width = result.getWidth();
|
|
||||||
int height = result.getHeight();
|
|
||||||
int[] pixels = new int[width * height];
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
int offset = y * width;
|
|
||||||
for (int x = 0; x < width; x++) {
|
|
||||||
pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.WHITE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bitmap bitmap = Bitmap.createBitmap(width, height,
|
|
||||||
Bitmap.Config.ARGB_8888);
|
|
||||||
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
|
|
||||||
|
|
||||||
return bitmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void sendData(String data){
|
private void sendData(String data){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
qrCount = (data.length()/qrSize)+1;
|
qrCount = (data.length()/qrSize)+1;
|
||||||
qrIndexD.setText(String.valueOf(qrCount));
|
qrIndexD.setText(String.valueOf(qrCount));
|
||||||
|
|
||||||
// alert("size", ""+binding.qrSizeSlider.getProgress()+"\n"+binding.qrSizeSlider.getMax());
|
|
||||||
|
|
||||||
qrSpeedSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
qrSpeedSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||||
qrDelay = -(minQrSpeed - progress - maxQrSpeed + 1);
|
qrDelay = ((double) progress /maxQrSpeed) - 1;
|
||||||
|
// startLoop();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onStartTrackingTouch(SeekBar seekBar) {}
|
public void onStartTrackingTouch(SeekBar seekBar) {}
|
||||||
@@ -172,43 +135,24 @@ public class CodeGeneratorView extends Fragment {
|
|||||||
qrCount = ((data.length()+1)/qrSize) +1;
|
qrCount = ((data.length()+1)/qrSize) +1;
|
||||||
qrIndexD.setText(String.valueOf(qrCount));
|
qrIndexD.setText(String.valueOf(qrCount));
|
||||||
sendData(data);
|
sendData(data);
|
||||||
|
// startLoop();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// qrSizeSlider.setProgress(qr);
|
AlertManager.startLoading("Generating codes...");
|
||||||
|
|
||||||
qrBitmaps = new ArrayList<>();
|
new TaskRunner().executeAsync(new CodeGenTask(data, new Random().nextInt(255), qrSize, qrCount, imageSize), result -> {
|
||||||
|
qrBitmaps = result;
|
||||||
int randID = new Random().nextInt(255);
|
AlertManager.stopLoading();
|
||||||
|
|
||||||
for(int i=0;i<=((data.length()+1)/qrSize);i++){
|
|
||||||
final int start = i*qrSize;
|
|
||||||
int end = (i+1)*qrSize;
|
|
||||||
if(end >= data.length()){
|
|
||||||
end = data.length();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
// alert("test", ""+Math.ceil((double)data.length()/(double)qrSize));
|
|
||||||
qrBitmaps.add(generateQrCode(
|
|
||||||
fileEditor.byteToChar(fileEditor.internalDataVersion) +
|
|
||||||
String.valueOf(fileEditor.byteToChar(randID)) +
|
|
||||||
fileEditor.byteToChar(i) +
|
|
||||||
fileEditor.byteToChar(qrCount - 1) +
|
|
||||||
data.substring(start, end)
|
|
||||||
));
|
|
||||||
// alert("title", ""+(qrCount-1));
|
|
||||||
}catch (WriterException e){
|
|
||||||
AlertManager.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qrIndex = 0;
|
qrIndex = 0;
|
||||||
if(timer != null){
|
});
|
||||||
timer.cancel();
|
|
||||||
}
|
|
||||||
qrLoop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateQr(){
|
private void updateQr(){
|
||||||
|
if(qrBitmaps.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
qrImage.setImageBitmap(qrBitmaps.get(qrIndex));
|
qrImage.setImageBitmap(qrBitmaps.get(qrIndex));
|
||||||
if(qrDelay > 0) {
|
if(qrDelay > 0) {
|
||||||
this.qrIndex += 1;
|
this.qrIndex += 1;
|
||||||
@@ -225,13 +169,36 @@ public class CodeGeneratorView extends Fragment {
|
|||||||
qrIndexN.setText(String.valueOf(qrIndex+1));
|
qrIndexN.setText(String.valueOf(qrIndex+1));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void qrLoop(){
|
private boolean shouldstop = false;
|
||||||
timer = new CountDownTimer(minQrSpeed-Math.abs(qrDelay)+1, 1000) {
|
|
||||||
public void onTick(long millisUntilFinished) {}
|
private void startLoop() {
|
||||||
public void onFinish() {
|
final Handler handler = new Handler();
|
||||||
updateQr();
|
Runnable runnable = new Runnable() {
|
||||||
qrLoop();
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if(shouldstop){
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}.start();
|
try{
|
||||||
|
updateQr();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
AlertManager.error(e);
|
||||||
|
}
|
||||||
|
finally{
|
||||||
|
double a = ((double) maxQrSpeed) / (Math.abs(qrDelay));
|
||||||
|
a = Math.min(Math.max(a, maxQrSpeed), minQrSpeed);
|
||||||
|
handler.postDelayed(this, (long) a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
handler.post(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
shouldstop = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-5
@@ -2,6 +2,10 @@ 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
|
// From https://github.com/dlazaro66/QRCodeReaderView/blob/master/samples/src/main/java/com/example/qr_readerexample/PointsOverlayView.java
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.code_scanned_color;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.code_selected_color;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.code_unscanned_color;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
@@ -13,6 +17,7 @@ import android.view.View;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
// Shows the progress of receiving data over codes.
|
||||||
public class CodeOverlayView extends View {
|
public class CodeOverlayView extends View {
|
||||||
|
|
||||||
PointF[] points;
|
PointF[] points;
|
||||||
@@ -37,7 +42,7 @@ public class CodeOverlayView extends View {
|
|||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
paint = new Paint();
|
paint = new Paint();
|
||||||
paint.setColor(Color.YELLOW);
|
paint.setColor(code_selected_color);
|
||||||
paint.setStyle(Paint.Style.FILL);
|
paint.setStyle(Paint.Style.FILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +65,7 @@ public class CodeOverlayView extends View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(barColors != null){
|
if(barColors != null){
|
||||||
final double width = getWidth()/barColors.length;
|
final double width = (double) getWidth() /barColors.length;
|
||||||
|
|
||||||
final int top = 0;
|
final int top = 0;
|
||||||
final int bottom = barHeight;
|
final int bottom = barHeight;
|
||||||
@@ -69,12 +74,12 @@ public class CodeOverlayView extends View {
|
|||||||
|
|
||||||
final int num = barColors[i];
|
final int num = barColors[i];
|
||||||
|
|
||||||
int c = Color.RED;
|
int c = code_unscanned_color;
|
||||||
|
|
||||||
if(num == 2){
|
if(num == 2){
|
||||||
c = Color.GREEN;
|
c = code_scanned_color;
|
||||||
}else if(num == 1){
|
}else if(num == 1){
|
||||||
c = Color.YELLOW;
|
c = code_selected_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Paint p = new Paint();
|
final Paint p = new Paint();
|
||||||
|
|||||||
@@ -14,18 +14,69 @@ import com.google.zxing.Reader;
|
|||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
import com.google.zxing.common.HybridBinarizer;
|
import com.google.zxing.common.HybridBinarizer;
|
||||||
import com.google.zxing.datamatrix.DataMatrixReader;
|
import com.google.zxing.datamatrix.DataMatrixReader;
|
||||||
|
import com.ridgebotics.ridgescout.utility.TaskRunner;
|
||||||
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class CodeScanTask extends AsyncTask<String, String, String>{
|
// Background task for code scanning, to not slow down the scanner.
|
||||||
private Function<String, String> resultFunction = null;
|
//public class CodeScanTask extends AsyncTask<String, String, String>{
|
||||||
|
// private Function<String, String> resultFunction = null;
|
||||||
|
// private Bitmap image;
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// protected String doInBackground(String... str) {
|
||||||
|
// if(image == null){return null;}
|
||||||
|
//
|
||||||
|
// int width = image.getWidth();
|
||||||
|
// int height = image.getHeight();
|
||||||
|
// int[] pixels = new int[width * height];
|
||||||
|
// image.getPixels(pixels, 0, width, 0, 0, width, height);
|
||||||
|
//
|
||||||
|
// RGBLuminanceSource source = new RGBLuminanceSource(width, height, pixels);
|
||||||
|
// BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||||
|
//
|
||||||
|
// Map<DecodeHintType, Object> hints = new HashMap<>();
|
||||||
|
// hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
|
||||||
|
//// hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
|
||||||
|
// hints.put(DecodeHintType.POSSIBLE_FORMATS, EnumSet.of(BarcodeFormat.DATA_MATRIX));
|
||||||
|
//
|
||||||
|
// Reader reader = new DataMatrixReader();
|
||||||
|
// try {
|
||||||
|
// Result result = reader.decode(binaryBitmap, hints);
|
||||||
|
// return result.getText();
|
||||||
|
// } catch (NotFoundException | ChecksumException | FormatException e) {
|
||||||
|
//// AlertManager.error(e);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// public void setImage(Bitmap image){this.image = image;}
|
||||||
|
// public void onResult(Function<String, String> func) {
|
||||||
|
// this.resultFunction = func;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// protected void onPostExecute(String result) {
|
||||||
|
// super.onPostExecute(result);
|
||||||
|
// if(resultFunction != null){
|
||||||
|
// resultFunction.apply(result);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
public class CodeScanTask implements Callable<String> {
|
||||||
private Bitmap image;
|
private Bitmap image;
|
||||||
|
|
||||||
|
public CodeScanTask(Bitmap image) {
|
||||||
|
this.image = image;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String doInBackground(String... str) {
|
public String call() {
|
||||||
if(image == null){return null;}
|
if(image == null){return null;}
|
||||||
|
|
||||||
int width = image.getWidth();
|
int width = image.getWidth();
|
||||||
@@ -51,17 +102,4 @@ public class CodeScanTask extends AsyncTask<String, String, String>{
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public void setImage(Bitmap image){this.image = image;}
|
|
||||||
public void onResult(Function<String, String> func) {
|
|
||||||
this.resultFunction = func;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(String result) {
|
|
||||||
super.onPostExecute(result);
|
|
||||||
if(resultFunction != null){
|
|
||||||
resultFunction.apply(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+52
-46
@@ -6,6 +6,7 @@ import android.Manifest;
|
|||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Matrix;
|
||||||
import android.media.Image;
|
import android.media.Image;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -33,22 +34,25 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.lifecycle.LifecycleOwner;
|
import androidx.lifecycle.LifecycleOwner;
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentTransferCodeReceiverBinding;
|
import com.ridgebotics.ridgescout.databinding.FragmentTransferCodeReceiverBinding;
|
||||||
import com.ridgebotics.ridgescout.databinding.FragmentTransferCodeSenderBinding;
|
import com.ridgebotics.ridgescout.types.ScoutingFile;
|
||||||
import com.ridgebotics.ridgescout.types.file;
|
|
||||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||||
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
import com.ridgebotics.ridgescout.utility.BuiltByteParser;
|
||||||
import com.ridgebotics.ridgescout.utility.fileEditor;
|
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.ridgebotics.ridgescout.utility.TaskRunner;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.units.qual.C;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
//public class scannerView extends androidx.appcompat.widget.AppCompatImageView {
|
// Recieves data from the camera, scanning codes.
|
||||||
public class CodeScannerView extends Fragment {
|
public class CodeScannerView extends Fragment {
|
||||||
private CodeOverlayView CodeOverlayView;
|
private CodeOverlayView CodeOverlayView;
|
||||||
private Handler uiHandler;
|
private Handler uiHandler;
|
||||||
@@ -63,21 +67,12 @@ public class CodeScannerView extends Fragment {
|
|||||||
alert.create().show();
|
alert.create().show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private float scale = 0;
|
|
||||||
private final int downscale = 1;
|
private final int downscale = 1;
|
||||||
private LifecycleOwner lifecycle;
|
private LifecycleOwner lifecycle;
|
||||||
|
|
||||||
private void setImage(Bitmap bmp){
|
private void setImage(Bitmap bmp){
|
||||||
if(scale == 0) {
|
|
||||||
scale = ((float) binding.container.getWidth() / bmp.getWidth()) * ((float) 16 / 9);
|
|
||||||
binding.scannerImage.setTranslationX(0);
|
|
||||||
binding.scannerImage.setTranslationY(0);
|
|
||||||
}
|
|
||||||
scanQRCode(bmp);
|
scanQRCode(bmp);
|
||||||
binding.scannerImage.setImageBitmap(bmp);
|
binding.scannerImage.setImageBitmap(bmp);
|
||||||
binding.scannerThreshold.bringToFront();
|
|
||||||
// alert("test", getChildCount()+"");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// private Bitmap img
|
// private Bitmap img
|
||||||
@@ -100,37 +95,38 @@ public class CodeScannerView extends Fragment {
|
|||||||
final int height = image.getHeight();
|
final int height = image.getHeight();
|
||||||
|
|
||||||
int[] pixels = new int[width * height];
|
int[] pixels = new int[width * height];
|
||||||
for (int y = 0; y < height; y++) {
|
for (int i = 0; i < width*height; i++) {
|
||||||
for (int x = 0; x < width; x++) {
|
int L = levelMap[yBuffer.get(i) & 0xff];
|
||||||
int L = levelMap[yBuffer.get() & 0xff];
|
pixels[i] = 0xff000000 | (L << 16) | (L << 8) | L;
|
||||||
pixels[y * width + x] = 0xff000000 | (L << 16) | (L << 8) | L;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Matrix matrix = new Matrix();
|
||||||
|
|
||||||
|
matrix.postRotate(90);
|
||||||
|
|
||||||
|
|
||||||
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||||
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
|
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
|
||||||
|
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
|
||||||
|
// Bitmap.rota
|
||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
public void scanQRCode(Bitmap bitmap) {
|
public void scanQRCode(Bitmap bitmap) {
|
||||||
|
|
||||||
CodeScanTask async = new CodeScanTask();
|
// CodeScanTask async = new CodeScanTask();
|
||||||
async.setImage(bitmap);
|
new TaskRunner().executeAsync(new CodeScanTask(bitmap), data -> {
|
||||||
async.onResult(data -> {
|
|
||||||
if(data != null){
|
if(data != null){
|
||||||
// alert("test", ""+fileEditor.byteFromChar(data.charAt(0)));
|
// alert("test", ""+fileEditor.byteFromChar(data.charAt(0)));
|
||||||
compileData(
|
compileData(
|
||||||
fileEditor.byteFromChar(data.charAt(0)),
|
FileEditor.byteFromChar(data.charAt(0)),
|
||||||
fileEditor.byteFromChar(data.charAt(1)),
|
FileEditor.byteFromChar(data.charAt(1)),
|
||||||
fileEditor.byteFromChar(data.charAt(2)),
|
FileEditor.byteFromChar(data.charAt(2)),
|
||||||
(fileEditor.byteFromChar(data.charAt(3))+1),
|
(FileEditor.byteFromChar(data.charAt(3))+1),
|
||||||
data.substring(4)
|
data.substring(4)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
});
|
});
|
||||||
async.execute();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// return contents;
|
// return contents;
|
||||||
@@ -232,26 +228,23 @@ public class CodeScannerView extends Fragment {
|
|||||||
|
|
||||||
void bindPreview(@NonNull ProcessCameraProvider cameraProvider) {
|
void bindPreview(@NonNull ProcessCameraProvider cameraProvider) {
|
||||||
|
|
||||||
Preview preview = new Preview.Builder()
|
Preview preview = new Preview.Builder().build();
|
||||||
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
|
|
||||||
.setTargetRotation(Surface.ROTATION_180)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
CameraSelector cameraSelector = new CameraSelector.Builder()
|
CameraSelector cameraSelector = new CameraSelector.Builder()
|
||||||
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
|
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
|
||||||
|
|
||||||
// .addCameraFilter(CameraFilters.NON)
|
// .addCameraFilter(CameraFilters.NON)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
|
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
|
||||||
// .setTargetResolution(new Size(224, 224))
|
// .setTargetAspectRatio(AspectRatio.RATIO_16_9)
|
||||||
.setOutputImageRotationEnabled(false)
|
|
||||||
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
|
|
||||||
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
|
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
|
||||||
|
// .setOutputImageRotationEnabled(true)
|
||||||
|
// .setTargetRotation(Surface.ROTATION_0)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
||||||
imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() {
|
imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() {
|
||||||
@OptIn(markerClass = ExperimentalGetImage.class) @Override
|
@OptIn(markerClass = ExperimentalGetImage.class) @Override
|
||||||
public void analyze(@NonNull ImageProxy image) {
|
public void analyze(@NonNull ImageProxy image) {
|
||||||
@@ -270,6 +263,7 @@ public class CodeScannerView extends Fragment {
|
|||||||
});
|
});
|
||||||
|
|
||||||
cameraProvider.unbindAll();
|
cameraProvider.unbindAll();
|
||||||
|
// cameraProvider.ro
|
||||||
|
|
||||||
cameraProvider.bindToLifecycle(lifecycle,
|
cameraProvider.bindToLifecycle(lifecycle,
|
||||||
cameraSelector, imageAnalysis, preview);
|
cameraSelector, imageAnalysis, preview);
|
||||||
@@ -284,8 +278,8 @@ public class CodeScannerView extends Fragment {
|
|||||||
private int randID;
|
private int randID;
|
||||||
private int prevQrIndex;
|
private int prevQrIndex;
|
||||||
private void compileData(int dataVersion, int randID, int qrIndex, int qrCount, String qrData){
|
private void compileData(int dataVersion, int randID, int qrIndex, int qrCount, String qrData){
|
||||||
if(dataVersion != fileEditor.internalDataVersion){
|
if(dataVersion != FileEditor.internalDataVersion){
|
||||||
alert("Error", "Incorrect data version ("+dataVersion+" != "+fileEditor.internalDataVersion+")");
|
alert("Error", "Incorrect data version ("+dataVersion+" != "+ FileEditor.internalDataVersion+")");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,6 +290,7 @@ public class CodeScannerView extends Fragment {
|
|||||||
Log.i("title", ""+qrCount);
|
Log.i("title", ""+qrCount);
|
||||||
barColors = new int[qrCount];
|
barColors = new int[qrCount];
|
||||||
prevQrIndex = qrIndex;
|
prevQrIndex = qrIndex;
|
||||||
|
qrScannedCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean updated;
|
final boolean updated;
|
||||||
@@ -314,14 +309,26 @@ public class CodeScannerView extends Fragment {
|
|||||||
|
|
||||||
if(updated && qrScannedCount >= qrCount){
|
if(updated && qrScannedCount >= qrCount){
|
||||||
|
|
||||||
|
AlertManager.startLoading("Decoding data...");
|
||||||
|
new TaskRunner().executeAsync(new CodeDecodeTask(), result -> {
|
||||||
|
AlertManager.stopLoading();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
prevQrIndex = qrIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CodeDecodeTask implements Callable<Void> {
|
||||||
|
@Override
|
||||||
|
public Void call() {
|
||||||
String compiledString = "";
|
String compiledString = "";
|
||||||
for(int i=0;i<qrCount;i++){
|
for(int i=0;i<qrDataArr.length;i++){
|
||||||
compiledString += qrDataArr[i];
|
compiledString += qrDataArr[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
byte[] compiledBytes = compiledString.getBytes(StandardCharsets.ISO_8859_1);
|
byte[] compiledBytes = compiledString.getBytes(StandardCharsets.ISO_8859_1);
|
||||||
byte[] resultBytes = fileEditor.blockUncompress(compiledBytes);
|
byte[] resultBytes = FileEditor.blockUncompress(compiledBytes);
|
||||||
|
|
||||||
|
|
||||||
String result_filenames = "";
|
String result_filenames = "";
|
||||||
@@ -330,8 +337,8 @@ public class CodeScannerView extends Fragment {
|
|||||||
ArrayList<BuiltByteParser.parsedObject> result = bbp.parse();
|
ArrayList<BuiltByteParser.parsedObject> result = bbp.parse();
|
||||||
|
|
||||||
for(int i = 0; i < result.size(); i++){
|
for(int i = 0; i < result.size(); i++){
|
||||||
if(result.get(i).getType() != file.typecode) continue;
|
if(result.get(i).getType() != ScoutingFile.typecode) continue;
|
||||||
file f = file.decode((byte[]) result.get(i).get());
|
ScoutingFile f = ScoutingFile.decode((byte[]) result.get(i).get());
|
||||||
|
|
||||||
if(f != null)
|
if(f != null)
|
||||||
if(f.write())
|
if(f.write())
|
||||||
@@ -343,9 +350,8 @@ public class CodeScannerView extends Fragment {
|
|||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
AlertManager.error(e);
|
AlertManager.error(e);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
prevQrIndex = qrIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,204 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.views;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
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;
|
||||||
|
|
||||||
|
// Unused. AI-generated dynamic wallpaper for 2025 season.
|
||||||
|
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,108 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.views;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.candlestick_color;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
// Shows the scale for a candlestick chart.
|
||||||
|
public class CandlestickHeader extends View {
|
||||||
|
|
||||||
|
private float absoluteMin = 0;
|
||||||
|
private float absoluteMax = 100;
|
||||||
|
|
||||||
|
// Number of scale marks to show
|
||||||
|
private final int SCALE_MARKS = 5;
|
||||||
|
|
||||||
|
// Padding and dimensions
|
||||||
|
private final int PADDING_LEFT = 50;
|
||||||
|
private final int PADDING_RIGHT = 50;
|
||||||
|
private final int PADDING_TOP = 10;
|
||||||
|
private final int PADDING_BOTTOM = 10;
|
||||||
|
private final int TICK_HEIGHT = 10;
|
||||||
|
|
||||||
|
private Paint linePaint;
|
||||||
|
private Paint textPaint;
|
||||||
|
|
||||||
|
public CandlestickHeader(Context context) {
|
||||||
|
super(context);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CandlestickHeader(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CandlestickHeader(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
linePaint.setColor(candlestick_color);
|
||||||
|
linePaint.setStrokeWidth(2f);
|
||||||
|
linePaint.setStyle(Paint.Style.STROKE);
|
||||||
|
|
||||||
|
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
textPaint.setColor(candlestick_color);
|
||||||
|
textPaint.setTextSize(30f);
|
||||||
|
textPaint.setTextAlign(Paint.Align.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the scale range for the header
|
||||||
|
*
|
||||||
|
* @param absoluteMin Absolute minimum of the dataset
|
||||||
|
* @param absoluteMax Absolute maximum of the dataset
|
||||||
|
*/
|
||||||
|
public void setScale(float absoluteMin, float absoluteMax) {
|
||||||
|
this.absoluteMin = absoluteMin;
|
||||||
|
this.absoluteMax = absoluteMax;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
int desiredWidth = 600;
|
||||||
|
int desiredHeight = 80; // Height for the scale with labels
|
||||||
|
|
||||||
|
int width = resolveSize(desiredWidth, widthMeasureSpec);
|
||||||
|
int height = resolveSize(desiredHeight, heightMeasureSpec);
|
||||||
|
|
||||||
|
setMeasuredDimension(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDraw(Canvas canvas) {
|
||||||
|
super.onDraw(canvas);
|
||||||
|
|
||||||
|
int width = getWidth();
|
||||||
|
int height = getHeight();
|
||||||
|
|
||||||
|
// Draw horizontal axis
|
||||||
|
float y = height - PADDING_BOTTOM;
|
||||||
|
canvas.drawLine(PADDING_LEFT, y, width - PADDING_RIGHT, y, linePaint);
|
||||||
|
|
||||||
|
// Calculate interval between scale marks
|
||||||
|
float availableWidth = width - PADDING_LEFT - PADDING_RIGHT;
|
||||||
|
float intervalValue = (absoluteMax - absoluteMin) / (SCALE_MARKS - 1);
|
||||||
|
float intervalPixels = availableWidth / (SCALE_MARKS - 1);
|
||||||
|
|
||||||
|
// Draw scale marks and labels
|
||||||
|
for (int i = 0; i < SCALE_MARKS; i++) {
|
||||||
|
float x = PADDING_LEFT + (intervalPixels * i);
|
||||||
|
float value = absoluteMin + (intervalValue * i);
|
||||||
|
|
||||||
|
// Draw tick mark
|
||||||
|
canvas.drawLine(x, y, x, y - TICK_HEIGHT, linePaint);
|
||||||
|
|
||||||
|
// Draw label
|
||||||
|
canvas.drawText(String.format("%.1f", value), x, y - TICK_HEIGHT - 10, textPaint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,215 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.views;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.candlestick_color;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.types.data.RawDataType;
|
||||||
|
import com.ridgebotics.ridgescout.ui.data.DataProcessing;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
// A single candlestick chart row.
|
||||||
|
public class CandlestickView extends View {
|
||||||
|
|
||||||
|
// Data points
|
||||||
|
private float min = 0;
|
||||||
|
private float max = 0;
|
||||||
|
private float lowerQuartile = 0;
|
||||||
|
private float upperQuartile = 0;
|
||||||
|
public float average = 0;
|
||||||
|
|
||||||
|
// Dataset absolute bounds for scaling
|
||||||
|
private float absoluteMin = 0;
|
||||||
|
private float absoluteMax = 100;
|
||||||
|
|
||||||
|
// Padding and dimensions
|
||||||
|
private final int PADDING_LEFT = 50;
|
||||||
|
private final int PADDING_RIGHT = 50;
|
||||||
|
private final int PADDING_TOP = 20;
|
||||||
|
private final int PADDING_BOTTOM = 20;
|
||||||
|
private final int CANDLESTICK_HEIGHT = 60;
|
||||||
|
private final int WHISKER_HEIGHT = 10;
|
||||||
|
|
||||||
|
// Paint objects
|
||||||
|
private Paint boxPaint;
|
||||||
|
private Paint whiskerPaint;
|
||||||
|
private Paint averagePaint;
|
||||||
|
private Paint textPaint;
|
||||||
|
|
||||||
|
public CandlestickView(Context context) {
|
||||||
|
super(context);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CandlestickView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CandlestickView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
// Initialize paint objects
|
||||||
|
boxPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
boxPaint.setColor(candlestick_color);
|
||||||
|
boxPaint.setStyle(Paint.Style.STROKE);
|
||||||
|
boxPaint.setStrokeWidth(2f);
|
||||||
|
|
||||||
|
whiskerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
whiskerPaint.setColor(candlestick_color);
|
||||||
|
whiskerPaint.setStrokeWidth(2f);
|
||||||
|
whiskerPaint.setStyle(Paint.Style.STROKE);
|
||||||
|
|
||||||
|
averagePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
averagePaint.setColor(candlestick_color);
|
||||||
|
averagePaint.setStrokeWidth(3f);
|
||||||
|
|
||||||
|
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
textPaint.setColor(candlestick_color);
|
||||||
|
textPaint.setTextSize(30f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set data for the candlestick chart
|
||||||
|
*
|
||||||
|
* @param min Minimum value
|
||||||
|
* @param lowerQuartile Lower quartile value
|
||||||
|
* @param average Average value
|
||||||
|
* @param upperQuartile Upper quartile value
|
||||||
|
* @param max Maximum value
|
||||||
|
* @param absoluteMin Absolute minimum of the dataset
|
||||||
|
* @param absoluteMax Absolute maximum of the dataset
|
||||||
|
*/
|
||||||
|
public void setData(float min, float lowerQuartile, float average,
|
||||||
|
float upperQuartile, float max,
|
||||||
|
float absoluteMin, float absoluteMax) {
|
||||||
|
this.min = min;
|
||||||
|
this.lowerQuartile = lowerQuartile;
|
||||||
|
this.average = average;
|
||||||
|
this.upperQuartile = upperQuartile;
|
||||||
|
this.max = max;
|
||||||
|
this.absoluteMin = absoluteMin;
|
||||||
|
this.absoluteMax = absoluteMax;
|
||||||
|
|
||||||
|
// Request redraw
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
int desiredWidth = 600;
|
||||||
|
int desiredHeight = CANDLESTICK_HEIGHT + PADDING_TOP + PADDING_BOTTOM;
|
||||||
|
|
||||||
|
int width = resolveSize(desiredWidth, widthMeasureSpec);
|
||||||
|
int height = resolveSize(desiredHeight, heightMeasureSpec);
|
||||||
|
|
||||||
|
setMeasuredDimension(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDraw(Canvas canvas) {
|
||||||
|
super.onDraw(canvas);
|
||||||
|
|
||||||
|
int width = getWidth();
|
||||||
|
int height = getHeight();
|
||||||
|
|
||||||
|
// Calculate scaling factor for data points
|
||||||
|
float availableWidth = width - PADDING_LEFT - PADDING_RIGHT;
|
||||||
|
float scale = availableWidth / (absoluteMax - absoluteMin);
|
||||||
|
|
||||||
|
// Calculate vertical center of the view
|
||||||
|
int centerY = height / 2;
|
||||||
|
|
||||||
|
// Calculate scaled positions
|
||||||
|
float scaledMin = PADDING_LEFT + (min - absoluteMin) * scale;
|
||||||
|
float scaledLQ = PADDING_LEFT + (lowerQuartile - absoluteMin) * scale;
|
||||||
|
float scaledAvg = PADDING_LEFT + (average - absoluteMin) * scale;
|
||||||
|
float scaledUQ = PADDING_LEFT + (upperQuartile - absoluteMin) * scale;
|
||||||
|
float scaledMax = PADDING_LEFT + (max - absoluteMin) * scale;
|
||||||
|
|
||||||
|
// Draw the box (interquartile range)
|
||||||
|
if(lowerQuartile != upperQuartile) {
|
||||||
|
RectF box = new RectF(
|
||||||
|
scaledLQ,
|
||||||
|
centerY - CANDLESTICK_HEIGHT / 2,
|
||||||
|
scaledUQ,
|
||||||
|
centerY + CANDLESTICK_HEIGHT / 2);
|
||||||
|
canvas.drawRect(box, boxPaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw whiskers (min to lower quartile and upper quartile to max)
|
||||||
|
// Left whisker
|
||||||
|
canvas.drawLine(scaledMin, centerY, scaledLQ, centerY, whiskerPaint);
|
||||||
|
canvas.drawLine(
|
||||||
|
scaledMin,
|
||||||
|
centerY - WHISKER_HEIGHT,
|
||||||
|
scaledMin,
|
||||||
|
centerY + WHISKER_HEIGHT,
|
||||||
|
whiskerPaint);
|
||||||
|
|
||||||
|
// Right whisker
|
||||||
|
canvas.drawLine(scaledUQ, centerY, scaledMax, centerY, whiskerPaint);
|
||||||
|
canvas.drawLine(
|
||||||
|
scaledMax,
|
||||||
|
centerY - WHISKER_HEIGHT,
|
||||||
|
scaledMax,
|
||||||
|
centerY + WHISKER_HEIGHT,
|
||||||
|
whiskerPaint);
|
||||||
|
|
||||||
|
// Draw average line
|
||||||
|
canvas.drawLine(
|
||||||
|
scaledAvg,
|
||||||
|
centerY - CANDLESTICK_HEIGHT / 2,
|
||||||
|
scaledAvg,
|
||||||
|
centerY + CANDLESTICK_HEIGHT / 2,
|
||||||
|
averagePaint);
|
||||||
|
|
||||||
|
// Draw labels
|
||||||
|
// canvas.drawText(String.format("%.1f", min), scaledMin - 20, centerY - CANDLESTICK_HEIGHT / 2 - 10, textPaint);
|
||||||
|
// canvas.drawText(String.format("%.1f", max), scaledMax - 20, centerY - CANDLESTICK_HEIGHT / 2 - 10, textPaint);
|
||||||
|
// canvas.drawText(String.format("%.1f", average), scaledAvg - 20, centerY + CANDLESTICK_HEIGHT / 2 + 30, textPaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int teamNum;
|
||||||
|
|
||||||
|
public void fromTeamData(List<RawDataType> teamData, Integer teamNum, float absmin, float absmax){
|
||||||
|
this.teamNum = teamNum;
|
||||||
|
int[] tmp_loc_bounds = DataProcessing.getNumberBounds(teamData);
|
||||||
|
int locmin = tmp_loc_bounds[0];
|
||||||
|
int locmax = tmp_loc_bounds[1];
|
||||||
|
|
||||||
|
float avg = 0;
|
||||||
|
|
||||||
|
for(int i = 0; i < teamData.size(); i++){
|
||||||
|
avg += (int) teamData.get(i).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
avg /= teamData.size();
|
||||||
|
|
||||||
|
float[] teamDataArray = new float[teamData.size()];
|
||||||
|
for(int i = 0; i < teamData.size(); i++){
|
||||||
|
teamDataArray[i] = (int) teamData.get(i).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
float lowerQuartile = 0;
|
||||||
|
float upperQuartile = 0;
|
||||||
|
|
||||||
|
if(teamDataArray.length != 0) {
|
||||||
|
lowerQuartile = DataProcessing.calculatePercentile(teamDataArray, 25);
|
||||||
|
upperQuartile = DataProcessing.calculatePercentile(teamDataArray, 75);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i(getClass().toString(), locmin + ", " + lowerQuartile + ", " + avg + ", " + upperQuartile + ", " + locmax);
|
||||||
|
setData(locmin, lowerQuartile, avg, upperQuartile, locmax, absmin, absmax);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.views;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.TableLayout;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.android.material.divider.MaterialDivider;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
// The notification view of a Custom dropdown notification
|
||||||
|
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,123 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.views;
|
||||||
|
|
||||||
|
import static android.app.PendingIntent.getActivity;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ScrollView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.R;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
// The dropdown element of a custom spinner view.
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.views;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TableRow;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.R;
|
||||||
|
import com.ridgebotics.ridgescout.types.input.FieldType;
|
||||||
|
|
||||||
|
public class FieldBorderedRow extends TableRow {
|
||||||
|
public FieldBorderedRow(Context context, @Nullable AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FieldBorderedRow(Context context) {
|
||||||
|
super(context);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
private ConstraintLayout box;
|
||||||
|
private View coloredBackground;
|
||||||
|
|
||||||
|
public void init(Context context) {
|
||||||
|
LayoutInflater.from(context).inflate(R.layout.view_field_border_row, this, true);
|
||||||
|
|
||||||
|
|
||||||
|
box = findViewById(R.id.field_option_box);
|
||||||
|
coloredBackground = findViewById(R.id.field_option_background);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(int color){
|
||||||
|
Drawable drawable = box.getBackground();
|
||||||
|
drawable.mutate();
|
||||||
|
drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
|
||||||
|
|
||||||
|
float[] hsv = new float[3];
|
||||||
|
Color.colorToHSV(color,hsv);
|
||||||
|
|
||||||
|
coloredBackground.setBackgroundColor(
|
||||||
|
Color.HSVToColor(127, new float[]{
|
||||||
|
hsv[0],
|
||||||
|
Math.min(hsv[1], 0.75f),
|
||||||
|
Math.min(hsv[2], 0.5f)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fromField(FieldType field){
|
||||||
|
((TextView) findViewById(R.id.field_option_name)).setText(field.name);
|
||||||
|
((TextView) findViewById(R.id.field_option_type)).setText(field.get_type_name());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addView(View v){
|
||||||
|
box.addView(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.views;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.R;
|
||||||
|
import com.ridgebotics.ridgescout.types.input.FieldType;
|
||||||
|
|
||||||
|
// Shows a display of the view in the view editor.
|
||||||
|
public class FieldDisplay extends ConstraintLayout {
|
||||||
|
public FieldDisplay(Context context, @Nullable AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FieldDisplay(Context context) {
|
||||||
|
super(context);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FieldType field;
|
||||||
|
|
||||||
|
public Button editButton;
|
||||||
|
|
||||||
|
// private View fieldView;
|
||||||
|
private ConstraintLayout box;
|
||||||
|
public View coloredBackground;
|
||||||
|
private LinearLayout fieldDisplayBox;
|
||||||
|
|
||||||
|
public void init(Context context) {
|
||||||
|
LayoutInflater.from(context).inflate(R.layout.view_field_display, this, true);
|
||||||
|
|
||||||
|
box = findViewById(R.id.field_box);
|
||||||
|
fieldDisplayBox = findViewById(R.id.field_display_box);
|
||||||
|
coloredBackground = findViewById(R.id.field_background);
|
||||||
|
|
||||||
|
editButton = findViewById(R.id.button_edit);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private ToggleTitleView toggleTitleView;
|
||||||
|
private View fieldView;
|
||||||
|
|
||||||
|
public void setField(FieldType field){
|
||||||
|
this.field = field;
|
||||||
|
|
||||||
|
// titleText.setText(field.name);
|
||||||
|
// typeText.setText(field.get_type_name());
|
||||||
|
|
||||||
|
toggleTitleView = new ToggleTitleView(getContext());
|
||||||
|
toggleTitleView.setTitle(field.name);
|
||||||
|
toggleTitleView.setDescription(field.description);
|
||||||
|
fieldView = field.createView(getContext(), dataType -> 0);
|
||||||
|
|
||||||
|
fieldDisplayBox.removeAllViews();
|
||||||
|
fieldDisplayBox.addView(toggleTitleView);
|
||||||
|
fieldDisplayBox.addView(fieldView);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// public void setField(View newView){
|
||||||
|
// if(fieldView != null)
|
||||||
|
// box.removeView(fieldView);
|
||||||
|
// box.addView(newView);
|
||||||
|
// fieldView = newView;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// public void fromTeam(frcTeam team){
|
||||||
|
// setTeamNumber(team.teamNumber);
|
||||||
|
// setTeamName(team.teamName);
|
||||||
|
//
|
||||||
|
// if(team.bitmap != null) {
|
||||||
|
// setTeamLogo(team.bitmap);
|
||||||
|
// }else{
|
||||||
|
// hideLogo();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// setColor(team.getTeamColor());
|
||||||
|
// }
|
||||||
|
public void showButtons(){
|
||||||
|
findViewById(R.id.buttons).setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hideButtons(){
|
||||||
|
findViewById(R.id.buttons).setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FieldType getField(){
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(int color){
|
||||||
|
Drawable drawable = box.getBackground();
|
||||||
|
drawable.mutate();
|
||||||
|
drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
|
||||||
|
|
||||||
|
float[] hsv = new float[3];
|
||||||
|
Color.colorToHSV(color,hsv);
|
||||||
|
|
||||||
|
coloredBackground.setBackgroundColor(
|
||||||
|
Color.HSVToColor(127, new float[]{
|
||||||
|
hsv[0],
|
||||||
|
Math.min(hsv[1] - 0.25f, 0.75f),
|
||||||
|
Math.min(hsv[2] - 0.25f, 0.5f)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
-2
@@ -1,4 +1,4 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.scouting;
|
package com.ridgebotics.ridgescout.ui.views;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -13,7 +13,9 @@ import android.widget.FrameLayout;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import com.ridgebotics.ridgescout.R;
|
import com.ridgebotics.ridgescout.R;
|
||||||
|
import com.ridgebotics.ridgescout.utility.SettingsManager;
|
||||||
|
|
||||||
|
// Custom view to display a field position.
|
||||||
public class FieldPosView extends FrameLayout {
|
public class FieldPosView extends FrameLayout {
|
||||||
private int x = -1;
|
private int x = -1;
|
||||||
private int y = -1;
|
private int y = -1;
|
||||||
@@ -72,7 +74,20 @@ public class FieldPosView extends FrameLayout {
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
setImageResource(R.drawable.field_2024);
|
switch(SettingsManager.getFieldImageIndex()){
|
||||||
|
case "2025":
|
||||||
|
setImageResource(R.drawable.field_2025);
|
||||||
|
break;
|
||||||
|
case "2025 (Flipped)":
|
||||||
|
setImageResource(R.drawable.field_2025_flipped);
|
||||||
|
break;
|
||||||
|
case "2026":
|
||||||
|
setImageResource(R.drawable.field_2026);
|
||||||
|
break;
|
||||||
|
case "2026 (Flipped)":
|
||||||
|
setImageResource(R.drawable.field_2026_flipped);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.views;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.R;
|
||||||
|
import com.ridgebotics.ridgescout.types.frcTeam;
|
||||||
|
|
||||||
|
import org.w3c.dom.Text;
|
||||||
|
|
||||||
|
// A view for displaying information about a team.
|
||||||
|
public class MatchScoutingIndicator extends RelativeLayout {
|
||||||
|
public MatchScoutingIndicator(Context context, @Nullable AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MatchScoutingIndicator(Context context) {
|
||||||
|
super(context);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextView match_indicator_alliance_pos_text;
|
||||||
|
public TextView match_indicator_bar_team_num;
|
||||||
|
public TextView match_indicator_matchnum;
|
||||||
|
public TextView match_indicator_username;
|
||||||
|
public ImageButton match_indicator_back_button;
|
||||||
|
public ImageButton match_indicator_next_button;
|
||||||
|
private ConstraintLayout box;
|
||||||
|
private View coloredBackground;
|
||||||
|
|
||||||
|
public void init(Context context) {
|
||||||
|
LayoutInflater.from(context).inflate(R.layout.view_match_scouting_indicator, this, true);
|
||||||
|
match_indicator_back_button = findViewById(R.id.match_indicator_back_button);
|
||||||
|
match_indicator_next_button = findViewById(R.id.match_indicator_next_button);
|
||||||
|
match_indicator_alliance_pos_text = findViewById(R.id.match_indicator_alliance_pos_text);
|
||||||
|
match_indicator_username = findViewById(R.id.match_indicator_username);
|
||||||
|
match_indicator_matchnum = findViewById(R.id.match_indicator_matchnum);
|
||||||
|
match_indicator_bar_team_num = findViewById(R.id.match_indicator_bar_team_num);
|
||||||
|
box = findViewById(R.id.file_indicator_box);
|
||||||
|
coloredBackground = findViewById(R.id.match_indicator_background);
|
||||||
|
|
||||||
|
int currentNightMode = getContext().getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||||
|
switch (currentNightMode) {
|
||||||
|
case Configuration.UI_MODE_NIGHT_NO:
|
||||||
|
// Night mode is not active on device
|
||||||
|
match_indicator_back_button.setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_IN);
|
||||||
|
match_indicator_next_button.setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_IN);
|
||||||
|
break;
|
||||||
|
case Configuration.UI_MODE_NIGHT_YES:
|
||||||
|
// Night mode is active on device
|
||||||
|
match_indicator_back_button.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN);
|
||||||
|
match_indicator_next_button.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username){
|
||||||
|
match_indicator_username.setText(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlliancePos(String alliancePos){
|
||||||
|
match_indicator_alliance_pos_text.setText(alliancePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMatchNum(String matchNum){
|
||||||
|
match_indicator_matchnum.setText(matchNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTeamNum(String teamNum){
|
||||||
|
match_indicator_bar_team_num.setText(teamNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(int color){
|
||||||
|
// Set color of main background rectangle
|
||||||
|
Drawable box_drawable = box.getBackground();
|
||||||
|
box_drawable.mutate();
|
||||||
|
box_drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
|
||||||
|
|
||||||
|
float[] hsv = new float[3];
|
||||||
|
Color.colorToHSV(color,hsv);
|
||||||
|
|
||||||
|
int background_color = Color.HSVToColor(220, new float[]{
|
||||||
|
hsv[0],
|
||||||
|
Math.min(hsv[1], 0.75f),
|
||||||
|
Math.min(hsv[2], 0.5f)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set color of main background rectangle, slightly dimmer
|
||||||
|
coloredBackground.setBackgroundColor(
|
||||||
|
background_color
|
||||||
|
);
|
||||||
|
|
||||||
|
Drawable left_drawable = match_indicator_back_button.getBackground();
|
||||||
|
left_drawable.mutate();
|
||||||
|
left_drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
|
||||||
|
|
||||||
|
Drawable right_drawable = match_indicator_next_button.getBackground();
|
||||||
|
right_drawable.mutate();
|
||||||
|
right_drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-5
@@ -1,14 +1,11 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.scouting;
|
package com.ridgebotics.ridgescout.ui.views;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
@@ -52,7 +49,7 @@ public class MultiFieldPosView extends FrameLayout {
|
|||||||
imageView.setAdjustViewBounds(true);
|
imageView.setAdjustViewBounds(true);
|
||||||
addView(imageView);
|
addView(imageView);
|
||||||
|
|
||||||
setImageResource(R.drawable.field_2024);
|
setImageResource(R.drawable.field_2025);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.views;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.R;
|
||||||
|
|
||||||
|
// A view for displaying information about a team.
|
||||||
|
public class PitScoutingIndicator extends RelativeLayout {
|
||||||
|
public PitScoutingIndicator(Context context, @Nullable AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PitScoutingIndicator(Context context) {
|
||||||
|
super(context);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextView pit_indicator_username;
|
||||||
|
public TextView pit_indicator_team_num;
|
||||||
|
private ConstraintLayout box;
|
||||||
|
private View coloredBackground;
|
||||||
|
|
||||||
|
public void init(Context context) {
|
||||||
|
LayoutInflater.from(context).inflate(R.layout.view_pit_scouting_indicator, this, true);
|
||||||
|
pit_indicator_username = findViewById(R.id.pit_indicator_username);
|
||||||
|
pit_indicator_team_num = findViewById(R.id.pit_indicator_teamnum);
|
||||||
|
|
||||||
|
box = findViewById(R.id.pit_indicator_box);
|
||||||
|
coloredBackground = findViewById(R.id.pit_indicator_background);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username){
|
||||||
|
pit_indicator_username.setText(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTeamNum(int teamNum) {
|
||||||
|
pit_indicator_team_num.setText(String.valueOf(teamNum));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(int color){
|
||||||
|
// Set color of main background rectangle
|
||||||
|
Drawable box_drawable = box.getBackground();
|
||||||
|
box_drawable.mutate();
|
||||||
|
box_drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
|
||||||
|
|
||||||
|
float[] hsv = new float[3];
|
||||||
|
Color.colorToHSV(color,hsv);
|
||||||
|
|
||||||
|
int background_color = Color.HSVToColor(220, new float[]{
|
||||||
|
hsv[0],
|
||||||
|
Math.min(hsv[1], 0.75f),
|
||||||
|
Math.min(hsv[2], 0.5f)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set color of main background rectangle, slightly dimmer
|
||||||
|
coloredBackground.setBackgroundColor(
|
||||||
|
background_color
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.views;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.R;
|
||||||
|
|
||||||
|
// Class for custom view displaying an event in the TBASelector.java
|
||||||
|
public class TBAEventOption extends LinearLayout {
|
||||||
|
public TBAEventOption(Context context, @Nullable AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TBAEventOption(Context context) {
|
||||||
|
super(context);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextView eventCode;
|
||||||
|
private TextView eventName;
|
||||||
|
private TextView eventType;
|
||||||
|
|
||||||
|
private ConstraintLayout box;
|
||||||
|
private View coloredBackground;
|
||||||
|
|
||||||
|
public void init(Context context) {
|
||||||
|
LayoutInflater.from(context).inflate(R.layout.view_tba_event, this, true);
|
||||||
|
|
||||||
|
eventCode = findViewById(R.id.tba_event_code);
|
||||||
|
eventName = findViewById(R.id.tba_event_name);
|
||||||
|
eventType = findViewById(R.id.tba_event_type);
|
||||||
|
|
||||||
|
|
||||||
|
box = findViewById(R.id.tba_event_box);
|
||||||
|
coloredBackground = findViewById(R.id.tba_event_background);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(String code){
|
||||||
|
eventCode.setText(String.valueOf(code));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name){
|
||||||
|
eventName.setText(name);
|
||||||
|
}
|
||||||
|
public void setType(String name){
|
||||||
|
eventType.setText(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// public void fromTeam(frcTeam team){
|
||||||
|
// setTeamNumber(team.teamNumber);
|
||||||
|
// setTeamName(team.teamName);
|
||||||
|
//
|
||||||
|
// if(team.bitmap != null) {
|
||||||
|
// setTeamLogo(team.bitmap);
|
||||||
|
// }else{
|
||||||
|
// hideLogo();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// setColor(team.getTeamColor());
|
||||||
|
// }
|
||||||
|
|
||||||
|
public void setColor(int color){
|
||||||
|
Drawable drawable = box.getBackground();
|
||||||
|
drawable.mutate();
|
||||||
|
drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
|
||||||
|
|
||||||
|
float[] hsv = new float[3];
|
||||||
|
Color.colorToHSV(color,hsv);
|
||||||
|
|
||||||
|
coloredBackground.setBackgroundColor(
|
||||||
|
Color.HSVToColor(127, new float[]{
|
||||||
|
hsv[0],
|
||||||
|
Math.min(hsv[1], 0.75f),
|
||||||
|
Math.min(hsv[2], 0.5f)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
-2
@@ -1,4 +1,4 @@
|
|||||||
package com.ridgebotics.ridgescout.ui.scouting;
|
package com.ridgebotics.ridgescout.ui.views;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
@@ -9,12 +9,15 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import com.ridgebotics.ridgescout.R;
|
import com.ridgebotics.ridgescout.R;
|
||||||
|
|
||||||
|
// Unused. This would be almost the same as the Fieldpos field, except it would support multiple positions.
|
||||||
public class TallyCounterView extends LinearLayout {
|
public class TallyCounterView extends LinearLayout {
|
||||||
private int count = 0;
|
private int count = 0;
|
||||||
private TextView countDisplay;
|
private TextView countDisplay;
|
||||||
private Button minusButton;
|
private Button minusButton;
|
||||||
private Button plusButton;
|
private Button plusButton;
|
||||||
private OnCountChangedListener onCountChangedListener;
|
private OnCountChangedListener onCountChangedListener;
|
||||||
|
private int min = 0;
|
||||||
|
private int max = -1;
|
||||||
|
|
||||||
public interface OnCountChangedListener {
|
public interface OnCountChangedListener {
|
||||||
void onCountChanged(int newCount);
|
void onCountChanged(int newCount);
|
||||||
@@ -45,20 +48,26 @@ public class TallyCounterView extends LinearLayout {
|
|||||||
updateDisplay();
|
updateDisplay();
|
||||||
|
|
||||||
minusButton.setOnClickListener(v -> {
|
minusButton.setOnClickListener(v -> {
|
||||||
if(count > 0) {
|
if(count > min) {
|
||||||
count--;
|
count--;
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
plusButton.setOnClickListener(v -> {
|
plusButton.setOnClickListener(v -> {
|
||||||
|
if(max == -1 || count < max){
|
||||||
count++;
|
count++;
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateDisplay() {
|
private void updateDisplay() {
|
||||||
countDisplay.setText(String.valueOf(count));
|
countDisplay.setText(String.valueOf(count));
|
||||||
|
|
||||||
|
minusButton.setEnabled(count > min);
|
||||||
|
plusButton.setEnabled(max == -1 || count < max);
|
||||||
|
|
||||||
if (onCountChangedListener != null) {
|
if (onCountChangedListener != null) {
|
||||||
onCountChangedListener.onCountChanged(count);
|
onCountChangedListener.onCountChanged(count);
|
||||||
}
|
}
|
||||||
@@ -69,6 +78,12 @@ public class TallyCounterView extends LinearLayout {
|
|||||||
updateDisplay();
|
updateDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setBounds(int min, int max){
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
public int getValue() {
|
public int getValue() {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.views;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.R;
|
||||||
|
import com.ridgebotics.ridgescout.types.frcTeam;
|
||||||
|
|
||||||
|
// A view for displaying information about a team.
|
||||||
|
public class TeamCard extends LinearLayout {
|
||||||
|
public TeamCard(Context context, @Nullable AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TeamCard(Context context) {
|
||||||
|
super(context);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextView teamNumber;
|
||||||
|
private TextView teamName;
|
||||||
|
private TextView teamDescription;
|
||||||
|
|
||||||
|
private ImageView teamLogo;
|
||||||
|
private ConstraintLayout box;
|
||||||
|
private View coloredBackground;
|
||||||
|
|
||||||
|
public void init(Context context) {
|
||||||
|
LayoutInflater.from(context).inflate(R.layout.view_team_card, this, true);
|
||||||
|
|
||||||
|
teamNumber = findViewById(R.id.team_card_number);
|
||||||
|
teamName = findViewById(R.id.team_card_name);
|
||||||
|
teamLogo = findViewById(R.id.team_card_logo);
|
||||||
|
teamDescription = findViewById(R.id.team_card_description);
|
||||||
|
|
||||||
|
|
||||||
|
box = findViewById(R.id.team_card_box);
|
||||||
|
coloredBackground = findViewById(R.id.team_card_background);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTeamNumber(int num){
|
||||||
|
teamNumber.setText(String.valueOf(num));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTeamName(String name){
|
||||||
|
teamName.setText(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTeamLogo(Bitmap bitmap){
|
||||||
|
teamLogo.setImageBitmap(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTeamDescription(String description){
|
||||||
|
teamDescription.setText(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hideLogo(){
|
||||||
|
teamLogo.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
public void showLogo(){
|
||||||
|
teamLogo.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fromTeam(frcTeam team){
|
||||||
|
setTeamNumber(team.teamNumber);
|
||||||
|
setTeamName(team.teamName);
|
||||||
|
|
||||||
|
if(team.bitmap != null) {
|
||||||
|
showLogo();
|
||||||
|
setTeamLogo(team.bitmap);
|
||||||
|
}else{
|
||||||
|
hideLogo();
|
||||||
|
}
|
||||||
|
|
||||||
|
setTeamDescription(team.getDescription());
|
||||||
|
|
||||||
|
setColor(team.getTeamColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(int color){
|
||||||
|
Drawable drawable = box.getBackground();
|
||||||
|
drawable.mutate();
|
||||||
|
drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
|
||||||
|
|
||||||
|
float[] hsv = new float[3];
|
||||||
|
Color.colorToHSV(color,hsv);
|
||||||
|
|
||||||
|
coloredBackground.setBackgroundColor(
|
||||||
|
Color.HSVToColor(127, new float[]{
|
||||||
|
hsv[0],
|
||||||
|
Math.min(hsv[1], 0.75f),
|
||||||
|
Math.min(hsv[2], 0.5f)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.views;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.R;
|
||||||
|
import com.ridgebotics.ridgescout.types.frcTeam;
|
||||||
|
|
||||||
|
// A view that acts as a row specifically to display a team and their icon in a list formmt.
|
||||||
|
public class TeamListOption extends LinearLayout {
|
||||||
|
public TeamListOption(Context context, @Nullable AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TeamListOption(Context context) {
|
||||||
|
super(context);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextView teamNumber;
|
||||||
|
private TextView teamName;
|
||||||
|
|
||||||
|
private ImageView teamLogo;
|
||||||
|
private ConstraintLayout box;
|
||||||
|
private View coloredBackground;
|
||||||
|
|
||||||
|
public void init(Context context) {
|
||||||
|
LayoutInflater.from(context).inflate(R.layout.view_team_option, this, true);
|
||||||
|
|
||||||
|
teamNumber = findViewById(R.id.field_option_type);
|
||||||
|
teamName = findViewById(R.id.field_option_name);
|
||||||
|
teamLogo = findViewById(R.id.team_option_logo);
|
||||||
|
|
||||||
|
|
||||||
|
box = findViewById(R.id.team_option_box);
|
||||||
|
coloredBackground = findViewById(R.id.team_option_background);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTeamNumber(int num){
|
||||||
|
teamNumber.setText(String.valueOf(num));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTeamName(String name){
|
||||||
|
teamName.setText(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTeamLogo(Bitmap bitmap){
|
||||||
|
teamLogo.setImageBitmap(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hideLogo(){
|
||||||
|
teamLogo.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
public void showLogo(){
|
||||||
|
teamLogo.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fromTeam(frcTeam team){
|
||||||
|
setTeamNumber(team.teamNumber);
|
||||||
|
setTeamName(team.teamName);
|
||||||
|
|
||||||
|
if(team.bitmap != null) {
|
||||||
|
setTeamLogo(team.bitmap);
|
||||||
|
}else{
|
||||||
|
hideLogo();
|
||||||
|
}
|
||||||
|
|
||||||
|
setColor(team.getTeamColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(int color){
|
||||||
|
Drawable drawable = box.getBackground();
|
||||||
|
drawable.mutate();
|
||||||
|
drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
|
||||||
|
|
||||||
|
float[] hsv = new float[3];
|
||||||
|
Color.colorToHSV(color,hsv);
|
||||||
|
|
||||||
|
coloredBackground.setBackgroundColor(
|
||||||
|
Color.HSVToColor(127, new float[]{
|
||||||
|
hsv[0],
|
||||||
|
Math.min(hsv[1], 0.75f),
|
||||||
|
Math.min(hsv[2], 0.5f)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
package com.ridgebotics.ridgescout.ui.views;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.toggletitle_black_background;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.toggletitle_no_background;
|
||||||
|
import static com.ridgebotics.ridgescout.utility.Colors.toggletitle_unselected;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
|
|
||||||
|
import com.ridgebotics.ridgescout.R;
|
||||||
|
|
||||||
|
// The enable and disable button for match and pit scouting
|
||||||
|
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();
|
||||||
|
|
||||||
|
if(onToggleListener != null)
|
||||||
|
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(toggletitle_unselected);
|
||||||
|
titleView.setTextColor(toggletitle_black_background);
|
||||||
|
}
|
||||||
|
public void enable(){
|
||||||
|
enabled = true;
|
||||||
|
toggle_title_checkbox.setChecked(true);
|
||||||
|
toggle_title_description.setVisibility(View.VISIBLE);
|
||||||
|
setBackgroundColor(toggletitle_no_background);
|
||||||
|
titleView.setTextAppearance(com.google.android.material.R.style.TextAppearance_MaterialComponents_Headline5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled){
|
||||||
|
if(enabled)
|
||||||
|
disable();
|
||||||
|
else
|
||||||
|
enable();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,71 +1,134 @@
|
|||||||
package com.ridgebotics.ridgescout.utility;
|
package com.ridgebotics.ridgescout.utility;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
import android.app.ProgressDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
// Class to cause alerts and popups
|
||||||
public class AlertManager {
|
public class AlertManager {
|
||||||
|
@SuppressLint("StaticFieldLeak")
|
||||||
public static Context context;
|
public static Context context;
|
||||||
|
|
||||||
public static void init(Context c){
|
public static void init(Context c){
|
||||||
context = c;
|
context = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static AlertDialog currentError;
|
||||||
|
private static final List<String> simpleErrorList = new ArrayList<>();
|
||||||
|
private static final List<String> errorList = new ArrayList<>();
|
||||||
|
|
||||||
public static void alert(String title, String content) {
|
public static void alert(String title, String content) {
|
||||||
((Activity) context).runOnUiThread(new Runnable() {
|
|
||||||
public void run() {
|
((Activity) context).runOnUiThread(() -> {
|
||||||
AlertDialog.Builder alert = new AlertDialog.Builder(context);
|
AlertDialog.Builder alert = new AlertDialog.Builder(context);
|
||||||
alert.setMessage(content);
|
|
||||||
alert.setTitle(title);
|
alert.setTitle(title);
|
||||||
|
alert.setMessage(content);
|
||||||
alert.setPositiveButton("OK", null);
|
alert.setPositiveButton("OK", null);
|
||||||
alert.setCancelable(true);
|
alert.setCancelable(true);
|
||||||
|
|
||||||
alert.create().show();
|
alert.create().show();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void toast(String content) {
|
public static void toast(String content) {
|
||||||
((Activity) context).runOnUiThread(new Runnable() {
|
((Activity) context).runOnUiThread(() -> Toast.makeText(context, content, Toast.LENGTH_LONG).show());
|
||||||
public void run() {
|
|
||||||
Toast.makeText(context, content, Toast.LENGTH_LONG).show();
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
public static void addSimpleError(String error) {
|
||||||
|
simpleErrorList.add(error);
|
||||||
|
updateErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void error(String content) {
|
public static void error(String content) {
|
||||||
((Activity) context).runOnUiThread(new Runnable() {
|
errorList.add(content);
|
||||||
public void run() {
|
updateErrors();
|
||||||
AlertDialog.Builder alert = new AlertDialog.Builder(context);
|
|
||||||
alert.setMessage(content);
|
|
||||||
alert.setTitle("Error!");
|
|
||||||
alert.setPositiveButton("OK", null);
|
|
||||||
alert.setCancelable(true);
|
|
||||||
|
|
||||||
alert.create().show();
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
public static void error(String title, String content) {
|
||||||
|
simpleErrorList.add(title);
|
||||||
|
errorList.add(content);
|
||||||
|
updateErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void error(Exception e) {
|
public static void error(Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
((Activity) context).runOnUiThread(new Runnable() {
|
// simpleErrorList.add(e.getMessage());
|
||||||
public void run() {
|
|
||||||
StringWriter sw = new StringWriter();
|
StringWriter sw = new StringWriter();
|
||||||
e.printStackTrace(new PrintWriter(sw));
|
e.printStackTrace(new PrintWriter(sw));
|
||||||
|
|
||||||
AlertDialog.Builder alert = new AlertDialog.Builder(context);
|
errorList.add(sw.getBuffer().toString());
|
||||||
alert.setMessage(sw.toString());
|
updateErrors();
|
||||||
alert.setTitle(e.getMessage());
|
|
||||||
alert.setPositiveButton("OK", null);
|
|
||||||
alert.setCancelable(true);
|
|
||||||
|
|
||||||
alert.create().show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void error(String title, Exception e) {
|
||||||
|
simpleErrorList.add(title);
|
||||||
|
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
e.printStackTrace(new PrintWriter(sw));
|
||||||
|
|
||||||
|
errorList.add(sw.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
updateErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateErrors(){
|
||||||
|
((Activity) context).runOnUiThread(() -> {
|
||||||
|
if(currentError != null && currentError.isShowing()){
|
||||||
|
DialogInterface tmp = currentError;
|
||||||
|
currentError = null;
|
||||||
|
tmp.dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
AlertDialog.Builder alert = new AlertDialog.Builder(context);
|
||||||
|
|
||||||
|
if(!simpleErrorList.isEmpty())
|
||||||
|
alert.setTitle(simpleErrorList.get(0) + (simpleErrorList.size() > 1 ? "..." : ""));
|
||||||
|
else
|
||||||
|
alert.setTitle(errorList.size() + " Error" + (errorList.size() != 1 ? "s" : "") + "!");
|
||||||
|
|
||||||
|
if(simpleErrorList.size() > 1)
|
||||||
|
alert.setMessage(String.join("\n", simpleErrorList));
|
||||||
|
|
||||||
|
alert.setPositiveButton("OK", (dialogInterface, i) -> {if(currentError != null){errorList.clear(); simpleErrorList.clear();}});
|
||||||
|
|
||||||
|
String detailedErrors = String.join("\n\n\n\n\n", errorList);
|
||||||
|
|
||||||
|
if(!errorList.isEmpty())
|
||||||
|
alert.setNeutralButton("View Detailed Error" + (errorList.size() != 1 ? "s" : ""), (dialogInterface, i) -> alert("Details", detailedErrors));
|
||||||
|
|
||||||
|
// alert.setOnDismissListener((x) -> {if(currentError != null){errorList.clear(); simpleErrorList.clear();}});
|
||||||
|
|
||||||
|
alert.setCancelable(true);
|
||||||
|
currentError = alert.create();
|
||||||
|
currentError.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ProgressDialog loadingDialog;
|
||||||
|
|
||||||
|
public static void startLoading(String title){
|
||||||
|
((Activity) context).runOnUiThread(() -> {
|
||||||
|
if(loadingDialog != null && loadingDialog.isShowing())
|
||||||
|
loadingDialog.dismiss();
|
||||||
|
loadingDialog = ProgressDialog.show(context, title, "Please wait...");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void stopLoading(){
|
||||||
|
((Activity) context).runOnUiThread(() -> {
|
||||||
|
if (loadingDialog != null)
|
||||||
|
loadingDialog.cancel();
|
||||||
|
loadingDialog = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,17 @@ package com.ridgebotics.ridgescout.utility;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
|
||||||
|
// Class to run a save function after a timeout of not calling the update function has been reached.
|
||||||
|
// Used for auto-saving in pit and match scouting.
|
||||||
public class AutoSaveManager {
|
public class AutoSaveManager {
|
||||||
private static final long AUTO_SAVE_DELAY = 2000; // 2 seconds
|
public static final long AUTO_SAVE_DELAY = 2000; // 2 seconds
|
||||||
|
|
||||||
private final Handler handler;
|
private final Handler handler;
|
||||||
private final Runnable autoSaveRunnable;
|
private final Runnable autoSaveRunnable;
|
||||||
private boolean isAutoSaveScheduled = false;
|
private boolean isAutoSaveScheduled = false;
|
||||||
private final AutoSaveFunction autoSaveFunction;
|
private final AutoSaveFunction autoSaveFunction;
|
||||||
public boolean isRunning = false;
|
public boolean isRunning = false;
|
||||||
|
private long delay;
|
||||||
|
|
||||||
// Functional interface for the auto-save function
|
// Functional interface for the auto-save function
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
@@ -18,8 +21,9 @@ public class AutoSaveManager {
|
|||||||
void save();
|
void save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AutoSaveManager(AutoSaveFunction autoSaveFunction) {
|
public AutoSaveManager(AutoSaveFunction autoSaveFunction, long delay) {
|
||||||
this.autoSaveFunction = autoSaveFunction;
|
this.autoSaveFunction = autoSaveFunction;
|
||||||
|
this.delay = delay;
|
||||||
handler = new Handler(Looper.getMainLooper());
|
handler = new Handler(Looper.getMainLooper());
|
||||||
autoSaveRunnable = new Runnable() {
|
autoSaveRunnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
package com.ridgebotics.ridgescout.utility;
|
package com.ridgebotics.ridgescout.utility;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.FileEditor.lengthHeaderBytes;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
|
// Class to decode the raw types from any of the scouting files
|
||||||
public class BuiltByteParser {
|
public class BuiltByteParser {
|
||||||
public static final Integer boolType = 0;
|
public static final Integer boolType = 0;
|
||||||
public static final Integer intType = 1;
|
public static final Integer intType = 1;
|
||||||
public static final Integer stringType = 2;
|
public static final Integer stringType = 2;
|
||||||
public static final Integer intArrayType = 3;
|
public static final Integer intArrayType = 3;
|
||||||
public static final Integer stringArrayType = 4;
|
public static final Integer stringArrayType = 4;
|
||||||
|
public static final Integer longType = 5;
|
||||||
|
|
||||||
public class byteParsingExeption extends Exception {
|
public static class byteParsingExeption extends Exception {
|
||||||
public byteParsingExeption() {}
|
public byteParsingExeption() {}
|
||||||
public byteParsingExeption(String message) {
|
public byteParsingExeption(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
@@ -58,6 +61,11 @@ public class BuiltByteParser {
|
|||||||
public Integer getType(){return stringArrayType;}
|
public Integer getType(){return stringArrayType;}
|
||||||
public Object get(){return arr;}
|
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 {
|
public class rawObject extends parsedObject {
|
||||||
@@ -70,26 +78,36 @@ public class BuiltByteParser {
|
|||||||
|
|
||||||
byte[] bytes;
|
byte[] bytes;
|
||||||
ArrayList<parsedObject> objects = new ArrayList<>();
|
ArrayList<parsedObject> objects = new ArrayList<>();
|
||||||
|
|
||||||
public BuiltByteParser(byte[] bytes){
|
public BuiltByteParser(byte[] bytes){
|
||||||
this.bytes = bytes;
|
this.bytes = bytes;
|
||||||
}
|
}
|
||||||
public ArrayList<parsedObject> parse() throws byteParsingExeption {
|
public ArrayList<parsedObject> parse() throws byteParsingExeption {
|
||||||
if(bytes.length < 3){throw new byteParsingExeption("Invalid length");}
|
try{
|
||||||
|
return parse(lengthHeaderBytes); // Try decoding with new format
|
||||||
|
}catch (byteParsingExeption e){
|
||||||
|
objects.clear(); // Clear previous attempt at decoding
|
||||||
|
return parse(lengthHeaderBytes - 1); // Try parsing with old format
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private ArrayList<parsedObject> parse(final int size) throws byteParsingExeption {
|
||||||
|
|
||||||
|
if(bytes.length < size + 1){throw new byteParsingExeption("Invalid length");}
|
||||||
int curIndex = 0;
|
int curIndex = 0;
|
||||||
while(true){
|
while(true){
|
||||||
// Log.i("t", String.valueOf(curIndex));
|
// Log.i("t", String.valueOf(curIndex));
|
||||||
final int length = fileEditor.fromBytes(fileEditor.getByteBlock(bytes, curIndex, curIndex+2), 2);
|
final int length = FileEditor.fromBytes(FileEditor.getByteBlock(bytes, curIndex, curIndex+size), size);
|
||||||
final int type = bytes[curIndex+2] & 0xFF;
|
final int type = bytes[curIndex+size] & 0xFF;
|
||||||
|
|
||||||
if(length == 0){
|
if(length == 0){
|
||||||
curIndex += 3;
|
curIndex += size;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
final byte[] block;
|
final byte[] block;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
block = fileEditor.getByteBlock(bytes, curIndex + 3, curIndex + length + 3);
|
block = FileEditor.getByteBlock(bytes, curIndex + size + 1, curIndex + length + size + 1);
|
||||||
} catch(Exception e){
|
} catch(Exception e){
|
||||||
throw new byteParsingExeption("Array out of bounds");
|
throw new byteParsingExeption("Array out of bounds");
|
||||||
}
|
}
|
||||||
@@ -102,7 +120,7 @@ public class BuiltByteParser {
|
|||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
intObject io = new intObject();
|
intObject io = new intObject();
|
||||||
io.num = fileEditor.fromBytes(block, length);
|
io.num = FileEditor.fromBytes(block, length);
|
||||||
objects.add(io);
|
objects.add(io);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
@@ -122,7 +140,7 @@ public class BuiltByteParser {
|
|||||||
|
|
||||||
intArrayObject ia = new intArrayObject();
|
intArrayObject ia = new intArrayObject();
|
||||||
ia.arr = intArr;
|
ia.arr = intArr;
|
||||||
System.out.println(Arrays.toString(intArr));
|
// System.out.println(Arrays.toString(intArr));lengthHeaderBytes
|
||||||
objects.add(ia);
|
objects.add(ia);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
@@ -140,6 +158,11 @@ public class BuiltByteParser {
|
|||||||
sa.arr = StringArr;
|
sa.arr = StringArr;
|
||||||
objects.add(sa);
|
objects.add(sa);
|
||||||
break;
|
break;
|
||||||
|
case 5:
|
||||||
|
longObject lo = new longObject();
|
||||||
|
lo.num = FileEditor.fromBytesLong(block, length);
|
||||||
|
objects.add(lo);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
rawObject ro = new rawObject(type);
|
rawObject ro = new rawObject(type);
|
||||||
ro.bytes = block;
|
ro.bytes = block;
|
||||||
@@ -147,7 +170,7 @@ public class BuiltByteParser {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
curIndex += length + 3;
|
curIndex += length + size + 1;
|
||||||
|
|
||||||
if(curIndex == bytes.length){
|
if(curIndex == bytes.length){
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
package com.ridgebotics.ridgescout.utility;
|
package com.ridgebotics.ridgescout.utility;
|
||||||
|
|
||||||
|
import static com.ridgebotics.ridgescout.utility.FileEditor.lengthHeaderBytes;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
// Class to encode the raw types from any of the scouting files
|
||||||
public class ByteBuilder {
|
public class ByteBuilder {
|
||||||
public static final int bool_id = 0;
|
public static final int bool_id = 0;
|
||||||
public static final int int_id = 1;
|
public static final int int_id = 1;
|
||||||
public static final int string_id = 2;
|
public static final int string_id = 2;
|
||||||
public static final int int_arr_id = 3;
|
public static final int int_arr_id = 3;
|
||||||
public static final int string_arr_id = 4;
|
public static final int string_arr_id = 4;
|
||||||
|
public static final int long_id = 5;
|
||||||
|
|
||||||
ArrayList<byteType> bytesToBuild = new ArrayList<>();
|
ArrayList<byteType> bytesToBuild = new ArrayList<>();
|
||||||
|
|
||||||
@@ -55,7 +59,7 @@ public class ByteBuilder {
|
|||||||
public byte getType(){return int_id;}
|
public byte getType(){return int_id;}
|
||||||
public int length(){return precision;}
|
public int length(){return precision;}
|
||||||
public byte[] build(){
|
public byte[] build(){
|
||||||
return fileEditor.toBytes(num, precision);
|
return FileEditor.toBytes(num, precision, lengthHeaderBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private int getLeastBytePrecision(int num){
|
private int getLeastBytePrecision(int num){
|
||||||
@@ -70,7 +74,7 @@ public class ByteBuilder {
|
|||||||
public ByteBuilder addInt(int num, int precision) throws buildingException {
|
public ByteBuilder addInt(int num, int precision) throws buildingException {
|
||||||
if(precision <= 0){throw new buildingException("Invalid precision: " + precision);}
|
if(precision <= 0){throw new buildingException("Invalid precision: " + precision);}
|
||||||
|
|
||||||
if(precision > 65536){throw new buildingException("Precision too large (greter than 65536)");}
|
if(precision > Math.pow(lengthHeaderBytes,8)){throw new buildingException("Precision too large (greter than 16777216)");}
|
||||||
if(precision < getLeastBytePrecision(num)){throw new buildingException("Precision too small");}
|
if(precision < getLeastBytePrecision(num)){throw new buildingException("Precision too small");}
|
||||||
|
|
||||||
if(num > Integer.MAX_VALUE){throw new buildingException("Integer overflow");}
|
if(num > Integer.MAX_VALUE){throw new buildingException("Integer overflow");}
|
||||||
@@ -95,7 +99,7 @@ public class ByteBuilder {
|
|||||||
}
|
}
|
||||||
public ByteBuilder addString(String str) throws buildingException {
|
public ByteBuilder addString(String str) throws buildingException {
|
||||||
str = blankStrNull(str);
|
str = blankStrNull(str);
|
||||||
if(str.length() > 65536){throw new buildingException("String too long (greater than 65536)");}
|
if(str.length() > Math.pow(lengthHeaderBytes,8)){throw new buildingException("String too long (greater than 16777216)");}
|
||||||
|
|
||||||
stringType stringType = new stringType();
|
stringType stringType = new stringType();
|
||||||
// To get the length correctly, the string bytes need to be precalculated
|
// To get the length correctly, the string bytes need to be precalculated
|
||||||
@@ -153,6 +157,41 @@ public class ByteBuilder {
|
|||||||
return this;
|
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, lengthHeaderBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 > Math.pow(lengthHeaderBytes,8)){throw new buildingException("Precision too large (greter than 16777216)");}
|
||||||
|
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 {
|
private class rawType extends byteType {
|
||||||
public int type;
|
public int type;
|
||||||
public byte[] bytes;
|
public byte[] bytes;
|
||||||
@@ -164,7 +203,7 @@ public class ByteBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuilder addRaw(int type, byte[] bytes) throws buildingException {
|
public ByteBuilder addRaw(int type, byte[] bytes) throws buildingException {
|
||||||
if(bytes.length > 65536){throw new buildingException("Byte array length to long (greater than 65536)");}
|
if(bytes.length > 16777216){throw new buildingException("Byte array length to long (greater than 16777216)");}
|
||||||
|
|
||||||
rawType rawType = new rawType();
|
rawType rawType = new rawType();
|
||||||
rawType.type = type;
|
rawType.type = type;
|
||||||
@@ -177,7 +216,7 @@ public class ByteBuilder {
|
|||||||
public byte[] build() throws buildingException {
|
public byte[] build() throws buildingException {
|
||||||
if(bytesToBuild.size() == 0){throw new buildingException("Cannot build null data");}
|
if(bytesToBuild.size() == 0){throw new buildingException("Cannot build null data");}
|
||||||
|
|
||||||
int length = bytesToBuild.size() * 3;
|
int length = bytesToBuild.size() * (lengthHeaderBytes + 1);
|
||||||
for(byteType bt : bytesToBuild){
|
for(byteType bt : bytesToBuild){
|
||||||
length += bt.length();
|
length += bt.length();
|
||||||
}
|
}
|
||||||
@@ -187,12 +226,13 @@ public class ByteBuilder {
|
|||||||
|
|
||||||
for(byteType bt : bytesToBuild){
|
for(byteType bt : bytesToBuild){
|
||||||
|
|
||||||
byte[] blockLength = fileEditor.toBytes(bt.length(), 2);
|
byte[] blockLength = FileEditor.toBytes(bt.length(), lengthHeaderBytes + 1, lengthHeaderBytes);
|
||||||
|
|
||||||
bytes[bytesFilled] = blockLength[0];
|
for(int i = 0; i < lengthHeaderBytes; i++) {
|
||||||
bytesFilled += 1;
|
bytes[bytesFilled] = blockLength[i];
|
||||||
bytes[bytesFilled] = blockLength[1];
|
|
||||||
bytesFilled += 1;
|
bytesFilled += 1;
|
||||||
|
}
|
||||||
|
|
||||||
bytes[bytesFilled] = bt.getType();
|
bytes[bytesFilled] = bt.getType();
|
||||||
bytesFilled += 1;
|
bytesFilled += 1;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package com.ridgebotics.ridgescout.utility;
|
||||||
|
|
||||||
|
import android.graphics.Color;
|
||||||
|
|
||||||
|
// Constants for most of the colors in the entire app.
|
||||||
|
public class Colors {
|
||||||
|
// Lists and stuff
|
||||||
|
public static final int color_found = 0x7f00ff00;
|
||||||
|
public static final int color_rescout = 0xff007fff;
|
||||||
|
public static final int color_not_found = 0x7f7f0000;
|
||||||
|
|
||||||
|
|
||||||
|
public static final int background_color = 0x5000ff00;
|
||||||
|
public static final int unfocused_background_color = 0x50118811;
|
||||||
|
|
||||||
|
|
||||||
|
public static final int unsaved_color = 0xffaa0000;
|
||||||
|
public static final int saved_color = 0xff00aa00;
|
||||||
|
public static final int rescout_color = 0xff007fff;
|
||||||
|
|
||||||
|
|
||||||
|
// Data graphs
|
||||||
|
public static final int chart_background = 0xff252025;
|
||||||
|
public static final int chart_text = Color.WHITE;
|
||||||
|
|
||||||
|
public static final int[] checkbox_colors = {0x7f00ff00, 0x7f7f0000};
|
||||||
|
public static final int checkbox_data_color = Color.RED;;
|
||||||
|
public static final int checkbox_value_text_color = Color.BLACK;
|
||||||
|
|
||||||
|
public static final int dropdown_value_text_1 = Color.BLACK;
|
||||||
|
public static final int dropdown_value_text_2 = Color.RED;
|
||||||
|
|
||||||
|
public static final int fieldpos_data = Color.BLUE;
|
||||||
|
|
||||||
|
|
||||||
|
public static final int number_data = Color.BLUE;
|
||||||
|
|
||||||
|
|
||||||
|
public static final int slider_data = Color.BLUE;
|
||||||
|
|
||||||
|
|
||||||
|
public static final int tally_data = Color.BLUE;
|
||||||
|
|
||||||
|
|
||||||
|
public static final int text_data = Color.BLUE;
|
||||||
|
|
||||||
|
|
||||||
|
// Code scanner
|
||||||
|
public static final int code_scanned_color = Color.GREEN;
|
||||||
|
public static final int code_selected_color = Color.YELLOW;
|
||||||
|
public static final int code_unscanned_color = Color.RED;
|
||||||
|
|
||||||
|
// Toggle title
|
||||||
|
public static final int toggletitle_no_background = 0x00000000;
|
||||||
|
public static final int toggletitle_black_background = 0xff000000;
|
||||||
|
public static final int toggletitle_unselected = 0xffff0000;
|
||||||
|
// public static final int toggletitle_no_background = 0x00000000;
|
||||||
|
|
||||||
|
|
||||||
|
// Data fragment
|
||||||
|
public static final int datafragment_option_1 = 0xff509050;
|
||||||
|
public static final int datafragment_option_2 = 0xff307030;
|
||||||
|
|
||||||
|
|
||||||
|
// fileselector
|
||||||
|
public static final int fileselector_selected_color = 0x5000ff00;
|
||||||
|
public static final int fileselector_unselected_color = 0x50006600;
|
||||||
|
|
||||||
|
// TBA
|
||||||
|
public static final int tba_previous = Color.argb(30, 64,64,64);
|
||||||
|
public static final int tba_current = 0x7f00ff00;
|
||||||
|
public static final int tba_next = Color.argb(30, 192,192,192);
|
||||||
|
public static final int tba_red = 0x50ff0000;
|
||||||
|
public static final int tba_blue = 0x500000ff;
|
||||||
|
public static final int tba_toggle_background = 0x30000000;
|
||||||
|
|
||||||
|
// Candlestick
|
||||||
|
public static final int candlestick_color = Color.GREEN;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user