Skip to content

Commit

Permalink
Added DataProcess class and moved some functions
Browse files Browse the repository at this point in the history
Co-authored-by: Jamie Grenier <[email protected]>
Co-authored-by: Ajay Ramachandran <[email protected]>
  • Loading branch information
3 people committed Jun 5, 2021
1 parent 3d6fdce commit f9e301d
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 91 deletions.
118 changes: 28 additions & 90 deletions src/main/java/uorocketry/basestation/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import uorocketry.basestation.connections.DataReceiver;
import uorocketry.basestation.control.StateButton;
import uorocketry.basestation.data.DataHolder;
import uorocketry.basestation.data.DataProcessor;
import uorocketry.basestation.data.DataTableCellRenderer;
import uorocketry.basestation.data.DataType;
import uorocketry.basestation.external.GoogleEarthUpdater;
Expand All @@ -72,8 +73,7 @@ public class Main implements ComponentListener, ChangeListener, ActionListener,
public static final String CONFIG_LOCATION = "data/config.json";
/** How many data points are there. By default, it is the number of labels */
public static List<Integer> dataLength = new ArrayList<>(2);
/** Separator for the data */
public static final String SEPARATOR = ",";

/** Data file location for the simulation (new line separated for each event). This does not include the extension/ */
public static final String SIM_DATA_LOCATION = "data/data";
public static final String SIM_DATA_EXTENSION = ".txt";
Expand Down Expand Up @@ -111,7 +111,7 @@ public class Main implements ComponentListener, ChangeListener, ActionListener,
/** Is this running in simulation mode. Must be set at the beginning as it changes the setup. */
public static boolean simulation = false;

public List<List<DataHolder>> allData = new ArrayList<>(2);
public DataProcessor dataProcessor;

