mirror of
https://github.com/Team4388/RidgeScout.git
synced 2026-06-09 00:37:59 -06:00
Add CSV exporting
This commit is contained in:
@@ -6,10 +6,10 @@ Ridgebotics 2025 scouting app in Android
|
||||
- Make the "Report" menu, A tool that lets users select data to display from the the teams and compare menus.
|
||||
- Make practice mode
|
||||
#### Data Analysis:
|
||||
- Add CSV exporting of match scouting data.
|
||||
- Statbotics intigration
|
||||
- AI overview of scouting data for a team???
|
||||
#### Functionality:
|
||||
- When a field is created, make updated scouting data return null values, not the default value
|
||||
- Make the system for blank and unselected fields better.
|
||||
- Add more types of data fields.
|
||||
- Make server software to allow for easy sync over wifi
|
||||
@@ -21,7 +21,6 @@ Ridgebotics 2025 scouting app in Android
|
||||
#### Data Analysis:
|
||||
- Make the "Compare" menu, cross comparing team's stats.
|
||||
#### Functionality:
|
||||
- Make pit and match data field builder UIs. I don't want to have to keep editing a variable
|
||||
|
||||
|
||||
## Done:
|
||||
@@ -30,6 +29,7 @@ Ridgebotics 2025 scouting app in Android
|
||||
#### 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.
|
||||
@@ -37,3 +37,4 @@ Ridgebotics 2025 scouting app in Android
|
||||
- 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
|
||||
|
||||
@@ -40,6 +40,15 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -64,12 +64,12 @@ public class ScoutingDataWriter {
|
||||
case 1: // Int
|
||||
dataTypes[i] = intType.newNull(values[version][i].name);
|
||||
dataTypes[i].forceSetValue(objects.get(i+2).get());
|
||||
System.out.println("Loaded INT: " + values[version][i].name + ", ("+ dataTypes[i].get() +")");
|
||||
//System.out.println("Loaded INT: " + values[version][i].name + ", ("+ dataTypes[i].get() +")");
|
||||
break;
|
||||
case 2: // String
|
||||
dataTypes[i] = stringType.newNull(values[version][i].name);
|
||||
dataTypes[i].forceSetValue(objects.get(i+2).get());
|
||||
System.out.println("Loaded STR: " + values[version][i].name + ", ("+ dataTypes[i].get() +")");
|
||||
//System.out.println("Loaded STR: " + values[version][i].name + ", ("+ dataTypes[i].get() +")");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
package com.astatin3.scoutingapp2025.ui.transfer;
|
||||
|
||||
import static com.astatin3.scoutingapp2025.utility.DataManager.evcode;
|
||||
import static com.astatin3.scoutingapp2025.utility.DataManager.event;
|
||||
import static com.astatin3.scoutingapp2025.utility.DataManager.match_latest_values;
|
||||
import static com.astatin3.scoutingapp2025.utility.DataManager.pit_latest_values;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
import com.astatin3.scoutingapp2025.scoutingData.ScoutingDataWriter;
|
||||
import com.astatin3.scoutingapp2025.types.data.dataType;
|
||||
import com.astatin3.scoutingapp2025.types.frcMatch;
|
||||
import com.astatin3.scoutingapp2025.types.frcTeam;
|
||||
import com.astatin3.scoutingapp2025.utility.AlertManager;
|
||||
import com.astatin3.scoutingapp2025.utility.DataManager;
|
||||
import com.astatin3.scoutingapp2025.utility.fileEditor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class CSVExport {
|
||||
private static String[] alliances = {"red", "blue"};
|
||||
|
||||
|
||||
public static void exportMatches(Context c){
|
||||
DataManager.reload_event();
|
||||
DataManager.reload_match_fields();
|
||||
|
||||
String data = "";
|
||||
|
||||
data += ("num,alliance,alliance_position,teamnum,");
|
||||
for(int i = 0; i < match_latest_values.length; i++){
|
||||
data += (match_latest_values[i].name + ",");
|
||||
}
|
||||
data += ("\n");
|
||||
|
||||
|
||||
for(int matchNum = 1; matchNum <= event.matches.size(); matchNum++){
|
||||
for(int allianceIndex = 0; allianceIndex <= 1; allianceIndex++){
|
||||
String alliance = alliances[allianceIndex];
|
||||
for(int alliancePos = 1; alliancePos <= 3; alliancePos++){
|
||||
data += (matchNum + ",");
|
||||
data += (alliance + ",");
|
||||
data += (alliancePos + ",");
|
||||
|
||||
frcMatch match = event.matches.get(matchNum-1);
|
||||
int teamNum = 0;
|
||||
|
||||
if(allianceIndex == 0){
|
||||
teamNum = match.redAlliance[alliancePos-1];
|
||||
}else{
|
||||
teamNum = match.blueAlliance[alliancePos-1];
|
||||
}
|
||||
|
||||
data += (teamNum + ",");
|
||||
|
||||
String filename = evcode+"-"+matchNum+"-"+alliance+"-"+alliancePos+"-"+teamNum+".matchscoutdata";
|
||||
if(!fileEditor.fileExist(filename)){
|
||||
data += ("null,".repeat(match_latest_values.length));
|
||||
}else{
|
||||
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.match_values, DataManager.match_transferValues);
|
||||
dataType[] types = psdr.data.array;
|
||||
for(int i = 0; i < types.length; i++) {
|
||||
data += (types[i].get() + ",");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data += ("\n");
|
||||
}}}
|
||||
|
||||
shareContent(c, evcode+"-matches.csv", data, "text/plain");
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void exportPits(Context c){
|
||||
DataManager.reload_event();
|
||||
DataManager.reload_pit_fields();
|
||||
|
||||
String data = "";
|
||||
|
||||
data += ("teamnum,teamname,city,teamnum,stateOrProv,school,country,startingYear,");
|
||||
for(int i = 0; i < pit_latest_values.length; i++){
|
||||
data += (pit_latest_values[i].name + ",");
|
||||
}
|
||||
data += ("\n");
|
||||
|
||||
|
||||
for(int teamIndex = 0; teamIndex < event.teams.size(); teamIndex++){
|
||||
frcTeam team = event.teams.get(teamIndex);
|
||||
|
||||
data += (team.teamNumber + ",");
|
||||
data += (team.teamName + ",");
|
||||
data += (team.city + ",");
|
||||
data += (team.stateOrProv + ",");
|
||||
data += (team.school + ",");
|
||||
data += (team.country + ",");
|
||||
data += (team.startingYear + ",");
|
||||
|
||||
String filename = evcode+"-"+team.teamNumber+".pitscoutdata";
|
||||
if(!fileEditor.fileExist(filename)){
|
||||
data += ("null,".repeat(pit_latest_values.length));
|
||||
}else{
|
||||
ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.pit_values, DataManager.pit_transferValues);
|
||||
dataType[] types = psdr.data.array;
|
||||
for(int i = 0; i < types.length; i++) {
|
||||
data += (types[i].get() + ",");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data += ("\n");
|
||||
}
|
||||
|
||||
// System.out.print(data);
|
||||
|
||||
shareContent(c, evcode+"-pits.csv", data, "text/plain");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static void shareContent(Context context, String fileName, String content, String mimeType) {
|
||||
try {
|
||||
File file = new File(context.getCacheDir(), fileName);
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
fos.write(content.getBytes());
|
||||
fos.close();
|
||||
|
||||
Uri fileUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", file);
|
||||
|
||||
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||
shareIntent.setType(mimeType);
|
||||
shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
|
||||
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
context.startActivity(Intent.createChooser(shareIntent, "Share using"));
|
||||
} catch (IOException e) {
|
||||
AlertManager.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.astatin3.scoutingapp2025.ui.transfer;
|
||||
import static androidx.navigation.fragment.FragmentKt.findNavController;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@@ -21,14 +22,12 @@ import com.astatin3.scoutingapp2025.ui.transfer.codes.CodeGeneratorView;
|
||||
public class TransferFragment extends Fragment {
|
||||
private FragmentTransferBinding binding;
|
||||
|
||||
private boolean submenu = false;
|
||||
|
||||
private enum TransferTypes {
|
||||
CAMERA,
|
||||
BLUETOOTH,
|
||||
LOCAL_WIFI,
|
||||
SCOUTING_SERVER
|
||||
}
|
||||
// private enum TransferTypes {
|
||||
// CAMERA,
|
||||
// BLUETOOTH,
|
||||
// LOCAL_WIFI,
|
||||
// SCOUTING_SERVER
|
||||
// }
|
||||
|
||||
String evcode;
|
||||
|
||||
@@ -68,6 +67,7 @@ public class TransferFragment extends Fragment {
|
||||
if(evcode.equals("unset")){
|
||||
binding.noEventError.setVisibility(View.VISIBLE);
|
||||
binding.uploadButton.setVisibility(View.GONE);
|
||||
binding.CSVButton.setVisibility(View.GONE);
|
||||
binding.downloadButton.setVisibility(View.VISIBLE);
|
||||
return binding.getRoot();
|
||||
}
|
||||
@@ -76,6 +76,34 @@ public class TransferFragment extends Fragment {
|
||||
start_upload();
|
||||
});
|
||||
|
||||
binding.CSVButton.setOnClickListener(v -> {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle("Chose data");
|
||||
|
||||
builder.setNegativeButton("Pit data", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
CSVExport.exportPits(getContext());
|
||||
}
|
||||
});
|
||||
|
||||
builder.setPositiveButton("Match data", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
CSVExport.exportMatches(getContext());
|
||||
}
|
||||
});
|
||||
|
||||
builder.setNeutralButton("Cancel", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
builder.show();
|
||||
});
|
||||
|
||||
if(!latestSettings.settings.get_wifi_mode())
|
||||
binding.TBAButton.setVisibility(View.GONE);
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@ public class DataManager {
|
||||
public static String evcode;
|
||||
public static frcEvent event;
|
||||
public static void reload_event(){
|
||||
evcode = getevcode(); event = frcEvent.decode(fileEditor.readFile(evcode + ".eventdata"));
|
||||
evcode = getevcode();
|
||||
event = frcEvent.decode(fileEditor.readFile(evcode + ".eventdata"));
|
||||
}
|
||||
|
||||
public static String getevcode() {
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="gone">
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<Button
|
||||
android:id="@+id/uploadButton"
|
||||
@@ -39,6 +38,17 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/CSVButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="CSV"
|
||||
android:textSize="34sp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/downloadButton"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/uploadButton" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/downloadButton"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -13,18 +13,6 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/file_selector_searchbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:background="#D33D3D3D"
|
||||
android:ems="10"
|
||||
android:inputType="text"
|
||||
android:textColor="#FFFFFF"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@@ -47,4 +35,16 @@
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/file_selector_searchbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:background="#D33D3D3D"
|
||||
android:ems="10"
|
||||
android:inputType="text"
|
||||
android:textColor="#FFFFFF"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths>
|
||||
<cache-path name="shared_files" path="/" />
|
||||
</paths>
|
||||
Reference in New Issue
Block a user