diff --git a/TODO.md b/TODO.md index 3bd3537..296dd5c 100644 --- a/TODO.md +++ b/TODO.md @@ -4,35 +4,17 @@ ##### Data Analysis: - Statbotics intigration??? ##### Functionality: +- Test new FTP thing +- UUIDs instead of names for the fields +- Fix data storage crashes ### 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 +- "Send Meta Files" button \ No newline at end of file diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/CompareFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/CompareFragment.java deleted file mode 100644 index 3812088..0000000 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/CompareFragment.java +++ /dev/null @@ -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(); - } -} diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/DataFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/DataFragment.java index 84805ba..4c91875 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/DataFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/DataFragment.java @@ -44,8 +44,6 @@ public class DataFragment extends Fragment { binding.buttons.setVisibility(View.VISIBLE); binding.teamsButton.setEnabled(false); - binding.compareButton.setEnabled(false); - binding.reportButton.setEnabled(false); binding.fieldsButton.setVisibility(View.VISIBLE); @@ -65,15 +63,6 @@ public class DataFragment extends Fragment { }); findNavController(this).navigate(R.id.action_navigation_data_to_navigation_team_selector); }); - - binding.compareButton.setOnClickListener(v -> { - findNavController(this).navigate(R.id.action_navigation_data_to_navigation_data_compare); - }); - - binding.reportButton.setOnClickListener(v -> { - findNavController(this).navigate(R.id.action_navigation_data_to_navigation_data_report_selector); - }); - return root; } } \ No newline at end of file diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/ReportFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/ReportFragment.java deleted file mode 100644 index cd45483..0000000 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/ReportFragment.java +++ /dev/null @@ -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()); - } - }); - } -} diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/ReportSelectorFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/ReportSelectorFragment.java deleted file mode 100644 index 2a95899..0000000 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/ReportSelectorFragment.java +++ /dev/null @@ -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); - }); - } -} diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/settings/settingsFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/settings/settingsFragment.java index d6b5d90..7671f18 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/settings/settingsFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/settings/settingsFragment.java @@ -3,6 +3,7 @@ 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.FTPSendMetaFiles; import static com.ridgebotics.ridgescout.utility.settingsManager.FTPServer; import static com.ridgebotics.ridgescout.utility.settingsManager.SelEVCodeKey; import static com.ridgebotics.ridgescout.utility.settingsManager.TeamNumKey; @@ -238,7 +239,11 @@ public class settingsFragment extends Fragment { addViews(addDropdownByString("Alliance Position", alliance_pos_list, AllyPosKey)); addViews(addNumberEdit("Team Number", TeamNumKey)); - View[] FTPDependency = addStringEdit("FTP Server", FTPServer); + View[] FTPDependency = concatArrays( + addCheckbox("Send Meta Files", FTPSendMetaFiles, new View[]{}), + addStringEdit("FTP Server", FTPServer) + ); + View[] WifiDependency = addCheckbox("FTP Enabled", FTPEnabled, FTPDependency); addViews(addCheckbox("Wifi Mode", WifiModeKey, concatArrays(FTPDependency, WifiDependency))); addViews(WifiDependency); diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/FTPSync.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/FTPSync.java index 76a904e..696ae20 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/FTPSync.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/FTPSync.java @@ -1,8 +1,10 @@ package com.ridgebotics.ridgescout.ui.transfer; //import static com.ridgebotics.ridgescout.utility.DataManager.evcode; +import static com.ridgebotics.ridgescout.utility.DataManager.evcode; import static com.ridgebotics.ridgescout.utility.fileEditor.baseDir; +import com.ridgebotics.ridgescout.ui.data.FieldEditorHelper; import com.ridgebotics.ridgescout.utility.AlertManager; import com.ridgebotics.ridgescout.utility.BuiltByteParser; import com.ridgebotics.ridgescout.utility.ByteBuilder; @@ -21,6 +23,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.net.InetAddress; +import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.HashMap; @@ -91,7 +94,17 @@ public class FTPSync extends Thread { public void run() { + boolean sendMetaFiles = settingsManager.getFTPSendMetaFiles(); + + // Meta files + String[] meta_string_array = new String[]{ + "matches.fields", + "pits.fields", + evcode+".eventdata" + }; + try { + // Login to FTP ftpClient = new FTPClient(); InetAddress address = InetAddress.getByName(settingsManager.getFTPServer()); ftpClient.connect(address); @@ -103,10 +116,14 @@ public class FTPSync extends Thread { File[] localFiles = localDir.listFiles(); Map remoteTimestamps = getTimestamps(); + // Loop through local files and send all that are more recent if (localFiles != null) { for (File localFile : localFiles) { if(localFile.isDirectory()) continue; + // Remove timestamts file if(localFile.getName().equals(timestampsFilename)) continue; + // Remove meta files if the option is disabled + if(!sendMetaFiles && Arrays.stream(meta_string_array).anyMatch(localFile.getName()::equals)) continue; Date remoteTimestamp = remoteTimestamps.get(localFile.getName()); diff --git a/app/src/main/java/com/ridgebotics/ridgescout/utility/ollama/OllamaClient.java b/app/src/main/java/com/ridgebotics/ridgescout/utility/ollama/OllamaClient.java deleted file mode 100644 index 14983f1..0000000 --- a/app/src/main/java/com/ridgebotics/ridgescout/utility/ollama/OllamaClient.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.ridgebotics.ridgescout.utility.ollama; - -import androidx.annotation.NonNull; - -import com.ridgebotics.ridgescout.utility.AlertManager; -//import com.ridgebotics.ridgescout.utility.ollama.types.Messages; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.IOException; - -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.MediaType; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; -import okhttp3.ResponseBody; -import okhttp3.OkHttpClient; - -public class OllamaClient { - private static final String MODEL_KEY = "llama3"; - private static final String OLLAMA_URL_KEY = "http://199.204.135.71:11434"; - - private static final String GENERATE_PATH = "/api/generate"; - - public interface ollamaListener { - void onResponse(String response); - void onComplete(); - } - - private static String promptToJson(String prompt){ - - try { - JSONObject jobj = new JSONObject(); - jobj.put("model", "llama3"); - jobj.put("prompt", prompt); - return jobj.toString(); - } catch (JSONException e){ - AlertManager.error(e); - } - return "{}"; - } - - public static void run(String prompt, ollamaListener listener){ -// ChatRequest chatRequest = new ChatRequest(MODEL_KEY, llamaMessages.messages,true); - - RequestBody body = RequestBody.create(promptToJson(prompt), MediaType.parse("application/json")); - - Request request = new Request.Builder() - .url(OLLAMA_URL_KEY+GENERATE_PATH) - .post(body) - .build(); - - new OkHttpClient().newCall(request).enqueue(new Callback() { - @Override - public void onFailure(@NonNull Call call, @NonNull IOException e) { - AlertManager.error(e); - } - - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { - responseStreamer(response, listener); - } - }); - } - - - private static void responseStreamer(Response r, ollamaListener listener){ - String line; - ResponseBody body = r.body(); - if(body == null) - return; - try { - while ((line = body.source().readUtf8Line()) != null) { -// System.out.println(line); - JSONObject json = new JSONObject(line); - - listener.onResponse(json.getString("response")); - if(json.getBoolean("done")) - listener.onComplete(); - } - } catch (IOException | NumberFormatException | IllegalStateException | JSONException e) { -// addMessage(chatResponse,fullResponse.toString(),stopButton,sendButton); - AlertManager.error(e); - } - } -} diff --git a/app/src/main/java/com/ridgebotics/ridgescout/utility/ollama/PromptCreator.java b/app/src/main/java/com/ridgebotics/ridgescout/utility/ollama/PromptCreator.java deleted file mode 100644 index 420f096..0000000 --- a/app/src/main/java/com/ridgebotics/ridgescout/utility/ollama/PromptCreator.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.ridgebotics.ridgescout.utility.ollama; - -import static com.ridgebotics.ridgescout.utility.DataManager.evcode; -import static com.ridgebotics.ridgescout.utility.DataManager.event; -import static com.ridgebotics.ridgescout.utility.DataManager.match_latest_values; -import static com.ridgebotics.ridgescout.utility.DataManager.pit_latest_values; - -import com.ridgebotics.ridgescout.scoutingData.ScoutingDataWriter; -import com.ridgebotics.ridgescout.types.data.dataType; -import com.ridgebotics.ridgescout.types.data.intType; -import com.ridgebotics.ridgescout.types.data.stringType; -import com.ridgebotics.ridgescout.types.frcMatch; -import com.ridgebotics.ridgescout.types.input.dropdownType; -import com.ridgebotics.ridgescout.types.input.inputType; -import com.ridgebotics.ridgescout.types.input.sliderType; -import com.ridgebotics.ridgescout.utility.DataManager; -import com.ridgebotics.ridgescout.utility.fileEditor; - -public class PromptCreator { - private static String fieldSummary(inputType field){ - String summary = field.name + ": "; - switch (field.getInputType()){ - case DROPDOWN: - summary += "The index of a dropdown with the possible options: [" +String.join(", ", ((dropdownType) field).text_options) + "]"; - break; - case SLIDER: - sliderType slider = (sliderType) field; - summary += "A slider with the range ["+slider.min+","+slider.max+"]"; - break; - case TALLY: - summary += "A tally counter"; - break; - case NOTES_INPUT: - summary += "Raw text input"; - break; - } - return summary; - } - - public static String genMatchPrompt(int matchIndex){ - String prompt = "Below is a list of data collected from an FRC match. Generate a qualitative and concise summary of the teams listed, using both numerical and textual data collected in the summary. Additionally, rank the teams in order of their performance.\n\n"; - - frcMatch curmatch = event.matches.get(matchIndex); - - prompt += "## Pit scouting\n"; prompt += "This is a list of the different fields that are present in the pit scouting data:\n"; - - for(int i = 0; i < pit_latest_values.length; i++){ - prompt += (i+1) + ") " + fieldSummary(pit_latest_values[i]) + "\n"; - } - prompt += ("\nData:\n"); - - for(int a = 0; a < 6; a++){ - int teamNum = 0; - if(a < 3) - teamNum = curmatch.redAlliance[a]; - else - teamNum = curmatch.blueAlliance[a-3]; - - prompt += "\nTeam " + teamNum + " pit scout data:\n"; - - String filename = evcode+"-"+teamNum+".pitscoutdata"; - - if (!fileEditor.fileExist(filename)) continue; - - ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.pit_values, DataManager.pit_transferValues); - dataType[] types = psdr.data.array; - for(int i = 0; i < types.length; i++) { - boolean isNull = true; - switch (types[i].getValueType()){ - case NUM: - isNull = intType.isNull((int) types[i].get()); - break; - case STRING: - isNull = stringType.isNull((String) types[i].get()); - break; - } - if(isNull){ - prompt += match_latest_values[i].name + ": null\n"; - }else{ - prompt += match_latest_values[i].name + ": " + types[i].get() + "\n"; - } - } - } - - prompt += "\n## Match scouting\n"; - prompt += "This is a list of the different fields that are present in the match scouting data:\n"; - - for(int i = 0; i < match_latest_values.length; i++){ - prompt += (i+1) + ") " + fieldSummary(match_latest_values[i]) + "\n"; - } - - prompt += ("\nData:\n"); - - for(int a = 0; a < 6; a++){ - int teamNum = 0; - if(a < 3) - teamNum = curmatch.redAlliance[a]; - else - teamNum = curmatch.blueAlliance[a-3]; - - prompt += "\nTeam " + teamNum + " Match scout data for match " + curmatch.matchIndex +":\n"; - - frcMatch[] matchNums = event.getTeamMatches(teamNum); - - for(int b = 0; b < matchNums.length; b++) { - frcMatch match = matchNums[b]; - - String alliance = ""; - int alliancePos = 0; - - for(int c = 0; c < 6; c++) { - if(c<3){ - if(match.redAlliance[c] != teamNum) continue; - alliance = "red"; - alliancePos = c+1; - break; - }else{ - if(match.blueAlliance[c-3] != teamNum) continue; - alliance = "blue"; - alliancePos = c-2; - break; - } - } - - String filename = evcode + "-" + match.matchIndex + "-" + alliance + "-" + alliancePos + "-" + teamNum + ".matchscoutdata"; - - if (!fileEditor.fileExist(filename)) continue; - - ScoutingDataWriter.ParsedScoutingDataResult psdr = ScoutingDataWriter.load(filename, DataManager.match_values, DataManager.match_transferValues); - dataType[] types = psdr.data.array; - for (int i = 0; i < types.length; i++) { - boolean isNull = true; - switch (types[i].getValueType()){ - case NUM: - isNull = intType.isNull((int) types[i].get()); - break; - case STRING: - isNull = stringType.isNull((String) types[i].get()); - break; - } - if(isNull){ - prompt += match_latest_values[i].name + ": null\n"; - }else{ - prompt += match_latest_values[i].name + ": " + types[i].get() + "\n"; - } - } - prompt += "\n"; - } - } - return prompt; - } -} diff --git a/app/src/main/java/com/ridgebotics/ridgescout/utility/settingsManager.java b/app/src/main/java/com/ridgebotics/ridgescout/utility/settingsManager.java index 3a9190c..9278fa3 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/utility/settingsManager.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/utility/settingsManager.java @@ -21,6 +21,7 @@ public class settingsManager { public static final String BtUUIDKey = "bt_uuid"; public static final String FTPEnabled = "ftp_enabled"; public static final String FTPServer = "ftp_server"; + public static final String FTPSendMetaFiles = "ftp_send_meta_files"; public static Map defaults = getDefaults(); private static Map getDefaults(){ @@ -36,6 +37,7 @@ public class settingsManager { hm.put(BtUUIDKey, UUID.randomUUID().toString()); hm.put(FTPEnabled, false); hm.put(FTPServer, "0.0.0.0"); + hm.put(FTPSendMetaFiles, false); return hm; } @@ -57,8 +59,9 @@ public class settingsManager { getEditor() .putString(BtUUIDKey, (String) defaults.get( BtUUIDKey )).apply(); - getEditor().putBoolean(FTPEnabled, (boolean) defaults.get(FTPEnabled )).apply(); - getEditor() .putString(FTPServer, (String) defaults.get( BtUUIDKey )).apply(); + getEditor().putBoolean(FTPEnabled, (boolean) defaults.get( FTPEnabled )).apply(); + getEditor() .putString(FTPServer, (String) defaults.get( FTPServer )).apply(); + getEditor().putBoolean(FTPSendMetaFiles, (boolean) defaults.get( FTPSendMetaFiles )).apply(); } // IDK why I decided to format these functions like this. It looks cool though. @@ -94,6 +97,9 @@ public class settingsManager { public static String getFTPServer(){return prefs.getString( FTPServer, (String) defaults.get(FTPServer));} public static void setFTPServer(String str){ getEditor().putString( FTPServer,str).apply();} + public static boolean getFTPSendMetaFiles(){return prefs.getBoolean(FTPServer, (boolean) defaults.get(FTPServer));} + public static void setFTPSendMetaFiles(String str){getEditor().putString(FTPServer,str).apply();} + } diff --git a/app/src/main/res/layout/fragment_data.xml b/app/src/main/res/layout/fragment_data.xml index a594c04..e41cad9 100644 --- a/app/src/main/res/layout/fragment_data.xml +++ b/app/src/main/res/layout/fragment_data.xml @@ -44,33 +44,10 @@ android:layout_height="wrap_content" android:text="Teams" android:textSize="34sp" - app:layout_constraintBottom_toTopOf="@id/compareButton" + app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/fieldsButton" /> -