Attempt to get F-Droid working

This commit is contained in:
Astatin3
2024-09-15 22:47:45 -06:00
parent 138158e2ee
commit 3f88c9a05e
74 changed files with 372 additions and 366 deletions
@@ -0,0 +1,72 @@
package com.ridgebotics.ridgescout.utility;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.widget.Toast;
import java.io.PrintWriter;
import java.io.StringWriter;
public class AlertManager {
public static Context context;
public static void init(Context c){
context = c;
}
public static void alert(String title, String content) {
((Activity) context).runOnUiThread(new Runnable() {
public void run() {
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setMessage(content);
alert.setTitle(title);
alert.setPositiveButton("OK", null);
alert.setCancelable(true);
alert.create().show();
}
});
}
public static void toast(String content) {
((Activity) context).runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(context, content, Toast.LENGTH_LONG).show();
}
});
}
public static void error(String content) {
((Activity) context).runOnUiThread(new Runnable() {
public void run() {
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(Exception e) {
e.printStackTrace();
((Activity) context).runOnUiThread(new Runnable() {
public void run() {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setMessage(sw.toString());
alert.setTitle(e.getMessage());
alert.setPositiveButton("OK", null);
alert.setCancelable(true);
alert.create().show();
}
});
}
}
@@ -0,0 +1,75 @@
package com.ridgebotics.ridgescout.utility;
import android.os.Handler;
import android.os.Looper;
public class AutoSaveManager {
private static final long AUTO_SAVE_DELAY = 2000; // 2 seconds
private final Handler handler;
private final Runnable autoSaveRunnable;
private boolean isAutoSaveScheduled = false;
private final AutoSaveFunction autoSaveFunction;
public boolean isRunning = false;
// Functional interface for the auto-save function
@FunctionalInterface
public interface AutoSaveFunction {
void save();
}
public AutoSaveManager(AutoSaveFunction autoSaveFunction) {
this.autoSaveFunction = autoSaveFunction;
handler = new Handler(Looper.getMainLooper());
autoSaveRunnable = new Runnable() {
@Override
public void run() {
performAutoSave();
isAutoSaveScheduled = false;
}
};
}
public void start() {
isRunning = true;
}
public void stop() {
isRunning = false;
handler.removeCallbacks(autoSaveRunnable);
isAutoSaveScheduled = false;
}
public void update() {
if (!isRunning) {
return; // Don't schedule auto-saves when not running
}
// Cancel any previously scheduled auto-save
handler.removeCallbacks(autoSaveRunnable);
// Schedule a new auto-save
handler.postDelayed(autoSaveRunnable, AUTO_SAVE_DELAY);
isAutoSaveScheduled = true;
}
private void performAutoSave() {
if (isRunning) {
// Call the provided auto-save function
autoSaveFunction.save();
}
}
public void onDestroy() {
// Remove any pending auto-save tasks when the activity or fragment is destroyed
stop();
}
public boolean isAutoSaveScheduled() {
return isAutoSaveScheduled;
}
public boolean isRunning() {
return isRunning;
}
}
@@ -0,0 +1,159 @@
package com.ridgebotics.ridgescout.utility;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
public class BuiltByteParser {
public static final Integer boolType = 0;
public static final Integer intType = 1;
public static final Integer stringType = 2;
public static final Integer intArrayType = 3;
public static final Integer stringArrayType = 4;
public class byteParsingExeption extends Exception {
public byteParsingExeption() {}
public byteParsingExeption(String message) {
super(message);
}
}
public static String unBlankStrNull(String str){
if(str.equals("ƒ")){
return "";
}
else return str;
}
public abstract class parsedObject {
public abstract Integer getType();
public abstract Object get();
}
public class boolObject extends parsedObject{
boolean val;
public Integer getType(){return boolType;}
public Object get(){return val;}
}
public class intObject extends parsedObject{
int num;
public Integer getType(){return intType;}
public Object get(){return num;}
}
public class stringObject extends parsedObject{
String str;
public Integer getType(){return stringType;}
public Object get(){return str;}
}
public class intArrayObject extends parsedObject{
int[] arr;
public Integer getType(){return intArrayType;}
public Object get(){return arr;}
}
public class stringArrayObject extends parsedObject{
String[] arr;
public Integer getType(){return stringArrayType;}
public Object get(){return arr;}
}
public class rawObject extends parsedObject {
private int type;
public rawObject(int type){this.type = type;}
byte[] bytes;
public Integer getType(){return type;}
public Object get(){return bytes;}
}
byte[] bytes;
ArrayList<parsedObject> objects = new ArrayList<>();
public BuiltByteParser(byte[] bytes){
this.bytes = bytes;
}
public ArrayList<parsedObject> parse() throws byteParsingExeption {
if(bytes.length < 3){throw new byteParsingExeption("Invalid length");}
int curIndex = 0;
while(true){
// Log.i("t", String.valueOf(curIndex));
final int length = fileEditor.fromBytes(fileEditor.getByteBlock(bytes, curIndex, curIndex+2), 2);
final int type = bytes[curIndex+2] & 0xFF;
if(length == 0){
curIndex += 3;
continue;
}
final byte[] block;
try {
block = fileEditor.getByteBlock(bytes, curIndex + 3, curIndex + length + 3);
} catch(Exception e){
throw new byteParsingExeption("Array out of bounds");
}
switch(type){
case 0:
boolObject bo = new boolObject();
bo.val = block[0] == (byte) 1;
objects.add(bo);
break;
case 1:
intObject io = new intObject();
io.num = fileEditor.fromBytes(block, length);
objects.add(io);
break;
case 2:
stringObject so = new stringObject();
so.str = unBlankStrNull(new String(block, StandardCharsets.UTF_8));
objects.add(so);
break;
case 3:
BuiltByteParser int_bbp = new BuiltByteParser(block);
ArrayList<parsedObject> intArrayObjects = int_bbp.parse();
int[] intArr = new int[intArrayObjects.size()];
for(int i = 0; i < intArrayObjects.size(); i ++){
intArr[i] = (int) intArrayObjects.get(i).get();
}
intArrayObject ia = new intArrayObject();
ia.arr = intArr;
objects.add(ia);
break;
case 4:
BuiltByteParser str_bbp = new BuiltByteParser(block);
ArrayList<parsedObject> strArrayObjects = str_bbp.parse();
String[] StringArr = new String[strArrayObjects.size()];
for(int i = 0; i < strArrayObjects.size(); i ++){
StringArr[i] = (String) strArrayObjects.get(i).get();
}
stringArrayObject sa = new stringArrayObject();
sa.arr = StringArr;
objects.add(sa);
break;
default:
rawObject ro = new rawObject(type);
ro.bytes = block;
objects.add(ro);
break;
}
curIndex += length + 3;
if(curIndex == bytes.length){
break;
}else if(curIndex > bytes.length){
throw new byteParsingExeption("Block length problem");
}
}
return objects;
}
}
@@ -0,0 +1,214 @@
package com.ridgebotics.ridgescout.utility;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
public class ByteBuilder {
public static final int bool_id = 0;
public static final int int_id = 1;
public static final int string_id = 2;
public static final int int_arr_id = 3;
public static final int string_arr_id = 4;
ArrayList<byteType> bytesToBuild = new ArrayList<>();
public class buildingException extends Exception {
public buildingException() {}
public buildingException(String message) {
super(message);
}
}
private abstract static class byteType {
public abstract byte getType();
public abstract int length();
public abstract byte[] build();
}
public static String blankStrNull(String str){
if(str.isEmpty() || str.isEmpty()){
return "ƒ";
}
else return str;
}
private class boolType extends byteType {
public boolean val;
public byte getType(){return bool_id;}
public int length(){return 1;}
public byte[] build(){
return new byte[]{(byte) (val ? 1 : 0)};
}
}
public ByteBuilder addBool(boolean n) throws buildingException {
boolType boolType = new boolType();
boolType.val = n;
bytesToBuild.add(boolType);
return this;
}
private class intType extends byteType {
public int precision;
public int num;
public byte getType(){return int_id;}
public int length(){return precision;}
public byte[] build(){
return fileEditor.toBytes(num, precision);
}
}
private int getLeastBytePrecision(int num){
if(num <= 1){return 1;}
return (int) Math.ceil(Math.log(Math.abs(num))/Math.log(8));
}
public ByteBuilder addInt(int num) throws buildingException {
// Get closest number of bytes
int precision = getLeastBytePrecision(num);
return addInt(num, precision);
}
public ByteBuilder addInt(int num, int precision) throws buildingException {
if(precision <= 0){throw new buildingException("Invalid precision: " + precision);}
if(precision > 65536){throw new buildingException("Precision too large (greter than 65536)");}
if(precision < getLeastBytePrecision(num)){throw new buildingException("Precision too small");}
if(num > Integer.MAX_VALUE){throw new buildingException("Integer overflow");}
if(num < Integer.MIN_VALUE){throw new buildingException("Integer overflow");}
intType intType = new intType();
intType.num = num;
intType.precision = precision;
bytesToBuild.add(intType);
return this;
}
private class stringType extends byteType {
public byte[] bytes;
public byte getType(){return string_id;}
public int length(){return bytes.length;}
public byte[] build(){
return bytes;
// return str.getBytes(charset);
}
}
public ByteBuilder addString(String str) throws buildingException {
str = blankStrNull(str);
if(str.length() > 65536){throw new buildingException("String too long (greater than 65536)");}
stringType stringType = new stringType();
// To get the length correctly, the string bytes need to be precalculated
stringType.bytes = str.getBytes(StandardCharsets.UTF_8);
bytesToBuild.add(stringType);
return this;
}
private class intArrayType extends byteType {
public byte[] bytes;
public byte getType(){return int_arr_id;}
public int length(){return bytes.length;}
public byte[] build(){
return bytes;
// return str.getBytes(charset);
}
}
public ByteBuilder addIntArray(int[] arr) throws buildingException {
intArrayType intArrayType = new intArrayType();
ByteBuilder bb = new ByteBuilder();
for(int i = 0; i < arr.length; i++){
bb.addInt(arr[i]);
}
intArrayType.bytes = bb.build();
bytesToBuild.add(intArrayType);
return this;
}
private class stringArrayType extends byteType {
public byte[] bytes;
public byte getType(){return string_arr_id;}
public int length(){return bytes.length;}
public byte[] build(){
return bytes;
// return str.getBytes(charset);
}
}
public ByteBuilder addStringArray(String[] arr) throws buildingException {
stringArrayType stringArrayType = new stringArrayType();
ByteBuilder bb = new ByteBuilder();
for(int i = 0; i < arr.length; i++){
bb.addString(arr[i]);
}
stringArrayType.bytes = bb.build();
bytesToBuild.add(stringArrayType);
return this;
}
private class rawType extends byteType {
public int type;
public byte[] bytes;
public byte getType(){return (byte) type;}
public int length(){return bytes.length;}
public byte[] build(){
return bytes;
}
}
public ByteBuilder addRaw(int type, byte[] bytes) throws buildingException {
if(bytes.length > 65536){throw new buildingException("Byte array length to long (greater than 65536)");}
rawType rawType = new rawType();
rawType.type = type;
rawType.bytes = bytes;
bytesToBuild.add(rawType);
return this;
}
public byte[] build() throws buildingException {
if(bytesToBuild.size() == 0){throw new buildingException("Cannot build null data");}
int length = bytesToBuild.size() * 3;
for(byteType bt : bytesToBuild){
length += bt.length();
}
byte[] bytes = new byte[length];
int bytesFilled = 0;
for(byteType bt : bytesToBuild){
byte[] blockLength = fileEditor.toBytes(bt.length(), 2);
bytes[bytesFilled] = blockLength[0];
bytesFilled += 1;
bytes[bytesFilled] = blockLength[1];
bytesFilled += 1;
bytes[bytesFilled] = bt.getType();
bytesFilled += 1;
// if(bt.length == 0)
// continue;
int i = 1;
byte[] newBytes = bt.build();
for(byte b : newBytes){
// Log.i("i", (bytesFilled+1) + "/" + length + " (" + i + "/" + bt.length() + ")");
bytes[bytesFilled] = b;
bytesFilled += 1;
i++;
}
}
return bytes;
}
}
@@ -0,0 +1,38 @@
package com.ridgebotics.ridgescout.utility;
import com.ridgebotics.ridgescout.SettingsVersionStack.latestSettings;
import com.ridgebotics.ridgescout.scoutingData.fields;
import com.ridgebotics.ridgescout.scoutingData.transfer.transferType;
import com.ridgebotics.ridgescout.types.frcEvent;
import com.ridgebotics.ridgescout.types.input.inputType;
public class DataManager {
public static String evcode;
public static frcEvent event;
public static void reload_event(){
evcode = getevcode();
event = frcEvent.decode(fileEditor.readFile(evcode + ".eventdata"));
}
public static String getevcode() {
return latestSettings.settings.get_evcode();
}
public static inputType[][] match_values;
public static inputType[] match_latest_values;
public static transferType[][] match_transferValues;
public static void reload_match_fields(){
match_values = fields.load(fields.matchFieldsFilename);
match_latest_values = match_values[match_values.length-1];
match_transferValues = transferType.get_transfer_values(match_values);
}
public static inputType[][] pit_values;
public static inputType[] pit_latest_values;
public static transferType[][] pit_transferValues;
public static void reload_pit_fields(){
pit_values = fields.load(fields.pitsFieldsFilename);
pit_latest_values = pit_values[pit_values.length-1];
pit_transferValues = transferType.get_transfer_values(pit_values);
}
}
@@ -0,0 +1,23 @@
package com.ridgebotics.ridgescout.utility;
import org.json.JSONArray;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class JSONUtil {
public static JSONArray sort(JSONArray array, Comparator c){
List asList = new ArrayList(array.length());
for (int i=0; i<array.length(); i++){
asList.add(array.opt(i));
}
asList.sort(c);
JSONArray res = new JSONArray();
for (Object o : asList){
res.put(o);
}
return res;
}
}
@@ -0,0 +1,158 @@
package com.ridgebotics.ridgescout.utility;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import android.view.MotionEvent;
import android.widget.TableLayout;
public class ReorderableTableLayout extends TableLayout {
private boolean reorderingEnabled = false;
private int draggedRowIndex = -1;
private float lastY;
private List<View> rows;
private List<Integer> reorderedIndices;
private int rowHeight;
public ReorderableTableLayout(Context context) {
super(context);
init();
}
public ReorderableTableLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
rows = new ArrayList<>();
reorderedIndices = new ArrayList<>();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (!reorderingEnabled) {
return super.onInterceptTouchEvent(ev);
}
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
lastY = ev.getY();
draggedRowIndex = getRowIndexAtY(lastY);
if (draggedRowIndex != -1) {
View draggedRow = getChildAt(draggedRowIndex);
rowHeight = draggedRow.getHeight();
saveOriginalOrder();
return true;
}
break;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public void addView(View child) {
super.addView(child);
reorderedIndices.add(reorderedIndices.size());
}
@Override
public void removeAllViews() {
super.removeAllViews();
reorderedIndices.clear();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!reorderingEnabled || draggedRowIndex == -1) {
return super.onTouchEvent(event);
}
float currentY = event.getY();
int targetIndex = getRowIndexAtY(currentY);
View child = getChildAt(targetIndex);
if(child != null)
getChildAt(targetIndex).callOnClick();
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
if (targetIndex != -1 && targetIndex != draggedRowIndex) {
updateRowOrder(draggedRowIndex, targetIndex);
draggedRowIndex = targetIndex;
}
lastY = currentY;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
draggedRowIndex = -1;
break;
}
return true;
}
private int getRowIndexAtY(float y) {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (y >= child.getTop() && y <= child.getBottom()) {
return i;
}
}
return -1;
}
private void saveOriginalOrder() {
rows.clear();
for (int i = 0; i < getChildCount(); i++) {
rows.add(getChildAt(i));
}
}
public void updateRowOrder(int fromIndex, int toIndex) {
saveOriginalOrder();
if (fromIndex < toIndex) {
for (int i = fromIndex; i < toIndex; i++) {
Collections.swap(rows, i, i + 1);
Collections.swap(reorderedIndices, i, i + 1);
}
} else {
for (int i = fromIndex; i > toIndex; i--) {
Collections.swap(rows, i, i - 1);
Collections.swap(reorderedIndices, i, i - 1);
}
}
removeAllViewsInLayout();
for (View view : rows) {
addViewInLayout(view, -1, view.getLayoutParams(), true);
}
requestLayout();
invalidate();
}
public void setReorderingEnabled(boolean enabled) {
reorderingEnabled = enabled;
}
public List<Integer> getReorderedIndexes() {
return reorderedIndices;
}
public void removeElement(int unshuffledindex){
System.out.println(Arrays.toString(new List[]{reorderedIndices}));
reorderedIndices.remove(unshuffledindex);
for (int i = 0; i < reorderedIndices.size(); i++) {
if(reorderedIndices.get(i) > unshuffledindex)
reorderedIndices.set(i, reorderedIndices.get(i) - 1);
}
System.out.println(Arrays.toString(new List[]{reorderedIndices}));
}
}
@@ -0,0 +1,77 @@
package com.ridgebotics.ridgescout.utility;
import android.os.AsyncTask;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.function.Function;
import javax.net.ssl.HttpsURLConnection;
public class RequestTask extends AsyncTask<String, String, String> {
private Function<String, String> resultFunction = null;
@Override
protected String doInBackground(String... uri) {
try {
URL url = new URL(uri[0]);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
String[] headers = uri[1].split(", ");
for(String header : headers){
String[] split = header.split(": ");
conn.setRequestProperty(split[0], split[1]);
}
if(conn.getResponseCode() == HttpsURLConnection.HTTP_OK){
// ByteArrayOutputStream out = new ByteArrayOutputStream();
return readStream(conn.getInputStream());
// Do normal input or output stream reading
}
else {
return null; // See documentation for more info on response handling
}
} catch (IOException e) {
AlertManager.error(e);
}
return null;
}
private static String readStream(InputStream in) {
BufferedReader reader = null;
StringBuilder response = new StringBuilder();
try {
reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
} catch (IOException e) {
AlertManager.error(e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
AlertManager.error(e);
}
}
}
return response.toString();
}
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);
}
}
}
@@ -0,0 +1,55 @@
package com.ridgebotics.ridgescout.utility;
import android.content.Context;
import org.tensorflow.lite.support.label.Category;
import org.tensorflow.lite.task.text.nlclassifier.NLClassifier;
import java.util.List;
public class SentimentAnalysis {
private static NLClassifier textClassifier;
public static void init(Context context){
try {
textClassifier = NLClassifier.createFromFile(context, "text_classification_v2.tflite");
} catch (Exception e) {
AlertManager.error(e);
}
}
public interface resultCallback {
public void onFinish(float data);
}
public static void analyse(String input, resultCallback result){
new Thread(new Runnable() {
@Override
public void run() {
List<Category> results = textClassifier.classify(input);
for(int i = 0; i < results.size(); i++){
Category cat = results.get(i);
switch (cat.getLabel()){
case "Positive":
result.onFinish(cat.getScore());
break;
}
}
}
}).start();
}
public static float analyse_sync(String input){
List<Category> results = textClassifier.classify(input);
for(int i = 0; i < results.size(); i++){
Category cat = results.get(i);
switch (cat.getLabel()){
case "Positive":
return cat.getScore();
}
}
return 0;
}
}
@@ -0,0 +1,37 @@
package com.ridgebotics.ridgescout.utility;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import androidx.core.content.FileProvider;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class SharePrompt {
public static void shareContent(Context context, String fileName, String content, String mimeType) {
shareContent(context, fileName, content.getBytes(), mimeType);
}
public static void shareContent(Context context, String fileName, byte[] content, String mimeType) {
try {
File file = new File(context.getCacheDir(), fileName);
FileOutputStream fos = new FileOutputStream(file);
fos.write(content);
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);
}
}
}
@@ -0,0 +1,371 @@
package com.ridgebotics.ridgescout.utility;
import android.content.Context;
import com.ridgebotics.ridgescout.types.frcEvent;
import com.ridgebotics.ridgescout.types.frcTeam;
import com.ridgebotics.ridgescout.SettingsVersionStack.latestSettings;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
public final class fileEditor {
private final static String baseDir = "/data/data/com.ridgebotics.ridgescout/";
public static final byte internalDataVersion = 0x01;
public static final int maxCompressedBlockSize = 4096;
public static String binaryVisualize(byte[] bytes){
String returnStr = "";
for (byte aByte : bytes) {
for (int b = 7; b >= 0; b--) {
returnStr += String.valueOf((aByte >> b) & 1);
}
returnStr += " (" + (int) aByte + ")\n";
}
return returnStr;
}
public static char byteToChar(int num){
return new String(toBytes(num, 1), StandardCharsets.ISO_8859_1).charAt(0);
}
public static byte[] toBytes(int num, int byteCount){
if(num > (Math.pow(2,byteCount*8)-1)){
throw new BufferOverflowException();
}
byte[] bytes = new byte[byteCount];
for(int i=0;i<byteCount;i++){
bytes[i] = (byte)(num >> (i*8));
}
return bytes;
}
public static int fromBytes(byte[] bytes, int byteCount){
int returnInt = 0;
for(int i=0;i<byteCount;i++){
returnInt |= (bytes[i] & 0xFF) << (i*8);
}
return returnInt;
}
public static int byteFromChar(char c){
byte[] bytes = (String.valueOf(c)).getBytes(Charset.defaultCharset());
return Byte.toUnsignedInt(bytes[0]);
}
public static byte[] getByteBlock(byte[] bytes, int start, int end){
end = Math.min(end, bytes.length);
byte[] dataBlock = new byte[end-start];
for(int a=start;a<end;a++){
// Log.i("test", start+", "+a+", "+end);
dataBlock[a-start] = bytes[a];
}
return dataBlock;
}
public static byte[] compress(byte[] input) {
Deflater deflater = new Deflater();
deflater.setInput(input);
deflater.finish();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[maxCompressedBlockSize];
while (!deflater.finished()) {
int compressedSize = deflater.deflate(buffer);
outputStream.write(buffer, 0, compressedSize);
}
return outputStream.toByteArray();
}
public static byte[] blockCompress(byte[] inputData) {
List<byte[]> compiledData = new ArrayList<>();
for(int i=0;i<Math.ceil((double) inputData.length / fileEditor.maxCompressedBlockSize);i++){
final int start = i*fileEditor.maxCompressedBlockSize;
int end = ((i+1)*fileEditor.maxCompressedBlockSize);
if(end > inputData.length) {
end = inputData.length;
}
byte[] dataBlock = fileEditor.getByteBlock(inputData, start, end);
final byte[] compressedBlock = fileEditor.compress(dataBlock);
compiledData.add(fileEditor.toBytes(compressedBlock.length, 2));
compiledData.add(compressedBlock);
}
return combineByteArrays(compiledData);
}
public static byte[] blockUncompress(byte[] data) throws DataFormatException {
List<byte[]> uncompressedData = new ArrayList<>();
int curIndex = 0;
while (curIndex < data.length) {
final int blockLength = fileEditor.fromBytes(fileEditor.getByteBlock(data, curIndex, curIndex + 2), 2);
uncompressedData.add(
decompress(
fileEditor.getByteBlock(data, curIndex + 2, curIndex + blockLength + 2)
)
);
curIndex += blockLength + 2;
}
return combineByteArrays(uncompressedData);
}
public static byte[] decompress(byte[] input) throws DataFormatException {
Inflater inflater = new Inflater();
inflater.setInput(input);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[maxCompressedBlockSize];
while (inflater.getRemaining() > 0) {
int decompressedSize = inflater.inflate(buffer);
if (decompressedSize == 0) {
break;
}
outputStream.write(buffer, 0, decompressedSize);
}
return outputStream.toByteArray();
}
public static byte[] combineByteArrays(List<byte[]> arrayList) {
// Calculate the total length of the combined array
int totalLength = arrayList.stream()
.mapToInt(array -> array.length)
.sum();
// Create a new byte array with the total length
byte[] result = new byte[totalLength];
// Copy each array into the result array
int offset = 0;
for (byte[] array : arrayList) {
System.arraycopy(array, 0, result, offset, array.length);
offset += array.length;
}
return result;
}
public static boolean writeFile(String filepath, byte[] data) {
try {
FileOutputStream output = new FileOutputStream(baseDir + filepath);
output.write(data);
output.close();
return true;
}
catch (IOException e) {
AlertManager.error(e);
return false;
}
}
public static boolean createFile(String filepath){
if(fileExist(filepath)){
return true;
}
try {
File file = new File(baseDir + filepath);
return file.createNewFile();
}
catch (IOException e) {
AlertManager.error(e);
return false;
}
}
public static boolean fileExist(String path){
File f = new File(baseDir + path);
return f.exists() && !f.isDirectory();
}
public static byte[] readFile(String path){
return readFileExact(baseDir + path);
}
public static byte[] readFileExact(String path){
File file = new File(path);
int size = (int) file.length();
byte[] bytes = new byte[size];
try {
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file));
buf.read(bytes, 0, bytes.length);
buf.close();
return bytes;
} catch (FileNotFoundException e) {
AlertManager.error(e);
return null;
} catch (IOException e) {
AlertManager.error(e);
return null;
}
}
private static String intSplit(int[] intArr, String splitStr){
String returnStr = "";
for(int i=0;i<intArr.length;i++){
returnStr += String.valueOf(intArr[i]);
if(i != intArr.length-1){
returnStr += splitStr;
}
}
return returnStr;
}
public static boolean setEvent(frcEvent event){
final String filename = (event.eventCode + ".eventdata");
if(latestSettings.settings.get_evcode().equals("unset")){
latestSettings.settings.set_evcode(event.eventCode);
}
return writeFile(filename, event.encode());
}
public static ArrayList<String> getEventList(){
File f = new File(baseDir);
File[] files = f.listFiles();
ArrayList<String> outFiles = new ArrayList<>();
if(files == null){return outFiles;}
for (File file : files) {
if(!file.isDirectory() && file.getName().endsWith(".eventdata")) {
outFiles.add(file.getName().substring(0,file.getName().length()-10));
}
}
Collections.sort(outFiles);
return outFiles;
}
public static String[] getMatchesByTeamNum(String evcode, int teamNum){
File f = new File(baseDir);
File[] files = f.listFiles();
ArrayList<String> outFiles = new ArrayList<>();
if(files == null){return new String[0];}
for (File file : files) {
String name = file.getName();
if(!file.isDirectory() && name.startsWith(evcode+"-") && name.endsWith("-"+teamNum+".matchscoutdata")) {
outFiles.add(file.getName());
}
}
String[] filenames = outFiles.toArray(new String[0]);
Arrays.sort(filenames, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return Integer.valueOf(o1.split("-")[1]).compareTo(Integer.valueOf(o2.split("-")[1]));
}
});
return filenames;
}
public static String[] getEventFiles(String evcode){
File f = new File(baseDir);
File[] files = f.listFiles();
if(files == null){return new String[0];}
ArrayList<String> outFiles = new ArrayList<>();
outFiles.add("matches.fields");
outFiles.add("pits.fields");
// outFiles.add(evcode + ".eventdata");
for (File file : files) {
String name = file.getName();
if(!file.isDirectory() && name.startsWith(evcode)) {
outFiles.add(file.getName());
}
}
String[] filenames = outFiles.toArray(new String[0]);
Arrays.sort(filenames, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
try {
if(!o1.contains("-") || !o2.contains("-"))
return 0;
return Integer.valueOf(o1.split("-")[1]).compareTo(Integer.valueOf(o2.split("-")[1]));
} catch (Exception e){
return 0;
}
}
});
return filenames;
}
public static boolean setTeams(Context context, String key, ArrayList<frcTeam> teams){
return true;
}
}