kauron/estraba
Archived
1
0
Fork 0

initial Dashboard distance -> time commit

This commit is contained in:
Jesús Vélez Palacios 2016-05-24 13:47:49 +02:00
parent 05d052fb00
commit b0433a32df
9 changed files with 157 additions and 66 deletions

View file

@ -58,11 +58,6 @@
<artifactId>controlsfx</artifactId>
<version>8.40.10</version>
</dependency>
<dependency>
<groupId>jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.0.13</version>
</dependency>
<dependency>
<groupId>com.github.rterp</groupId>
<artifactId>GMapsFX</artifactId>

View file

@ -61,6 +61,7 @@ public class App extends Application {
stage.setResizable(false);
stage.setScene(new Scene(root));
if (getParameters().getUnnamed().size() == 1) {
loader.<SplashController>getController().loadGPXFile(new File(getParameters().getUnnamed().get(0)));
}

View file

@ -38,6 +38,7 @@ import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.chart.AreaChart;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.PieChart;
@ -45,6 +46,7 @@ import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import jgpx.model.analysis.Chunk;
@ -58,38 +60,40 @@ import java.util.ResourceBundle;
public class DashboardController implements Initializable, MapComponentInitializedListener {
final int N = 0, S = 1, E = 2, W = 3;
final double[] coord = new double[4];
@FXML
private AnchorPane root;
@FXML
private Tab tabDashboard, tabMap, tabGraph, tabSettings;
@FXML
private ImageView imgHR, imgSpeed, imgCadence, imgDate, imgDistance, imgElevation;
@FXML
private Label valueHRAvg, valueHRMin, valueHRMax, valueSpeedAvg, valueSpeedMax, valueCadenceAvg, valueCadenceMax,
valueDate, valueTime, valueActiveTime, valueTotalTime, valueDistance, valueElevation, labelMotivationUpper,
valueAscent, valueDescent, labelMotivatorLower;
@FXML
private JFXSpinner mapSpinner;
@FXML
private PieChart zoneChart;
@FXML
private GoogleMapView mapView;
private ObservableList<Chunk> chunks;
@FXML
private JFXButton elevationButton, speedButton, hrButton, cadenceButton;
@FXML
private AreaChart<Double, Double> elevationChart;
@FXML
private AreaChart<Long, Double> elevationTChart;
@FXML
private LineChart<Double, Double> speedChart, hrChart, cadenceChart, mapChart;
@FXML
private LineChart<Long, Double> speedTChart, hrTChart, cadenceTChart;
@Override
public void initialize(URL location, ResourceBundle resources) {
// populate map icons
@ -105,6 +109,15 @@ public class DashboardController implements Initializable, MapComponentInitializ
imgDate.setImage(new Image(App.class.getResourceAsStream("img/date.png")));
imgDistance.setImage(new Image(App.class.getResourceAsStream("img/distance.png")));
imgElevation.setImage(new Image(App.class.getResourceAsStream("img/elevation.png")));
}
@FXML
private void toggleChart(MouseEvent e) {
System.out.println("hi");
for (Node n : ((Node) e.getSource()).getParent().getChildrenUnmodifiable())
n.setVisible(!n.isVisible());
}
@FXML
@ -149,9 +162,13 @@ public class DashboardController implements Initializable, MapComponentInitializ
// populate the charts
elevationChart.getData().add(bundle.elevationSeries);
elevationTChart.getData().add(bundle.elevationTSeries);
speedChart.getData().add(bundle.speedSeries);
speedTChart.getData().add(bundle.speedTSeries);
hrChart.getData().add(bundle.hrSeries);
hrTChart.getData().add(bundle.hrTSeries);
cadenceChart.getData().add(bundle.cadenceSeries);
cadenceTChart.getData().add(bundle.cadenceTSeries);
//initialize map
chunks = bundle.chunks;
@ -161,8 +178,6 @@ public class DashboardController implements Initializable, MapComponentInitializ
@Override
public void mapInitialized() {
// When the JS init is done
final int N = 0, S = 1, E = 2, W = 3;
final double[] coord = new double[4];
coord[0] = Double.MIN_VALUE;
coord[1] = Double.MAX_VALUE;
coord[2] = Double.MIN_VALUE;
@ -212,13 +227,20 @@ public class DashboardController implements Initializable, MapComponentInitializ
chunks.get(chunks.size() - 1).getLastPoint().getLongitude()))
.title("label.end")));
// Adjust the map to the correct center and zoom
map.fitBounds(new LatLongBounds(
mapView.setVisible(true);
mapSpinner.setVisible(false);
mapView.heightProperty().addListener(e -> centerMap());
mapView.widthProperty().addListener(e -> centerMap());
centerMap();
}
private void centerMap() {
mapView.getMap().setZoom(getBoundsZoomLevel(coord, mapView.getHeight(), mapView.getWidth()));
mapView.getMap().fitBounds(new LatLongBounds(
new LatLong(coord[S], coord[W]),
new LatLong(coord[N], coord[E])
));
map.setZoom(getBoundsZoomLevel(coord, mapView.getHeight(), mapView.getWidth()));
mapView.setVisible(true);
mapSpinner.setVisible(false);
}
/**

View file

@ -30,7 +30,6 @@ import com.jfoenix.controls.JFXSnackbar;
import com.jfoenix.controls.JFXSpinner;
import es.kauron.estraba.App;
import es.kauron.estraba.model.DataBundle;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
@ -100,8 +99,14 @@ public class SplashController implements Initializable{
snackbar.show("Loading file", 5000);
Thread th = new Thread(new Task<DataBundle>() {
@Override
protected DataBundle call() throws Exception {
return DataBundle.loadFrom(file);
protected DataBundle call() {
DataBundle db = null;
try {
db = DataBundle.loadFrom(file);
} catch (Exception e) {
e.printStackTrace();
}
return db;
}
@Override
@ -117,6 +122,7 @@ public class SplashController implements Initializable{
loader.<DashboardController>getController().load(bundle);
((Stage) root.getScene().getWindow()).setScene(new Scene(parent));
} catch (IOException e) {
e.printStackTrace();
errorLoading();
}
}
@ -145,37 +151,33 @@ public class SplashController implements Initializable{
}
});
Platform.runLater(() -> root.getScene().setOnDragOver(e -> {
root.setOnDragOver(e -> {
Dragboard db = e.getDragboard();
if (db.hasFiles()) {
e.acceptTransferModes(TransferMode.COPY);
} else {
e.consume();
}
}));
});
// Dropping over surface
Platform.runLater(() -> root.getScene().setOnDragDropped(e -> {
root.setOnDragDropped(e -> {
Dragboard db = e.getDragboard();
boolean success = false;
if (db.hasFiles()) {
success = true;
String filePath = null;
for (File file : db.getFiles()) {
filePath = file.getAbsolutePath();
System.out.println(filePath);
}
loadGPXFile(db.getFiles().get(0).getAbsoluteFile());
}
e.setDropCompleted(success);
e.consume();
}));
});
}
private void errorLoading() {
buttonLoad.setVisible(true);
labelWelcome.setVisible(true);
spinner.setVisible(false);
snackbar.show("Error loading file", 3000);
snackbar.show(App.GENERAL_BUNDLE.getString("error.file"), 3000);
}
}

View file

@ -40,23 +40,24 @@ import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.time.Duration;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
public class DataBundle {
public static final int N = 0, S = 1, E = 2, W = 3;
private static final double DISTANCE_EPSILON = 1E-6;
private static final double KILOMETER_CUTOFF = 10000;
public String HRAvg, HRMax, HRMin, speedAvg, speedMax, cadenceAvg, cadenceMax;
public String date, time, activeTime, totalTime, distance, elevation, ascent, descent;
public XYChart.Series<Double, Double> elevationSeries, speedSeries, hrSeries, cadenceSeries;
public XYChart.Series<Long, Double> elevationTSeries, speedTSeries, hrTSeries, cadenceTSeries;
public ObservableList<PieChart.Data> pieData;
public ObservableList<Chunk> chunks;
private DataBundle(TrackData track) {
HRAvg = track.getAverageHeartrate() + App.GENERAL_BUNDLE.getString("unit.bpm");
HRMax = track.getMaxHeartrate() + App.GENERAL_BUNDLE.getString("unit.bpm");
HRMin = track.getMinHeartRate() + App.GENERAL_BUNDLE.getString("unit.bpm");
@ -87,23 +88,34 @@ public class DataBundle {
// traverse the chunks
chunks = track.getChunks();
double currentDistance = 0.0;
Duration currentTime = Duration.ZERO;
double currentHeight = chunks.get(0).getFirstPoint().getElevation();
elevationSeries = new XYChart.Series<>();
elevationTSeries = new XYChart.Series<>();
cadenceSeries = new XYChart.Series<>();
cadenceTSeries = new XYChart.Series<>();
hrSeries = new XYChart.Series<>();
hrTSeries = new XYChart.Series<>();
speedSeries = new XYChart.Series<>();
speedTSeries = new XYChart.Series<>();
pieData = FXCollections.observableArrayList();
for (Chunk chunk : chunks) {
currentDistance += chunk.getDistance();
if (chunk.getDistance() < DISTANCE_EPSILON) continue;
currentTime = currentTime.plus(chunk.getMovingTime());
if (chunk.getDistance() < DISTANCE_EPSILON ||
chunk.getMovingTime().getSeconds() < 1) continue;
currentHeight += chunk.getAscent() - chunk.getDescend();
elevationSeries.getData().add(new XYChart.Data<>(currentDistance, currentHeight));
elevationTSeries.getData().add(new XYChart.Data<>(currentTime.toMinutes(), currentHeight));
speedSeries.getData().add(new XYChart.Data<>(currentDistance, chunk.getSpeed()*3.6)); // m/s
speedTSeries.getData().add(new XYChart.Data<>(currentTime.toMinutes(), chunk.getSpeed() * 3.6)); // m/s
hrSeries.getData().add(new XYChart.Data<>(currentDistance, chunk.getAvgHeartRate()));
hrTSeries.getData().add(new XYChart.Data<>(currentTime.toMinutes(), chunk.getAvgHeartRate()));
cadenceSeries.getData().add(new XYChart.Data<>(currentDistance, chunk.getAvgCadence()));
cadenceTSeries.getData().add(new XYChart.Data<>(currentTime.toMinutes(), chunk.getAvgCadence()));
String zone;
if (chunk.getAvgHeartRate() > 170) zone = App.GENERAL_BUNDLE.getString("zone.anaerobic");

View file

@ -365,7 +365,7 @@
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
<StackPane prefHeight="150.0" prefWidth="200.0" VBox.vgrow="ALWAYS" >
<StackPane prefHeight="150.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
<children>
<GoogleMapView fx:id="mapView" />
<JFXSpinner fx:id="mapSpinner" />
@ -422,38 +422,94 @@
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
<AreaChart fx:id="elevationChart" createSymbols="false" legendVisible="false" minHeight="100.0">
<xAxis>
<NumberAxis side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" />
</yAxis>
</AreaChart>
<LineChart fx:id="speedChart" createSymbols="false" legendVisible="false" minHeight="100.0">
<xAxis>
<NumberAxis />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" />
</yAxis>
</LineChart>
<LineChart fx:id="hrChart" createSymbols="false" legendVisible="false" minHeight="100.0">
<xAxis>
<NumberAxis side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" />
</yAxis>
</LineChart>
<LineChart fx:id="cadenceChart" createSymbols="false" legendVisible="false" minHeight="100.0">
<xAxis>
<NumberAxis side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" />
</yAxis>
</LineChart>
<StackPane>
<children>
<AreaChart fx:id="elevationChart" createSymbols="false" legendVisible="false" minHeight="100.0"
onMouseClicked="#toggleChart">
<xAxis>
<NumberAxis side="BOTTOM"/>
</xAxis>
<yAxis>
<NumberAxis side="LEFT"/>
</yAxis>
</AreaChart>
<AreaChart fx:id="elevationTChart" createSymbols="false" layoutX="10.0" layoutY="10.0"
legendVisible="false" minHeight="100.0" onMouseClicked="#toggleChart" visible="false">
<xAxis>
<NumberAxis/>
</xAxis>
<yAxis>
<NumberAxis side="LEFT"/>
</yAxis>
</AreaChart>
</children>
</StackPane>
<StackPane>
<children>
<LineChart fx:id="speedChart" createSymbols="false" legendVisible="false" minHeight="100.0"
onMouseClicked="#toggleChart">
<xAxis>
<NumberAxis/>
</xAxis>
<yAxis>
<NumberAxis side="LEFT"/>
</yAxis>
</LineChart>
<LineChart fx:id="speedTChart" createSymbols="false" layoutX="10.0" layoutY="10.0"
legendVisible="false" minHeight="100.0" onMouseClicked="#toggleChart" visible="false">
<xAxis>
<NumberAxis/>
</xAxis>
<yAxis>
<NumberAxis side="LEFT"/>
</yAxis>
</LineChart>
</children>
</StackPane>
<StackPane>
<children>
<LineChart fx:id="hrChart" createSymbols="false" legendVisible="false" minHeight="100.0"
onMouseClicked="#toggleChart">
<xAxis>
<NumberAxis side="BOTTOM"/>
</xAxis>
<yAxis>
<NumberAxis side="LEFT"/>
</yAxis>
</LineChart>
<LineChart fx:id="hrTChart" createSymbols="false" layoutX="10.0" layoutY="10.0" legendVisible="false"
minHeight="100.0" onMouseClicked="#toggleChart" visible="false">
<xAxis>
<NumberAxis/>
</xAxis>
<yAxis>
<NumberAxis side="LEFT"/>
</yAxis>
</LineChart>
</children>
</StackPane>
<StackPane>
<children>
<LineChart fx:id="cadenceChart" createSymbols="false" legendVisible="false" minHeight="100.0"
onMouseClicked="#toggleChart">
<xAxis>
<NumberAxis side="BOTTOM"/>
</xAxis>
<yAxis>
<NumberAxis side="LEFT"/>
</yAxis>
</LineChart>
<LineChart fx:id="cadenceTChart" createSymbols="false" layoutX="10.0" layoutY="10.0"
legendVisible="false" minHeight="100.0" onMouseClicked="#toggleChart" visible="false">
<xAxis>
<NumberAxis/>
</xAxis>
<yAxis>
<NumberAxis side="LEFT"/>
</yAxis>
</LineChart>
</children>
</StackPane>
</VBox>
</Tab>
<Tab fx:id="tabSettings" text="%tab.settings">

View file

@ -25,6 +25,7 @@
app.extension=GPX data files
app.title=ESTRABA
error.file=Error loading file
label.begin=Salida
label.cadence=Cadence
label.distance=Distance

View file

@ -25,6 +25,7 @@
app.extension=Arxius GPX
app.title=ESTRABA
error.file=Error
label.begin=Salida
label.cadence=Cadencia
label.distance=Distancia

View file

@ -25,6 +25,7 @@
app.extension=Archivos de datos GPX
app.title=ESTRABA
error.file=Error al cargar el archivo
label.begin=Salida
label.cadence=Cadencia
label.distance=Distancia