List<String[]> labels = new ArrayList<>();
JSONObject config = null;
Expand Down Expand Up @@ -181,7 +181,7 @@ public Main() {

// Different setups depending on if simulation or not
setupData();

// Setup Google Earth map support
if (googleEarth) {
setupGoogleEarth();
Expand All @@ -196,14 +196,13 @@ public Main() {
updateUI();
}

public void setupData() {
allData = new ArrayList<>(dataSourceCount);
private void setupData() {
dataProcessor = new DataProcessor(config, dataSourceCount);

currentDataIndexes = new ArrayList<>(dataSourceCount);
minDataIndexes = new ArrayList<>(dataSourceCount);

for (int i = 0; i < dataSourceCount; i++) {
allData.add(new ArrayList<>());

// Add data indexes
currentDataIndexes.add(0);
minDataIndexes.add(0);
Expand Down Expand Up @@ -361,7 +360,7 @@ public void setupWebView() {

public void updateUI() {
// If not ready yet
if (allData.size() == 0 || updatingUI) return;
if (dataProcessor== null || dataProcessor.getAllData().size() == 0 || updatingUI) return;

updatingUI = true;

Expand All @@ -372,23 +371,23 @@ public void updateUI() {
private void updateUIInternal() {
try {
// Update every table's data
for (int i = 0; i < allData.size(); i++) {
for (int i = 0; i < dataProcessor.getAllData().size(); i++) {
// If not ready yet
if (allData.get(i).size() == 0) continue;
if (dataProcessor.getAllData().get(i).size() == 0) continue;

// Don't change slider if paused
if (!paused) {
// Set max value of the sliders
window.maxSliders.get(i).setMaximum(allData.get(i).size() - 1);
window.minSliders.get(i).setMaximum(allData.get(i).size() - 1);
window.maxSliders.get(i).setMaximum(dataProcessor.getAllData().get(i).size() - 1);
window.minSliders.get(i).setMaximum(dataProcessor.getAllData().get(i).size() - 1);

// Move position to end
if (latest) {
window.maxSliders.get(i).setValue(allData.get(i).size() - 1);
window.maxSliders.get(i).setValue(dataProcessor.getAllData().get(i).size() - 1);
}
}

DataHolder currentDataHolder = allData.get(i).get(currentDataIndexes.get(i));
DataHolder currentDataHolder = dataProcessor.getAllData().get(i).get(currentDataIndexes.get(i));

if (currentDataHolder != null) {
currentDataHolder.updateTableUIWithData(window.dataTables.get(i), labels.get(i));
Expand All @@ -410,11 +409,11 @@ private void updateUIInternal() {
}

if (googleEarth) {
googleEarthUpdater.updateKMLFile(allData, minDataIndexes, currentDataIndexes, config.getJSONArray("datasets"), false);
googleEarthUpdater.updateKMLFile(dataProcessor.getAllData(), minDataIndexes, currentDataIndexes, config.getJSONArray("datasets"), false);
}

if (webView) {
webViewUpdater.sendUpdate(allData, minDataIndexes, currentDataIndexes, config.getJSONArray("datasets"));
webViewUpdater.sendUpdate(dataProcessor.getAllData(), minDataIndexes, currentDataIndexes, config.getJSONArray("datasets"));
}

// Update every chart
Expand Down Expand Up @@ -469,11 +468,11 @@ public void updateChart(DataChart chart) {
if (onlyShowLatestData) minDataIndex = Math.max(maxDataIndex - maxDataPointsDisplayed, minDataIndex);

for (int i = minDataIndex; i <= maxDataIndex; i++) {
if (allData.get(chart.yType.tableIndex).size() == 0) continue;
if (dataProcessor.getAllData().get(chart.yType.tableIndex).size() == 0) continue;

DataHolder data = allData.get(chart.yType.tableIndex).get(i);
DataHolder data = dataProcessor.getAllData().get(chart.yType.tableIndex).get(i);

DataHolder other = allData.get(chart.xTypes[0].tableIndex).get(i);
DataHolder other = dataProcessor.getAllData().get(chart.xTypes[0].tableIndex).get(i);

if (data != null && (other == null || !other.hiddenDataTypes.contains(other.types[chart.xTypes[0].index]))) {
altitudeDataX.add(data.data[chart.yType.index].getDecimalValue());
Expand All @@ -493,9 +492,9 @@ public void updateChart(DataChart chart) {
if (onlyShowLatestData) minDataIndex = Math.max(maxDataIndex - maxDataPointsDisplayed, minDataIndex);

for (int j = minDataIndex; j <= maxDataIndex; j++) {
if (allData.get(chart.yType.tableIndex).size() == 0) continue;
if (dataProcessor.getAllData().get(chart.yType.tableIndex).size() == 0) continue;

DataHolder data = allData.get(chart.xTypes[i].tableIndex).get(j);
DataHolder data = dataProcessor.getAllData().get(chart.xTypes[i].tableIndex).get(j);

if (data != null) {
// Ensures that not too many data points are displayed
Expand Down Expand Up @@ -584,15 +583,15 @@ public void loadSimulationData(int index, String fileName) {
}

List<DataHolder> dataHolders = new ArrayList<DataHolder>();
allData.set(index, dataHolders);
dataProcessor.getAllData().set(index, dataHolders);

try {
try {
String line = null;

while ((line = br.readLine()) != null) {
// Parse this line and add it as a data point
dataHolders.add(parseData(line, index));
dataHolders.add(dataProcessor.parseData(line, index));
}
} finally {
br.close();
Expand All @@ -602,67 +601,6 @@ public void loadSimulationData(int index, String fileName) {
}
}

public DataHolder parseData(String data, int tableIndex) {
DataHolder dataHolder = new DataHolder(tableIndex, config.getJSONArray("datasets").getJSONObject(tableIndex));

// Clear out the b' ' stuff added that is only meant for the radio to see
data = data.replaceAll("b'|\\\\r\\\\n'", "");
if (data.endsWith(",")) data = data.substring(0, data.length() - 1);

// Semi-colon separated
String[] splitData = data.split(SEPARATOR);
if (splitData.length != dataHolder.data.length) {
//invalid data
System.err.println("Line with invalid data (Not the correct amount of data). It was " + splitData.length);

return null;
}

// TODO: Potentially remove and test this
// Ensure that the timestamp has not gone back in time
try {
DataHolder lastDataPointDataHolder = findLastValidDataPoint(allData.get(tableIndex));

int timestampIndex = config.getJSONArray("datasets").getJSONObject(tableIndex).getInt("timestampIndex");
if (lastDataPointDataHolder != null) {
Float value = lastDataPointDataHolder.data[timestampIndex].getDecimalValue();
if (value != null && Float.parseFloat(splitData[timestampIndex]) < value) {
System.err.println("Timestamp just went backwards");

// Treat as invalid data
return null;
}
}
} catch (NumberFormatException | JSONException e) {}

for (int i = 0; i < splitData.length; i++) {
if (!dataHolder.set(i, splitData[i])) {
System.err.println("Failed to set data handler");

// Parsing failed
return null;
}
}

return dataHolder;
}

/**
* Find last non null data point
*
* @param currentTableData
* @return DataHolder if found, null otherwise
*/
private DataHolder findLastValidDataPoint(List<DataHolder> currentTableData) {
for (int i = currentTableData.size() - 1; i >= 0; i--) {
if (currentTableData.get(i) != null) {
return currentTableData.get(i);
}
}

return null;
}

/**
* Run once at the beginning of simulation mode
*/
Expand Down Expand Up @@ -746,7 +684,7 @@ public void stateChanged(ChangeEvent e) {
public void receivedData(DeviceConnection deviceConnection, byte[] data) {
String delimitedMessage = new String(data, StandardCharsets.UTF_8);

allData.get(deviceConnection.getTableIndex()).add(parseData(delimitedMessage, deviceConnection.getTableIndex()));
dataProcessor.getAllData().get(deviceConnection.getTableIndex()).add(dataProcessor.parseData(delimitedMessage, deviceConnection.getTableIndex()));

updateUI();

Expand Down Expand Up @@ -777,8 +715,8 @@ public void actionPerformed(ActionEvent e) {
if (e.getSource() == window.clearDataButton) {
if (JOptionPane.showConfirmDialog(window,
"Are you sure you would like to clear all the data?") == 0) {
for (int i = 0; i < allData.size(); i++) {
allData.get(i).clear();
for (int i = 0; i < dataProcessor.getAllData().size(); i++) {
dataProcessor.getAllData().get(i).clear();
}

updateUI();
Expand Down Expand Up @@ -817,7 +755,7 @@ public void actionPerformed(ActionEvent e) {
window.latestButton.setText("Detach From Latest");

for (int i = 0; i < window.maxSliders.size(); i++) {
window.maxSliders.get(i).setValue(allData.get(0).size() - 1);
window.maxSliders.get(i).setValue(dataProcessor.getAllData().get(0).size() - 1);
}
} else {
window.latestButton.setText("Latest");
Expand Down Expand Up @@ -857,7 +795,7 @@ public void actionPerformed(ActionEvent e) {
} else if (e.getSource() == window.dataDeletionModeCheckBox) {
dataDeletionMode = window.dataDeletionModeCheckBox.isSelected();
} else if (e.getSource() == window.restoreDeletedData) {
for (List<DataHolder> dataHolders : allData) {
for (List<DataHolder> dataHolders : dataProcessor.getAllData()) {
for (DataHolder dataHolder : dataHolders) {
// See if the hidden list needs to be cleared
if (dataHolder != null && !dataHolder.hiddenDataTypes.isEmpty()) {
Expand Down
100 changes: 100 additions & 0 deletions src/main/java/uorocketry/basestation/data/DataProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package uorocketry.basestation.data;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONException;
import org.json.JSONObject;

import uorocketry.basestation.connections.DataReceiver;
import uorocketry.basestation.connections.DeviceConnection;

public class DataProcessor implements DataReceiver {

private List<List<DataHolder>> allData = new ArrayList<>(2);
private JSONObject config;

public DataProcessor(JSONObject config, int dataSourceCount) {
this.config = config;

allData = new ArrayList<>(dataSourceCount);
for (int i = 0; i < dataSourceCount; i++) {
allData.add(new ArrayList<>());
}
}

/** Separator for the data */
public static final String SEPARATOR = ",";

@Override
public void receivedData(DeviceConnection deviceConnection, byte[] data) {

}

public DataHolder parseData(String data, int tableIndex) {
DataHolder dataHolder = new DataHolder(tableIndex, config.getJSONArray("datasets").getJSONObject(tableIndex));

// Clear out the b' ' stuff added that is only meant for the radio to see
data = data.replaceAll("b'|\\\\r\\\\n'", "");
if (data.endsWith(",")) data = data.substring(0, data.length() - 1);

// Semi-colon separated
String[] splitData = data.split(SEPARATOR);
if (splitData.length != dataHolder.data.length) {
//invalid data
System.err.println("Line with invalid data (Not the correct amount of data). It was " + splitData.length);

return null;
}

// TODO: Potentially remove and test this
// Ensure that the timestamp has not gone back in time
try {
DataHolder lastDataPointDataHolder = findLastValidDataPoint(allData.get(tableIndex));

int timestampIndex = config.getJSONArray("datasets").getJSONObject(tableIndex).getInt("timestampIndex");
if (lastDataPointDataHolder != null) {
Float value = lastDataPointDataHolder.data[timestampIndex].getDecimalValue();
if (value != null && Float.parseFloat(splitData[timestampIndex]) < value) {
System.err.println("Timestamp just went backwards");

// Treat as invalid data
return null;
}
}
} catch (NumberFormatException | JSONException e) {}

for (int i = 0; i < splitData.length; i++) {
if (!dataHolder.set(i, splitData[i])) {
System.err.println("Failed to set data handler");

// Parsing failed
return null;
}
}

return dataHolder;
}

/**
* Find last non null data point
*
* @param currentTableData
* @return DataHolder if found, null otherwise
*/
private DataHolder findLastValidDataPoint(List<DataHolder> currentTableData) {
for (int i = currentTableData.size() - 1; i >= 0; i--) {
if (currentTableData.get(i) != null) {
return currentTableData.get(i);
}
}

return null;
}

public List<List<DataHolder>> getAllData() {
return allData;
}


}
2 changes: 1 addition & 1 deletion src/main/java/uorocketry/basestation/panel/SnapPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ public void mouseDragged(MouseEvent e) {
// Find all data points near the click
for (int xTypeIndex = 0; xTypeIndex < chart.xTypes.length; xTypeIndex++) {
DataType currentType = chart.xTypes[xTypeIndex];
List<DataHolder> dataHolders = chart.main.allData.get(currentType.tableIndex);
List<DataHolder> dataHolders = chart.main.dataProcessor.getAllData().get(currentType.tableIndex);

// Y axis depends on the which data is being checked
double yMousePos = chart.chartPanel.getChart().getChartYFromCoordinate(e.getY(), xTypeIndex);
Expand Down

0 comments on commit f9e301d

Please sign in to comment.