From 7ff348af489ad12a72c539a2a4ae1894fff04ddc Mon Sep 17 00:00:00 2001 From: David George Date: Tue, 16 Feb 2016 00:06:44 +0100 Subject: [PATCH] Changes for version 2.7 --- .gitignore | 6 + properties/MessageBundle_en.properties | 1 + run.sh | 2 +- src/com/wattzap/Main.java | 1 - src/com/wattzap/MenuBar.java | 22 ++- src/com/wattzap/model/RLVReader.java | 6 +- src/com/wattzap/model/TTSReader.java | 5 +- src/com/wattzap/model/UserPreferences.java | 9 ++ src/com/wattzap/model/ant/SpeedListener.java | 72 ++++++---- src/com/wattzap/model/dto/Point.java | 26 ++-- src/com/wattzap/model/dto/Telemetry.java | 115 ++++++--------- src/com/wattzap/utils/FitImporter.java | 2 +- src/com/wattzap/utils/TcxWriter.java | 47 +++---- src/com/wattzap/view/AboutPanel.java | 2 +- src/com/wattzap/view/AntOdometer.java | 38 ++--- src/com/wattzap/view/MainFrame.java | 2 +- src/com/wattzap/view/RouteFilePicker.java | 57 +++++--- src/com/wattzap/view/VideoPlayer.java | 95 +++++++++++-- src/com/wattzap/view/Workouts.java | 97 +++++++------ src/com/wattzap/view/graphs/SCHRGraph.java | 5 +- src/com/wattzap/view/prefs/Preferences.java | 17 ++- .../view/training/TrainingDisplay.java | 1 + test/com/wattzap/model/TTSReaderTest.java | 22 ++- .../wattzap/model/ant/SpeedListenerTest.java | 132 ++++++++++++++++++ test/com/wattzap/utils/StringXORerTest.java | 2 +- 25 files changed, 527 insertions(+), 257 deletions(-) create mode 100644 test/com/wattzap/model/ant/SpeedListenerTest.java diff --git a/.gitignore b/.gitignore index 0cac84f..8c27b5b 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,9 @@ bin/ src-pe/ plugins/ jre6/ +jre7/ +.classpath +.project +build-mac.xml +libvlc.dll +libvlccore.dll diff --git a/properties/MessageBundle_en.properties b/properties/MessageBundle_en.properties index 955c27f..889a39d 100644 --- a/properties/MessageBundle_en.properties +++ b/properties/MessageBundle_en.properties @@ -76,6 +76,7 @@ route=Route saveclose=Save and Close saveGPS=Save with GPS and Altitude data? save=Save +saveroute=Save as GPX scatter=Scatter Plots schr=Speed/Cadence/Heart-rate scid=Speed and Cadence ID diff --git a/run.sh b/run.sh index a6f470a..d0667d3 100755 --- a/run.sh +++ b/run.sh @@ -1,3 +1,3 @@ -LIBS="bin:lib:properties:lib/derby.jar:lib/opencsv-2.3.jar:lib/com-sun-tools-visualvm-charts.jar:lib/com-sun-tools-visualvm-uisupport.jar:lib/commons-lang3-3.2.1.jar:lib/gpx-creator-0.1-beta.jar:lib/hamcrest-core-1.3.jar:lib/jcommon-1.0.17.jar:lib/jcommon-1.0.18.jar:lib/jformica-core1.6.jar:lib/jformica-jsr80-1.6.jar:lib/jfreechart-1.0.14.jar:lib/jna-3.5.1.jar:lib/junit-4.11.jar:lib/miglayout-core-4.2.jar:lib/miglayout-swing-4.2.jar:lib/org-netbeans-lib-profiler-charts.jar:lib/org-netbeans-lib-profiler-ui.jar:lib/org-openide-util-lookup.jar:lib/org-openide-util.jar:lib/usb-api-1.0.2.jar:lib/usb4java-1.2.0.jar:lib/usb4java-javax-1.2.0.jar:lib/vlcj-2.2.0.jar:lib/log4j-1.2.17.jar" +LIBS="bin;lib;properties;lib/derby.jar;lib/opencsv-2.3.jar;lib/com-sun-tools-visualvm-charts.jar;lib/com-sun-tools-visualvm-uisupport.jar;lib/commons-lang3-3.2.1.jar;lib/gpx-creator-0.1-beta.jar;lib/hamcrest-core-1.3.jar;lib/jcommon-1.0.17.jar;lib/jcommon-1.0.18.jar;lib/jformica-core1.6.jar;lib/jformica-jsr80-1.6.jar;lib/jfreechart-1.0.14.jar;lib/jna-3.5.1.jar;lib/junit-4.11.jar;lib/miglayout-core-4.2.jar;lib/miglayout-swing-4.2.jar;lib/org-netbeans-lib-profiler-charts.jar;lib/org-netbeans-lib-profiler-ui.jar;lib/org-openide-util-lookup.jar;lib/org-openide-util.jar;lib/usb-api-1.0.2.jar;lib/usb4java-1.2.0.jar;lib/usb4java-javax-1.2.0.jar;lib/vlcj-2.2.0.jar;lib/log4j-1.2.17.jar" java -cp $LIBS -Dlog4j.logger.level=DEBUG com.wattzap.Main diff --git a/src/com/wattzap/Main.java b/src/com/wattzap/Main.java index d067343..53e1c11 100644 --- a/src/com/wattzap/Main.java +++ b/src/com/wattzap/Main.java @@ -19,7 +19,6 @@ import java.awt.Container; import java.awt.Dimension; import java.awt.EventQueue; -import java.awt.Rectangle; import java.awt.Toolkit; import java.io.IOException; import java.util.HashMap; diff --git a/src/com/wattzap/MenuBar.java b/src/com/wattzap/MenuBar.java index d108064..33c8b92 100644 --- a/src/com/wattzap/MenuBar.java +++ b/src/com/wattzap/MenuBar.java @@ -43,13 +43,15 @@ * Externalize menu setup to this class. Registers for Locale change messages so * we can reinitialize text when language changes. * - * (c) 2014-2015 David George / Wattzap.com + * (c) 2014-2016 David George / Wattzap.com * * @author David George * @date 25 November 2014 */ public class MenuBar implements MessageCallback { private final static UserPreferences userPrefs = UserPreferences.INSTANCE; + + public final static String SAVEROUTE = "save"; private final JMenu fileMenu; private final JMenu trainingMenu; @@ -61,6 +63,7 @@ public class MenuBar implements MessageCallback { private final JMenuItem quitMenuItem; // File Menu Items private final JMenuItem openMenuItem; + private final JMenuItem saveRouteMenuItem; private MenuItem closeMenuItem; // Training private final JMenuItem trainMenuItem; @@ -79,6 +82,8 @@ public MenuBar(MainFrame frame) { // Preferences Preferences preferences = new Preferences(); prefMenuItem = new JMenuItem(); + prefMenuItem.setAccelerator(KeyStroke.getKeyStroke('P', Toolkit + .getDefaultToolkit().getMenuShortcutKeyMask(), false)); prefMenuItem.addActionListener(preferences); // About Dialog @@ -106,6 +111,12 @@ public MenuBar(MainFrame frame) { RouteFilePicker picker = new RouteFilePicker(frame); openMenuItem.addActionListener(picker); + + saveRouteMenuItem = new JMenuItem(); + saveRouteMenuItem.setActionCommand(SAVEROUTE); + + saveRouteMenuItem.addActionListener(picker); + fileMenu.add(saveRouteMenuItem); closeMenuItem = new MenuItem(Messages.CLOSE); fileMenu.add(closeMenuItem); @@ -129,18 +140,26 @@ public MenuBar(MainFrame frame) { trainMenuItem.addActionListener(tPicker); } analizeMenuItem = new JMenuItem(); + analizeMenuItem.setAccelerator(KeyStroke.getKeyStroke('A', Toolkit + .getDefaultToolkit().getMenuShortcutKeyMask(), false)); trainingMenu.add(analizeMenuItem); analizeMenuItem.setActionCommand(TrainingController.analyze); saveMenuItem = new JMenuItem(); + saveMenuItem.setAccelerator(KeyStroke.getKeyStroke('S', Toolkit + .getDefaultToolkit().getMenuShortcutKeyMask(), false)); saveMenuItem.setActionCommand(TrainingController.save); trainingMenu.add(saveMenuItem); viewMenuItem = new JMenuItem(); + viewMenuItem.setAccelerator(KeyStroke.getKeyStroke('V', Toolkit + .getDefaultToolkit().getMenuShortcutKeyMask(), false)); viewMenuItem.setActionCommand(TrainingController.view); trainingMenu.add(viewMenuItem); recoverMenuItem = new JMenuItem(); + recoverMenuItem.setAccelerator(KeyStroke.getKeyStroke('R', Toolkit + .getDefaultToolkit().getMenuShortcutKeyMask(), false)); recoverMenuItem.setActionCommand(TrainingController.recover); trainingMenu.add(recoverMenuItem); @@ -184,6 +203,7 @@ private void doText() { fileMenu.setText(userPrefs.getString("route")); openMenuItem.setText(userPrefs.getString("open")); closeMenuItem.setText(userPrefs.getString("close")); + saveRouteMenuItem.setText(userPrefs.getString("saveroute")); trainingMenu.setText(userPrefs.getString("training")); analizeMenuItem.setText( diff --git a/src/com/wattzap/model/RLVReader.java b/src/com/wattzap/model/RLVReader.java index 2248db8..73f66fe 100644 --- a/src/com/wattzap/model/RLVReader.java +++ b/src/com/wattzap/model/RLVReader.java @@ -204,7 +204,7 @@ public void load(String filename) { normPower = 1.2 * (UserPreferences.INSTANCE.getMaxPower() / maxPower); } // 40% of FTP - float recoveryPower = UserPreferences.INSTANCE.getMaxPower() * 0.4f; + int recoveryPower = (int) (UserPreferences.INSTANCE.getMaxPower() / 0.4); if (recoveryPower == 0) { recoveryPower = 75; } @@ -221,7 +221,7 @@ public void load(String filename) { runningDistance += distance; // Normalize power - rlvP.setPower(p.getPower() * normPower); + rlvP.setPower((int) (p.getPower() * normPower)); if (rlvP.getPower() < recoveryPower) { // put a floor on minimum power rlvP.setPower(recoveryPower); @@ -249,7 +249,7 @@ public void load(String filename) { } } // Normalize power - p.setPower(p.getPower() * normPower); + p.setPower((int) (p.getPower() * normPower)); if (p.getPower() < recoveryPower) { // put a floor on minimum power p.setPower(recoveryPower); diff --git a/src/com/wattzap/model/TTSReader.java b/src/com/wattzap/model/TTSReader.java index 05d1be3..5995213 100644 --- a/src/com/wattzap/model/TTSReader.java +++ b/src/com/wattzap/model/TTSReader.java @@ -579,11 +579,10 @@ private void GPSData(int version, byte[] data) { double lon = Float.intBitsToFloat(getUInt(data, i * 16 + 8)); double altitude = Float.intBitsToFloat(getUInt(data, i * 16 + 12)); - // System.out.println("alt " + altitude + " distance " + distance); - - // GPX Data + // GPS Data Waypoint wayPoint = new Waypoint(lat, lon); wayPoint.setEle(altitude); + path.addWaypoint(wayPoint); while (pointCount < pointList.size()) { diff --git a/src/com/wattzap/model/UserPreferences.java b/src/com/wattzap/model/UserPreferences.java index c8908fc..bb935d1 100644 --- a/src/com/wattzap/model/UserPreferences.java +++ b/src/com/wattzap/model/UserPreferences.java @@ -228,6 +228,15 @@ public boolean isMetric() { public void setUnits(boolean value) { setBoolean("units", value); } + + // For automatic screen shots + public boolean isScreenshot() { + return getBoolean("screenshot", false); + } + + public void setScreenshot(boolean value) { + setBoolean("screenshot", value); + } // Social public String getSLUser() { diff --git a/src/com/wattzap/model/ant/SpeedListener.java b/src/com/wattzap/model/ant/SpeedListener.java index c653e41..9743067 100644 --- a/src/com/wattzap/model/ant/SpeedListener.java +++ b/src/com/wattzap/model/ant/SpeedListener.java @@ -35,7 +35,7 @@ * @author David George * @date 24th November 2014 * - * (c) 2014 David George / Wattzap.com + * (c) 2014-2016 David George / Wattzap.com */ public class SpeedListener extends AntListener implements MessageCallback { public static String name = "C:SPD"; @@ -49,8 +49,8 @@ public class SpeedListener extends AntListener implements MessageCallback { private boolean initializing = false; private Rolling powerRatio; private boolean simulSpeed; - private static long elapsedTime; - private static long elapsedTimestamp = 0; + //private static long elapsedTime; + //private static long elapsedTimestamp = 0; private double distance = 0.0; RouteReader routeData; @@ -94,8 +94,6 @@ public void receiveMessage(BroadcastDataMessage message) { * @return Telemetry or null if no reliable data could be calculated. */ Telemetry getTelemetry(int time, int count) { - - if (lastCount == -1) { // first time thru, initialize counters lastCount = count; @@ -108,7 +106,7 @@ Telemetry getTelemetry(int time, int count) { initializing = false; lastCount = count; lastTime = time; - elapsedTime = System.currentTimeMillis(); + //elapsedTime = System.currentTimeMillis(); } return null; } @@ -128,25 +126,33 @@ Telemetry getTelemetry(int time, int count) { return null; } - if(tDiff == 0){ + //if(tDiff == 0){ //no new value received from sensor could be normal at slow speed if cCount < 6 - cCount++; - } else { + //cCount++; + //} else { //a new value received from sensor clear cCount - cCount = 0; - } + //cCount = 0; + //} double speed = 0; double distanceKM = 0; Telemetry t = new Telemetry(); - //allow trainer speed null for down - long timestamp = System.currentTimeMillis(); - if (tDiff == 0 && elapsedTimestamp > 0 && routeData != null && routeData.getPoint(distance).getGradient() < 0) { - tDiff = (int) (timestamp - elapsedTimestamp)*1024/1000; - } - - elapsedTimestamp = timestamp; + /* + * This allows us to record a speed when we are slowing down to stop by using realtime rather than anttime for readings. + * + * tDiff is zero - so no time difference. + * elapsedtime is not zero so we've started recording + * gradient is less than zero, so downhill + */ + //long timestamp = System.currentTimeMillis(); + //if (tDiff == 0 && elapsedTimestamp > 0 && routeData != null && routeData.getPoint(distance).getGradient() < 0) { + //tDiff = (int) (timestamp - elapsedTimestamp)*1024/1000; + //System.out.println(">>> " + tDiff + " sDiff " + sDiff); + + //} + //elapsedTimestamp = timestamp; + if (tDiff > 0 ) { if(sDiff == 0){ if(cCount < 12){ @@ -159,7 +165,7 @@ Telemetry getTelemetry(int time, int count) { } double timeS = ((double) tDiff) / 1024; - elapsedTime += (int) (timeS * 1000); + //elapsedTime += (int) (timeS * 1000); distanceKM = (sDiff * wheelSize) / 100000; speed = distanceKM / (timeS / (3600)); @@ -172,14 +178,14 @@ Telemetry getTelemetry(int time, int count) { // based on power and gradient using magic sauce if (simulSpeed && routeData != null) { Point p = routeData.getPoint(distance); - + if (routeData.routeType() == RouteReader.SLOPE) { if (p == null) { // end of the road distance = 0.0; return null; } - if (powerWatts >= 0) { + if (powerWatts > 0) { // only works when power is positive, this is most of // the time on a turbo double realSpeed = (power.getRealSpeed(mass, @@ -198,21 +204,25 @@ Telemetry getTelemetry(int time, int count) { * Power Profile: speed is the ratio of our trainer power to * the expected power, we also apply a bit of smoothing */ - double ratio = powerRatio.add(powerWatts / p.getPower()); + double ratio = powerRatio.add(powerWatts / (double)p.getPower()); // speed is video speed * power ratio speed = p.getSpeed() * ratio; distanceKM = (speed / 3600) * timeS; } - if(distanceKM == 0){ + //if(distanceKM == 0){ //the down is to small for have speed. we stop chrono (rollback the increase of elapsedTime) - elapsedTime -= (int) (timeS * 1000); - } + //elapsedTime -= (int) (timeS * 1000); + //} + } + + cCount = 0; // received a value, reset counter + } else { + cCount++; + if (cCount < 6) { + // a zero value may just be due to too fast sensor update, wait 6 messages before sending zero + return null; } - - } else if (cCount < 6) { - // a zero value may just be due to too fast sensor update, wait 6 messages before sending zero - return null; } lastTime = time; @@ -231,7 +241,9 @@ Telemetry getTelemetry(int time, int count) { t.setLongitude(p.getLongitude()); } t.setSpeed(speed); - t.setTime(elapsedTime); + //t.setTime(elapsedTime); + t.setTime(System.currentTimeMillis()); // use realtime + distance += distanceKM; logger.debug("sending " + t); diff --git a/src/com/wattzap/model/dto/Point.java b/src/com/wattzap/model/dto/Point.java index 174cdbe..85ac365 100644 --- a/src/com/wattzap/model/dto/Point.java +++ b/src/com/wattzap/model/dto/Point.java @@ -19,7 +19,7 @@ * * Represents a data point from a route or power file (gpx, rlv, pwr etc) * - * @author David George (c) Copyright 2013 + * @author David George (c) Copyright 2013-2016 * @date 19 June 2013 */ public class Point { @@ -27,9 +27,9 @@ public class Point { private double longitude; private double elevation; private double distanceFromStart; - private double gradientOrPower; + private double gradient; + private int power; private double speed; - // private double level; private long time; public double getSpeed() { @@ -49,19 +49,19 @@ public void setTime(long time) { } public double getGradient() { - return gradientOrPower; + return gradient; } - public double getPower() { - return gradientOrPower; // overload gradient with power + public int getPower() { + return power; // overload gradient with power } public void setGradient(double gradient) { - this.gradientOrPower = gradient; + this.gradient = gradient; } - public void setPower(double power) { - this.gradientOrPower = power; + public void setPower(int power) { + this.power = power; } public double getLatitude() { @@ -100,7 +100,11 @@ public void setDistanceFromStart(double distanceFromStart) { public String toString() { return "Point [latitude=" + latitude + ", longitude=" + longitude + ", elevation=" + elevation + ", distanceFromStart=" - + distanceFromStart + ", gradient=" + gradientOrPower - + ", speed=" + speed + ", time=" + time + "]"; + + distanceFromStart + ", gradient=" + gradient + ", power=" + + power + ", speed=" + speed + ", time=" + time + "]"; + } + + public String getTcxExtensionsXml() { + return ""; } } diff --git a/src/com/wattzap/model/dto/Telemetry.java b/src/com/wattzap/model/dto/Telemetry.java index d80390f..960a5fd 100644 --- a/src/com/wattzap/model/dto/Telemetry.java +++ b/src/com/wattzap/model/dto/Telemetry.java @@ -24,39 +24,32 @@ * @author David George (c) Copyright 2013 * @date 19 June 2013 */ -public class Telemetry implements Serializable { +public class Telemetry extends Point implements Serializable { private static final double KMTOMILES = 1.609344; - private double speed; private int cadence; private double distance; - private int power; - private double elevation; - private double gradient; - private double latitude; - private double longitude; private int heartRate; private long time; private int resistance; public Telemetry() { - speed = -1; - power = -1; - latitude = 91; - longitude = 181; + setSpeed(-1); + setPower(-1); + setLatitude(91); + setLongitude(181); heartRate = -1; - } public Telemetry(Telemetry t) { - speed = t.speed; + setSpeed(t.getSpeed()); cadence = t.cadence; distance = t.distance; - power = t.power; - elevation = t.elevation; - gradient = t.gradient; - latitude = t.latitude; - longitude = t.longitude; + setPower(t.getPower()); + setElevation(t.getElevation()); + setGradient(t.getGradient()); + setLatitude(t.getLatitude()); + setLongitude(t.getLongitude()); heartRate = t.heartRate; time = t.time; } @@ -77,58 +70,14 @@ public void setHeartRate(int heartRate) { this.heartRate = heartRate; } - public double getLatitude() { - return latitude; - } - - public void setLatitude(double latitude) { - this.latitude = latitude; - } - - public double getLongitude() { - return longitude; - } - - public void setLongitude(double longitude) { - this.longitude = longitude; - } - - public double getElevation() { - return elevation; - } - - public void setElevation(double elevation) { - this.elevation = elevation; - } - - public double getGradient() { - return gradient; - } - - public void setGradient(double gradient) { - this.gradient = gradient; - } - - public int getPower() { - return power; - } - - public void setPower(int power) { - this.power = power; - } - - public void setSpeed(double speed) { - this.speed = speed; + public double getSpeedMPH() { + return getSpeed() / KMTOMILES; } public double getSpeedKMH() { - return speed; - } - - public double getSpeedMPH() { - return speed / KMTOMILES; + return getSpeed(); } - + public void setCadence(int cadence) { this.cadence = cadence; } @@ -178,11 +127,33 @@ public int getResistance() { @Override public String toString() { - return "Telemetry [speed=" + speed + ", cadence=" + cadence - + ", distance=" + distance + ", power=" + power - + ", elevation=" + elevation + ", gradient=" + gradient - + ", latitude=" + latitude + ", longitude=" + longitude - + ", heartRate=" + heartRate + " tt " + heartRate + ", time=" - + time / 1000 + "]"; + return "Telemetry [cadence=" + cadence + + ", distance=" + distance + ", heartRate=" + heartRate + " tt " + heartRate + ", time=" + + time / 1000 + "]" + super.toString(); + } + + @Override + public String getTcxExtensionsXml() { + StringBuilder sb = new StringBuilder(); + + sb.append(" "); + sb.append(""); + sb.append(heartRate); + sb.append(""); + sb.append("\n"); + sb.append(" "); + sb.append(Math.min(254, cadence)); + sb.append("\n"); + sb.append(" "); + sb.append(""); + sb.append(""); + sb.append(getPower()); + sb.append(""); + sb.append(""); + sb.append(getSpeedKMH()); + sb.append(""); + sb.append(""); + + return sb.toString(); } } diff --git a/src/com/wattzap/utils/FitImporter.java b/src/com/wattzap/utils/FitImporter.java index 5518e73..f1f816e 100644 --- a/src/com/wattzap/utils/FitImporter.java +++ b/src/com/wattzap/utils/FitImporter.java @@ -79,7 +79,7 @@ public FitImporter(String fileName) { point.getGradient(), point.getSpeedKMH()); if (p > userPrefs.getMaxPower() - && (p > (last.getPower() * 2.0))) { + && (p > (last.getPower() * 2))) { // We are above FTP and power has doubled, remove power // spikes p = (int) (last.getPower() * 1.05); diff --git a/src/com/wattzap/utils/TcxWriter.java b/src/com/wattzap/utils/TcxWriter.java index 49183ed..2bd7f6a 100644 --- a/src/com/wattzap/utils/TcxWriter.java +++ b/src/com/wattzap/utils/TcxWriter.java @@ -24,6 +24,7 @@ import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; +import java.util.List; import java.util.Locale; import java.util.TimeZone; @@ -32,6 +33,7 @@ import com.wattzap.model.RouteReader; import com.wattzap.model.UserPreferences; +import com.wattzap.model.dto.Point; import com.wattzap.model.dto.Telemetry; /** @@ -92,7 +94,7 @@ public void writeHeader() { pw.println(); } - public void writeStartTrack(Telemetry start, Telemetry end) { + public void writeStartTrack(Point start, Point end) { if (pw == null) { return; } @@ -107,7 +109,7 @@ public void writeStartTrack(Telemetry start, Telemetry end) { pw.print((end.getTime() - start.getTime()) / 1000); pw.println(""); pw.print(" "); - pw.print(end.getDistanceMeters()); + pw.print(end.getDistanceFromStart()); pw.println(""); // TODO max speed etc. // Calories are a required element just put in 0. @@ -122,7 +124,7 @@ public void writeOpenSegment() { } } - public void writeLocation(Telemetry t, int gpsData) { + public void writeLocation(Point t, int gpsData) { if (pw == null) { return; } @@ -146,30 +148,17 @@ public void writeLocation(Telemetry t, int gpsData) { pw.println(" "); + pw.print(" "); + pw.print(t.getElevation()); + pw.println(""); } - pw.print(" "); - pw.print(t.getElevation()); - pw.println(""); pw.print(" "); - pw.print(t.getDistanceMeters()); + pw.print(t.getDistanceFromStart()); pw.println(""); - pw.print(" "); - pw.print(""); - pw.print(t.getHeartRate()); - pw.print(""); - pw.println(""); - pw.print(" "); - pw.print(Math.min(254, t.getCadence())); - pw.println(""); - pw.print(" "); - pw.print(""); - pw.print(""); - pw.print(t.getPower()); - pw.print(""); - pw.print(""); - pw.print(t.getSpeedKMH()); - pw.print(""); - pw.println(""); + + pw.print(t.getTcxExtensionsXml());; + + pw.println(" "); } @@ -267,15 +256,15 @@ private void writeVersion() { * 0 - save GPS data, 1 - drop GPS data * @return */ - public String save(ArrayList data, int gpsData) { + public String save(List data, int gpsData) { String fileName = null; if (data == null || data.size() == 0) { logger.info("No training data to save"); return fileName; } - Telemetry firstPoint = data.get(0); - Telemetry lastPoint = data.get(data.size() - 1); + Point firstPoint = data.get(0); + Point lastPoint = data.get(data.size() - 1); fileName = getWorkoutName(firstPoint.getTime()); File file = new File(UserPreferences.INSTANCE.getUserDataDirectory() @@ -295,8 +284,8 @@ public String save(ArrayList data, int gpsData) { writeStartTrack(firstPoint, lastPoint); writeOpenSegment(); - Telemetry last = null; - for (Telemetry t : data) { + Point last = null; + for (Point t : data) { if (t.getLatitude() > 90 || t.getLongitude() > 180) { // No GPS data to save writeLocation(t, 1); diff --git a/src/com/wattzap/view/AboutPanel.java b/src/com/wattzap/view/AboutPanel.java index 47b9f05..6629df0 100644 --- a/src/com/wattzap/view/AboutPanel.java +++ b/src/com/wattzap/view/AboutPanel.java @@ -68,7 +68,7 @@ public AboutPanel() { if (key == null || key.length() == 0) { userPrefs.setRegistrationKey("Community Edition"); } - about.setText("WattzAp Community Edition

Version 2.6
26th October 2015"); + about.setText("WattzAp Community Edition

Version 2.7
12th February 2016"); add(about,"alignx right, span"); debug = new JCheckBox("Enable Debugging"); diff --git a/src/com/wattzap/view/AntOdometer.java b/src/com/wattzap/view/AntOdometer.java index f098ac1..d9e92c5 100644 --- a/src/com/wattzap/view/AntOdometer.java +++ b/src/com/wattzap/view/AntOdometer.java @@ -193,13 +193,11 @@ public AntOdometer() { private void initLabels(boolean metric) { if (metric) { - speedText - .setText(userPrefs.getString("speed") + " (km/h)"); + speedText.setText(userPrefs.getString("speed") + " (km/h)"); distText.setText(userPrefs.getString("distance") + " (km)"); } else { speedText.setText(userPrefs.getString("speed") + " (mph)"); - distText.setText(userPrefs.getString("distance") - + " (miles)"); + distText.setText(userPrefs.getString("distance") + " (miles)"); } } @@ -225,21 +223,24 @@ public void callback(Messages message, Object o) { t.getDistanceMiles())); } - if (current != null) { - int i = current.isPowerInRange(t.getPower()); - if (i < 0) { - powerLabel.setForeground(skyBlue); - powerLabel.setText("" + t.getPower()); - } else if (i > 0) { - powerLabel.setForeground(Color.RED); - powerLabel.setText("" + t.getPower()); + int power = t.getPower(); + if (power != -1) { + if (current != null) { + int i = current.isPowerInRange(power); + if (i < 0) { + powerLabel.setForeground(skyBlue); + powerLabel.setText("" + power); + } else if (i > 0) { + powerLabel.setForeground(Color.RED); + powerLabel.setText("" + power); + } else { + powerLabel.setForeground(Color.WHITE); + powerLabel.setText("" + power); + } + } else { - powerLabel.setForeground(Color.WHITE); - powerLabel.setText("" + t.getPower()); + powerLabel.setText("" + power); } - - } else { - powerLabel.setText("" + t.getPower()); } chronoLabel.setText(timeFormat.format(new Date(t.getTime() @@ -328,8 +329,7 @@ public void callback(Messages message, Object o) { switch (type) { case RouteReader.POWER: slopeText.setText(userPrefs.getString("target_power")); - levelText - .setText(userPrefs.getString("distance_left")); + levelText.setText(userPrefs.getString("distance_left")); break; case RouteReader.SLOPE: slopeText.setText(userPrefs.getString("slope") + " %"); diff --git a/src/com/wattzap/view/MainFrame.java b/src/com/wattzap/view/MainFrame.java index 3a318cd..410282e 100644 --- a/src/com/wattzap/view/MainFrame.java +++ b/src/com/wattzap/view/MainFrame.java @@ -42,7 +42,7 @@ public class MainFrame extends JFrame implements ActionListener, MessageCallback { private static final long serialVersionUID = -4597500546349817204L; - private static final String appName = "WattzAp"; + private static final String appName = "WattzAp v2.7"; private Logger logger = LogManager.getLogger("Main Frame"); diff --git a/src/com/wattzap/view/RouteFilePicker.java b/src/com/wattzap/view/RouteFilePicker.java index 452d64f..281dafa 100644 --- a/src/com/wattzap/view/RouteFilePicker.java +++ b/src/com/wattzap/view/RouteFilePicker.java @@ -30,6 +30,8 @@ import org.apache.log4j.LogManager; import org.apache.log4j.Logger; +import com.gpxcreator.gpxpanel.GPXFile; +import com.wattzap.MenuBar; import com.wattzap.controller.MessageBus; import com.wattzap.controller.Messages; import com.wattzap.model.Readers; @@ -46,7 +48,8 @@ */ public class RouteFilePicker extends JFileChooser implements ActionListener { private static final long serialVersionUID = 1L; - JFrame frame; + private JFrame frame; + private RouteReader track; private static Logger logger = LogManager.getLogger("Route File Picker"); @@ -91,27 +94,43 @@ public final void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); logger.debug(command); - int retVal = showOpenDialog(frame); - File file = getSelectedFile(); - try { - if (retVal == JFileChooser.APPROVE_OPTION) { - UserPreferences.INSTANCE.setRouteDir(file.getParent()); - RouteReader track; - String ext = file.getName().substring( - file.getName().length() - 3); - track = Readers.INSTANCE.getReader(ext); - if (track != null) { - track.load(file.getAbsolutePath()); - MessageBus.INSTANCE.send(Messages.GPXLOAD, track); - } + if (command.equals(MenuBar.SAVEROUTE)) { + GPXFile gpx = track.getGpxFile(); + if (gpx == null || !"tts".equals(track.getExtension())) { + JOptionPane.showMessageDialog( + frame, + "No routing information or not TTS " + + track.getFilename(), "Error", + JOptionPane.ERROR_MESSAGE); } else { - logger.info("Open command cancelled by user."); + File f = new File(track.getFilename() + ".gpx"); + gpx.saveToGPXFile(f); + } + } else { + + int retVal = showOpenDialog(frame); + File file = getSelectedFile(); + try { + if (retVal == JFileChooser.APPROVE_OPTION) { + UserPreferences.INSTANCE.setRouteDir(file.getParent()); + + String ext = file.getName().substring( + file.getName().length() - 3); + track = Readers.INSTANCE.getReader(ext); + if (track != null) { + track.load(file.getAbsolutePath()); + MessageBus.INSTANCE.send(Messages.GPXLOAD, track); + } + } else { + logger.info("Open command cancelled by user."); + } + } catch (Exception ex) { + JOptionPane.showMessageDialog(frame, ex.getMessage() + " " + + file.getAbsolutePath(), "Error", + JOptionPane.ERROR_MESSAGE); } - } catch (Exception ex) { - JOptionPane.showMessageDialog(frame, - ex.getMessage() + " " + file.getAbsolutePath(), "Error", - JOptionPane.ERROR_MESSAGE); } + } /** Listen to the slider. */ diff --git a/src/com/wattzap/view/VideoPlayer.java b/src/com/wattzap/view/VideoPlayer.java index 1e47997..ab0c553 100644 --- a/src/com/wattzap/view/VideoPlayer.java +++ b/src/com/wattzap/view/VideoPlayer.java @@ -18,13 +18,13 @@ import java.awt.Canvas; import java.awt.Color; import java.awt.Rectangle; -import java.awt.event.ActionEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; +import java.awt.Robot; +import java.awt.image.BufferedImage; import java.io.File; import java.math.BigDecimal; import java.math.RoundingMode; +import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JPanel; @@ -70,6 +70,8 @@ public class VideoPlayer extends JFrame implements MessageCallback { private EmbeddedMediaPlayer mPlayer; private MediaPlayerFactory mediaPlayerFactory; private Canvas canvas; + private ScreenGrabber grabber = null; + int imageCount = 0; long startTime = 0; long mapStartTime; @@ -96,12 +98,12 @@ public VideoPlayer(JFrame main, JPanel odo) { this.mainFrame = main; setTitle("Video - www.WattzAp.com"); - //setUndecorated(true); + // setUndecorated(true); ImageIcon img = new ImageIcon("icons/video.jpg"); setIconImage(img.getImage()); /* Messages we are interested in */ - //MessageBus.INSTANCE.register(Messages.SPEED, this); + // MessageBus.INSTANCE.register(Messages.SPEED, this); MessageBus.INSTANCE.register(Messages.STARTPOS, this); MessageBus.INSTANCE.register(Messages.STOP, this); MessageBus.INSTANCE.register(Messages.CLOSE, this); @@ -264,22 +266,30 @@ private void setSpeed(Telemetry t) { */ @Override public void callback(Messages message, Object o) { + switch (message) { case SPEED: + if (grabber == null && UserPreferences.INSTANCE.isScreenshot()) { + (grabber = new ScreenGrabber(this, 300)).start(); + } if (videoLoaded && routeData != null) { Telemetry t = (Telemetry) o; setSpeed(t); } + break; case STOP: if (mPlayer != null) { - if (mPlayer.isPlaying()) { logger.debug("Pausing video player"); mPlayer.pause(); } } + if (grabber != null) { + grabber.shutdown(); + grabber = null; + } break; case START: break; @@ -297,8 +307,10 @@ public void callback(Messages message, Object o) { mPlayer.setPosition(pos); } } + break; case CLOSE: + // by default add to telemetry frame remove(odo); mainFrame.add(odo, "cell 0 2, grow"); @@ -316,6 +328,10 @@ public void callback(Messages message, Object o) { routeData.close(); len = 0; } + if (grabber != null) { + grabber.shutdown(); + grabber = null; + } break; case GPXLOAD: routeData = (RouteReader) o; @@ -337,12 +353,11 @@ public void callback(Messages message, Object o) { mainFrame.repaint(); mPlayer.enableOverlay(false); mPlayer.prepareMedia(videoFile + ext); - + long DurationInSeconds;// gives us video time mPlayer.parseMedia(); DurationInSeconds = (mPlayer.getMediaMeta().getLength()); - //System.out.println("duration " + DurationInSeconds); - + // System.out.println("duration " + DurationInSeconds); add(odo, java.awt.BorderLayout.SOUTH); videoLoaded = true; @@ -350,12 +365,11 @@ public void callback(Messages message, Object o) { revalidate(this); setVisible(true); MessageBus.INSTANCE.register(Messages.SPEED, this); - + fps = mPlayer.getFps(); len = mPlayer.getLength(); - //System.out.println("fps " + fps + " len " + len); - - + // System.out.println("fps " + fps + " len " + len); + break; } } @@ -384,4 +398,59 @@ private void revalidate(JFrame frame) { frame.validate(); } + /** + * Helper class to take periodic screen shots + */ + public class ScreenGrabber extends Thread { + JFrame frame; + long seconds; + private String userDir; + private volatile boolean done = false; + + ScreenGrabber(JFrame frame, long seconds) { + this.seconds = seconds; + this.frame = frame; + userDir = UserPreferences.INSTANCE.getUserDataDirectory(); + } + + public void run() { + while (!done) { + try { + Thread.sleep(seconds * 1000); + } catch (InterruptedException e) { + } + screenshot(); + imageCount++; + } + } + + public void shutdown() { + done = true; + } + + /** + * take a screen shot + */ + void screenshot() { + try { + + Robot robot = new Robot(); + // Capture the screen shot of the area of the screen defined by + // the rectangle + + BufferedImage bi = robot.createScreenCapture(new Rectangle( + frame.getX(), frame.getY(), + frame.getWidth(), frame.getHeight())); + ImageIO.write(bi, "png", new File(userDir + "/screen-" + + imageCount + ".png")); + + } catch (Exception e) { + logger.error("Exception to write image " + + e.getLocalizedMessage()); + } + + } + + } + } \ No newline at end of file diff --git a/src/com/wattzap/view/Workouts.java b/src/com/wattzap/view/Workouts.java index 317f2e5..d80fe33 100644 --- a/src/com/wattzap/view/Workouts.java +++ b/src/com/wattzap/view/Workouts.java @@ -70,6 +70,7 @@ import com.wattzap.utils.ActivityReader; import com.wattzap.utils.TcxWriter; import com.wattzap.view.graphs.DistributionGraph; +import com.wattzap.view.graphs.GPanel; import com.wattzap.view.graphs.GenericScatterGraph; import com.wattzap.view.graphs.MMPGraph; import com.wattzap.view.graphs.SCHRGraph; @@ -141,7 +142,7 @@ public Workouts() { this.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); selectedRows = null; - DefaultTableModel model = new DefaultTableModel(0,columnNames.length); + DefaultTableModel model = new DefaultTableModel(0, columnNames.length); loadData(model); table = new JTable(model); @@ -203,7 +204,7 @@ public void valueChanged(ListSelectionEvent e) { // need button for Load, Delete // Create and set up the window. - frame = new JFrame( ); + frame = new JFrame(); ImageIcon img = new ImageIcon("icons/turbo.jpg"); frame.setIconImage(img.getImage()); @@ -260,8 +261,7 @@ public void valueChanged(ListSelectionEvent e) { powerWattsMenuItem.addActionListener(this); scatMenu.add(powerWattsMenuItem); - quadAnalysisMenuItem = new JMenuItem( - userPrefs.getString("quadAnal")); + quadAnalysisMenuItem = new JMenuItem(userPrefs.getString("quadAnal")); quadAnalysisMenuItem.setActionCommand(qaGraph); quadAnalysisMenuItem.addActionListener(this); scatMenu.add(quadAnalysisMenuItem); @@ -373,8 +373,7 @@ public void actionPerformed(ActionEvent e) { logger.info("Out of time " + UserPreferences.INSTANCE.getEvalTime()); JOptionPane.showMessageDialog(this, - UserPreferences.INSTANCE - .getString("trial_expired"), + UserPreferences.INSTANCE.getString("trial_expired"), UserPreferences.INSTANCE.getString("warning"), JOptionPane.WARNING_MESSAGE); return; @@ -414,7 +413,8 @@ public void actionPerformed(ActionEvent e) { } JOptionPane.showMessageDialog(this, importedFiles.toString(), - userPrefs.getString("import"), JOptionPane.INFORMATION_MESSAGE); + userPrefs.getString("import"), + JOptionPane.INFORMATION_MESSAGE); return; } @@ -448,8 +448,7 @@ public void actionPerformed(ActionEvent e) { public int getKey(Telemetry t) { return getKey(t.getPower()); } - }, 15, userPrefs.getString("pdGr"), - userPrefs.getString("poWtt")); + }, 15, userPrefs.getString("pdGr"), userPrefs.getString("poWtt")); return; } if (cdGraph.equals(command)) { @@ -458,8 +457,7 @@ public int getKey(Telemetry t) { public int getKey(Telemetry t) { return getKey(t.getCadence()); } - }, 5, userPrefs.getString("cDgr"), - userPrefs.getString("cDrpm")); + }, 5, userPrefs.getString("cDgr"), userPrefs.getString("cDrpm")); return; } if (hrdGraph.equals(command)) { @@ -471,8 +469,7 @@ public int getKey(Telemetry t) { return getKey(t.getHeartRate()); } - }, 10, userPrefs.getString("hrDgr"), - userPrefs.getString("hrBpm")); + }, 10, userPrefs.getString("hrDgr"), userPrefs.getString("hrBpm")); return; } if (tlGraph.equals(command)) { @@ -488,7 +485,8 @@ public int getKey(Telemetry t) { public String getValueLabel(int v) { return TrainingItem.getTrainingName(v) + " " + v; } - }, 0, userPrefs.getString("trainDist"), userPrefs.getString("trainlevel")); + }, 0, userPrefs.getString("trainDist"), + userPrefs.getString("trainlevel")); return; } if (tlhrGraph.equals(command)) { @@ -504,7 +502,8 @@ public int getKey(Telemetry t) { public String getValueLabel(int v) { return TrainingItem.getTrainingName(v) + " " + v; } - }, 0, userPrefs.getString("trainlevelhr"), userPrefs.getString("trainlevel")); + }, 0, userPrefs.getString("trainlevelhr"), + userPrefs.getString("trainlevel")); return; } } @@ -522,8 +521,8 @@ public String getValueLabel(int v) { private boolean load() { if (selectedRows == null || selectedRows.isEmpty()) { JOptionPane.showMessageDialog(this, - userPrefs.getString("noDataDisp"), userPrefs.getString("noData"), - JOptionPane.ERROR_MESSAGE); + userPrefs.getString("noDataDisp"), + userPrefs.getString("noData"), JOptionPane.ERROR_MESSAGE); return false; } else if (listChanged == false && telemetry != null) { // data already loaded and nothing changed @@ -560,8 +559,8 @@ private boolean load() { void reanalyze() { if (selectedRows == null || selectedRows.isEmpty()) { JOptionPane.showMessageDialog(this, - userPrefs.getString("noDataDisp"), userPrefs.getString("noData"), - JOptionPane.ERROR_MESSAGE); + userPrefs.getString("noDataDisp"), + userPrefs.getString("noData"), JOptionPane.ERROR_MESSAGE); return; } @@ -644,7 +643,7 @@ public void mmpGraph() { for (Entry entry : powerValues.descendingMap() .entrySet()) { Integer pwr = entry.getKey(); // power, Y axis - + if (total == 0) { // first time thru total = entry.getValue(); @@ -655,23 +654,24 @@ public void mmpGraph() { } else { total += entry.getValue(); // time in milliseconds - X axis } - if (total > (20*60*1000) && ftp20 == 0) { + if (total > (20 * 60 * 1000) && ftp20 == 0) { // 20 minutes ftp20 = pwr; - ftp20T = total/1000; + ftp20T = total / 1000; } - if (total > (60*60*1000) && ftp == 0) { + if (total > (60 * 60 * 1000) && ftp == 0) { // 20 minutes ftp = pwr; - ftpT = total/1000; + ftpT = total / 1000; } - + series.addOrUpdate(total / 1000, (double) pwr); }// for MMPGraph mmp = new MMPGraph(series, ftp20, ftp20T, ftp, ftpT); - JFrame frame = new JFrame(userPrefs.getString("mmp")); + String title = userPrefs.getString("mmp"); + JFrame frame = new JFrame(title); ImageIcon img = new ImageIcon("icons/turbo.jpg"); frame.setIconImage(img.getImage()); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); @@ -679,7 +679,7 @@ public void mmpGraph() { // Create and set up the content pane. mmp.setOpaque(true); // content panes must be opaque - frame.setContentPane(mmp); + frame.setContentPane(new GPanel(mmp, removeNonASCII(title))); // Display the window. frame.pack(); @@ -734,14 +734,15 @@ private void QuadrantAnalysis() { series3.add(3, aepf); mmp.addLine(series3); - JFrame frame = new JFrame(userPrefs.getString("quadAnal")); + String title = userPrefs.getString("quadAnal"); + JFrame frame = new JFrame(title); ImageIcon img = new ImageIcon("icons/turbo.jpg"); frame.setIconImage(img.getImage()); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // Create and set up the content pane. mmp.setOpaque(true); // content panes must be opaque - frame.setContentPane(mmp); + frame.setContentPane(new GPanel(mmp, removeNonASCII(title))); // Display the window. frame.pack(); @@ -764,9 +765,10 @@ private void CSScatterPlot() { }// for GenericScatterGraph mmp = new GenericScatterGraph(series, - userPrefs.getString("poWtt"), - userPrefs.getString("cDrpm")); - JFrame frame = new JFrame(userPrefs.getString("cadPow")); + userPrefs.getString("poWtt"), userPrefs.getString("cDrpm")); + + String title = userPrefs.getString("cadPow"); + JFrame frame = new JFrame(title); ImageIcon img = new ImageIcon("icons/turbo.jpg"); frame.setIconImage(img.getImage()); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); @@ -774,7 +776,7 @@ private void CSScatterPlot() { // Create and set up the content pane. mmp.setOpaque(true); // content panes must be opaque - frame.setContentPane(mmp); + frame.setContentPane(new GPanel(mmp, removeNonASCII(title))); // Display the window. frame.pack(); @@ -794,9 +796,10 @@ public void HRWattsScatterPlot() { }// for GenericScatterGraph mmp = new GenericScatterGraph(series, - userPrefs.getString("poWtt"), - userPrefs.getString("hrBpm")); - JFrame frame = new JFrame(userPrefs.getString("hrPow")); + userPrefs.getString("poWtt"), userPrefs.getString("hrBpm")); + + String title = userPrefs.getString("hrPow"); + JFrame frame = new JFrame(title); ImageIcon img = new ImageIcon("icons/turbo.jpg"); frame.setIconImage(img.getImage()); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); @@ -804,7 +807,7 @@ public void HRWattsScatterPlot() { // Create and set up the content pane. mmp.setOpaque(true); // content panes must be opaque - frame.setContentPane(mmp); + frame.setContentPane(new GPanel(mmp, removeNonASCII(title))); // Display the window. frame.pack(); @@ -825,7 +828,7 @@ public void DistributionGraph(DistributionAccessor da, int scale, // Create and set up the content pane. dgGraph.setOpaque(true); // content panes must be opaque - frame.setContentPane(dgGraph); + frame.setContentPane(new GPanel(dgGraph, removeNonASCII(title))); // Display the window. frame.pack(); @@ -850,14 +853,14 @@ public void SCHRGraph() { pchrGraph.updateValues(1); pchrGraph.updateWorkoutData(workoutData); - JFrame frame = new JFrame(userPrefs.getString("rideSum")); + String title = userPrefs.getString("rideSum"); + JFrame frame = new JFrame(title); ImageIcon img = new ImageIcon("icons/turbo.jpg"); frame.setIconImage(img.getImage()); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - // Create and set up the content pane. pchrGraph.setOpaque(true); // content panes must be opaque - frame.setContentPane(pchrGraph); + frame.setContentPane(new GPanel(pchrGraph, removeNonASCII(title))); // Display the window. frame.pack(); @@ -872,8 +875,7 @@ void delete() { } StringBuilder output = new StringBuilder(); - output.append(UserPreferences.INSTANCE.getString("delMsg") - + "\n\n"); + output.append(UserPreferences.INSTANCE.getString("delMsg") + "\n\n"); int[] rows = new int[selectedRows.size()]; Iterator row = selectedRows.iterator(); @@ -922,8 +924,9 @@ private void deleteSelectedRows(int[] rows) { * Setup button text, makes it easy to update if locale is changed */ private void doText() { - frame.setTitle("Wattzap Analyzer - " + userPrefs.getString("training_analysis")); - + frame.setTitle("Wattzap Analyzer - " + + userPrefs.getString("training_analysis")); + summaryMenu.setText(userPrefs.getString("summary")); mmpMenuItem.setText(userPrefs.getString("mmp")); schrMenuItem.setText(userPrefs.getString("schr")); @@ -962,6 +965,10 @@ public void callback(Messages message, Object o) { } } + private String removeNonASCII(String s) { + return s.replaceAll("[^\\x00-\\x7F]", ""); + } + public class MyCellRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; diff --git a/src/com/wattzap/view/graphs/SCHRGraph.java b/src/com/wattzap/view/graphs/SCHRGraph.java index b911902..21261b6 100644 --- a/src/com/wattzap/view/graphs/SCHRGraph.java +++ b/src/com/wattzap/view/graphs/SCHRGraph.java @@ -54,7 +54,7 @@ /** * Speed, Cadence, Heart-Rate Graph * - * @author David George (c) Copyright 2014,2015 + * @author David George (c) Copyright 2014-2016 * @date 18 April 2014 */ public class SCHRGraph extends JPanel { @@ -246,6 +246,7 @@ public Paint getItemPaint(int row, int column) { SmoothingPanel smoothingPanel = new SmoothingPanel(this); add(smoothingPanel, BorderLayout.SOUTH); + //infoPanel = new InfoPanel(); //add(infoPanel, BorderLayout.NORTH); setVisible(true); @@ -291,6 +292,8 @@ public void updateWorkoutData(WorkoutData data) { } infoPanel.update(data); } + + private static final long serialVersionUID = 1L; } diff --git a/src/com/wattzap/view/prefs/Preferences.java b/src/com/wattzap/view/prefs/Preferences.java index 6265ed9..e9c44cf 100644 --- a/src/com/wattzap/view/prefs/Preferences.java +++ b/src/com/wattzap/view/prefs/Preferences.java @@ -69,7 +69,8 @@ public class Preferences extends JFrame implements ActionListener, JTextField maxHR; JTextField maxPwr; JCheckBox units; - + JCheckBox screenshot; + JButton saveButton; JButton cancelButton; JTabbedPane jtp; @@ -207,7 +208,6 @@ private void userdata(JPanel tab) { tab.add(units); langLabel = new JLabel(); - tab.add(langLabel); int index = 0; @@ -227,6 +227,12 @@ private void userdata(JPanel tab) { index++; } tab.add(languageList, "span"); + + screenshot = new JCheckBox("Auto Screenshot"); + screenshot.setSelected(userPrefs.isScreenshot()); + screenshot.setActionCommand("screenshot"); + screenshot.addActionListener(this); + tab.add(screenshot); } @Override @@ -259,6 +265,12 @@ public void actionPerformed(ActionEvent e) { userPrefs.getBikeWeight())); } + } else if ("screenshot".equals(command)) { + if (screenshot.isSelected()) { + userPrefs.setScreenshot(true); + } else { + userPrefs.setScreenshot(false); + } } else if ("cancel".equals(command)) { setVisible(false); // you can't see me! dispose(); // Destroy the JFrame object @@ -325,6 +337,7 @@ public void updatePreferences() { PowerProfiles pp = PowerProfiles.INSTANCE; Power p = pp.getProfile(profile); userPrefs.setPowerProfile(profile); + if (p.getResitanceLevels() > 1) { int level = trainerPanel.getResistanceLevel(); userPrefs.setResistance(level); diff --git a/src/com/wattzap/view/training/TrainingDisplay.java b/src/com/wattzap/view/training/TrainingDisplay.java index 3840d6c..e55f075 100644 --- a/src/com/wattzap/view/training/TrainingDisplay.java +++ b/src/com/wattzap/view/training/TrainingDisplay.java @@ -144,6 +144,7 @@ private void createModels(TrainingData tData) { } support = ChartFactory.createSimpleXYChart(descriptor); + chart = support.getChart(); add(chart, BorderLayout.CENTER); chart.setVisible(true); diff --git a/test/com/wattzap/model/TTSReaderTest.java b/test/com/wattzap/model/TTSReaderTest.java index 4790fee..0cf1503 100644 --- a/test/com/wattzap/model/TTSReaderTest.java +++ b/test/com/wattzap/model/TTSReaderTest.java @@ -17,6 +17,9 @@ import java.io.File; import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.junit.After; import org.junit.Assert; @@ -25,6 +28,7 @@ import com.gpxcreator.gpxpanel.GPXFile; import com.wattzap.model.dto.Point; +import com.wattzap.utils.TcxWriter; public class TTSReaderTest { TTSReader ttsReader; @@ -52,7 +56,7 @@ public void routeType() { Assert.assertEquals(TTSReader.SLOPE, ttsReader.routeType()); } - // @Test + @Test public void loadMortiroloRoute() { // String[] files = new String[] { "./resources/test/tts/IT_Eroica.tts", @@ -71,21 +75,31 @@ public void loadMortiroloRoute() { System.err.println("File " + file); } + out.println("File " + file); ttsReader.load(file); + + TcxWriter writer = new TcxWriter(); + List list = new ArrayList(Arrays.asList(ttsReader.getPoints())); + String fileName = writer.save(list, 0); + out.println(""); } } - // @Test + //@Test public void loadEroicaRoute() { String file = "./resources/test/tts/IT_Eroica.tts"; out.println("File " + file); ttsReader.load(file); + + TcxWriter writer = new TcxWriter(); + List list = new ArrayList(Arrays.asList(ttsReader.getPoints())); + String fileName = writer.save(list, 0); - out.println(""); + out.println("" + fileName); } @Test @@ -108,6 +122,8 @@ public void loadSanSebRoute() { + gpx.getEleMaxMeters()); File f = new File("/home/david/tmp.gpx"); gpx.saveToGPXFile(f); + + } // @Test diff --git a/test/com/wattzap/model/ant/SpeedListenerTest.java b/test/com/wattzap/model/ant/SpeedListenerTest.java new file mode 100644 index 0000000..209e854 --- /dev/null +++ b/test/com/wattzap/model/ant/SpeedListenerTest.java @@ -0,0 +1,132 @@ +/* This file is part of Wattzap Community Edition. + * + * Wattzap Community Edtion is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Wattzap Community Edition is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Wattzap. If not, see . + */ +package com.wattzap.model.ant; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.wattzap.controller.Messages; +import com.wattzap.model.RouteReader; +import com.wattzap.model.TTSReader; +import com.wattzap.model.dto.Telemetry; + +public class SpeedListenerTest { + SpeedListener listener; + RouteReader ttsReader; + + @Before + public void setup() { + listener = new SpeedListener(); + ttsReader = new TTSReader(); + String file = "./resources/test/tts/E_SanSebastian2011-Demo.tts"; + System.out.println("File " + file); + ttsReader.load(file); + + // load gps here + listener.callback(Messages.GPXLOAD, ttsReader); + listener.callback(Messages.START, null); + } + + @After + public void tearDown() { + + } + + @Test + public void testBackwardsCount() { + Telemetry t; + + t = listener.getTelemetry(0, 0); + System.out.println(t); + t = listener.getTelemetry(1000, 1); + System.out.println(t); + t = listener.getTelemetry(2000, 2); + System.out.println(t); + t = listener.getTelemetry(3000, 3); + System.out.println(t); + t = listener.getTelemetry(4000, 3); + System.out.println(t); + t = listener.getTelemetry(1000, 4); + System.out.println(t); + t = listener.getTelemetry(2000, 5); + System.out.println(t); + t = listener.getTelemetry(4000, 3); + System.out.println(t); + } + + @Test + public void testZeroSpeed() { + Telemetry t; + + t = listener.getTelemetry(0, 0); + System.out.println(t); + t = listener.getTelemetry(1000, 1); + System.out.println(t); + t = listener.getTelemetry(2000, 2); + System.out.println(t); + t = listener.getTelemetry(3000, 3); + System.out.println(t); + t = listener.getTelemetry(4000, 4); + System.out.println(t); + t = listener.getTelemetry(5000, 5); + System.out.println(t); + t = listener.getTelemetry(6000, 6); + System.out.println(t); + t = listener.getTelemetry(7000, 6); + System.out.println(t); + t = listener.getTelemetry(8000, 6); + System.out.println(t); + t = listener.getTelemetry(9000, 6); // 3 + System.out.println(t); + t = listener.getTelemetry(9001, 6); + System.out.println(t); + t = listener.getTelemetry(9002, 6); + System.out.println(t); + t = listener.getTelemetry(9003, 6); + System.out.println(t); + t = listener.getTelemetry(9004, 6); + System.out.println(t); + t = listener.getTelemetry(14000, 6); + System.out.println(t); + t = listener.getTelemetry(15000, 6); + System.out.println(t); + t = listener.getTelemetry(16000, 6); + System.out.println(t); + t = listener.getTelemetry(17000, 6); + System.out.println(t); + t = listener.getTelemetry(18000, 6); + System.out.println(t); + t = listener.getTelemetry(19000, 6); + System.out.println(t); + t = listener.getTelemetry(20000, 6); + + System.out.println(t); + t = listener.getTelemetry(21000, 6); + + System.out.println(t); + t = listener.getTelemetry(22000, 6); + + System.out.println(t); + t = listener.getTelemetry(23000, 6); + + System.out.println(t); + t = listener.getTelemetry(7000, 7); + System.out.println(t); + + } + +} diff --git a/test/com/wattzap/utils/StringXORerTest.java b/test/com/wattzap/utils/StringXORerTest.java index 0164365..831cdf4 100644 --- a/test/com/wattzap/utils/StringXORerTest.java +++ b/test/com/wattzap/utils/StringXORerTest.java @@ -23,7 +23,7 @@ public class StringXORerTest { @Test public void encodeString() { String s = StringXORer - .encode("WattzAp Turbo Trainer Software

Version: 2.6
Date: 26th October
(c) 2015, All rights reserved
", + .encode("WattzAp Turbo Trainer Software

Version: 2.7
Date: 10th February
(c) 2016, All rights reserved
", cryptKey); System.out.println(s); s = StringXORer.decode(s, cryptKey);