mirror of
https://github.com/Team4388/RidgeScout.git
synced 2026-06-09 08:38:03 -06:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 76a1b1ff70 | |||
| 82465f213f | |||
| 3c7a879f51 | |||
| 3157de62ff | |||
| 5ddc032be9 |
Vendored
BIN
Binary file not shown.
@@ -25,8 +25,8 @@ android {
|
|||||||
applicationId = "com.ridgebotics.ridgescout"
|
applicationId = "com.ridgebotics.ridgescout"
|
||||||
minSdk = 24
|
minSdk = 24
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 12 // **IMPORTANT** Increment this before releasing on github
|
versionCode = 15 // **IMPORTANT** Increment this before releasing on github
|
||||||
versionName = "2.0"// **IMPORTANT** Change this before releasing on github (<Year num since 2024>.<Update Version>)
|
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"
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
@@ -47,11 +47,13 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
// Load default match fields
|
// Load default match fields
|
||||||
if(!FileEditor.fileExist(Fields.matchFieldsFilename)){
|
if(!FileEditor.fileExist(Fields.matchFieldsFilename)){
|
||||||
Fields.save(Fields.matchFieldsFilename, Fields.default_match_fields);
|
Fields.save(Fields.matchFieldsFilename, Fields.default_match_fields);
|
||||||
|
FileEditor.toTheArchaicPeriod(Fields.matchFieldsFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load default pit fields
|
// Load default pit fields
|
||||||
if(!FileEditor.fileExist(Fields.pitsFieldsFilename)){
|
if(!FileEditor.fileExist(Fields.pitsFieldsFilename)){
|
||||||
Fields.save(Fields.pitsFieldsFilename, Fields.default_pit_fields);
|
Fields.save(Fields.pitsFieldsFilename, Fields.default_pit_fields);
|
||||||
|
FileEditor.toTheArchaicPeriod(Fields.pitsFieldsFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get time zone for FTP file transfer
|
// get time zone for FTP file transfer
|
||||||
|
|||||||
@@ -30,36 +30,7 @@ public class Fields {
|
|||||||
|
|
||||||
public static final FieldType[][] default_match_fields = new FieldType[][] {
|
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}),
|
new FieldposType(uuid(),"Auto start pos", "Where does the robot start its auto?", new int[]{0,0})
|
||||||
|
|
||||||
new TallyType(uuid(),"Auto L4 Coral", "How many coral did this robot score in L4 during auto?", 0),
|
|
||||||
new TallyType(uuid(),"Auto L3 Coral", "How many coral did this robot score in L3 during auto?", 0),
|
|
||||||
new TallyType(uuid(),"Auto L2 Coral", "How many coral did this robot score in L2 during auto?", 0),
|
|
||||||
new TallyType(uuid(),"Auto L1/Trough Coral", "How many coral did this robot score in L1 during auto?", 0),
|
|
||||||
new TallyType(uuid(),"Auto Processor Algae", "How many algae did this robot score in the Barge during auto?", 0),
|
|
||||||
new TallyType(uuid(),"Auto Barge Algae", "How many algae did this robot score in the Barge during auto?", 0),
|
|
||||||
|
|
||||||
new DropdownType(uuid(),"Auto Quality", "How did the robot drive during auto?", new String[]{"Smooth", "Jittery"}, 0),
|
|
||||||
new TextType(uuid(),"Auto Comments", "Anything interesting about auto", ""),
|
|
||||||
|
|
||||||
new TallyType(uuid(),"Teleop L4 Coral", "How many coral did this robot score in L4 during auto?", 0),
|
|
||||||
new TallyType(uuid(),"Teleop L3 Coral", "How many coral did this robot score in L3 during auto?", 0),
|
|
||||||
new TallyType(uuid(),"Teleop L2 Coral", "How many coral did this robot score in L2 during auto?", 0),
|
|
||||||
new TallyType(uuid(),"Teleop L1 Coral", "How many coral did this robot score in L1 during auto?", 0),
|
|
||||||
new TallyType(uuid(),"Teleop Processor Algae", "How many algae did this robot score in the Barge during auto?", 0),
|
|
||||||
new TallyType(uuid(),"Teleop Barge Algae", "How many algae did this robot score in the Barge during auto?", 0),
|
|
||||||
|
|
||||||
new CheckboxType(uuid(),"Upper Algae Removal", "Did the robot remove upper Algae?", 0),
|
|
||||||
new CheckboxType(uuid(),"Lower Algae Removal", "Did the robot remove lower Algae?", 0),
|
|
||||||
|
|
||||||
new DropdownType(uuid(),"Teleop Quality", "How did the robot drive during Teleop?", new String[]{"Smooth", "Jittery"}, 0),
|
|
||||||
new TextType(uuid(),"Teleop Comments", "Anything interesting about Teleop", ""),
|
|
||||||
|
|
||||||
new DropdownType(uuid(),"Climb State", "What was the final condition of the robot?", new String[]{"Nothing", "Continued Cycling", "Park", "Attempted Shallow", "Shallow", "Attempted Deep", "Deep"}, 0),
|
|
||||||
|
|
||||||
new DropdownType(uuid(),"Robot Condition", "Was anything broken?", new String[]{"Everything was working", "Something was maybe broken", "Something was broken", "Robot was disabled for part of the match", "Missing robot"}, 0),
|
|
||||||
|
|
||||||
new TextType(uuid(),"Other Comments", "Any other comments you have", "")
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -69,14 +40,6 @@ public class Fields {
|
|||||||
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 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(),"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(),"Score Area", "What does this robot score?", new String[]{"Only Algae", "Mostly Algae", "Both", "Mostly Coral", "Only Coral"}, 0),
|
|
||||||
|
|
||||||
new CheckboxType(uuid(),"L4 Scoring", "Will the robot score in Layer 4?", 0),
|
|
||||||
new CheckboxType(uuid(),"L3 Scoring", "Will the robot score in Layer 3?", 0),
|
|
||||||
new CheckboxType(uuid(),"L2 Scoring", "Will the robot score in Layer 3?", 0),
|
|
||||||
new CheckboxType(uuid(),"L1/Trough Scoring", "Will the robot score in Layer 1?", 0),
|
|
||||||
new CheckboxType(uuid(),"Processor Scoring", "Will the robot score in the Processor?", 0),
|
|
||||||
new CheckboxType(uuid(),"Barge Scoring", "Will the robot score algae in the Barge?", 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 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 TextType(uuid(),"Auto Capability", "What autos does this team have?", ""),
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ public class DropdownType extends FieldType {
|
|||||||
.layout_match_wrap()
|
.layout_match_wrap()
|
||||||
.padding(20)
|
.padding(20)
|
||||||
.size(18)
|
.size(18)
|
||||||
.align_center()
|
.align_left()
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ public class NumberType extends FieldType {
|
|||||||
if(data.isNull()) return;
|
if(data.isNull()) return;
|
||||||
parent.addView(new TextViewBuilder(parent.getContext(), String.valueOf((int) data.get()))
|
parent.addView(new TextViewBuilder(parent.getContext(), String.valueOf((int) data.get()))
|
||||||
.layout_match_wrap()
|
.layout_match_wrap()
|
||||||
.align_center()
|
.align_left()
|
||||||
.size(24)
|
.size(24)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class TallyType extends FieldType {
|
|||||||
if(data.isNull()) return;
|
if(data.isNull()) return;
|
||||||
parent.addView(new TextViewBuilder(parent.getContext(), String.valueOf((int) data.get()))
|
parent.addView(new TextViewBuilder(parent.getContext(), String.valueOf((int) data.get()))
|
||||||
.layout_match_wrap()
|
.layout_match_wrap()
|
||||||
.align_center()
|
.align_left()
|
||||||
.size(24)
|
.size(24)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ public class TextType extends FieldType {
|
|||||||
if(data.isNull()) return;
|
if(data.isNull()) return;
|
||||||
parent.addView(new TextViewBuilder(parent.getContext(), (String) data.get())
|
parent.addView(new TextViewBuilder(parent.getContext(), (String) data.get())
|
||||||
.layout_match_wrap()
|
.layout_match_wrap()
|
||||||
.align_center()
|
.align_left()
|
||||||
.size(18)
|
.size(18)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ 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.content.Intent;
|
||||||
|
import android.graphics.Paint;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
@@ -221,19 +222,18 @@ public class TeamsFragment extends Fragment {
|
|||||||
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[matchIndex], match_values, match_transferValues);
|
ScoutingDataWriter.ParsedScoutingDataResult psda = ScoutingDataWriter.load(files[matchIndex], match_values, match_transferValues);
|
||||||
|
|
||||||
|
|
||||||
binding.matchArea.addView(
|
TextView title = new TextViewBuilder(getContext(),
|
||||||
new TextViewBuilder(getContext(), "M" + (match_num) + " " + split[2] + "-" + split[3] + " by " + psda.username)
|
"M" + (match_num) + " " + split[2] + "-" + split[3] + " by " + psda.username)
|
||||||
.align_center()
|
.align_center()
|
||||||
.size(30)
|
.size(30)
|
||||||
.padding(0, 0, 40, 5)
|
.padding(0, 0, 40, 5)
|
||||||
.build()
|
.build();
|
||||||
|
title.setPaintFlags(title.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
|
||||||
);
|
binding.matchArea.addView(title);
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < psda.data.array.length; i++) {
|
for (int i = 0; i < psda.data.array.length; i++) {
|
||||||
TextViewBuilder tv = new TextViewBuilder(getContext(), match_latest_values[i].name)
|
TextViewBuilder tv = new TextViewBuilder(getContext(), match_latest_values[i].name)
|
||||||
.align_center()
|
.align_left()
|
||||||
.size(25);
|
.size(25);
|
||||||
|
|
||||||
if (psda.data.array[i].isNull()) {
|
if (psda.data.array[i].isNull()) {
|
||||||
@@ -282,6 +282,7 @@ public class TeamsFragment extends Fragment {
|
|||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
if(data[i] != null)
|
if(data[i] != null)
|
||||||
match_latest_values[i].add_compiled_view(binding.matchArea, data[i]);
|
match_latest_values[i].add_compiled_view(binding.matchArea, data[i]);
|
||||||
}
|
}
|
||||||
@@ -307,13 +308,13 @@ public class TeamsFragment extends Fragment {
|
|||||||
|
|
||||||
for(int i = 0; i < match_latest_values.length; i++){
|
for(int i = 0; i < match_latest_values.length; i++){
|
||||||
|
|
||||||
binding.matchArea.addView(
|
TextView tv = new TextViewBuilder(getContext(), match_latest_values[i].name)
|
||||||
new TextViewBuilder(getContext(), match_latest_values[i].name)
|
|
||||||
.align_center()
|
.align_center()
|
||||||
.size(30)
|
.size(30)
|
||||||
.padding(0,0,20,5)
|
.padding(0,0,20,5)
|
||||||
.build()
|
.build();
|
||||||
);
|
tv.setPaintFlags(tv.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
|
||||||
|
binding.matchArea.addView(tv);
|
||||||
|
|
||||||
if(data[i] != null)
|
if(data[i] != null)
|
||||||
match_latest_values[i].add_history_view(binding.matchArea, data[i]);
|
match_latest_values[i].add_history_view(binding.matchArea, data[i]);
|
||||||
|
|||||||
@@ -152,6 +152,8 @@ public class SettingsFragment extends Fragment {
|
|||||||
|
|
||||||
manager.addItem(new CheckboxSettingsItem(EnableQuickAllianceChangeKey, "Enable quick alliance swap", null));
|
manager.addItem(new CheckboxSettingsItem(EnableQuickAllianceChangeKey, "Enable quick alliance swap", null));
|
||||||
manager.addItem(new DropdownSettingsItem(FieldImageKey, "Field Image", new String[]{
|
manager.addItem(new DropdownSettingsItem(FieldImageKey, "Field Image", new String[]{
|
||||||
|
"2026",
|
||||||
|
"2026 (Flipped)",
|
||||||
"2025",
|
"2025",
|
||||||
"2025 (Flipped)"
|
"2025 (Flipped)"
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -174,23 +174,24 @@ public class HttpSync extends Thread {
|
|||||||
|
|
||||||
TransferFile localFile = findInFileArray(localFiles, remoteFile.filename);
|
TransferFile localFile = findInFileArray(localFiles, remoteFile.filename);
|
||||||
|
|
||||||
boolean shouldUpload;
|
boolean shouldDownload;
|
||||||
|
|
||||||
// If there is no file on the sever, upload.
|
// If there is no file on the sever, upload.
|
||||||
if(localFile == null) {
|
if(localFile == null) {
|
||||||
shouldUpload = true;
|
shouldDownload = true;
|
||||||
} else {
|
} else {
|
||||||
// If the remote file is the same as the local one, do nothing.
|
// If the remote file is the same as the local one, do nothing.
|
||||||
boolean checksumsEqual = !Objects.equals(localFile.checksum, remoteFile.checksum);
|
|
||||||
|
boolean checksumsNotEqual = !Objects.equals(localFile.checksum, remoteFile.checksum);
|
||||||
// If the local file is updated after the remote file
|
// If the local file is updated after the remote file
|
||||||
boolean after = after(remoteFile.updated, localFile.updated);
|
boolean after = after(remoteFile.updated, localFile.updated);
|
||||||
// If the local file and remote file's upload dates are exactly the same
|
// If the local file and remote file's upload dates are exactly the same
|
||||||
boolean datesEqual = !localFile.updated.equals(remoteFile.updated);
|
boolean datesNotEqual = !localFile.updated.equals(remoteFile.updated);
|
||||||
|
|
||||||
shouldUpload = (!checksumsEqual && (after) && !datesEqual);
|
shouldDownload = checksumsNotEqual && after;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(shouldUpload) {
|
if(shouldDownload) {
|
||||||
downloadFile(remoteFile, serverIP);
|
downloadFile(remoteFile, serverIP);
|
||||||
// await();
|
// await();
|
||||||
Log.d(getClass().toString(), "RemoteFile: " + remoteFile.filename + ", " + remoteFile.checksum + ", " + remoteFile.updated + ": Downloaded");
|
Log.d(getClass().toString(), "RemoteFile: " + remoteFile.filename + ", " + remoteFile.checksum + ", " + remoteFile.updated + ": Downloaded");
|
||||||
|
|||||||
+1
-114
@@ -87,10 +87,6 @@ public class CodeScannerView extends Fragment {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int BLOCK_SIZE = 32; // Size of each block in pixels
|
|
||||||
|
|
||||||
|
|
||||||
private Bitmap toGreyscale(Image image){
|
private Bitmap toGreyscale(Image image){
|
||||||
// Turns out the "Y" In YUV is the Luminance of the pixel.
|
// Turns out the "Y" In YUV is the Luminance of the pixel.
|
||||||
// Makes converting to greyscale 1000x easier
|
// Makes converting to greyscale 1000x easier
|
||||||
@@ -98,17 +94,12 @@ public class CodeScannerView extends Fragment {
|
|||||||
final int width = image.getWidth();
|
final int width = image.getWidth();
|
||||||
final int height = image.getHeight();
|
final int height = image.getHeight();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int[] pixels = new int[width * height];
|
int[] pixels = new int[width * height];
|
||||||
for (int i = 0; i < width*height; i++) {
|
for (int i = 0; i < width*height; i++) {
|
||||||
// int L = levelMap[yBuffer.get(i) & 0xff];
|
int L = levelMap[yBuffer.get(i) & 0xff];
|
||||||
int L = yBuffer.get(i) & 0xff;
|
|
||||||
pixels[i] = 0xff000000 | (L << 16) | (L << 8) | L;
|
pixels[i] = 0xff000000 | (L << 16) | (L << 8) | L;
|
||||||
}
|
}
|
||||||
|
|
||||||
threshold(pixels, width, height);
|
|
||||||
|
|
||||||
Matrix matrix = new Matrix();
|
Matrix matrix = new Matrix();
|
||||||
|
|
||||||
matrix.postRotate(90);
|
matrix.postRotate(90);
|
||||||
@@ -121,110 +112,6 @@ public class CodeScannerView extends Fragment {
|
|||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs mean block binarization.
|
|
||||||
* * Note: The function name 'toGreyscale' is kept per your request,
|
|
||||||
* but this method actually performs binarization (Black/White).
|
|
||||||
*
|
|
||||||
* @param image The array of pixels (ARGB format, standard in Android)
|
|
||||||
* @param width The width of the image
|
|
||||||
* @param height The height of the image
|
|
||||||
*/
|
|
||||||
private void threshold(int[] image, int width, int height) {
|
|
||||||
|
|
||||||
// 1. Setup Block Grid Dimensions
|
|
||||||
// We use Math.ceil to ensure partial blocks at the edges are counted
|
|
||||||
int gridCols = (int) Math.ceil((double) width / BLOCK_SIZE);
|
|
||||||
int gridRows = (int) Math.ceil((double) height / BLOCK_SIZE);
|
|
||||||
|
|
||||||
// Arrays to store statistics for each block
|
|
||||||
int[] blockSums = new int[gridCols * gridRows];
|
|
||||||
int[] blockCounts = new int[gridCols * gridRows];
|
|
||||||
int[] blockMeans = new int[gridCols * gridRows];
|
|
||||||
|
|
||||||
// --- PASS 1: Compute Block Statistics (Mean Intensity) ---
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
int blockY = y / BLOCK_SIZE;
|
|
||||||
|
|
||||||
for (int x = 0; x < width; x++) {
|
|
||||||
int blockX = x / BLOCK_SIZE;
|
|
||||||
int blockIndex = blockY * gridCols + blockX;
|
|
||||||
|
|
||||||
// Extract average grayscale value from ARGB pixel
|
|
||||||
int pixel = image[y * width + x];
|
|
||||||
int r = (pixel >> 16) & 0xFF;
|
|
||||||
int g = (pixel >> 8) & 0xFF;
|
|
||||||
int b = pixel & 0xFF;
|
|
||||||
// Simple average (matches BoofCV's typical approach for generic buffers)
|
|
||||||
int gray = (r + g + b) / 3;
|
|
||||||
|
|
||||||
blockSums[blockIndex] += gray;
|
|
||||||
blockCounts[blockIndex]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the mean for every block
|
|
||||||
for (int i = 0; i < blockSums.length; i++) {
|
|
||||||
if (blockCounts[i] > 0) {
|
|
||||||
blockMeans[i] = blockSums[i] / blockCounts[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- PASS 2: Apply Threshold using Local 3x3 Block Region ---
|
|
||||||
for (int blockY = 0; blockY < gridRows; blockY++) {
|
|
||||||
for (int blockX = 0; blockX < gridCols; blockX++) {
|
|
||||||
|
|
||||||
// Calculate the threshold for this specific block
|
|
||||||
// by averaging the means of the surrounding 3x3 blocks.
|
|
||||||
// This corresponds to BoofCV's `thresholdFromLocalBlocks` logic.
|
|
||||||
long localSum = 0;
|
|
||||||
int localCount = 0;
|
|
||||||
|
|
||||||
int startGridY = Math.max(0, blockY - 1);
|
|
||||||
int endGridY = Math.min(gridRows - 1, blockY + 1);
|
|
||||||
int startGridX = Math.max(0, blockX - 1);
|
|
||||||
int endGridX = Math.min(gridCols - 1, blockX + 1);
|
|
||||||
|
|
||||||
for (int ny = startGridY; ny <= endGridY; ny++) {
|
|
||||||
for (int nx = startGridX; nx <= endGridX; nx++) {
|
|
||||||
localSum += blockMeans[ny * gridCols + nx];
|
|
||||||
localCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int threshold = (localCount > 0) ? (int) (localSum / localCount) : 127;
|
|
||||||
|
|
||||||
// Apply this threshold to all pixels within the current block
|
|
||||||
int startPixelX = blockX * BLOCK_SIZE;
|
|
||||||
int startPixelY = blockY * BLOCK_SIZE;
|
|
||||||
// Handle image boundary (if image size isn't perfectly divisible by block size)
|
|
||||||
int endPixelX = Math.min(startPixelX + BLOCK_SIZE, width);
|
|
||||||
int endPixelY = Math.min(startPixelY + BLOCK_SIZE, height);
|
|
||||||
|
|
||||||
for (int y = startPixelY; y < endPixelY; y++) {
|
|
||||||
for (int x = startPixelX; x < endPixelX; x++) {
|
|
||||||
int index = y * width + x;
|
|
||||||
|
|
||||||
// Recalculate gray to compare against threshold
|
|
||||||
int pixel = image[index];
|
|
||||||
int r = (pixel >> 16) & 0xFF;
|
|
||||||
int g = (pixel >> 8) & 0xFF;
|
|
||||||
int b = pixel & 0xFF;
|
|
||||||
int gray = (r + g + b) / 3;
|
|
||||||
|
|
||||||
// Binarize: Black if <= threshold, White if > threshold
|
|
||||||
if (gray <= threshold) {
|
|
||||||
image[index] = 0xFF000000; // Black (Alpha 255)
|
|
||||||
} else {
|
|
||||||
image[index] = 0xFFFFFFFF; // White (Alpha 255)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void scanQRCode(Bitmap bitmap) {
|
public void scanQRCode(Bitmap bitmap) {
|
||||||
|
|
||||||
// CodeScanTask async = new CodeScanTask();
|
// CodeScanTask async = new CodeScanTask();
|
||||||
|
|||||||
@@ -81,6 +81,12 @@ public class FieldPosView extends FrameLayout {
|
|||||||
case "2025 (Flipped)":
|
case "2025 (Flipped)":
|
||||||
setImageResource(R.drawable.field_2025_flipped);
|
setImageResource(R.drawable.field_2025_flipped);
|
||||||
break;
|
break;
|
||||||
|
case "2026":
|
||||||
|
setImageResource(R.drawable.field_2026);
|
||||||
|
break;
|
||||||
|
case "2026 (Flipped)":
|
||||||
|
setImageResource(R.drawable.field_2026_flipped);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -263,6 +263,11 @@ public final class FileEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sets the date modified to a long, long time ago
|
||||||
|
public static boolean toTheArchaicPeriod(String name) {
|
||||||
|
return new File(baseDir + name).setLastModified(0);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean createFile(String filepath){
|
public static boolean createFile(String filepath){
|
||||||
if(fileExist(filepath)){
|
if(fileExist(filepath)){
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -46,8 +46,8 @@ public class SettingsManager {
|
|||||||
hm.put(UnameKey, "Username");
|
hm.put(UnameKey, "Username");
|
||||||
hm.put(SelEVCodeKey, "unset");
|
hm.put(SelEVCodeKey, "unset");
|
||||||
hm.put(WifiModeKey, false);
|
hm.put(WifiModeKey, false);
|
||||||
hm.put(YearNumKey, 2025);
|
hm.put(YearNumKey, 2026);
|
||||||
hm.put(FieldImageKey, "2025");
|
hm.put(FieldImageKey, "2026");
|
||||||
hm.put(MatchNumKey, 0);
|
hm.put(MatchNumKey, 0);
|
||||||
hm.put(AllyPosKey, "red-1");
|
hm.put(AllyPosKey, "red-1");
|
||||||
hm.put(DataModeKey, 0);
|
hm.put(DataModeKey, 0);
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 636 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 954 KiB |
@@ -60,7 +60,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Pit Data"
|
android:text="Pit Data"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textSize="24sp"
|
android:textSize="35sp"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/team_description2"
|
app:layout_constraintTop_toBottomOf="@+id/team_description2"
|
||||||
tools:layout_editor_absoluteX="0dp" />
|
tools:layout_editor_absoluteX="0dp" />
|
||||||
|
|
||||||
@@ -73,6 +73,11 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/divider3"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="12dp"
|
||||||
|
android:background="?android:attr/listDivider" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@@ -81,7 +86,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Match Data"
|
android:text="Match Data"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textSize="24sp"
|
android:textSize="35sp"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/team_description2"
|
app:layout_constraintTop_toBottomOf="@+id/team_description2"
|
||||||
tools:layout_editor_absoluteX="0dp" />
|
tools:layout_editor_absoluteX="0dp" />
|
||||||
|
|
||||||
@@ -139,9 +144,13 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/divider2"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="?android:attr/listDivider" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "8.13.0"
|
agp = "8.13.2"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
junitVersion = "1.1.5"
|
junitVersion = "1.1.5"
|
||||||
espressoCore = "3.5.1"
|
espressoCore = "3.5.1"
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
@@ -17,7 +17,6 @@ dependencyResolutionManagement {
|
|||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven ( url = "https://jitpack.io" )
|
maven ( url = "https://jitpack.io" )
|
||||||
jcenter()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user