Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30c877a5f2 | ||
|
|
92d2601a5a | ||
|
|
113375669f | ||
|
|
cd0e9c184b | ||
|
|
28cbe359d4 |
25
.gitignore
vendored
@@ -1,33 +1,8 @@
|
||||
Makefile
|
||||
.qmake.stash
|
||||
|
||||
# old skool
|
||||
.svn
|
||||
*.pri
|
||||
|
||||
# osx noise
|
||||
.DS_Store
|
||||
profile
|
||||
|
||||
moc/
|
||||
obj/
|
||||
lib/
|
||||
bin/
|
||||
plugins/
|
||||
resources/
|
||||
src/debug/
|
||||
src/release/
|
||||
|
||||
qwt/src/debug/
|
||||
qwt/src/release/
|
||||
src/Makefile.Debug
|
||||
src/Makefile.Release
|
||||
src/object_script.GoldenCheetah.Debug
|
||||
src/object_script.GoldenCheetah.Release
|
||||
qwt/src/object_script.libqwt.Release
|
||||
qwt/src/object_script.libqwtd.Debug
|
||||
qwt/src/Makefile.Release
|
||||
qwt/src/Makefile.Debug
|
||||
qwt/textengines/mathml/debug/
|
||||
qwt/textengines/mathml/release/
|
||||
build.pro.user
|
||||
|
||||
373
INSTALL-LINUX
@@ -1,373 +0,0 @@
|
||||
+++++++++++++++++++++++
|
||||
LINUX BUILD WALKTHROUGH
|
||||
+++++++++++++++++++++++
|
||||
|
||||
Mark Liversedge
|
||||
John Ehrlinger
|
||||
|
||||
Jan 2015
|
||||
Version 1.2
|
||||
|
||||
A walkthrough of building GoldenCheetah from scratch on Ubuntu linux. This walkthrough
|
||||
should be largely the same for any Linux distro.
|
||||
|
||||
CONTENTS
|
||||
|
||||
1. BASIC INSTALLATION WITH MANDATORY DEPENDENCIES
|
||||
- QT
|
||||
- git
|
||||
|
||||
2. ADDING OPTIONAL DEPENDENCIES WHEN BUILDING VERSION 2
|
||||
- FTDI D2XX
|
||||
- SRMIO
|
||||
- liboauth
|
||||
- QwtPlot3d
|
||||
- libkml
|
||||
|
||||
3. ADDING OPTIONAL DEPENDENCIES WHEN BUILDING VERSION 3
|
||||
- checking out the release 3 branch & building with MANDATORY dependencies
|
||||
- flex
|
||||
- bison
|
||||
- libical - Diary window and CalDAV support (google/mobileme calendar integration)
|
||||
- libvlc - Video playback in training mode
|
||||
|
||||
1. BASIC INSTALLATION WITH MANDATORY DEPENDENCIES
|
||||
=================================================
|
||||
|
||||
Installed Ubuntu 11.04 from CD image amd-64.iso. You will not need to do this if you
|
||||
already have a Linux distribution installed. Left this step in to highlight the
|
||||
Linux distribution the commands below were executed on.
|
||||
|
||||
login and open a terminal to get a shell prompt
|
||||
|
||||
Download MANDATORY DEPENDENCIES (browser)
|
||||
-----------------------------------------
|
||||
Download and install the Qt 4.8 SDK from http://qt-project.org/
|
||||
Once that is completed test qmake is ok with: qmake --version (should report 4.7.0 or higher)
|
||||
|
||||
Install git with:
|
||||
$ sudo apt-get install git
|
||||
Said Y to prompt about all git files installed (git-gui et al)
|
||||
|
||||
Install FLEX and BISON
|
||||
----------------------
|
||||
|
||||
You will need flex v2.5.9 or later
|
||||
$ sudo apt-get install bison
|
||||
$ sudo apt-get install flex
|
||||
$ vi gcconfig.pri
|
||||
|
||||
Ensure you have the following lines (which are now also in gcconfig.pri.in which has
|
||||
been updated to reflect the new dependencies in version 3)
|
||||
|
||||
QMAKE_LEX = flex
|
||||
QMAKE_YACC = bison
|
||||
win32 {
|
||||
QMAKE_YACC = bison --file-prefix=y -t
|
||||
QMAKE_MOVE = cmd /c move
|
||||
QMAKE_DEL_FILE = rm -f
|
||||
}
|
||||
|
||||
Build!
|
||||
------
|
||||
$ make clean
|
||||
$ qmake
|
||||
$ make
|
||||
|
||||
You will now have a release3 binary but with none of the release3 dependencies compiled in.
|
||||
Get latest GOLDEN CHEETAH source files
|
||||
--------------------------------------
|
||||
$ mkdir -p ~/Projects/Live
|
||||
$ cd ~/Projects/Live
|
||||
$ git clone git://github.com/GoldenCheetah/GoldenCheetah.git
|
||||
$ cd GoldenCheetah
|
||||
|
||||
Configure MANDATORY DEPENDENCIES
|
||||
--------------------------------
|
||||
$ cd qwt
|
||||
$ cp qwtconfig.pri.in qwtconfig.pri
|
||||
$ cd ../src
|
||||
$ cp gcconfig.pri.in gcconfig.pri
|
||||
$ vi gcconfig.pri
|
||||
|
||||
Comment out the D2XX_INCLUDE and SRMIO_INSTALL lines for now (put # in first character of the line
|
||||
to comment out), we will install that in a moment, if we need to.
|
||||
|
||||
If you are building for your local host you may find that you get better performance if
|
||||
compiling with gcc -O3 (tree vectorization can have a significat impact) [or -Ofast]
|
||||
|
||||
If so you might like to uncomment:
|
||||
|
||||
QMAKE_CXXFLAGS += -O3
|
||||
|
||||
Save and exit
|
||||
|
||||
$ cd ..
|
||||
|
||||
BUILD WITH BASIC CONFIGURATION
|
||||
$ qmake -recursive
|
||||
$ make
|
||||
|
||||
Congratulations you have now build a basic GoldenCheetah and can run this safely. See below for
|
||||
optional dependencies you can install to support other features.
|
||||
|
||||
ADDING OPTIONAL DEPENDENCIES WHEN BUILDING VERSION 2
|
||||
====================================================
|
||||
|
||||
D2XX - For Powertap downloads via USB
|
||||
-------------------------------------
|
||||
|
||||
Download the FTDI drivers from http://www.ftdichip.com/Drivers/D2XX.htm (e.g. I used Linux
|
||||
64-bit drivers from http://www.ftdichip.com/Drivers/D2XX/Linux/libftd2xx1.0.4.tar.gz)
|
||||
|
||||
Extract into your home directory (I put mine into ~/Projects/ with archive manager which
|
||||
created a sub-directory ~/Projects/libftd2xx1.0.4
|
||||
|
||||
$ cd src
|
||||
$ vi gcconfig.pri
|
||||
|
||||
Uncomment the D2XX_INCLUDE entry and make it match (my home is /home/markl)
|
||||
D2XX_INCLUDE = /home/markl/libftd2xx1.0.4
|
||||
|
||||
Make clean is needed if you have previouslt built, since source files examine #defines before
|
||||
including this feature. You can skip it if you know why ;)
|
||||
$ make clean
|
||||
$ qmake
|
||||
$ make
|
||||
|
||||
You now have D2XX support, for downloading from a PT via a USB cradle.
|
||||
|
||||
SRMIO - For SRM powercontrol V downloads via Serial
|
||||
---------------------------------------------------
|
||||
|
||||
$ cd ~/Projects
|
||||
$ git clone git://github.com/rclasen/srmio srmio
|
||||
$ cd srmio
|
||||
|
||||
Get automake and tools, if you don't already have them (I didn't after a fresh install)
|
||||
$ sudo apt-get install automake
|
||||
$ sudo apt-get install libtool
|
||||
|
||||
Generate the configure script, run it, build and install srmio
|
||||
$ sh genautomake.sh
|
||||
$ ./configure
|
||||
$ make
|
||||
$ sudo make install
|
||||
|
||||
Lets go config GC and build with SRMIO
|
||||
$ cd ~/Projects/Live/GoldenCheetah/src
|
||||
$ vi gcconfig.pri
|
||||
|
||||
Uncomment the SRMIO_INSTALL and replace with the target used from srmio install:
|
||||
SRMIO_INSTALL = /usr/local/
|
||||
|
||||
At the bottom of gcconfig.pri you will see the include directory should reference from
|
||||
the base install location (/usr/local) make sure it says:
|
||||
|
||||
SRMIO_INCLUDE = $${SRMIO_INSTALL}/include
|
||||
SRMIO_LIB = $${SRMIO_INSTALL}/lib/libsrmio.a
|
||||
|
||||
Make clean is needed if you have previouslt built, since source files examine #defines before
|
||||
including this feature. You can skip it if you know why ;)
|
||||
$ make clean
|
||||
$ qmake
|
||||
$ make
|
||||
|
||||
You now have SRM support built in.
|
||||
|
||||
OAUTH/CRYPT - For Tweet my ride (twitter) support
|
||||
-------------------------------------------------
|
||||
|
||||
You should be able to install liboauth and dependencies
|
||||
directly with:
|
||||
$ sudo apt-get install liboauth-dev
|
||||
|
||||
If this does not work then:
|
||||
|
||||
Download the source from: http://sourceforge.net/projects/liboauth/files/liboauth-0.9.4.tar.gz/download and
|
||||
unpack it into ~/Projects/liboauth-0.9.4 using archive manager
|
||||
|
||||
$ cd ~/Projects/liboauth-0.9.4
|
||||
|
||||
You may find that libcurl is not installed (which liboauth depends upon) so download it
|
||||
from http://curl.haxx.se/download/curl-7.21.6.tar.gz and unpack it into ~/Projects/curl-7.21.6
|
||||
using archive manager to drag and drop into your Projects folder
|
||||
|
||||
$ cd ~/Projects/curl-7.21.6
|
||||
$ ./configure
|
||||
$ make
|
||||
$ sudo make install
|
||||
|
||||
You should now have libcurl and friends installed in /usr/local
|
||||
|
||||
You may find that liboauth also requires the openssl libs installed, these are available
|
||||
pre-packaged thankfully so:
|
||||
$ sudo apt-get install libssl-dev
|
||||
|
||||
This will also install zlibg which liboauth also desires.
|
||||
|
||||
$ cd ~/Projects/liboauth-0.9.4
|
||||
$ ./configure
|
||||
$ make
|
||||
$ sudo make install
|
||||
|
||||
Now we have liboauth and libcurl in /usr/local and libssl in /usr/lib, so we can go back to
|
||||
GoldenCheetah and update the gcconfig.pri to point at the right places:
|
||||
|
||||
$ cd ~/Projects/Live/GoldenCheetah/src
|
||||
$ vi gcconfig.pri
|
||||
|
||||
Make sure the following are set:
|
||||
LIBOAUTH_INSTALL = /usr/local
|
||||
LIBCRYPTO_INSTALL = -lcrypto
|
||||
LIBCURL_INSTALL=-lcurl
|
||||
|
||||
Make clean is needed if you have previously built, since source files examine #defines before
|
||||
including this feature. You can skip it if you know why ;)
|
||||
$ make clean
|
||||
$ qmake
|
||||
$ make
|
||||
|
||||
You can now tweet your rides and amaze your friends, or alternatively tweet your rides but
|
||||
omit to mention average power to hide your weaknesses.
|
||||
|
||||
LIBQWTPLOT3D - For 3D plot
|
||||
--------------------------
|
||||
|
||||
Download the tarball from http://qwtplot3d.svn.sourceforge.net/viewvc/qwtplot3d/branches/maintain_0_2_x/qwtplot3d/?view=tar
|
||||
and unarchive it into your Projects directory using archive manager. There is no version number it just creates a
|
||||
subdirectory called qwtplot3d
|
||||
|
||||
You will need to install libgl and extensions, this can be done with;
|
||||
$ sudo apt-get install libgl1-mesa-dev
|
||||
$ sudo apt-get install libglu-dev
|
||||
|
||||
On Ubuntu 12.10 I also ran
|
||||
$ sudo apt-get install freeglut3 freeglut3-dev
|
||||
|
||||
$ cd ~/Projects/qwtplot3d
|
||||
Edit the qwtplot3d.pri and add
|
||||
CONFIG += staticlib
|
||||
|
||||
You will find that on modern Linuxes you also need to fix include/qwt3d_global.h by adding the line:
|
||||
#include <GL/glu.h>
|
||||
|
||||
then build
|
||||
$ qmake
|
||||
$ make
|
||||
|
||||
Then to let gc know where the qwtplot3d libs are you need to edit gcconfig.pri;
|
||||
$ cd ~/Projects/Live/GoldenCheetah/src
|
||||
$ vi gcconfig.pri
|
||||
|
||||
And uncomment the following line and set the install directory to where you build
|
||||
QWT3D_INSTALL = ~/Projects/qwtplot3d
|
||||
|
||||
|
||||
|
||||
LIBKML - For export to Google Earth
|
||||
-----------------------------------
|
||||
|
||||
You will need Google Earth 5.2 or later and therefore libkml that supports this. Unfortunately at the time of writing
|
||||
the officially packaged libkml is too old, so you will need to install from source, which means you will need to have
|
||||
subversion installed and expat. You may be able to use the currently packaged libkml with
|
||||
|
||||
$ sudo apt-get install libkml-dev
|
||||
|
||||
if this does not work you will need to build from source:
|
||||
|
||||
$ sudo apt-get install subversion
|
||||
$ sudo apt-get install expat libexpat1 libexpat1-dev
|
||||
|
||||
Once svn is installed you can grab the libkml source and configure build etc:
|
||||
$ cd ~/Projects
|
||||
$ svn checkout http://libkml.googlecode.com/svn/trunk/ libkml
|
||||
$ cd libkml
|
||||
|
||||
You will need automake and friends (see SRMIO above)
|
||||
$ sh autogen.sh
|
||||
$ ./configure
|
||||
$ make
|
||||
$ make install
|
||||
$ sudo make install
|
||||
|
||||
If you get errors about use of 'long long' then edit:
|
||||
- src/kml/{convenience,dom,engine,regionator,xsd}/Makefile
|
||||
- examples/{engine,gpx,gx,hellonet,helloworld,regionator,xsd}/Makefile
|
||||
- and look for the flag -pedantic and remove it. I got this on Linux 64bit builds ymmv.
|
||||
|
||||
Once libkml is installed and built:
|
||||
|
||||
$ cd ~/Projects/Live/GoldenCheetah/src
|
||||
$ vi gcconfig.pri
|
||||
|
||||
Ensure KML_INSTALL=/usr/local
|
||||
|
||||
Make clean is needed if you have previously built, since source files examine #defines before
|
||||
including this feature. You can skip it if you know why ;)
|
||||
$ make clean
|
||||
$ qmake
|
||||
$ make
|
||||
|
||||
You can now export rides to Google Earth kml format.
|
||||
|
||||
ADDING OPTIONAL DEPENDENCIES WHEN BUILDING VERSION 3
|
||||
====================================================
|
||||
|
||||
|
||||
NOTE: When you run version 3 it will refresh ride metrics and CP files -- this only occurs the
|
||||
first time it runs (and will refresh only rides that change after that). I find it is best
|
||||
to import ride files once your build where you want it. i.e. don't import until you have
|
||||
got all your dependencies sorted.
|
||||
|
||||
NOTE: To reduce the dependencies on 'dormant' code there are a number of new pieces of source
|
||||
that are included in the release3 tree. Notably; qtsoap from qt-solutions, since they
|
||||
work but are likely to be archived and deprecated. If and when that happens we may well
|
||||
adopt whatever classes Trolltech introduce.
|
||||
|
||||
|
||||
LIBICAL - Diary integration with Google or MobileMe calendars
|
||||
-------------------------------------------------------------
|
||||
|
||||
$ cd ~/Projects/Live/GoldenCheetah/src
|
||||
|
||||
$ sudo apt-get install libical-dev
|
||||
$ vi gcconfig.pri
|
||||
|
||||
ICAL_INSTALL=/usr/include
|
||||
ICAL_LIBS=-lical
|
||||
|
||||
Since the src.pro wants ICAL installed in a different place we need to hack it, *** this will
|
||||
be fixed shortly ***
|
||||
|
||||
$ vi src.pro
|
||||
|
||||
Comment out the ICAL_LIBS entry:
|
||||
|
||||
#ICAL_LIBS = $${ICAL_INSTALL}/lib/libical.a
|
||||
|
||||
$ make clean
|
||||
$ qmake
|
||||
$ make
|
||||
|
||||
You should now have diary functions.
|
||||
|
||||
NOTE: That upload to MobileMe and Google requires a functioning https lib in QT. Depending
|
||||
upon the version installed this might not be the case and will need to be built and
|
||||
configured -- this is beyond the scope of this walkthough. Sorry.
|
||||
|
||||
LIBVLC - Video playback in Realtime (Experimental)
|
||||
--------------------------------------------------
|
||||
|
||||
You will need libvlc 1.1.9 or higher (1.1.8 is ok but will segv on exit)
|
||||
$ sudo apt-get install libvlc-dev
|
||||
|
||||
$ vi gcconfig.pri
|
||||
|
||||
Comment out VLC_INSTALL and it should read:
|
||||
|
||||
VLC_INSTALL = /usr/include/vlc/
|
||||
|
||||
$ make clean
|
||||
$ qmake
|
||||
$ make
|
||||
298
INSTALL-MAC
@@ -1,298 +0,0 @@
|
||||
+++++++++++++++++++++++
|
||||
MAC OSX BUILD WALKTHROUGH
|
||||
+++++++++++++++++++++++
|
||||
|
||||
Mark Liversedge
|
||||
|
||||
Jan 2015
|
||||
Version 1.2
|
||||
|
||||
A walkthrough of building GoldenCheetah from scratch on Mac OSX. This was performed
|
||||
on Mac OSX Lion (10.7) but the instructions are largely the same for all versions of
|
||||
Mac OS X.
|
||||
|
||||
CONTENTS
|
||||
|
||||
1. BASIC INSTALLATION WITH MANDATORY DEPENDENCIES
|
||||
- Xcode
|
||||
- Qt
|
||||
|
||||
2. ADDING OPTIONAL DEPENDENCIES
|
||||
- FTDI D2XX
|
||||
- SRMIO
|
||||
- liboauth
|
||||
- QwtPlot3d
|
||||
- libkml
|
||||
- libusb
|
||||
- libical
|
||||
|
||||
|
||||
1. BASIC INSTALLATION WITH MANDATORY DEPENDENCIES
|
||||
=================================================
|
||||
|
||||
Depending upon the speed of your internet connection and availability of the
|
||||
required software the steps in section 1 will take approximately 1 hour.
|
||||
|
||||
1.1 Ensure OS X is up-to-date
|
||||
-----------------------------
|
||||
|
||||
Make sure you have applied all the latest updates to Mac OS X. This can be
|
||||
found from the system menu, apple, about this mac, software update.
|
||||
|
||||
This walkthrough was performed on an iMac running 10.7.2 (Lion)
|
||||
|
||||
1.2 Install XCode from App Store
|
||||
--------------------------------
|
||||
|
||||
If you are building on 10.6 or higher you should install Xcode4, for earlier
|
||||
releases you will need Xcode 3.1.4. If you have capable hardware you should
|
||||
consider upgrading to Lion to get the latest bug fixes and capabilities.
|
||||
|
||||
To install Xcode on Lion you need to download it via the App Store. You can
|
||||
launch the App Store from launchpad, or it may be already in your dock.
|
||||
|
||||
Under the search box type in Xcode and it will return a few optios, generally
|
||||
Xcode is the first item and shows a blueprint with a hammer icon. Click on
|
||||
this to install it. It should be free. The usual app store process will apply
|
||||
as the application is downloaded and installed. The download is about 2GB
|
||||
so do bear this in mind if you have limits on your internet bandwidth or cap.
|
||||
|
||||
1.3 Run the Xcode installer
|
||||
---------------------------
|
||||
|
||||
The app store download will have added an Install Xcode icon in the launchpad.
|
||||
Go ahead and run it.
|
||||
|
||||
Xcode includes all the development tools such as a compiler, debugger and
|
||||
SDKs. It also installs the 'git' tool for working with Git repositories.
|
||||
|
||||
It will run through a wizard to install, just read and then accept the license
|
||||
agreement and let it get on with it. If you don't like the license then quit
|
||||
and use the development builds from goldencheetah.stand2surtf.net.
|
||||
|
||||
You may find it borks at iTunes helper running, you will
|
||||
need to force quit the iTunes helper via Finder, Applications, Utilities,
|
||||
Activity Monitor if this happens.
|
||||
|
||||
1.4 Get the source code
|
||||
-----------------------
|
||||
|
||||
We store all the Golden Cheetah source code on github.com, it is a great
|
||||
site holding repositories for many open source projects.
|
||||
|
||||
First open up a terminal session, then;
|
||||
|
||||
$ cd
|
||||
$ mkdir Projects
|
||||
$ cd Projects
|
||||
$ git clone git://github.com/GoldenCheetah/GoldenCheetah.git
|
||||
|
||||
You will now have the GoldenCheetah sources downloaded into a 'GoldenCheetah'
|
||||
directory in your home directory, under another folder called 'Projects'.
|
||||
|
||||
$ cd GoldenCheetah
|
||||
$ ls
|
||||
|
||||
You should see a number of directories such as doc, qwt, src etc. If you are
|
||||
building the latest development release you may need to check it out. At the
|
||||
time of writing the latest development release is release_3.0.0dev, if you
|
||||
want to build version 3 then you should perform the next command, otherwise
|
||||
skip to 1.5.
|
||||
|
||||
$ checkout release_3.0.0dev
|
||||
$ ls
|
||||
|
||||
You will now see an updated version of this walkthrough, please jump to using
|
||||
that since it may be more up-to-date than this walkthrough (depending upon
|
||||
where you got it from of course!).
|
||||
|
||||
1.5 Install the QT SDK
|
||||
----------------------
|
||||
|
||||
GoldenCheetah is developed using the Nokia QT toolkit, it is large and will
|
||||
need to be downloaded and installed from their website. Alternatively, you
|
||||
can intall qt via macports (http://www.macports.org) as described in section
|
||||
1.5.1.
|
||||
|
||||
As of today, the latest stable release is 4.7.4, we need 4.7 or higher so
|
||||
go ahead and download the offline installer - it has everything you need
|
||||
but is about 1.3GB. Please make sure you download the installer for Mac
|
||||
OS X 10.6 or later, 64-bit.
|
||||
|
||||
The url for QT downloads is: http://qt.nokia.com/downloads and whilst the
|
||||
offline installer is only 12mb it will still call back and download the
|
||||
required objects as you install, I think it is better to get it all in
|
||||
one hit (and you can save it to reinstall on another computer or if you
|
||||
want to rebuild/reinstall for any other reason).
|
||||
|
||||
Once the QT SDK is downloaded you will have a .dmg (disk image) that you
|
||||
need to mount by double clicking on it. You will then get a volume mounted
|
||||
and shown on your desktop. Go ahead and double click that to start the install
|
||||
process. It is probably called something like 'Qt SDK Installer'.
|
||||
|
||||
It will popup with a dialog warning that this is downloaded from the internet
|
||||
and are you sure you want to open it? Go ahead and click Open.
|
||||
|
||||
A wizard will now guide you through the QT install process. Go ahead and accept
|
||||
all the defaults, it will install in your home directory and avoid updating the
|
||||
system directories, this means you are less likely to bork your Mac OSX installation.
|
||||
|
||||
Read and accept the license agreement and then continue and install.
|
||||
|
||||
We need to make sure that a program called qmake is installed in a directory where
|
||||
it can be found. So, we need to create a link from what we just installed in the
|
||||
user programs folder. For QT SDK1.1 (4.7.4) we need to:
|
||||
|
||||
$ sudo ln -s ~/QtSDK/Desktop/Qt/474/gcc/bin/qmake /usr/bin/qmake
|
||||
|
||||
1.5.1 Install via Mac Ports
|
||||
---------------------------
|
||||
|
||||
If you have macports installed, you can install the qt dependices
|
||||
with the following commands:
|
||||
|
||||
$ sudo port install qt4-mac
|
||||
$ sudo port install qt4-mac-sqlite3-plugin
|
||||
|
||||
1.6 DEPRECATED
|
||||
--------------
|
||||
|
||||
No longer need this step (install boost)
|
||||
|
||||
1.7 Configure and Build GoldenCheetah (with no optional dependencies)
|
||||
---------------------------------------------------------------------
|
||||
|
||||
First thing we need to do is set the build configuration, this means editing the
|
||||
private build profile settings. There is one for qwt (a charting library) and
|
||||
there is another for GoldenCheetah itself.
|
||||
|
||||
$ cd ~/Projects/GoldenCheetah/qwt
|
||||
$ cp qwtconfig.pri.in qwtconfig.pri
|
||||
$ cd ../src
|
||||
$ cp gcconfig.pri.in gcconfig.pri
|
||||
$ vi gcconfig.pri
|
||||
|
||||
In that last step you can use whatever editor you feel most comfortable with.
|
||||
|
||||
For now we will comment out some of the dependencies we have not installed
|
||||
support for yet:
|
||||
|
||||
#SRMIO_INSTALL = /usr/local/srmio
|
||||
#D2XX_INCLUDE = /usr/local/include/D2XX
|
||||
|
||||
we may need to additionally configure to use the local compression
|
||||
libraries (at least I did), by adding the following line:
|
||||
|
||||
LIBS += -lz
|
||||
|
||||
Lastly, since we are on Lion, we can also uncomment and change the following line:
|
||||
|
||||
DEFINES += GC_HAVE_LION
|
||||
|
||||
Once the changes have been made we are now ready to build for the first time. You
|
||||
may notice a lot of warning messages about the version of O/S not being supported.
|
||||
This is because QT does not officially support Lion at this point in time (but it
|
||||
does work). You can either ignore the warning messages or (like me) go and edit out
|
||||
the warning (once you have seen the message once you don't need reminding every
|
||||
time you compile).
|
||||
|
||||
To do this, edit the file in question as an administrator:
|
||||
|
||||
$ sudo vi ~/QtSDK/Desktop/Qt/474/gcc/include/QtCore/qglobal.h
|
||||
|
||||
And comment out line 320 (or thereabouts):
|
||||
|
||||
//# warning "This version of Mac OS X is unsupported"
|
||||
|
||||
Once this is done you can kick off the build:
|
||||
|
||||
$ cd .. #this should put you in the top level dir containing this file
|
||||
$ qmake -recursive
|
||||
$ make
|
||||
|
||||
If make fails to find a Makefile then qmake is configured, by default, to create
|
||||
an xcode project file. You will need to change the qmake command above to tell it
|
||||
to create a makefile with the following:
|
||||
$ qmake -spec macx-g++ -recursive
|
||||
$ make
|
||||
|
||||
Once this completes you will have a GoldenCheetah.app in the src directory which
|
||||
can be launched:
|
||||
|
||||
$ open src/GoldenCheetah.app
|
||||
|
||||
And you're up and running.
|
||||
|
||||
2. ADDING OPTIONAL DEPENDENCIES
|
||||
===============================
|
||||
|
||||
- SRMIO
|
||||
- liboauth
|
||||
- QwtPlot3d
|
||||
- libkml
|
||||
- libusb
|
||||
- libical
|
||||
|
||||
Since these optional dependencies are more complex and require more advanced
|
||||
technical skills we do not provide a walkthrough for building them all but
|
||||
instead provide the configure settings and any special considerations that
|
||||
should be taken into account.
|
||||
|
||||
2.1 SRMIO - For working with PC 5/6/7
|
||||
-------------------------------------
|
||||
|
||||
SRMIO (git)
|
||||
./configure CFLAGS="-isysroot /Developer/SDKs/MacOSX10.7.sdk -arch x86_64" CPPFLAGS=-I/usr/local/D2XX/ --disable-dependency-tracking
|
||||
|
||||
2.2 Liboauth - For Twitter support
|
||||
----------------------------------
|
||||
|
||||
oauth (0.8.8)
|
||||
|
||||
./configure CFLAGS="-isysroot /Developer/SDKs/MacOSX10.7.sdk -arch x86_64 CURL_CFLAGS="-I/Developer/SDKs/MacOSX10.7.sdk/usr/include/curl" CURL_LIBS="-lcurl" --disable-dependency-tracking
|
||||
|
||||
2.3 QwtPlot3d - For 3d plot support
|
||||
-----------------------------------
|
||||
|
||||
qwtplot3d (maintain_0_2_x)
|
||||
|
||||
Add the following to qwtplot3d.pro:
|
||||
CONFIG += x86_64 static
|
||||
QMAKE_MAC_SDK=/Developer/SDKs/MacOSX10.7.sdk
|
||||
|
||||
2.4 libkml - For export to Google Earth
|
||||
---------------------------------------
|
||||
|
||||
expat (2.0.1)
|
||||
./configure CFLAGS="-isysroot /Developer/SDKs/MacOSX10.7.sdk -arch x86_64" --disable-dependency-tracking
|
||||
|
||||
libkml (pulled down from the svn repo)
|
||||
|
||||
./configure CFLAGS="-isysroot /Developer/SDKs/MacOSX10.7.sdk -arch x86_64" --disable-dependency-tracking --with-expat-include-dir=/usr/local/include --with-expat-lib-dir=/usr/local/lib --disable-swig CXXFLAGS="-isysroot /Developer/SDKs/MacOSX10.7.sdk -arch x86_64"
|
||||
|
||||
note: the added CXXFLAGS helped clear the -Werror flag that stopped compilation.
|
||||
|
||||
2.5 libusb - For Garmin USB2 stick support
|
||||
------------------------------------------
|
||||
|
||||
libusb (0.1.12)
|
||||
|
||||
To compile on OSX you need to apply the patch here:
|
||||
https://trac.macports.org/browser/trunk/dports/devel/libusb-legacy/files?rev=97840
|
||||
|
||||
Then:
|
||||
./configure --prefix=/opt/libusb/ CFLAGS="-arch x86_64" CXXFLAGS="-arch x86_64" --disable-dependency-tracking
|
||||
then
|
||||
sed -i 'bak' 's|CC -dynamiclib|CC -dynamiclib -arch x86_64|g' libtool
|
||||
make
|
||||
make install
|
||||
|
||||
note: that the sed line updates some commands in libtool. not sure why the arch clags are not getting passed.
|
||||
|
||||
2.6 libical
|
||||
-----------
|
||||
|
||||
libical (0.46)
|
||||
first run autogen.sh
|
||||
then
|
||||
./configure CFLAGS="-isysroot /Developer/SDKs/MacOSX10.7.sdk -arch x86_64" --disable-dependency-tracking
|
||||
117
INSTALL-WIN32
@@ -1,117 +0,0 @@
|
||||
Please note: This is an old build instruction set for Version 2.x.
|
||||
|
||||
Most of it is still fairly valid for version 3.x.
|
||||
|
||||
Minimum build requirements are: Qt 4.8 with Qt.4.8.4 recommended.
|
||||
|
||||
All other libs are find the best that you can except for libusb which requires 0.1.12.
|
||||
|
||||
I have found that the cross compiler at http://mxe.cc/ to be great for building GC and SRMIO.
|
||||
|
||||
+++++++++++++++++++++++
|
||||
WIN32 BUILD WALKTHROUGH
|
||||
+++++++++++++++++++++++
|
||||
|
||||
Gareth Coco
|
||||
|
||||
May 2011
|
||||
|
||||
For my install, I am installing all my files into the directory: d:\coding.
|
||||
You can use any directory structure you like, you’ll just have to change paths.
|
||||
Just ensure that any folder path you use does not have a space in it.
|
||||
|
||||
Download the NSI installer application. I use the Portable Apps version from:
|
||||
http://portableapps.com/apps/development/nsis_portable
|
||||
- Install in D:\Coding\NSISPortable\
|
||||
|
||||
Download Qt SDK from:
|
||||
http://qt.nokia.com/downloads/sdk-windows-cpp
|
||||
(File I am using is qt-sdk-win-opensource-2010.02.1.exe)
|
||||
- Install in D:\Coding\Qt
|
||||
|
||||
Download the D2XX drivers:
|
||||
http://www.ftdichip.com/Drivers/D2XX.htm
|
||||
(File I am using is: CDM 202.06.00 WHQL Certified.zip)
|
||||
- Install in D:\Coding\D2XX
|
||||
|
||||
Download qwt-plot3d from:
|
||||
http://sourceforge.net/projects/qwtplot3d/files/
|
||||
(File I am using is qwtplot3d-0.2.7.zip)
|
||||
- Install in D:\Coding\qwtplot3d
|
||||
|
||||
Edit D:\coding\qwtplot3d\src\qwt3d_function.cpp
|
||||
- Add at top of file: #include <cstdio>
|
||||
Edit D:\coding\qwtplot3d\qwtplot3d.pro
|
||||
- Comment out: #win32:TEMPLATE = vclib
|
||||
|
||||
Then I start the “Qt Command Prompt” from the Qt SDK folder.
|
||||
|
||||
d:
|
||||
cd d:\coding\qwtplot3d\
|
||||
qmake -win32
|
||||
mingw32-make release
|
||||
|
||||
Now check out your favourite web sites until the code is built.
|
||||
|
||||
Leave the Qt Command Prompt window open as we use it later.
|
||||
|
||||
Download GoldenCheetah source
|
||||
(Either use GIT – git://github.com/GoldenCheetah/GoldenCheetah.git
|
||||
or download the zip file:
|
||||
http://github.com/GoldenCheetah/GoldenCheetah/zipball/master)
|
||||
- Install in D:\Coding\GoldenCheetah
|
||||
|
||||
Copy D:\Coding\GoldenCheetah\src\gccconfig.pri.in
|
||||
to D:\Coding\GoldenCheetah\src\gccconfig.pri and edit
|
||||
- Set: D2XX_INCLUDE = d:/coding/D2XX
|
||||
- Comment out #SRMIO_INSTALL
|
||||
- Comment out: CONFIG += debug
|
||||
- Uncomment: CONFIG += static
|
||||
|
||||
Copy D:\Coding\GoldenCheetah\qwt\qwtconfig.pri.in
|
||||
to D:\Coding\GoldenCheetah\qwt\qwtconfig.pri and edit
|
||||
- Set win32 { INSTALLBASE = D:/Coding/Qt }
|
||||
- In #Qt4 win32 { section
|
||||
– Comment out: #CONFIG += debug # release/debug/debug_and_release
|
||||
– Add in: CONFIG += release
|
||||
|
||||
Using the “Qt Command Prompt” window from before:
|
||||
|
||||
cd d:\coding\GoldenCheetah
|
||||
qmake -win32 -recursive
|
||||
mingw32-make release
|
||||
|
||||
Go back to checking your email or favourite web sites while this builds.
|
||||
|
||||
When all is finished, you should have a release version in:
|
||||
|
||||
D:\Coding\GoldenCheetah\src\release\
|
||||
|
||||
Next , move required build files into the d:\coding\GoldenCheetah\src\release directory.
|
||||
|
||||
cd d:\coding\GoldenCheetah
|
||||
copy /y ..\Qt\qt\bin\mingwm10.dll src\release\
|
||||
copy /y ..\Qt\qt\bin\QtCore4.dll src\release\
|
||||
copy /y ..\Qt\qt\bin\QtGui4.dll src\release\
|
||||
copy /y ..\Qt\qt\bin\QtSql4.dll src\release\
|
||||
copy /y ..\Qt\qt\bin\QtXml4.dll src\release\
|
||||
copy /y ..\Qt\qt\bin\QtNetwork4.dll src\release\
|
||||
copy /y ..\Qt\qt\bin\QtOpenGL4.dll src\release\
|
||||
copy /y ..\Qt\qt\bin\QtWebKit4.dll src\release\
|
||||
copy /y ..\Qt\qt\bin\QtXmlPatterns4.dll src\release\
|
||||
copy /y ..\Qt\qt\bin\phonon4.dll src\release\
|
||||
copy /y ..\Qt\qt\bin\libgcc_s_dw2-1.dll src\release\
|
||||
copy /y ..\qwtplot3d\lib\qwtplot3d.dll src\release\
|
||||
mkdir src\release\sqldrivers
|
||||
copy /y ..\Qt\qt\plugins\sqldrivers\qsqlite4.dll src\release\sqldrivers\
|
||||
mkdir src\release\imageformats
|
||||
copy /y ..\Qt\qt\plugins\imageformats\qjpeg4.dll src\release\imageformats\
|
||||
|
||||
To build the self installer:
|
||||
|
||||
cd d:\coding\GoldenCheetah\src\win32
|
||||
d:\coding\NSISPortable\App\NSIS\makensis.exe GoldenCheetahInstall.nsi
|
||||
|
||||
You should find the installer file in the directory you are in.
|
||||
|
||||
Install and enjoy.
|
||||
20
README
@@ -1,9 +1,15 @@
|
||||
Golden Cheetah install and build instructions are documented
|
||||
for each platform;
|
||||
To build
|
||||
|
||||
INSTALL-WIN32 For building on Microsoft Windows
|
||||
INSTALL-LINUX For building on Ubuntu Linux
|
||||
INSTALL-MAC For building on Apple OS X
|
||||
cp src/gcconfig.pri.in src/gcconfig.pri
|
||||
cp qwt/qwtconfig.pri.in qwt/qwtconfig.pri
|
||||
|
||||
Alternatively official builds are available from http://www.goldencheetah.org
|
||||
whilst latest developer builds are available from http://goldencheetah.stand2surf.net
|
||||
Edit both src/gcconfig.pri and qwt/qwtconfig.pri as necessary, then
|
||||
|
||||
qmake
|
||||
make
|
||||
|
||||
To uninstall the older FTDI VCP drivers on Mac OS X, open a Terminal and type:
|
||||
|
||||
sudo mv /System/Library/Extensions/FTDIUSBSerialDriver.kext /tmp
|
||||
|
||||
Type your password when prompted, then restart your computer.
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
From 44a403d45ae049e7ade3e9b47a39778dcacf4382 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Liversedge <liversedge@gmail.com>
|
||||
Date: Thu, 28 Mar 2013 22:03:35 +0000
|
||||
Subject: [PATCH] Fixup no threads for GC
|
||||
|
||||
---
|
||||
src/core/CLucene/debug/lucenebase.h | 2 +-
|
||||
src/shared/CLucene/LuceneThreads.h | 21 ++++++++++++++++++---
|
||||
src/shared/CLucene/util/Misc.cpp | 2 ++
|
||||
src/shared/CLucene/util/Misc.h | 2 ++
|
||||
4 files changed, 23 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/core/CLucene/debug/lucenebase.h b/src/core/CLucene/debug/lucenebase.h
|
||||
index c053f11..9732ce6 100644
|
||||
--- a/src/core/CLucene/debug/lucenebase.h
|
||||
+++ b/src/core/CLucene/debug/lucenebase.h
|
||||
@@ -6,7 +6,7 @@
|
||||
------------------------------------------------------------------------------*/
|
||||
#ifndef _lucene_debug_lucenebase_
|
||||
#define _lucene_debug_lucenebase_
|
||||
-
|
||||
+#define _CL_DISABLE_MULTITHREADING
|
||||
#include "CLucene/LuceneThreads.h"
|
||||
|
||||
CL_NS_DEF(debug)
|
||||
diff --git a/src/shared/CLucene/LuceneThreads.h b/src/shared/CLucene/LuceneThreads.h
|
||||
index 97072ee..662ff2f 100644
|
||||
--- a/src/shared/CLucene/LuceneThreads.h
|
||||
+++ b/src/shared/CLucene/LuceneThreads.h
|
||||
@@ -13,10 +13,10 @@ class CLuceneThreadIdCompare;
|
||||
|
||||
#if defined(_CL_DISABLE_MULTITHREADING)
|
||||
#define SCOPED_LOCK_MUTEX(theMutex)
|
||||
- #define DEFINE_MUTEX(x)
|
||||
+ //#define DEFINE_MUTEX(x)
|
||||
#define DEFINE_MUTABLE_MUTEX(x)
|
||||
#define DEFINE_CONDITION(x)
|
||||
- #define STATIC_DEFINE_MUTEX(x)
|
||||
+ //#define STATIC_DEFINE_MUTEX(x)
|
||||
#define CONDITION_WAIT(theMutex, theCondition)
|
||||
#define CONDITION_NOTIFYALL(theCondition)
|
||||
#define _LUCENE_CURRTHREADID 1
|
||||
@@ -25,11 +25,26 @@ class CLuceneThreadIdCompare;
|
||||
#define _LUCENE_THREAD_FUNC_RETURN(val) return (int)val;
|
||||
#define _LUCENE_THREAD_CREATE(func, arg) (*func)(arg)
|
||||
#define _LUCENE_THREAD_JOIN(value) //nothing to do...
|
||||
- #define _LUCENE_THREADMUTEX void*
|
||||
+ //#define _LUCENE_THREADMUTEX void*
|
||||
|
||||
#define _LUCENE_ATOMIC_INC(theInteger) (++(*theInteger))
|
||||
#define _LUCENE_ATOMIC_DEC(theInteger) (--(*theInteger))
|
||||
#define _LUCENE_ATOMIC_INT int
|
||||
+#define _LUCENE_ATOMIC_INT_SET(x,v) x=v
|
||||
+#define _LUCENE_ATOMIC_INT_GET(x) x
|
||||
+
|
||||
+struct CLUCENE_SHARED_EXPORT mutex_thread
|
||||
+{
|
||||
+ void lock() {}
|
||||
+ void unlock() {}
|
||||
+};
|
||||
+#define _LUCENE_THREADMUTEX CL_NS(util)::mutex_thread
|
||||
+
|
||||
+#define DEFINE_MUTEX(theMutex) _LUCENE_THREADMUTEX theMutex;
|
||||
+#define STATIC_DEFINE_MUTEX(theMutex) static _LUCENE_THREADMUTEX theMutex;
|
||||
+
|
||||
+#define CONDITION_WAIT(theMutex, theCondition)
|
||||
+#define CONDITION_NOTIFYALL(theCondition)
|
||||
#else
|
||||
#if defined(_LUCENE_DONTIMPLEMENT_THREADMUTEX)
|
||||
//do nothing
|
||||
diff --git a/src/shared/CLucene/util/Misc.cpp b/src/shared/CLucene/util/Misc.cpp
|
||||
index 240b827..ec9eabd 100644
|
||||
--- a/src/shared/CLucene/util/Misc.cpp
|
||||
+++ b/src/shared/CLucene/util/Misc.cpp
|
||||
@@ -466,6 +466,7 @@ bool Misc::listFiles(const char* directory, std::vector<std::string>& files, boo
|
||||
std::string Misc::toString(const bool value){
|
||||
return value ? "true" : "false";
|
||||
}
|
||||
+#ifndef _CL_DISABLE_MULTITHREADING
|
||||
std::string Misc::toString(_LUCENE_THREADID_TYPE value){
|
||||
static int32_t nextindex = 0;
|
||||
static std::map<_LUCENE_THREADID_TYPE, int32_t> ids;
|
||||
@@ -474,6 +475,7 @@ std::string Misc::toString(_LUCENE_THREADID_TYPE value){
|
||||
}
|
||||
return toString(ids[value]);
|
||||
}
|
||||
+#endif
|
||||
std::string Misc::toString(const int32_t value){
|
||||
char buf[20];
|
||||
TCHAR tbuf[20];
|
||||
diff --git a/src/shared/CLucene/util/Misc.h b/src/shared/CLucene/util/Misc.h
|
||||
index aea7c42..4196e24 100644
|
||||
--- a/src/shared/CLucene/util/Misc.h
|
||||
+++ b/src/shared/CLucene/util/Misc.h
|
||||
@@ -67,7 +67,9 @@ CL_NS_DEF(util)
|
||||
|
||||
static std::string toString(const int32_t value);
|
||||
static std::string toString(const int64_t value);
|
||||
+#ifndef _CL_DISABLE_MULTITHREADING
|
||||
static std::string toString(const _LUCENE_THREADID_TYPE value);
|
||||
+#endif
|
||||
static std::string toString(const bool value);
|
||||
static std::string toString(const float_t value);
|
||||
static std::string toString(const TCHAR* s, int32_t len=-1);
|
||||
--
|
||||
1.7.8.msysgit.0
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
Clucene-2.3.3.4-NoThreads.patch - To patch Clucene on Windows to remove patching
|
||||
Fortius USB Driver Stubs.zip - Drivers for use with Fortius without Tacx software
|
||||
Install_D2XX_drivers.mpkg.zip - D2XX installer for Windows
|
||||
Universal_D2XX0.1.6.dmg - D2XX installer for Mac OSX
|
||||
libusb-0.1.12.tar.gz - Libusb (patched) to work with GoldenCheetah
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
12
contrib/RideLogger/.gitignore
vendored
@@ -1,12 +0,0 @@
|
||||
# Ignores for Eclipse
|
||||
/.settings/
|
||||
|
||||
# Ignores for Android Projects
|
||||
/bin/
|
||||
/gen/
|
||||
/publish/
|
||||
/local.properties
|
||||
/secure.properties
|
||||
|
||||
# Ignores for Mac machines
|
||||
.DS_Store
|
||||
@@ -1,39 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE AndroidXML>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:installLocation="auto"
|
||||
package="com.ridelogger"
|
||||
android:versionCode="040000"
|
||||
android:versionName="4.0.0"
|
||||
android:icon="@drawable/ic_launcher" >
|
||||
<uses-sdk android:minSdkVersion="14"
|
||||
android:targetSdkVersion="21" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.SEND_SMS"/>
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@android:style/Theme.DeviceDefault.Light" >
|
||||
<service
|
||||
android:name="com.ridelogger.RideService"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/service_name" >
|
||||
</service>
|
||||
<activity
|
||||
android:name="com.ridelogger.StartActivity"
|
||||
android:label="@string/app_name" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.ridelogger.SettingsActivity"
|
||||
android:label="@string/setting_title" >
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
|
Before Width: | Height: | Size: 176 KiB |
@@ -1,3 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<lint>
|
||||
</lint>
|
||||
@@ -1,68 +0,0 @@
|
||||
# This is a configuration file for ProGuard.
|
||||
# http://proguard.sourceforge.net/index.html#manual/usage.html
|
||||
|
||||
# Optimizations: If you don't want to optimize, use the
|
||||
# proguard-android.txt configuration file instead of this one, which
|
||||
# turns off the optimization flags. Adding optimization introduces
|
||||
# certain risks, since for example not all optimizations performed by
|
||||
# ProGuard works on all versions of Dalvik. The following flags turn
|
||||
# off various optimizations known to have issues, but the list may not
|
||||
# be complete or up to date. (The "arithmetic" optimization can be
|
||||
# used if you are only targeting Android 2.0 or later.) Make sure you
|
||||
# test thoroughly if you go this route.
|
||||
-optimizations code/simplification/arithmetic,code/simplification/cast,field/*,class/merging/*
|
||||
-optimizationpasses 24
|
||||
-allowaccessmodification
|
||||
-dontpreverify
|
||||
|
||||
# The remainder of this file is identical to the non-optimized version
|
||||
# of the Proguard configuration file (except that the other file has
|
||||
# flags to turn off optimization).
|
||||
|
||||
-dontusemixedcaseclassnames
|
||||
-dontskipnonpubliclibraryclasses
|
||||
-verbose
|
||||
|
||||
-keepattributes *Annotation*
|
||||
-keep public class com.google.vending.licensing.ILicensingService
|
||||
-keep public class com.android.vending.licensing.ILicensingService
|
||||
|
||||
# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
# keep setters in Views so that animations can still work.
|
||||
# see http://proguard.sourceforge.net/manual/examples.html#beans
|
||||
-keepclassmembers public class * extends android.view.View {
|
||||
void set*(***);
|
||||
*** get*();
|
||||
}
|
||||
|
||||
# We want to keep methods in Activity that could be used in the XML attribute onClick
|
||||
-keepclassmembers class * extends android.app.Activity {
|
||||
public void *(android.view.View);
|
||||
}
|
||||
|
||||
# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
||||
|
||||
-keepclassmembers class **.R$* {
|
||||
public static <fields>;
|
||||
}
|
||||
|
||||
# The support library contains references to newer platform versions.
|
||||
# Don't warn about those in case this app is linking against an older
|
||||
# platform version. We know about them, and they are safe.
|
||||
-dontwarn android.support.**
|
||||
|
||||
-keep public class com.ridelogger.SettingsActivity$GeneralFragment
|
||||
-keep public class com.ridelogger.SettingsActivity$AntFragment
|
||||
-keep public class com.ridelogger.SettingsActivity$SensorsFragment
|
||||
@@ -1,15 +0,0 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system edit
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
#
|
||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||
proguard.config=proguard-android-optimize.txt
|
||||
|
||||
# Project target.
|
||||
target=android-21
|
||||
min=android-14
|
||||
|
Before Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 12 KiB |
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE AndroidXML>
|
||||
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/LayoutData"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:numColumns="auto_fit"
|
||||
android:stretchMode="columnWidth"
|
||||
android:gravity="right"
|
||||
/>
|
||||
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<preference-headers
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<header android:fragment="com.ridelogger.SettingsActivity$GeneralFragment"
|
||||
android:title="@string/setting_general_title"
|
||||
android:summary="@string/setting_general_note" />
|
||||
<header android:fragment="com.ridelogger.SettingsActivity$AntFragment"
|
||||
android:title="@string/setting_ant_title"
|
||||
android:summary="@string/setting_ant_note" />
|
||||
<header android:fragment="com.ridelogger.SettingsActivity$SensorsFragment"
|
||||
android:title="@string/setting_sensors_title"
|
||||
android:summary="@string/setting_sensors_note" />
|
||||
</preference-headers>
|
||||
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
|
||||
<item android:id="@+id/Start"
|
||||
android:title="@string/start" />
|
||||
<item android:id="@+id/Stop"
|
||||
android:title="@string/stop" />
|
||||
<item android:id="@+id/Settings"
|
||||
android:title="@string/edit_settings"
|
||||
android:showAsAction="never" />
|
||||
</menu>
|
||||
@@ -1,97 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE AndroidXML>
|
||||
<resources>
|
||||
<string name="app_name">Ride Logger</string>
|
||||
<string name="service_name">Logging Ride</string>
|
||||
|
||||
<string name="emergency_contact_dialog_title">Emergency Contact</string>
|
||||
<string name="emergency_contact_dialog_note">Should a text messesage be sent on ride start and periodically to let your emergency contact know you are alright?</string>
|
||||
|
||||
<string name="sms_period_dialog_title">Emergency Contact SMS Period</string>
|
||||
<string name="sms_period_dialog_note">Period in Minutes:</string>
|
||||
|
||||
<string name="crash_detection_dialog_title">Crash Detection</string>
|
||||
<string name="crash_detection_dialog_note">Should a text messesage be sent on crash detction to your emergency contact?</string>
|
||||
|
||||
<string name="emergency_contact_number_dialog_title">Emergency Contact Number</string>
|
||||
<string name="emergency_contact_number_dialog_note">Emergency phone number to update position on crash detection</string>
|
||||
|
||||
<string name="ant_setup_title">Set Ant+</string>
|
||||
<string name="ant_setup_note">Pair your Ant+ devices now?</string>
|
||||
|
||||
<string name="ant_pair_dialog_title">Select Ant Devices</string>
|
||||
<string name="ant_pair_dialog_button_note">Pair</string>
|
||||
|
||||
<string name="gc_rider_name_dialog_title">Enter Rider Name</string>
|
||||
<string name="gc_rider_name_dialog_note">What is your Golder Cheata Rider Name?</string>
|
||||
|
||||
<string name="save_setting_button">Next</string>
|
||||
<string name="skip_setting_button">Skip</string>
|
||||
|
||||
<string name="boolean_dialog_yes">Yes</string>
|
||||
<string name="boolean_dialog_no">No</string>
|
||||
|
||||
<string name="starting_ride">Starting Ride!</string>
|
||||
<string name="stopping_ride">Stoping Ride!</string>
|
||||
|
||||
<string name="ride_on">Ride On</string>
|
||||
<string name="building_ride">Building ride: </string>
|
||||
|
||||
<string name="click_to_stop"> Click to stop ride.</string>
|
||||
|
||||
<string name="ride_start_title">Start Ride</string>
|
||||
<string name="ride_start_note">Make sure locations is turned on. Internet connection is NOT required.</string>
|
||||
|
||||
<string name="start">Start Logging</string>
|
||||
<string name="edit_settings">Settings</string>
|
||||
|
||||
<string name="ride_stop_title">Ride in Progress</string>
|
||||
<string name="ride_stop_note">Would you like to stop the ride or view current values.</string>
|
||||
|
||||
<string name="stop">Stop Logging</string>
|
||||
<string name="view">View</string>
|
||||
|
||||
<string name="crash_warning">WARNING CRASH!</string>
|
||||
<string name="crash_confirm">CRASH CONFIRMED!</string>
|
||||
<string name="crash_unknow_location">Unknow location.</string>
|
||||
<string name="crash_magnitude">Mag</string>
|
||||
|
||||
<string name="ride_start_sms">I\'m starting my ride.</string>
|
||||
<string name="ride_stop_sms">I have finished my ride.</string>
|
||||
<string name="riding_ok_sms">I\'m ok.</string>
|
||||
|
||||
<string name="setting_title">Settings</string>
|
||||
|
||||
<string name="setting_general_title">General</string>
|
||||
<string name="setting_general_note">Settings</string>
|
||||
|
||||
<string name="setting_ant_title">Ant+</string>
|
||||
<string name="setting_ant_note">Setup your Ant+ Devices</string>
|
||||
|
||||
<string name="searching_for_ants">Searching for Ant+ Devices...</string>
|
||||
<string name="found_ants">Found Ant+ Devices, Press to Pair.</string>
|
||||
<string name="no_found_ants">Nothing found to pair.</string>
|
||||
|
||||
<string name="setting_sensors_title">Display Sensors</string>
|
||||
<string name="setting_sensors_note">List of Sensors Display</string>
|
||||
|
||||
<string name="setting_wheel_size">Wheel Circumference in Meters</string>
|
||||
|
||||
<string name="imperial_units_title">Imperial Units</string>
|
||||
<string name="imperial_units_note">Show Measurements in Imperial Units</string>
|
||||
|
||||
<string name="setting_size_title">Display Text Size</string>
|
||||
|
||||
<string name="PREFS_NAME">RideLogger</string>
|
||||
<string name="PREF_RIDER_NAME">RiderName</string>
|
||||
<string name="PREF_EMERGENCY_NUMBER">EmergencyNumbuer</string>
|
||||
<string name="PREF_DETECT_CRASH">DetectCrash</string>
|
||||
<string name="PREF_PHONE_HOME">PhoneHome</string>
|
||||
<string name="PREF_PAIRED_ANTS">PairedAnts</string>
|
||||
<string name="PREF_PHONE_HOME_PERIOD">PhoneHomePeriod</string>
|
||||
<string name="PREF_TRACKING_SENSORS">TrackingSensors</string>
|
||||
<string name="PREF_TRACKING_SIZE">TrackingSize</string>
|
||||
<string name="PREF_TRACKING_IMPERIAL_UNITS">TrackingImperialUnits</string>
|
||||
<string name="PREF_WHEEL_SIZE">WheelSize</string>
|
||||
|
||||
</resources>
|
||||
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<PreferenceCategory
|
||||
android:title="@string/PREFS_NAME">
|
||||
|
||||
<MultiSelectListPreference
|
||||
android:key="@string/PREF_PAIRED_ANTS"
|
||||
android:title="@string/ant_pair_dialog_title"
|
||||
android:summary="@string/ant_pair_dialog_button_note"
|
||||
/>
|
||||
|
||||
<EditTextPreference
|
||||
android:key="@string/PREF_WHEEL_SIZE"
|
||||
android:title="@string/setting_wheel_size"
|
||||
android:defaultValue="2.096"
|
||||
/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -1,42 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<PreferenceCategory
|
||||
android:title="@string/PREFS_NAME"
|
||||
android:persistent="true">
|
||||
|
||||
<EditTextPreference
|
||||
android:key="@string/PREF_RIDER_NAME"
|
||||
android:title="@string/gc_rider_name_dialog_title"
|
||||
android:summary="@string/gc_rider_name_dialog_note" />
|
||||
|
||||
<EditTextPreference
|
||||
android:key="@string/PREF_EMERGENCY_NUMBER"
|
||||
android:title="@string/emergency_contact_number_dialog_title"
|
||||
android:summary="@string/emergency_contact_number_dialog_note" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:layout="?android:attr/preferenceLayoutChild"
|
||||
android:dependency="@string/PREF_EMERGENCY_NUMBER"
|
||||
android:key="@string/PREF_DETECT_CRASH"
|
||||
android:title="@string/crash_detection_dialog_title"
|
||||
android:summary="@string/crash_detection_dialog_note" />
|
||||
|
||||
<!-- The visual style of a child is defined by this styled theme attribute. -->
|
||||
<CheckBoxPreference
|
||||
android:layout="?android:attr/preferenceLayoutChild"
|
||||
android:dependency="@string/PREF_EMERGENCY_NUMBER"
|
||||
android:key="@string/PREF_PHONE_HOME"
|
||||
android:title="@string/emergency_contact_dialog_title"
|
||||
android:summary="@string/emergency_contact_dialog_note" />
|
||||
|
||||
<EditTextPreference
|
||||
android:layout="?android:attr/preferenceLayoutChild"
|
||||
android:dependency="@string/PREF_PHONE_HOME"
|
||||
android:key="@string/PREF_PHONE_HOME_PERIOD"
|
||||
android:title="@string/sms_period_dialog_title"
|
||||
android:summary="@string/sms_period_dialog_note"
|
||||
android:defaultValue="20" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<PreferenceCategory
|
||||
android:title="@string/PREFS_NAME">
|
||||
|
||||
<MultiSelectListPreference
|
||||
android:key="@string/PREF_TRACKING_SENSORS"
|
||||
android:title="@string/setting_sensors_title"
|
||||
android:summary="@string/setting_sensors_note"
|
||||
/>
|
||||
<CheckBoxPreference
|
||||
android:key="@string/PREF_TRACKING_IMPERIAL_UNITS"
|
||||
android:title="@string/imperial_units_title"
|
||||
android:summary="@string/imperial_units_note"
|
||||
/>
|
||||
|
||||
<EditTextPreference
|
||||
android:key="@string/PREF_TRACKING_SIZE"
|
||||
android:title="@string/setting_size_title"
|
||||
android:defaultValue="20"
|
||||
/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -1,281 +0,0 @@
|
||||
package com.ridelogger;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Typeface;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.GridView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class CurrentValuesAdapter extends BaseAdapter {
|
||||
private StartActivity context;
|
||||
|
||||
private int[] keys;
|
||||
private String[] values;
|
||||
private String[] keyLabels;
|
||||
private int size = 20;
|
||||
private boolean imperial = false;
|
||||
private SharedPreferences settings = null;
|
||||
|
||||
private GridView layout;
|
||||
|
||||
public CurrentValuesAdapter(StartActivity c, GridView pLayout) {
|
||||
context = c;
|
||||
layout = pLayout;
|
||||
|
||||
layout.setBackgroundColor(Color.BLACK);
|
||||
layout.setVerticalSpacing(4);
|
||||
layout.setHorizontalSpacing(4);
|
||||
|
||||
settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
Set<String> sensors = settings.getStringSet(context.getString(R.string.PREF_TRACKING_SENSORS), null);
|
||||
|
||||
size = Integer.valueOf(settings.getString(context.getString(R.string.PREF_TRACKING_SIZE), "20"));
|
||||
imperial = settings.getBoolean(context.getString(R.string.PREF_TRACKING_IMPERIAL_UNITS), false);
|
||||
|
||||
initKeys(sensors);
|
||||
initKeyLables();
|
||||
initValues();
|
||||
|
||||
settings.registerOnSharedPreferenceChangeListener(
|
||||
new SharedPreferences.OnSharedPreferenceChangeListener() {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String pkey) {
|
||||
if(pkey == context.getString(R.string.PREF_TRACKING_SIZE)) {
|
||||
size = Integer.valueOf(sharedPreferences.getString(context.getString(R.string.PREF_TRACKING_SIZE), "20"));
|
||||
setupWidth();
|
||||
notifyDataSetChanged();
|
||||
} else if (pkey == context.getString(R.string.PREF_TRACKING_SENSORS)) {
|
||||
Set<String> sensors = sharedPreferences.getStringSet(context.getString(R.string.PREF_TRACKING_SENSORS), null);
|
||||
|
||||
initKeys(sensors);
|
||||
initKeyLables();
|
||||
initValues();
|
||||
|
||||
layout.setAdapter(CurrentValuesAdapter.this);
|
||||
notifyDataSetChanged();
|
||||
} else if (pkey == context.getString(R.string.PREF_TRACKING_IMPERIAL_UNITS)) {
|
||||
imperial = sharedPreferences.getBoolean(pkey, false);
|
||||
|
||||
initKeyLables();
|
||||
initValues();
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private void initKeys(Set<String> sensors) {
|
||||
if(sensors != null && sensors.size() > 0) {
|
||||
keys = new int[sensors.size()];
|
||||
int i = 0;
|
||||
for(String sensor : sensors) {
|
||||
keys[i] = Integer.parseInt(sensor);
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
keys = new int[RideService.KEYS.length];
|
||||
for (int i = 0; i < RideService.KEYS.length; i++) {
|
||||
keys[i] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initKeyLables() {
|
||||
keyLabels = new String[keys.length];
|
||||
|
||||
if(!imperial) {
|
||||
for(int key : keys) {
|
||||
keyLabels[key] = RideService.KEYS[key].toString().toLowerCase();
|
||||
}
|
||||
} else {
|
||||
for(int key : keys) {
|
||||
switch (key) {
|
||||
case RideService.ALTITUDE:
|
||||
keyLabels[key] = "ft";
|
||||
break;
|
||||
|
||||
case RideService.KPH:
|
||||
keyLabels[key] = "mph";
|
||||
break;
|
||||
|
||||
case RideService.KM:
|
||||
keyLabels[key] = "m";
|
||||
break;
|
||||
|
||||
default:
|
||||
keyLabels[key] = RideService.KEYS[key].toString().toLowerCase();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initValues() {
|
||||
values = new String[keys.length];
|
||||
for (int key : keys) {
|
||||
if(key == RideService.SECS) {
|
||||
values[key] = "00:00:00";
|
||||
} else {
|
||||
values[key] = "0.0";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private RelativeLayout newRelativeLayout(int key) {
|
||||
RelativeLayout view = new RelativeLayout(context);
|
||||
view.setBackgroundColor(Color.WHITE);
|
||||
|
||||
TextView valueView = newValueTv(key);
|
||||
TextView keyView = newKeyTv(key);
|
||||
|
||||
RelativeLayout.LayoutParams valueLayoutParams = new RelativeLayout.LayoutParams(
|
||||
RelativeLayout.LayoutParams.WRAP_CONTENT,
|
||||
RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||
);
|
||||
|
||||
valueLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
|
||||
valueLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
|
||||
|
||||
view.addView(valueView, valueLayoutParams);
|
||||
|
||||
RelativeLayout.LayoutParams keyLayoutParams = new RelativeLayout.LayoutParams(
|
||||
RelativeLayout.LayoutParams.WRAP_CONTENT,
|
||||
RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||
);
|
||||
|
||||
keyLayoutParams.addRule(RelativeLayout.BELOW, valueView.getId());
|
||||
keyLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
|
||||
keyLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
|
||||
|
||||
view.addView(keyView, keyLayoutParams);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
private TextView newValueTv(int key){
|
||||
TextView tv = new TextView(context);
|
||||
tv.setTextAppearance(context, android.R.attr.textAppearanceLarge);
|
||||
tv.setTypeface(Typeface.MONOSPACE, Typeface.BOLD);
|
||||
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
|
||||
tv.setText(values[key]);
|
||||
tv.setId(key + 1);
|
||||
return tv;
|
||||
}
|
||||
|
||||
|
||||
private TextView newKeyTv(int key){
|
||||
TextView tv = new TextView(context);
|
||||
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
|
||||
tv.setBackgroundColor(Color.LTGRAY);
|
||||
tv.setTypeface(Typeface.MONOSPACE, Typeface.BOLD);
|
||||
tv.setPadding(4, 1, 4, 1);
|
||||
tv.setText(keyLabels[key]);
|
||||
return tv;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return keys.length;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
if (convertView == null) {
|
||||
return newRelativeLayout(keys[position]);
|
||||
} else {
|
||||
RelativeLayout view = (RelativeLayout) convertView;
|
||||
TextView valueView = (TextView) (view.getChildAt(0));
|
||||
TextView valueKey = (TextView) (view.getChildAt(1));
|
||||
|
||||
if(valueView.getText() != values[keys[position]])
|
||||
valueView.setText(values[keys[position]]);
|
||||
|
||||
valueView.setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
|
||||
|
||||
if(valueKey.getText() != keyLabels[keys[position]])
|
||||
valueKey.setText(keyLabels[keys[position]]);
|
||||
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void update(float[] current_float_values) {
|
||||
for (int key: keys) {
|
||||
if(key == RideService.SECS) {
|
||||
int hr = (int) (current_float_values[key]/3600);
|
||||
int rem = (int) (current_float_values[key]%3600);
|
||||
int mn = rem/60;
|
||||
int sec = rem%60;
|
||||
|
||||
values[key] = (hr<10 ? "0" : "") + hr + ":" + (mn<10 ? "0" : "") + mn + ":" + (sec<10 ? "0" : "")+sec;
|
||||
} else if(!imperial) {
|
||||
values[key] = String.format("%.1f", current_float_values[key]);
|
||||
} else {
|
||||
switch (key) {
|
||||
case RideService.ALTITUDE:
|
||||
values[key] = String.format("%.1f", current_float_values[key] * 3.28084);
|
||||
break;
|
||||
|
||||
case RideService.KPH:
|
||||
values[key] = String.format("%.1f", current_float_values[key] * 0.621371);
|
||||
break;
|
||||
|
||||
case RideService.KM:
|
||||
values[key] = String.format("%.1f", current_float_values[key] * 0.621371);
|
||||
break;
|
||||
|
||||
default:
|
||||
values[key] = String.format("%.1f", current_float_values[key]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the size of the cell basted on 8 chars wide and the configured size param
|
||||
* @return int
|
||||
*/
|
||||
private void setupWidth() {
|
||||
TextView tv = new TextView(context);
|
||||
tv.setTextAppearance(context, android.R.attr.textAppearanceLarge);
|
||||
tv.setTypeface(Typeface.MONOSPACE, Typeface.BOLD);
|
||||
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
|
||||
tv.setText(String.format("%.1f", 1111.11));
|
||||
|
||||
Rect bounds = new Rect();
|
||||
tv.getPaint().getTextBounds("00:00:00", 0, "00:00:00".length(), bounds);
|
||||
|
||||
layout.setColumnWidth(bounds.width() + 16);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.ridelogger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
public class GzipWriter extends GZIPOutputStream {
|
||||
public GzipWriter(OutputStream os) throws IOException {
|
||||
super(os);
|
||||
}
|
||||
|
||||
public void write(String data) throws IOException {
|
||||
super.write(data.getBytes());
|
||||
}
|
||||
|
||||
public void write(float data) throws IOException {
|
||||
super.write(Float.floatToIntBits(data));
|
||||
}
|
||||
|
||||
public void write(CharSequence data) throws IOException {
|
||||
byte[] barr = new byte[data.length()];
|
||||
for (int i = 0; i < barr.length; i++) {
|
||||
barr[i] = (byte) data.charAt(i);
|
||||
}
|
||||
|
||||
super.write(barr);
|
||||
}
|
||||
}
|
||||
@@ -1,417 +0,0 @@
|
||||
package com.ridelogger;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import com.dsi.ant.plugins.antplus.pcc.defines.DeviceType;
|
||||
import com.dsi.ant.plugins.utility.log.LogAnt;
|
||||
import com.ridelogger.formats.BaseFormat;
|
||||
import com.ridelogger.formats.JsonFormat;
|
||||
import com.ridelogger.listners.Base;
|
||||
import com.ridelogger.listners.Gps;
|
||||
import com.ridelogger.listners.HeartRate;
|
||||
import com.ridelogger.listners.Power;
|
||||
import com.ridelogger.listners.Sensors;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.app.TaskStackBuilder;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.telephony.PhoneNumberUtils;
|
||||
import android.telephony.SmsManager;
|
||||
|
||||
|
||||
/**
|
||||
* RideService
|
||||
* @author Chet Henry
|
||||
* Performs ride logging from sensors as an android service
|
||||
*/
|
||||
public class RideService extends Service
|
||||
{
|
||||
public static final int notifyID = 1; //Id of the notification in the top android bar that this class creates and alters
|
||||
|
||||
public static final int SECS = 0;
|
||||
public static final int KPH = 1;
|
||||
public static final int ALTITUDE = 2;
|
||||
public static final int bearing = 3;
|
||||
public static final int gpsa = 4;
|
||||
public static final int LAT = 5;
|
||||
public static final int LON = 6;
|
||||
public static final int HR = 7;
|
||||
public static final int WATTS = 8;
|
||||
public static final int NM = 9;
|
||||
public static final int CAD = 10;
|
||||
public static final int KM = 11;
|
||||
public static final int LTE = 12;
|
||||
public static final int RTE = 13;
|
||||
public static final int SNPLC = 14;
|
||||
public static final int SNPR = 15;
|
||||
public static final int ms2x = 16;
|
||||
public static final int ms2y = 17;
|
||||
public static final int ms2z = 18;
|
||||
public static final int temp = 19;
|
||||
public static final int uTx = 20;
|
||||
public static final int uTy = 21;
|
||||
public static final int uTz = 22;
|
||||
public static final int press = 23;
|
||||
public static final int lux = 24;
|
||||
|
||||
public static CharSequence[] KEYS = {
|
||||
"SECS",
|
||||
"KPH",
|
||||
"ALTITUDE",
|
||||
"bearing",
|
||||
"gpsa",
|
||||
"LAT",
|
||||
"LON",
|
||||
"HR",
|
||||
"WATTS",
|
||||
"NM",
|
||||
"CAD",
|
||||
"KM",
|
||||
"LTE",
|
||||
"RTE",
|
||||
"SNPLC",
|
||||
"SNPR",
|
||||
"ms2x",
|
||||
"ms2y",
|
||||
"ms2z",
|
||||
"temp",
|
||||
"uTx",
|
||||
"uTy",
|
||||
"uTz",
|
||||
"press",
|
||||
"lux"
|
||||
};
|
||||
|
||||
public GzipWriter buf; //writes to log file buffered
|
||||
public long startTime; //start time of the ride
|
||||
public float[] currentValues = new float[RideService.KEYS.length]; //float array of current values
|
||||
private Messenger mMessenger = null; //class to send back current values if needed
|
||||
private boolean rideStarted = false; //have we started logging the ride
|
||||
private int sensor_index = 0; //current index of sensors
|
||||
private String emergencyNumbuer; //the number to send the messages to
|
||||
private Timer timer; //timer class to control the periodic messages
|
||||
private Timer timerUI; //timer class to control the periodic messages
|
||||
private Base<?>[] sensors; //list of sensors tracking
|
||||
public BaseFormat<?> fileFormat;
|
||||
|
||||
|
||||
/**
|
||||
* starts the ride on service start
|
||||
*/
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
startRide();
|
||||
return Service.START_NOT_STICKY;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns the messenger to talk to the app with
|
||||
*/
|
||||
@Override
|
||||
public IBinder onBind(Intent arg0) {
|
||||
mMessenger = new Messenger(new Handler() { // Handler of incoming messages from clients.
|
||||
Messenger replyTo;
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if(timerUI != null) {
|
||||
timerUI.cancel();
|
||||
timerUI = null;
|
||||
}
|
||||
|
||||
timerUI = new Timer();
|
||||
|
||||
if(msg.replyTo != null) {
|
||||
replyTo = msg.replyTo;
|
||||
timerUI.scheduleAtFixedRate(
|
||||
new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
Message msg = Message.obtain(null, 2, 0, 0);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable("currentValues", currentValues);
|
||||
msg.setData(bundle);
|
||||
try {
|
||||
replyTo.send(msg);
|
||||
} catch (RemoteException e) {}
|
||||
}
|
||||
},
|
||||
1000,
|
||||
1000
|
||||
); //every second update the screen
|
||||
}
|
||||
}
|
||||
}); // Target we publish for clients to send messages to IncomingHandler.
|
||||
|
||||
return mMessenger.getBinder();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* releases the timer that sends messages to the app
|
||||
*/
|
||||
@Override
|
||||
public boolean onUnbind (Intent intent) {
|
||||
if(timerUI != null) {
|
||||
timerUI.cancel();
|
||||
timerUI = null;
|
||||
}
|
||||
|
||||
mMessenger = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* stop the ride on service stop
|
||||
*/
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
stopRide();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* start a ride if there is not one started yet
|
||||
*/
|
||||
protected void startRide() {
|
||||
if(rideStarted) return;
|
||||
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
emergencyNumbuer = settings.getString(getString(R.string.PREF_EMERGENCY_NUMBER), "");
|
||||
currentValues[SECS] = (float) 0.0;
|
||||
|
||||
startTime = System.currentTimeMillis();
|
||||
|
||||
|
||||
Date startDate = new Date(startTime);
|
||||
|
||||
SimpleDateFormat startTimef = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
|
||||
SimpleDateFormat filef = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
|
||||
SimpleDateFormat month = new SimpleDateFormat("MMMMM");
|
||||
SimpleDateFormat year = new SimpleDateFormat("yyyy");
|
||||
SimpleDateFormat day = new SimpleDateFormat("EEEEE");
|
||||
|
||||
startTimef.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
filef.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
month.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
year.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
day.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
|
||||
final String fileName = filef.format(startDate) + ".json.gz";
|
||||
|
||||
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
|
||||
fileFormat = new JsonFormat(this);
|
||||
fileFormat.createFile();
|
||||
fileFormat.writeHeader();
|
||||
|
||||
LogAnt.setDebugLevel(LogAnt.DebugLevel.NONE, this);
|
||||
|
||||
final Set<String> pairedAnts = settings.getStringSet(getString(R.string.PREF_PAIRED_ANTS), null);
|
||||
|
||||
if(pairedAnts != null && !pairedAnts.isEmpty()){
|
||||
sensors = new Base<?>[pairedAnts.size() + 2];
|
||||
for(String deviceNumber: pairedAnts) {
|
||||
DeviceType deviceType = DeviceType.getValueFromInt(settings.getInt(deviceNumber, 0));
|
||||
switch (deviceType) {
|
||||
case BIKE_CADENCE:
|
||||
break;
|
||||
case BIKE_POWER:
|
||||
sensors[sensor_index++] = new Power(Integer.valueOf(deviceNumber), this);
|
||||
break;
|
||||
case BIKE_SPD:
|
||||
break;
|
||||
case BIKE_SPDCAD:
|
||||
break;
|
||||
case BLOOD_PRESSURE:
|
||||
break;
|
||||
case ENVIRONMENT:
|
||||
break;
|
||||
case WEIGHT_SCALE:
|
||||
break;
|
||||
case HEARTRATE:
|
||||
sensors[sensor_index++] = new HeartRate(Integer.valueOf(deviceNumber), this);
|
||||
break;
|
||||
case STRIDE_SDM:
|
||||
break;
|
||||
case FITNESS_EQUIPMENT:
|
||||
break;
|
||||
case GEOCACHE:
|
||||
case CONTROLLABLE_DEVICE:
|
||||
break;
|
||||
case UNKNOWN:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sensors = new Base<?>[4];
|
||||
sensors[sensor_index++] = new HeartRate(0, this);
|
||||
sensors[sensor_index++] = new Power(0, this);
|
||||
}
|
||||
|
||||
sensors[sensor_index++] = new Gps(this);
|
||||
sensors[sensor_index++] = new Sensors(this);
|
||||
}
|
||||
rideStarted = true;
|
||||
|
||||
if(settings.getBoolean(getString(R.string.PREF_PHONE_HOME), false)) {
|
||||
timer = new Timer();
|
||||
int period = Integer.parseInt(settings.getString(getString(R.string.PREF_PHONE_HOME_PERIOD), "10"));
|
||||
|
||||
timer.scheduleAtFixedRate(
|
||||
new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
phoneHome();
|
||||
}
|
||||
},
|
||||
60000 * period,
|
||||
60000 * period
|
||||
); //every ten min let them know where you are at
|
||||
phoneStart();
|
||||
}
|
||||
|
||||
//build the notification in the top android drawer
|
||||
NotificationCompat.Builder mBuilder = new NotificationCompat
|
||||
.Builder(this)
|
||||
.setSmallIcon(R.drawable.ic_launcher)
|
||||
.setContentTitle(getString(R.string.ride_on))
|
||||
.setContentText(getString(R.string.building_ride) + " " + fileName + " " + getString(R.string.click_to_stop))
|
||||
.setProgress(0, 0, true)
|
||||
.setContentIntent(
|
||||
TaskStackBuilder
|
||||
.create(this)
|
||||
.addParentStack(StartActivity.class)
|
||||
.addNextIntent(new Intent(this, StartActivity.class))
|
||||
.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
);
|
||||
|
||||
startForeground(notifyID, mBuilder.build());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* let a love one know where you are at about every 10 min
|
||||
*/
|
||||
public void phoneCrash(double mag) {
|
||||
smsHome(
|
||||
getString(R.string.crash_warning) + "\n" + getLocationLink()
|
||||
+ "\n " + getString(R.string.crash_magnitude) + ": " + String.valueOf(mag)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* confirm the crash if we are not moving
|
||||
*/
|
||||
public void phoneCrashConfirm() {
|
||||
smsHome(getString(R.string.crash_confirm) + "!\n" + getLocationLink());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* let them know we are starting
|
||||
*/
|
||||
public void phoneStart() {
|
||||
smsWithLocation(getString(R.string.ride_start_sms));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* let them know we are stopping
|
||||
*/
|
||||
public void phoneStop() {
|
||||
smsWithLocation(getString(R.string.ride_stop_sms));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* send an sms with location
|
||||
*/
|
||||
public void smsWithLocation(String body) {
|
||||
smsHome(body + "\n " + getLocationLink());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* let a love one know where you are at about every 10 min
|
||||
*/
|
||||
public void phoneHome() {
|
||||
smsWithLocation(getString(R.string.riding_ok_sms));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* send a sms message
|
||||
*/
|
||||
public void smsHome(String body) {
|
||||
SmsManager smsManager = SmsManager.getDefault();
|
||||
if(emergencyNumbuer != null && PhoneNumberUtils.isWellFormedSmsAddress(emergencyNumbuer)) {
|
||||
smsManager.sendTextMessage(emergencyNumbuer, null, body, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public String getLocationLink() {
|
||||
if(currentValues[LAT] != 0.0 || currentValues[LON] != 0.0) {
|
||||
return "https://www.google.com/maps/place/" + currentValues[LAT] + "," + currentValues[LON];
|
||||
}
|
||||
return getString(R.string.crash_unknow_location);
|
||||
}
|
||||
|
||||
|
||||
//stop the ride and clean up resources
|
||||
protected void stopRide() {
|
||||
if(!rideStarted) return;
|
||||
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
if(settings.getBoolean(getString(R.string.PREF_PHONE_HOME), false)) {
|
||||
phoneStop();
|
||||
}
|
||||
|
||||
for(Base<?> sensor: sensors) {
|
||||
if(sensor != null) {
|
||||
sensor.onDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
//stop the phoneHome timer if we need to.
|
||||
if(timer != null) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
|
||||
if(timerUI != null) {
|
||||
timerUI.cancel();
|
||||
timerUI = null;
|
||||
}
|
||||
|
||||
fileFormat.writeFooter();
|
||||
|
||||
rideStarted = false;
|
||||
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
mNotificationManager.cancel(notifyID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,274 +0,0 @@
|
||||
package com.ridelogger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import com.dsi.ant.plugins.antplus.pcc.defines.DeviceType;
|
||||
import com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult;
|
||||
import com.dsi.ant.plugins.antplus.pccbase.MultiDeviceSearch;
|
||||
import com.dsi.ant.plugins.antplus.pccbase.MultiDeviceSearch.MultiDeviceSearchResult;
|
||||
import com.dsi.ant.plugins.utility.log.LogAnt;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningServiceInfo;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.preference.MultiSelectListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
public class SettingsActivity extends PreferenceActivity {
|
||||
|
||||
static ArrayList<MultiDeviceSearchResult> foundDevices = new ArrayList<MultiDeviceSearchResult>();
|
||||
|
||||
/**
|
||||
* This fragment contains a second-level set of preference that you
|
||||
* can get to by tapping an item in the first preferences fragment.
|
||||
*/
|
||||
public static class GeneralFragment extends PreferenceFragment {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
// Load the preferences from an XML resource
|
||||
addPreferencesFromResource(R.xml.general_settings);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
// TODO Auto-generated method stub
|
||||
super.onResume();
|
||||
|
||||
if(((SettingsActivity) getActivity()).getServiceRunning(RideService.class) != null) {
|
||||
Preference pref = findPreference(getString(R.string.PREF_RIDER_NAME));
|
||||
pref.setEnabled(false);
|
||||
|
||||
pref = findPreference(getString(R.string.PREF_EMERGENCY_NUMBER));
|
||||
pref.setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This fragment contains a second-level set of preference that you
|
||||
* can get to by tapping an item in the first preferences fragment.
|
||||
*/
|
||||
public static class SensorsFragment extends PreferenceFragment {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.sensors_settings);
|
||||
MultiSelectListPreference mMultiSelectListPreference = (MultiSelectListPreference) findPreference(getString(R.string.PREF_TRACKING_SENSORS));
|
||||
mMultiSelectListPreference.setEntries( RideService.KEYS );
|
||||
|
||||
CharSequence[] keys = new CharSequence[RideService.KEYS.length];
|
||||
|
||||
for (int i = 0; i < RideService.KEYS.length; i++) {
|
||||
keys[i] = String.valueOf(i);
|
||||
}
|
||||
mMultiSelectListPreference.setEntryValues(keys);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isValidFragment(String fragment) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This fragment contains a second-level set of preference that you
|
||||
* can get to by tapping an item in the first preferences fragment.
|
||||
*/
|
||||
public static class AntFragment extends PreferenceFragment {
|
||||
private MultiDeviceSearch mSearch;
|
||||
private MultiSelectListPreference mMultiSelectListPreference;
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
// TODO Auto-generated method stub
|
||||
super.onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.ant_settings);
|
||||
mMultiSelectListPreference = (MultiSelectListPreference) findPreference(getString(R.string.PREF_PAIRED_ANTS));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
// TODO Auto-generated method stub
|
||||
super.onResume();
|
||||
initAntSearch();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* search for ant+ if we are not recording
|
||||
*/
|
||||
public void initAntSearch() {
|
||||
mMultiSelectListPreference.setEnabled(false);
|
||||
if(((SettingsActivity) getActivity()).getServiceRunning(RideService.class) == null) {
|
||||
mMultiSelectListPreference.setSummary(R.string.searching_for_ants);
|
||||
|
||||
setupAnt();
|
||||
|
||||
Timer timer = new Timer();
|
||||
final Handler handler = new Handler();
|
||||
|
||||
timer.schedule(
|
||||
new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(mMultiSelectListPreference.getEntryValues().length > 0) {
|
||||
handler.post(new Runnable() {
|
||||
public void run() {
|
||||
mMultiSelectListPreference.setEnabled(true);
|
||||
mMultiSelectListPreference.setSummary(R.string.found_ants);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
handler.post(new Runnable() {
|
||||
public void run() {
|
||||
mMultiSelectListPreference.setEnabled(true);
|
||||
mMultiSelectListPreference.setSummary(R.string.no_found_ants);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
5000
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* try to pair some ant+ devices
|
||||
*/
|
||||
protected void setupAnt() {
|
||||
MultiDeviceSearch.SearchCallbacks mCallback;
|
||||
MultiDeviceSearch.RssiCallback mRssiCallback;
|
||||
|
||||
updateList(foundDevices);
|
||||
|
||||
LogAnt.setDebugLevel(LogAnt.DebugLevel.NONE, this.getActivity());
|
||||
|
||||
mCallback = new MultiDeviceSearch.SearchCallbacks(){
|
||||
public void onDeviceFound(final MultiDeviceSearchResult deviceFound)
|
||||
{
|
||||
if(!foundDevices.contains(deviceFound)) {
|
||||
foundDevices.add(deviceFound);
|
||||
updateList(foundDevices);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSearchStopped(RequestAccessResult arg0) {}
|
||||
};
|
||||
|
||||
mRssiCallback = new MultiDeviceSearch.RssiCallback() {
|
||||
@Override
|
||||
public void onRssiUpdate(final int resultId, final int rssi){}
|
||||
};
|
||||
|
||||
// start the multi-device search
|
||||
mSearch = new MultiDeviceSearch(this.getActivity(), EnumSet.allOf(DeviceType.class), mCallback, mRssiCallback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* dialog of soon to be paired ant devices
|
||||
* @param foundDevices
|
||||
*/
|
||||
protected void updateList(final ArrayList<MultiDeviceSearchResult> foundDevices) {
|
||||
ArrayList<CharSequence> foundDevicesString = new ArrayList<CharSequence>();
|
||||
ArrayList<CharSequence> foundDevicesValues = new ArrayList<CharSequence>();
|
||||
|
||||
for(MultiDeviceSearchResult device : foundDevices) {
|
||||
foundDevicesString.add(device.getAntDeviceType() + ": " + String.valueOf(device.getAntDeviceNumber()));
|
||||
}
|
||||
|
||||
for(MultiDeviceSearchResult device : foundDevices) {
|
||||
foundDevicesValues.add(String.valueOf(device.getAntDeviceNumber()));
|
||||
}
|
||||
|
||||
if(mMultiSelectListPreference != null) {
|
||||
mMultiSelectListPreference.setEntries(
|
||||
foundDevicesString.toArray(new CharSequence[foundDevicesString.size()])
|
||||
);
|
||||
mMultiSelectListPreference.setEntryValues(
|
||||
foundDevicesValues.toArray(new CharSequence[foundDevicesValues.size()])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if(mSearch != null) mSearch.close();
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the activity with the top-level headers.
|
||||
*/
|
||||
@Override
|
||||
public void onBuildHeaders(List<Header> target) {
|
||||
loadHeadersFromResource(R.layout.settings, target);
|
||||
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
settings.registerOnSharedPreferenceChangeListener(
|
||||
new SharedPreferences.OnSharedPreferenceChangeListener() {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String pkey) {
|
||||
if (pkey == getString(R.string.PREF_PAIRED_ANTS)) {
|
||||
Set<String> sensors = sharedPreferences.getStringSet(pkey, null);
|
||||
if(sensors != null && sensors.size() > 0) {
|
||||
Editor editor = sharedPreferences.edit();
|
||||
for(MultiDeviceSearchResult result : foundDevices) {
|
||||
sensors.contains(String.valueOf(result.getAntDeviceNumber()));
|
||||
editor.putInt(String.valueOf(result.getAntDeviceNumber()), result.getAntDeviceType().getIntValue());
|
||||
}
|
||||
editor.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* is a service running or not
|
||||
* @param serviceClass
|
||||
* @return
|
||||
*/
|
||||
public RunningServiceInfo getServiceRunning(Class<?> serviceClass) {
|
||||
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
|
||||
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
|
||||
if (serviceClass.getName().equals(service.service.getClassName())) {
|
||||
return service;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,215 +0,0 @@
|
||||
package com.ridelogger;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningServiceInfo;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.GridView;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class StartActivity extends FragmentActivity
|
||||
{
|
||||
private MenuItem startMenu;
|
||||
private MenuItem stopMenu;
|
||||
|
||||
private ServiceConnection mConnection;
|
||||
static CurrentValuesAdapter currentValuesAdapter;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu items for use in the action bar
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.start_activity, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// Handle presses on the action bar items
|
||||
if(item.getItemId() == R.id.Settings) {
|
||||
setupSettings();
|
||||
} else if(item.getItemId() == R.id.Start) {
|
||||
startRide();
|
||||
} else {
|
||||
stopRide();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* start up our class
|
||||
*/
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_dashboard);
|
||||
|
||||
GridView layout = (GridView) findViewById(R.id.LayoutData);
|
||||
currentValuesAdapter = new CurrentValuesAdapter(this, layout);
|
||||
layout.setAdapter(currentValuesAdapter);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
bindToService();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
unBindToService();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
unBindToService();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* setup the settings for the user
|
||||
*/
|
||||
private void setupSettings() {
|
||||
Intent intent = new Intent(this, SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* stop ride and clean up references
|
||||
*/
|
||||
private void stopRide() {
|
||||
Toast toast = Toast.makeText(getApplicationContext(), getString(R.string.stopping_ride), Toast.LENGTH_LONG);
|
||||
toast.show();
|
||||
|
||||
Intent rsi = new Intent(this, RideService.class);
|
||||
this.stopService(rsi);
|
||||
finish();
|
||||
}
|
||||
|
||||
static final Handler mHandler = new Handler(){
|
||||
@Override
|
||||
public void handleMessage(Message msg_internal) {
|
||||
updateValues(msg_internal.getData());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* tell the service to start sending us messages with current values
|
||||
*/
|
||||
private void bindToService() {
|
||||
RunningServiceInfo service = getServiceRunning(RideService.class);
|
||||
|
||||
if(service != null) {
|
||||
mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
Messenger mService = new Messenger(service);
|
||||
try {
|
||||
Message msg = Message.obtain();
|
||||
msg.replyTo = new Messenger(mHandler);
|
||||
|
||||
mService.send(msg);
|
||||
} catch (RemoteException e) {
|
||||
// In this case the service has crashed before we could even do anything with it
|
||||
}
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {}
|
||||
};
|
||||
|
||||
bindService(new Intent(StartActivity.this, RideService.class), mConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* tell the service to stop sending us messages with current values
|
||||
*/
|
||||
private void unBindToService() {
|
||||
if (mConnection != null) {
|
||||
// Detach our existing connection.
|
||||
unbindService(mConnection);
|
||||
mConnection = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* update the text fields with current values
|
||||
* @param bundle
|
||||
*/
|
||||
private static void updateValues(Bundle bundle) {
|
||||
currentValuesAdapter.update((float[]) bundle.getSerializable("currentValues"));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
|
||||
RunningServiceInfo service = getServiceRunning(RideService.class);
|
||||
startMenu = menu.findItem(R.id.Start);
|
||||
stopMenu = menu.findItem(R.id.Stop);
|
||||
if(service == null) {
|
||||
startMenu.setVisible(true);
|
||||
stopMenu.setVisible(false);
|
||||
} else {
|
||||
startMenu.setVisible(false);
|
||||
stopMenu.setVisible(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* start the ride and notify the user of success
|
||||
*/
|
||||
private void startRide() {
|
||||
Intent rsi = new Intent(this, RideService.class);
|
||||
this.startService(rsi);
|
||||
|
||||
startMenu.setVisible(false);
|
||||
stopMenu.setVisible(true);
|
||||
|
||||
bindToService();
|
||||
|
||||
Toast toast = Toast.makeText(getApplicationContext(), getString(R.string.starting_ride), Toast.LENGTH_LONG);
|
||||
toast.show();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* is a service running or not
|
||||
* @param serviceClass
|
||||
* @return
|
||||
*/
|
||||
private RunningServiceInfo getServiceRunning(Class<?> serviceClass) {
|
||||
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
|
||||
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
|
||||
if (serviceClass.getName().equals(service.service.getClassName())) {
|
||||
return service;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package com.ridelogger.formats;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import android.os.Environment;
|
||||
|
||||
import com.ridelogger.GzipWriter;
|
||||
import com.ridelogger.RideService;
|
||||
|
||||
|
||||
public class BaseFormat<T> {
|
||||
protected GzipWriter buf;
|
||||
protected RideService context;
|
||||
protected String subExt = "";
|
||||
|
||||
public BaseFormat(RideService rideService) {
|
||||
context = rideService;
|
||||
}
|
||||
|
||||
|
||||
public void createFile() {
|
||||
File dir = new File(
|
||||
Environment.getExternalStorageDirectory(),
|
||||
"Rides"
|
||||
);
|
||||
|
||||
dir.mkdirs();
|
||||
|
||||
Date startDate = new Date(context.startTime);
|
||||
SimpleDateFormat filef = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
|
||||
String fileName = filef.format(startDate) + subExt + ".gz";
|
||||
|
||||
try {
|
||||
buf = new GzipWriter(new BufferedOutputStream(new FileOutputStream(new File(dir, fileName))));
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
|
||||
|
||||
public void writeHeader(){
|
||||
try {
|
||||
synchronized (buf) {
|
||||
for(CharSequence key : RideService.KEYS) {
|
||||
buf.write(key);
|
||||
buf.write(",");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
|
||||
|
||||
public void writeValues() {
|
||||
try {
|
||||
synchronized (buf) {
|
||||
for(float value : context.currentValues) {
|
||||
buf.write(value);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
|
||||
|
||||
public void writeFooter() {
|
||||
try {
|
||||
buf.close();
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
package com.ridelogger.formats;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import com.ridelogger.R;
|
||||
import com.ridelogger.RideService;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
public class JsonFormat extends BaseFormat<Object> {
|
||||
public JsonFormat(RideService rideService) {
|
||||
super(rideService);
|
||||
subExt = ".json";
|
||||
}
|
||||
|
||||
public void writeHeader() {
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
Date startDate = new Date(context.startTime);
|
||||
|
||||
SimpleDateFormat startTimef = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
|
||||
SimpleDateFormat filef = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
|
||||
SimpleDateFormat month = new SimpleDateFormat("MMMMM");
|
||||
SimpleDateFormat year = new SimpleDateFormat("yyyy");
|
||||
SimpleDateFormat day = new SimpleDateFormat("EEEEE");
|
||||
|
||||
startTimef.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
filef.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
month.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
year.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
day.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
|
||||
try {
|
||||
buf.write("{" +
|
||||
"\"RIDE\":{" +
|
||||
"\"STARTTIME\":\"" + startTimef.format(startDate) + " UTC\"," +
|
||||
"\"RECINTSECS\":1," +
|
||||
"\"DEVICETYPE\":\"Android\"," +
|
||||
"\"IDENTIFIER\":\"\"," +
|
||||
"\"TAGS\":{" +
|
||||
"\"Athlete\":\"" + settings.getString(context.getString(R.string.PREF_RIDER_NAME), "") + "\"," +
|
||||
"\"Calendar Text\":\"Auto Recored Android Ride\"," +
|
||||
"\"Change History\":\"\"," +
|
||||
"\"Data\":\"\"," +
|
||||
"\"Device\":\"\"," +
|
||||
"\"Device Info\":\"\"," +
|
||||
"\"File Format\":\"\"," +
|
||||
"\"Filename\":\"\"," +
|
||||
"\"Month\":\"" + month.format(startDate) +"\"," +
|
||||
"\"Notes\":\"\"," +
|
||||
"\"Objective\":\"\"," +
|
||||
"\"Sport\":\"Bike\"," +
|
||||
"\"Weekday\":\"" + day.format(startDate) + "\"," +
|
||||
"\"Workout Code\":\"\"," +
|
||||
"\"Year\":\"" + year.format(startDate) + "\"" +
|
||||
"}," +
|
||||
"\"SAMPLES\":[{\"SECS\":0}");
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
|
||||
|
||||
public void writeValues() {
|
||||
try {
|
||||
synchronized (buf) {
|
||||
buf.write(",{");
|
||||
buf.write("\"");
|
||||
buf.write(RideService.KEYS[0]);
|
||||
buf.write("\":");
|
||||
buf.write(String.format("%f", context.currentValues[0]));
|
||||
|
||||
for (int i = 1; i < context.currentValues.length; i++) {
|
||||
buf.write(",\"");
|
||||
buf.write(RideService.KEYS[i]);
|
||||
buf.write("\":");
|
||||
buf.write(String.format("%f", context.currentValues[i]));
|
||||
}
|
||||
|
||||
buf.write("}");
|
||||
}
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
|
||||
|
||||
public void writeFooter() {
|
||||
try {
|
||||
buf.write("]}}");
|
||||
|
||||
} catch (Exception e) {}
|
||||
super.writeFooter();
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package com.ridelogger.listners;
|
||||
|
||||
import com.dsi.ant.plugins.antplus.pcc.defines.DeviceState;
|
||||
import com.dsi.ant.plugins.antplus.pccbase.PccReleaseHandle;
|
||||
import com.dsi.ant.plugins.antplus.pccbase.AntPluginPcc.IDeviceStateChangeReceiver;
|
||||
import com.dsi.ant.plugins.antplus.pccbase.AntPluginPcc.IPluginAccessResultReceiver;
|
||||
import com.ridelogger.RideService;
|
||||
|
||||
|
||||
/**
|
||||
* Ant
|
||||
* @author Chet Henry
|
||||
* Listen to and log Ant+ events base class
|
||||
*/
|
||||
public abstract class Ant extends Base<Object>
|
||||
{
|
||||
protected PccReleaseHandle<?> releaseHandle; //Handle class
|
||||
public IPluginAccessResultReceiver<?> mResultReceiver; //Receiver class
|
||||
protected int deviceNumber = 0;
|
||||
|
||||
|
||||
//setup listeners and logging
|
||||
public Ant(int pDeviceNumber, RideService mContext)
|
||||
{
|
||||
super(mContext);
|
||||
deviceNumber = pDeviceNumber;
|
||||
}
|
||||
|
||||
|
||||
public IDeviceStateChangeReceiver mDeviceStateChangeReceiver = new IDeviceStateChangeReceiver()
|
||||
{
|
||||
@Override
|
||||
public void onDeviceStateChange(final DeviceState newDeviceState){
|
||||
//if we lose a device zero out its values
|
||||
if(newDeviceState.equals(DeviceState.DEAD)) {
|
||||
zeroReadings();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
abstract protected void requestAccess();
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroy()
|
||||
{
|
||||
if(releaseHandle != null) {
|
||||
releaseHandle.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
package com.ridelogger.listners;
|
||||
|
||||
import com.ridelogger.RideService;
|
||||
|
||||
/**
|
||||
* Base
|
||||
* @author Chet Henry
|
||||
* Base sensor class that has methods to time stamp are write to buffer
|
||||
*/
|
||||
public class Base<T>
|
||||
{
|
||||
public RideService context;
|
||||
|
||||
public Base(RideService mContext) {
|
||||
context = mContext;
|
||||
}
|
||||
|
||||
|
||||
public void alterCurrentData(int key, float value)
|
||||
{
|
||||
synchronized (context.currentValues) {
|
||||
context.currentValues[RideService.SECS] = getTs();
|
||||
context.currentValues[key] = value;
|
||||
context.fileFormat.writeValues();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void alterCurrentData(int[] keys, float[] values)
|
||||
{
|
||||
synchronized (context.currentValues) {
|
||||
context.currentValues[RideService.SECS] = getTs();
|
||||
|
||||
int i = 0;
|
||||
for (int key : keys) {
|
||||
context.currentValues[key] = values[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
context.fileFormat.writeValues();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//get current time stamp
|
||||
public float getTs() {
|
||||
return (float) ((System.currentTimeMillis() - context.startTime) / 1000.0);
|
||||
}
|
||||
|
||||
|
||||
//Clean up my listeners here
|
||||
public void onDestroy() {}
|
||||
|
||||
//zero any of my values
|
||||
public void zeroReadings() {}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package com.ridelogger.listners;
|
||||
|
||||
import com.ridelogger.RideService;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.location.LocationListener;
|
||||
import android.location.LocationManager;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* Gps
|
||||
* @author henry
|
||||
* Listen and log gps events
|
||||
*/
|
||||
public class Gps extends Base<Gps>
|
||||
{
|
||||
public Gps(RideService mContext)
|
||||
{
|
||||
super(mContext);
|
||||
|
||||
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
|
||||
|
||||
//listen to gps events and log them
|
||||
LocationListener locationListener = new LocationListener() {
|
||||
public void onLocationChanged(Location location) {
|
||||
int[] keys = {
|
||||
RideService.ALTITUDE,
|
||||
RideService.KPH,
|
||||
RideService.bearing,
|
||||
RideService.gpsa,
|
||||
RideService.LAT,
|
||||
RideService.LON
|
||||
};
|
||||
|
||||
float[] values = {
|
||||
(float) location.getAltitude(),
|
||||
location.getSpeed(),
|
||||
location.getBearing(),
|
||||
location.getAccuracy(),
|
||||
(float) location.getLatitude(),
|
||||
(float) location.getLongitude()
|
||||
};
|
||||
|
||||
alterCurrentData(keys, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged(String provider, int status, Bundle extras) {}
|
||||
|
||||
@Override
|
||||
public void onProviderEnabled(String provider) {}
|
||||
|
||||
@Override
|
||||
public void onProviderDisabled(String provider) {}
|
||||
};
|
||||
|
||||
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package com.ridelogger.listners;
|
||||
|
||||
import com.dsi.ant.plugins.antplus.pcc.AntPlusHeartRatePcc;
|
||||
import com.dsi.ant.plugins.antplus.pcc.AntPlusHeartRatePcc.DataState;
|
||||
import com.dsi.ant.plugins.antplus.pcc.AntPlusHeartRatePcc.IHeartRateDataReceiver;
|
||||
import com.dsi.ant.plugins.antplus.pcc.defines.DeviceState;
|
||||
import com.dsi.ant.plugins.antplus.pcc.defines.EventFlag;
|
||||
import com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult;
|
||||
import com.dsi.ant.plugins.antplus.pccbase.AntPluginPcc.IPluginAccessResultReceiver;
|
||||
import com.ridelogger.RideService;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* HeartRate
|
||||
* @author Chet Henry
|
||||
* Listen to and log Ant+ HearRate events
|
||||
*/
|
||||
public class HeartRate extends Ant
|
||||
{
|
||||
public IPluginAccessResultReceiver<AntPlusHeartRatePcc> mResultReceiver;
|
||||
|
||||
public HeartRate(int pDeviceNumber, RideService mContext) {
|
||||
super(pDeviceNumber, mContext);
|
||||
|
||||
mResultReceiver = new IPluginAccessResultReceiver<AntPlusHeartRatePcc>() {
|
||||
//Handle the result, connecting to events on success or reporting failure to user.
|
||||
@Override
|
||||
public void onResultReceived(AntPlusHeartRatePcc result, RequestAccessResult resultCode, DeviceState initialDeviceState)
|
||||
{
|
||||
if(resultCode == com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult.SUCCESS) {
|
||||
deviceNumber = result.getAntDeviceNumber();
|
||||
result.subscribeHeartRateDataEvent(
|
||||
new IHeartRateDataReceiver() {
|
||||
@Override
|
||||
public void onNewHeartRateData(final long estTimestamp, EnumSet<EventFlag> eventFlags, final int computedHeartRate, final long heartBeatCount, final BigDecimal heartBeatEventTime, final DataState dataState) {
|
||||
alterCurrentData(RideService.HR, (float) computedHeartRate);
|
||||
}
|
||||
}
|
||||
);
|
||||
} else if(resultCode == com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult.SEARCH_TIMEOUT) {
|
||||
if(deviceNumber != 0) {
|
||||
requestAccess();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
requestAccess();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void requestAccess() {
|
||||
releaseHandle = AntPlusHeartRatePcc.requestAccess(context, deviceNumber, 0, mResultReceiver, mDeviceStateChangeReceiver);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void zeroReadings()
|
||||
{
|
||||
alterCurrentData(RideService.HR, (float) 0.0);
|
||||
}
|
||||
}
|
||||
@@ -1,223 +0,0 @@
|
||||
package com.ridelogger.listners;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc;
|
||||
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.CalculatedWheelDistanceReceiver;
|
||||
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.CalculatedWheelSpeedReceiver;
|
||||
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.DataSource;
|
||||
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.ICalculatedCrankCadenceReceiver;
|
||||
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.ICalculatedPowerReceiver;
|
||||
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.ICalculatedTorqueReceiver;
|
||||
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.IInstantaneousCadenceReceiver;
|
||||
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.IRawPowerOnlyDataReceiver;
|
||||
import com.dsi.ant.plugins.antplus.pcc.defines.DeviceState;
|
||||
import com.dsi.ant.plugins.antplus.pcc.defines.EventFlag;
|
||||
import com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult;
|
||||
import com.dsi.ant.plugins.antplus.pccbase.AntPluginPcc.IPluginAccessResultReceiver;
|
||||
import com.ridelogger.R;
|
||||
import com.ridelogger.RideService;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* Power
|
||||
* @author Chet Henry
|
||||
* Listen to and log Ant+ Power events
|
||||
*/
|
||||
public class Power extends Ant
|
||||
{
|
||||
public BigDecimal wheelCircumferenceInMeters; //size of wheel to calculate speed
|
||||
public IPluginAccessResultReceiver<AntPlusBikePowerPcc> mResultReceiver;
|
||||
|
||||
//setup listeners and logging
|
||||
public Power(int pDeviceNumber, RideService mContext) {
|
||||
super(pDeviceNumber, mContext);
|
||||
|
||||
wheelCircumferenceInMeters = new BigDecimal(
|
||||
PreferenceManager.getDefaultSharedPreferences(context).getString(context.getString(R.string.PREF_WHEEL_SIZE), "2.096")
|
||||
);
|
||||
|
||||
//Handle messages
|
||||
mResultReceiver = new IPluginAccessResultReceiver<AntPlusBikePowerPcc>() {
|
||||
//Handle the result, connecting to events on success or reporting failure to user.
|
||||
@Override
|
||||
public void onResultReceived(AntPlusBikePowerPcc result, RequestAccessResult resultCode, DeviceState initialDeviceState) {
|
||||
if(resultCode == com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult.SUCCESS) {
|
||||
deviceNumber = result.getAntDeviceNumber();
|
||||
|
||||
result.subscribeCalculatedPowerEvent(new ICalculatedPowerReceiver() {
|
||||
@Override
|
||||
public void onNewCalculatedPower(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final DataSource dataSource, final BigDecimal calculatedPower) {
|
||||
alterCurrentData(RideService.WATTS, calculatedPower.floatValue());
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
result.subscribeCalculatedTorqueEvent(
|
||||
new ICalculatedTorqueReceiver() {
|
||||
@Override
|
||||
public void onNewCalculatedTorque(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final DataSource dataSource, final BigDecimal calculatedTorque) {
|
||||
alterCurrentData(RideService.NM, calculatedTorque.floatValue());
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
result.subscribeCalculatedCrankCadenceEvent(
|
||||
new ICalculatedCrankCadenceReceiver() {
|
||||
@Override
|
||||
public void onNewCalculatedCrankCadence(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final DataSource dataSource, final BigDecimal calculatedCrankCadence) {
|
||||
alterCurrentData(RideService.CAD, calculatedCrankCadence.floatValue());
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
result.subscribeCalculatedWheelSpeedEvent(
|
||||
new CalculatedWheelSpeedReceiver(wheelCircumferenceInMeters) {
|
||||
@Override
|
||||
public void onNewCalculatedWheelSpeed(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final DataSource dataSource, final BigDecimal calculatedWheelSpeed)
|
||||
{
|
||||
alterCurrentData(RideService.KPH, calculatedWheelSpeed.floatValue());
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
result.subscribeCalculatedWheelDistanceEvent(
|
||||
new CalculatedWheelDistanceReceiver(wheelCircumferenceInMeters) {
|
||||
@Override
|
||||
public void onNewCalculatedWheelDistance(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final DataSource dataSource, final BigDecimal calculatedWheelDistance)
|
||||
{
|
||||
alterCurrentData(RideService.KM, calculatedWheelDistance.floatValue());
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
result.subscribeInstantaneousCadenceEvent(
|
||||
new IInstantaneousCadenceReceiver() {
|
||||
@Override
|
||||
public void onNewInstantaneousCadence(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final DataSource dataSource, final int instantaneousCadence)
|
||||
{
|
||||
alterCurrentData(RideService.CAD, (float) instantaneousCadence);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
result.subscribeRawPowerOnlyDataEvent(
|
||||
new IRawPowerOnlyDataReceiver() {
|
||||
@Override
|
||||
public void onNewRawPowerOnlyData(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final long powerOnlyUpdateEventCount, final int instantaneousPower, final long accumulatedPower)
|
||||
{
|
||||
alterCurrentData(RideService.WATTS, (float) instantaneousPower);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/*result.subscribePedalPowerBalanceEvent(
|
||||
new IPedalPowerBalanceReceiver() {
|
||||
@Override
|
||||
public void onNewPedalPowerBalance(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final boolean rightPedalIndicator, final int pedalPowerPercentage)
|
||||
{
|
||||
alterCurrentData(RideService.LTE, pedalPowerPercentage);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
result.subscribeRawWheelTorqueDataEvent(
|
||||
new IRawWheelTorqueDataReceiver() {
|
||||
@Override
|
||||
public void onNewRawWheelTorqueData(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final long wheelTorqueUpdateEventCount, final long accumulatedWheelTicks, final BigDecimal accumulatedWheelPeriod, final BigDecimal accumulatedWheelTorque)
|
||||
{
|
||||
alterCurrentData(RideService.NM, accumulatedWheelTorque);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
result.subscribeRawCrankTorqueDataEvent(
|
||||
new IRawCrankTorqueDataReceiver() {
|
||||
@Override
|
||||
public void onNewRawCrankTorqueData(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final long crankTorqueUpdateEventCount, final long accumulatedCrankTicks, final BigDecimal accumulatedCrankPeriod, final BigDecimal accumulatedCrankTorque)
|
||||
{
|
||||
alterCurrentData(RideService.NM, accumulatedCrankTorque);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
result.subscribeTorqueEffectivenessEvent(
|
||||
new ITorqueEffectivenessReceiver() {
|
||||
@Override
|
||||
public void onNewTorqueEffectiveness(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final long powerOnlyUpdateEventCount, final BigDecimal leftTorqueEffectiveness, final BigDecimal rightTorqueEffectiveness)
|
||||
{
|
||||
int[] keys = {
|
||||
RideService.LTE,
|
||||
RideService.RTE
|
||||
};
|
||||
|
||||
float[] values = {
|
||||
leftTorqueEffectiveness,
|
||||
rightTorqueEffectiveness
|
||||
}
|
||||
|
||||
alterCurrentData(keys, values);
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
result.subscribePedalSmoothnessEvent(new IPedalSmoothnessReceiver() {
|
||||
@Override
|
||||
public void onNewPedalSmoothness(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final long powerOnlyUpdateEventCount, final boolean separatePedalSmoothnessSupport, final BigDecimal leftOrCombinedPedalSmoothness, final BigDecimal rightPedalSmoothness)
|
||||
{
|
||||
int[] keys = {
|
||||
RideService.SNPLC,
|
||||
RideService.SNPR
|
||||
};
|
||||
|
||||
float[] values = {
|
||||
leftOrCombinedPedalSmoothness,
|
||||
rightPedalSmoothness
|
||||
}
|
||||
|
||||
alterCurrentData(map);
|
||||
}
|
||||
}
|
||||
);*/
|
||||
} else if(resultCode == com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult.SEARCH_TIMEOUT) {
|
||||
if(deviceNumber != 0) {
|
||||
requestAccess();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
requestAccess();
|
||||
}
|
||||
|
||||
protected void requestAccess() {
|
||||
releaseHandle = AntPlusBikePowerPcc.requestAccess(context, deviceNumber, 0, mResultReceiver, mDeviceStateChangeReceiver);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void zeroReadings()
|
||||
{
|
||||
int[] keys = {
|
||||
RideService.WATTS,
|
||||
RideService.NM,
|
||||
RideService.CAD,
|
||||
RideService.KPH,
|
||||
RideService.KM
|
||||
};
|
||||
|
||||
float[] values = {
|
||||
(float) 0.0,
|
||||
(float) 0.0,
|
||||
(float) 0.0,
|
||||
(float) 0.0,
|
||||
(float) 0.0
|
||||
};
|
||||
|
||||
alterCurrentData(keys, values);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,222 +0,0 @@
|
||||
package com.ridelogger.listners;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import com.ridelogger.R;
|
||||
import com.ridelogger.RideService;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
/**
|
||||
* Sensors
|
||||
* @author Chet Henry
|
||||
* Listen to android sensor events and log them
|
||||
*/
|
||||
public class Sensors extends Base<Object>
|
||||
{
|
||||
public static final double CRASHMAGNITUDE = 30.0;
|
||||
|
||||
private SensorEventListener luxListner;
|
||||
private SensorEventListener accelListner;
|
||||
private SensorEventListener pressListner;
|
||||
private SensorEventListener tempListner;
|
||||
private SensorEventListener fieldListner;
|
||||
|
||||
public Sensors(RideService mContext)
|
||||
{
|
||||
super(mContext);
|
||||
|
||||
SensorManager mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
||||
|
||||
Sensor mLight = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
|
||||
Sensor mAccel = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
|
||||
Sensor mPress = mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);
|
||||
Sensor mTemp = mSensorManager.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE);
|
||||
Sensor mField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
|
||||
|
||||
if(mLight != null) {
|
||||
luxListner = new SensorEventListener() {
|
||||
@Override
|
||||
public final void onAccuracyChanged(Sensor sensor, int accuracy) {}
|
||||
|
||||
@Override
|
||||
public final void onSensorChanged(SensorEvent event) {
|
||||
// The light sensor returns a single value.
|
||||
// Many sensors return 3 values, one for each axis.
|
||||
alterCurrentData(RideService.lux, event.values[0]);
|
||||
}
|
||||
};
|
||||
|
||||
mSensorManager.registerListener(luxListner, mLight, 3000000);
|
||||
}
|
||||
|
||||
if(mAccel != null) {
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if(settings.getBoolean(context.getString(R.string.PREF_DETECT_CRASH), false)) {
|
||||
accelListner = new SensorEventListener() {
|
||||
private boolean crashed = false;
|
||||
private Timer timer = new Timer();
|
||||
private double[] St = new double[3];
|
||||
|
||||
@Override
|
||||
public final void onAccuracyChanged(Sensor sensor, int accuracy) {}
|
||||
|
||||
@Override
|
||||
public final void onSensorChanged(SensorEvent event) {
|
||||
int[] keys = {
|
||||
RideService.ms2x,
|
||||
RideService.ms2y,
|
||||
RideService.ms2z
|
||||
};
|
||||
|
||||
alterCurrentData(keys, event.values);
|
||||
|
||||
if(St.length == 0) {
|
||||
St[0] = event.values[0];
|
||||
St[1] = event.values[1];
|
||||
St[2] = event.values[2];
|
||||
}
|
||||
|
||||
St[0] = 0.6 * event.values[0] + 0.4 * St[0];
|
||||
St[1] = 0.6 * event.values[1] + 0.4 * St[1];
|
||||
St[2] = 0.6 * event.values[2] + 0.4 * St[2];
|
||||
|
||||
double amag = Math.sqrt(St[0]*St[0] + St[1]*St[1] + St[2]*St[2]);
|
||||
|
||||
if(amag > CRASHMAGNITUDE && !crashed) {
|
||||
crashed = true;
|
||||
context.phoneCrash(amag);
|
||||
|
||||
if(!Float.isNaN(context.currentValues[RideService.KPH])) {
|
||||
timer.schedule(
|
||||
new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
//if we are traveling less then 1km/h at 5 seconds after crash detection
|
||||
// confirm the crash
|
||||
if(1.0 > context.currentValues[RideService.KPH]) {
|
||||
context.phoneCrashConfirm();
|
||||
} else {
|
||||
crashed = false;
|
||||
context.phoneHome();
|
||||
}
|
||||
}
|
||||
},
|
||||
5000
|
||||
); //in five sec reset
|
||||
} else {
|
||||
timer.schedule(
|
||||
new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
crashed = false;
|
||||
}
|
||||
},
|
||||
180000
|
||||
); //in three min reset
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
accelListner = new SensorEventListener() {
|
||||
@Override
|
||||
public final void onAccuracyChanged(Sensor sensor, int accuracy) {}
|
||||
|
||||
@Override
|
||||
public final void onSensorChanged(SensorEvent event) {
|
||||
int[] keys = {
|
||||
RideService.ms2x,
|
||||
RideService.ms2y,
|
||||
RideService.ms2z
|
||||
};
|
||||
|
||||
alterCurrentData(keys, event.values);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
mSensorManager.registerListener(accelListner, mAccel, SensorManager.SENSOR_DELAY_NORMAL);
|
||||
}
|
||||
|
||||
if(mPress != null) {
|
||||
pressListner = new SensorEventListener() {
|
||||
@Override
|
||||
public final void onAccuracyChanged(Sensor sensor, int accuracy) {}
|
||||
|
||||
@Override
|
||||
public final void onSensorChanged(SensorEvent event) {
|
||||
// The light sensor returns a single value.
|
||||
// Many sensors return 3 values, one for each axis.
|
||||
alterCurrentData(RideService.press, event.values[0]);
|
||||
}
|
||||
};
|
||||
|
||||
mSensorManager.registerListener(pressListner, mPress, 3000000);
|
||||
}
|
||||
|
||||
if(mTemp != null) {
|
||||
tempListner = new SensorEventListener() {
|
||||
@Override
|
||||
public final void onAccuracyChanged(Sensor sensor, int accuracy) {}
|
||||
|
||||
@Override
|
||||
public final void onSensorChanged(SensorEvent event) {
|
||||
// The light sensor returns a single value.
|
||||
// Many sensors return 3 values, one for each axis.
|
||||
alterCurrentData(RideService.temp, event.values[0]);
|
||||
}
|
||||
};
|
||||
|
||||
mSensorManager.registerListener(tempListner, mTemp, 3000000);
|
||||
}
|
||||
|
||||
if(mField != null) {
|
||||
fieldListner = new SensorEventListener() {
|
||||
@Override
|
||||
public final void onAccuracyChanged(Sensor sensor, int accuracy) {}
|
||||
|
||||
@Override
|
||||
public final void onSensorChanged(SensorEvent event) {
|
||||
int[] keys = {
|
||||
RideService.uTx,
|
||||
RideService.uTy,
|
||||
RideService.uTz
|
||||
};
|
||||
|
||||
alterCurrentData(keys, event.values);
|
||||
}
|
||||
};
|
||||
|
||||
mSensorManager.registerListener(fieldListner, mField, SensorManager.SENSOR_DELAY_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy()
|
||||
{
|
||||
SensorManager mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
||||
if(luxListner != null) {
|
||||
mSensorManager.unregisterListener(luxListner);
|
||||
}
|
||||
if(accelListner != null) {
|
||||
mSensorManager.unregisterListener(accelListner);
|
||||
}
|
||||
if(pressListner != null) {
|
||||
mSensorManager.unregisterListener(pressListner);
|
||||
}
|
||||
if(tempListner != null) {
|
||||
mSensorManager.unregisterListener(tempListner);
|
||||
}
|
||||
if(fieldListner != null) {
|
||||
mSensorManager.unregisterListener(fieldListner);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,16 +2,12 @@
|
||||
CONTENT=$(wildcard *.content)
|
||||
HTML=$(subst .content,.html,$(CONTENT))
|
||||
TARBALLS=$(wildcard gc_*.tgz)
|
||||
OTHER= 3d.png choose-a-cyclist.png cpint.gp cpint.png critical-power-plot.png critical-power.png \
|
||||
cyclist-info.png editor.png gui-preview.png histogram-analysis.png logo.jpg logo.png \
|
||||
main-window.png map.png metrics-power.png metrics-timedist.png metrics-tiz.png pf-pv-plot.png \
|
||||
pm.png power.zones realtime.png ride-plot.png ride-plot2.png ride-summary.png sample.gp \
|
||||
sample.png weekly-summary.png google-earth.png aerolab.png
|
||||
OTHER=logo.jpg sample.gp sample.png cpint.gp cpint.png \
|
||||
critical-power-plot.png histogram-analysis.png pf-pv-plot.png \
|
||||
ride-plot.png ride-summary.png weekly-summary.png \
|
||||
choose-a-cyclist.png main-window.png critical-power.png \
|
||||
power.zones cyclist-info.png
|
||||
|
||||
BIN= GoldenCheetah_3.0.1_Mac_Universal.dmg \
|
||||
GoldenCheetah-3.0.1-1.fc18.x86_64.rpm \
|
||||
GoldenCheetah-3.0.1-1.fc19.x86_64.rpm \
|
||||
GoldenCheetah_3.0.1_Windows_Installer.exe
|
||||
|
||||
all: $(HTML)
|
||||
.PHONY: all clean install
|
||||
@@ -21,11 +17,7 @@ clean:
|
||||
|
||||
install:
|
||||
rsync -avz -e ssh $(HTML) $(TARBALLS) $(OTHER) \
|
||||
goldencheetah.org:/home/srhea/wwwroot/goldencheetah.org/
|
||||
|
||||
install-bin:
|
||||
rsync -avz -e ssh $(BIN) \
|
||||
goldencheetah.org:/home/srhea/wwwroot/goldencheetah.org/
|
||||
srhea.net:/home/srhea/wwwroot/goldencheetah.org/
|
||||
|
||||
bug-tracker.html: bug-tracker.content genpage.pl
|
||||
./genpage.pl "Bug Tracker" $< > $@
|
||||
@@ -42,24 +34,9 @@ contrib.html: contrib.content genpage.pl
|
||||
developers-guide.html: developers-guide.content genpage.pl
|
||||
./genpage.pl "Developer's Guide" $< > $@
|
||||
|
||||
older-releases.html: older-releases.content genpage.pl
|
||||
./genpage.pl "Older Releases" $< > $@
|
||||
|
||||
download.html: download.content genpage.pl
|
||||
./genpage.pl "Download" $< > $@
|
||||
|
||||
release-notes.html: release-notes.content genpage.pl
|
||||
./genpage.pl "Release Notes" $< > $@
|
||||
|
||||
release-notes_2.1.0.html: release-notes_2.1.0.content genpage.pl
|
||||
./genpage.pl "Release Notes 2.1.0" $< > $@
|
||||
|
||||
release-notes_3.0.0.html: release-notes_3.0.0.content genpage.pl
|
||||
./genpage.pl "Release Notes 3.0.0" $< > $@
|
||||
|
||||
release-notes_3.0.1.html: release-notes_3.0.1.content genpage.pl
|
||||
./genpage.pl "Release Notes 3.0.1" $< > $@
|
||||
|
||||
faq.html: faq.content genpage.pl
|
||||
./genpage.pl "Frequently Asked Questions" $< > $@
|
||||
|
||||
@@ -81,9 +58,6 @@ search.html: search.content genpage.pl
|
||||
users-guide.html: users-guide.content genpage.pl
|
||||
./genpage.pl "User's Guide" $< > $@
|
||||
|
||||
wiki.html: wiki.content genpage.pl
|
||||
./genpage.pl "Wiki" $< > $@
|
||||
|
||||
wishlist.html: wishlist.content genpage.pl
|
||||
./genpage.pl "Wish List" $< > $@
|
||||
|
||||
97
doc/bug-tracker.content
Normal file
@@ -0,0 +1,97 @@
|
||||
<p>We have an issue tracker set up at
|
||||
<a href=http://bugs.goldencheetah.org/projects/show/goldencheetah>
|
||||
bugs.goldencheetah.org</a>. Below are some guidelines for users and
|
||||
developers for working with the issue tracker.</p>
|
||||
<big><font face="arial,helvetica,sanserif">
|
||||
Report a new bug/feature
|
||||
</font></big>
|
||||
|
||||
<p> If you think that you have found a bug in GoldenCheetah or would like
|
||||
to request a new feature please report it by filing a new issue at our <a
|
||||
href=http://bugs.goldencheetah.org/projects/show/goldencheetah>issue
|
||||
tracker</a>. To report a bug/feature request go to the above link and
|
||||
follow these steps:
|
||||
|
||||
<ol>
|
||||
<li>Login or register for a new account.</li>
|
||||
<li>Click the "new issue" link near the top of the page.</li>
|
||||
<li>Select either "bug" or "feature" from the tracker drop-down menu.</li>
|
||||
<li>Fill out the form including as much detail as possible.<br>
|
||||
You can upload crashreports, problem files, or screenshots if they
|
||||
help document the issue.</li>
|
||||
<li>Click the create button to save your report.<br>
|
||||
This will also send a copy of your report to the Golden-Cheetah-Users
|
||||
mailing list.</li>
|
||||
</ol>
|
||||
<p>Thanks for helping to improve GoldenCheetah.</p>
|
||||
|
||||
<big><font face="arial,helvetica,sanserif">
|
||||
Managing issues in the tracker
|
||||
</font></big>
|
||||
|
||||
<p>To make it easier for all of us to track the status please try to
|
||||
adhere to a few simple guidelines listed below.</p>
|
||||
|
||||
<font face="arial,helvetica,sanserif">
|
||||
<b>Issue Status:</b>
|
||||
</font>
|
||||
<p>Depending on your account status (non-member, reporter, developer, or
|
||||
manager) you may be able to update the status of an existing issue. When
|
||||
working in the bug tracker please update the status appropriately.
|
||||
Current status options are:</p>
|
||||
|
||||
<ul>
|
||||
<li>New: Default status.
|
||||
|
||||
<li>Assigned: issue has been assigned to someone on the project. If you
|
||||
are a Developer you can assign an issue to someone, including
|
||||
yourself. If you are working on a fix, please change the status to
|
||||
Assigned, and post a message stating your plan of attack etc.
|
||||
|
||||
<li>Feedback: This could be used to alert others that you have a
|
||||
proposed fix that you want feed back on. Please attach patches and
|
||||
make a note. Also remember to tag the issue in your patches.
|
||||
|
||||
<li>Resolved: The issue has been corrected. People that have tested the
|
||||
patch or that submitted the bug should update to this status when
|
||||
they feel that it has been fixed. If it turns out that it was not
|
||||
resolved, most users can change the status back to "feedback". If
|
||||
you do so, please leave a note.
|
||||
|
||||
<li>Tempfix: A workaround for the issue has been posted, but we may still be
|
||||
working on a more long term solution.
|
||||
|
||||
<li>Closed: Those with commit access to Github are the only ones that
|
||||
can mark an issue as closed. That said, if you are submitting a
|
||||
patch that fixes and issue, please include the "fixes #<issuenum>"
|
||||
tag to your commit as this will automatically close the issue when your
|
||||
patch is accepted and pushed to github.
|
||||
</ul>
|
||||
|
||||
<font face="arial,helvetica,sanserif">
|
||||
<b>Tagging in messages</b>
|
||||
</font>
|
||||
<p>The tracker has a very basic tagging and markup scheme that is described in
|
||||
detail <a href="http://bugs.goldencheetah.org/help/wiki_syntax.html">here</a>.
|
||||
Perhaps the most useful feature is the ability to use tags to link issues,
|
||||
commits, etc. When commenting on an issue please use the following tags
|
||||
when appropriate to automatically create links when:</p>
|
||||
|
||||
<table align="center" width="600">
|
||||
<tr>
|
||||
<th>Tag</th>
|
||||
<th>Effect</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Issue #2</td>
|
||||
<td>Creates a link to existing Issue #2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>commit:e76247a</td>
|
||||
<td>Creates a link to commit e76247a</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>source:src/MainWindow.cpp</td>
|
||||
<td>Creates a link to src/Mainwindow.cpp in our git repo</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -22,40 +22,34 @@ other support, including:</p>
|
||||
<ul>
|
||||
<li>Robert Carlsen</li>
|
||||
<li>Rainer Clasen</li>
|
||||
<li>Chris Cleeland</li>
|
||||
<li>J.T. Conklin</li>
|
||||
<li>Dan Connelly</li>
|
||||
<li>Damien Grauser</li>
|
||||
<li>Steve Gribble</li>
|
||||
<li>Dag Gruneau</li>
|
||||
<li>Damian Grauser</li>
|
||||
<li>Ned Harding</li>
|
||||
<li>Aldy Hernandez</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td valign="top" width="33%">
|
||||
<ul>
|
||||
<li>Aldy Hernandez</li>
|
||||
<li>Jamie Kimberley</li>
|
||||
<li>Justin Knotzke</li>
|
||||
<li>Andrew Kruse</li>
|
||||
<li>Mark Liversedge</li>
|
||||
<li>Greg Lonnon</li>
|
||||
<li>Tom Montgomery</li>
|
||||
<li>Eric Murray</li>
|
||||
<li>Scott Overfield</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<ul>
|
||||
<li>Eric Murray</li>
|
||||
<li>Scott Overfield</li>
|
||||
<li>Mark Rages</li>
|
||||
<li>Robb Romans</li>
|
||||
<li>Mitsukuni Sato</li>
|
||||
<li>Berend de Schouwer</li>
|
||||
<li>Julian Simioni</li>
|
||||
<li>Greg Steele</li>
|
||||
<li>Tom Weichmann</li>
|
||||
<li>Keisuke Yamaguchi</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
@c gnupress.tex -- Common Texinfo macros for GNU Press books.
|
||||
@c
|
||||
@c Print in 7" x 9.25" format.
|
||||
@smallbook
|
||||
@advance@voffset by -0.25in
|
||||
@special{papersize=7in,9.25in}
|
||||
@c
|
||||
@c Since we are using @smallbook, we ought to use @smallfonts
|
||||
@tex
|
||||
\global\let\lisporig=\lisp
|
||||
\gdef\lisp{\smallexamplefonts\lisporig}%
|
||||
\global\let\exampleorig=\example
|
||||
\gdef\example{\smallexamplefonts\exampleorig}%
|
||||
\global\let\displayorig=\display
|
||||
\gdef\display{\smallexamplefonts\displayorig}%
|
||||
\global\let\formatorig=\format
|
||||
\gdef\format{\smallexamplefonts\formatorig}%
|
||||
@end tex
|
||||
@@ -1,161 +0,0 @@
|
||||
@c palatino.tex -- TeXinfo macros to set the default Roman font to Palatino
|
||||
@c
|
||||
@def@palatinoversion{2003-04-01.00}
|
||||
@c
|
||||
@c Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
@c
|
||||
@c This palatino.tex file is free software; you can redistribute it and/or
|
||||
@c modify it under the terms of the GNU General Public License as
|
||||
@c published by the Free Software Foundation; either version 2, or (at
|
||||
@c your option) any later version.
|
||||
@c
|
||||
@c This palatino.tex file is distributed in the hope that it will be
|
||||
@c useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
@c of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
@c General Public License for more details.
|
||||
@c
|
||||
@c You should have received a copy of the GNU General Public License
|
||||
@c along with this texinfo.tex file; see the file COPYING. If not, write
|
||||
@c to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
@c Boston, MA 02111-1307, USA.
|
||||
@c
|
||||
@c You should use this module, go to your root .texi file and make sure
|
||||
@c it reads like this:
|
||||
@c \input texinfo @c -*-texinfo-*-
|
||||
@c @input palatino
|
||||
|
||||
@message{Loading palatino [version @palatinoversion]:}
|
||||
|
||||
@c Turn on the normal TeX command characters.
|
||||
@catcode`\=0
|
||||
\catcode`\%=14
|
||||
% Set the font macro #1 to the font named #2#3. #4 is the point size.
|
||||
% We save \setfont as \setfontorig, so we can restore it at the end of this
|
||||
% section.
|
||||
\catcode`\#=6
|
||||
\let\setfontorig=\setfont
|
||||
\def\setfont#1#2#3#4{\font#1=#2#3 at #4}
|
||||
\catcode`\#=\other
|
||||
|
||||
% Set Palatino as the default roman font face
|
||||
\def\rmfontprefix{ppl}
|
||||
|
||||
% Only define roman font attributes here.
|
||||
\def\rmshape{r}
|
||||
\def\rmbshape{b}
|
||||
\def\bfshape{b}
|
||||
\def\bxshape{b}
|
||||
\def\itshape{ri}
|
||||
\def\itbshape{bi}
|
||||
\def\slshape{ro}
|
||||
\def\slbshape{bo}
|
||||
\def\scshape{rc}
|
||||
\def\scbshape{bc}
|
||||
|
||||
\ifx\bigger\relax
|
||||
% not really supported.
|
||||
\def\mainmagstep{12pt}
|
||||
\setfont\textrm\rmfontprefix\rmshape{\mainmagstep}
|
||||
\else
|
||||
\def\mainmagstep{10pt}
|
||||
\setfont\textrm\rmfontprefix\rmshape{\mainmagstep}
|
||||
\fi
|
||||
% Instead of cmb10, you many want to use cmbx10.
|
||||
% cmbx10 is a prettier font on its own, but cmb10
|
||||
% looks better when embedded in a line with cmr10.
|
||||
\setfont\textbf\rmfontprefix\bfshape{\mainmagstep}
|
||||
\setfont\textit\rmfontprefix\itshape{\mainmagstep}
|
||||
\setfont\textsl\rmfontprefix\slshape{\mainmagstep}
|
||||
\setfont\textsc\rmfontprefix\scshape{\mainmagstep}
|
||||
\font\texti=zppler7m at \mainmagstep
|
||||
\font\textsy=zppler7y at \mainmagstep
|
||||
|
||||
% A few fonts for \defun, etc.
|
||||
\setfont\defbf\rmfontprefix\bxshape{10pt} %was 1314
|
||||
\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
|
||||
|
||||
% Fonts for indices, footnotes, small examples (9pt).
|
||||
\setfont\smallrm\rmfontprefix\rmshape{9pt}
|
||||
\setfont\smallbf\rmfontprefix\bfshape{9pt}
|
||||
\setfont\smallit\rmfontprefix\itshape{9pt}
|
||||
\setfont\smallsl\rmfontprefix\slshape{9pt}
|
||||
\setfont\smallsc\rmfontprefix\scshape{9pt}
|
||||
\font\smalli=zppler7m at 9pt
|
||||
\font\smallsy=zppler7y at 9pt
|
||||
|
||||
% Fonts for small examples (8pt).
|
||||
\setfont\smallerrm\rmfontprefix\rmshape{8pt}
|
||||
\setfont\smallerbf\rmfontprefix\bfshape{8pt}
|
||||
\setfont\smallerit\rmfontprefix\itshape{8pt}
|
||||
\setfont\smallersl\rmfontprefix\slshape{8pt}
|
||||
\setfont\smallersc\rmfontprefix\scshape{8pt}
|
||||
\font\smalleri=zppler7m at 8pt
|
||||
\font\smallersy=zppler7y at 8pt
|
||||
|
||||
% Fonts for title page:
|
||||
\setfont\titlerm\rmfontprefix\rmbshape{18pt}
|
||||
\setfont\titleit\rmfontprefix\itbshape{18pt}
|
||||
\setfont\titlesl\rmfontprefix\slbshape{18pt}
|
||||
\let\titlebf=\titlerm
|
||||
\setfont\titlesc\rmfontprefix\scbshape{18pt}
|
||||
\font\titlei=zppler7m at 18pt
|
||||
\font\titlesy=zppler7y at 18pt
|
||||
\def\authorrm{\secrm}
|
||||
\def\authortt{\sectt}
|
||||
|
||||
% Chapter (and unnumbered) fonts (17.28pt).
|
||||
\setfont\chaprm\rmfontprefix\rmbshape{17.28pt}
|
||||
\setfont\chapit\rmfontprefix\itbshape{17.28pt}
|
||||
\setfont\chapsl\rmfontprefix\slbshape{17.28pt}
|
||||
\let\chapbf=\chaprm
|
||||
\setfont\chapsc\rmfontprefix\scbshape{17.28pt}
|
||||
\font\chapi=zppler7m at 17.28pt
|
||||
\font\chapsy=zppler7y at 17.28pt
|
||||
|
||||
% Section fonts (14.4pt).
|
||||
\setfont\secrm\rmfontprefix\rmbshape{14.4pt}
|
||||
\setfont\secit\rmfontprefix\itbshape{14.4pt}
|
||||
\setfont\secsl\rmfontprefix\slbshape{14.4pt}
|
||||
\let\secbf\secrm
|
||||
\setfont\secsc\rmfontprefix\scbshape{14.4pt}
|
||||
\font\seci=zppler7m at 14.4pt
|
||||
\font\secsy=zppler7y at 14.4pt
|
||||
|
||||
% Subsection fonts (13.15pt).
|
||||
\setfont\ssecrm\rmfontprefix\rmbshape{13.15pt}
|
||||
\setfont\ssecit\rmfontprefix\itbshape{13.15pt}
|
||||
\setfont\ssecsl\rmfontprefix\slbshape{13.15pt}
|
||||
\let\ssecbf\ssecrm
|
||||
\setfont\ssecsc\rmfontprefix\scbshape{13.15pt}
|
||||
\font\sseci=zppler7m at 13.15pt
|
||||
\font\ssecsy=zppler7y at 13.15pt
|
||||
% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
|
||||
% but that is not a standard magnification.
|
||||
|
||||
% Fonts for short table of contents.
|
||||
\setfont\shortcontrm\rmfontprefix\rmshape{12pt}
|
||||
\setfont\shortcontbf\rmfontprefix\bxshape{12pt}
|
||||
\setfont\shortcontsl\rmfontprefix\slshape{12pt}
|
||||
|
||||
% Set keyfont as well.
|
||||
\setfont\keyrm\rmfontprefix\rmshape{8pt}
|
||||
\font\keysy=zppler7y at 9pt
|
||||
|
||||
\let\setfont=\setfontorig
|
||||
\def\setfontorig{\relax}
|
||||
|
||||
% Restore the TeXinfo character set.
|
||||
\catcode`\\=\active
|
||||
@catcode`@%=@other
|
||||
|
||||
@c Set initial fonts (again)
|
||||
@textfonts
|
||||
@rm
|
||||
|
||||
@c Local variables:
|
||||
@c eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
@c page-delimiter: "^\\\\message"
|
||||
@c time-stamp-start: "def\\\\palatinoversion{"
|
||||
@c time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
@c time-stamp-end: "}"
|
||||
@c End:
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 139 KiB After Width: | Height: | Size: 139 KiB |
|
Before Width: | Height: | Size: 149 KiB After Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 195 KiB |
@@ -1,48 +0,0 @@
|
||||
<mockup version="1.0" skin="sketch" fontFace="Balsamiq Sans" measuredW="591" measuredH="228" mockupW="566" mockupH="205">
|
||||
<controls>
|
||||
<control controlID="0" controlTypeID="com.balsamiq.mockups::Canvas" x="25" y="23" w="566" h="205" measuredW="100" measuredH="70" zOrder="0" locked="false" isInGroup="-1"/>
|
||||
<control controlID="1" controlTypeID="com.balsamiq.mockups::HRule" x="31" y="37" w="560" h="-1" measuredW="100" measuredH="10" zOrder="1" locked="false" isInGroup="-1"/>
|
||||
<control controlID="2" controlTypeID="com.balsamiq.mockups::Label" x="34" y="23" w="-1" h="-1" measuredW="110" measuredH="21" zOrder="2" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Compare%20Intervals</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="3" controlTypeID="com.balsamiq.mockups::CheckBox" x="40" y="191" w="-1" h="-1" measuredW="110" measuredH="22" zOrder="3" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Compare%20Delta</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="4" controlTypeID="com.balsamiq.mockups::Canvas" x="34" y="52" w="414" h="133" measuredW="100" measuredH="70" zOrder="4" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<borderStyle>roundedDotted</borderStyle>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="6" controlTypeID="com.balsamiq.mockups::List" x="456" y="47" w="128" h="174" measuredW="100" measuredH="174" zOrder="5" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>May%202x20s%0ABarhatch%20Climbs%0ASub%204%20ToSH%0AMarmottes%0AAdH%20Ascents%0ABox%20Hill%202009%0ABox%20Hill%202013%0ABox%20Hill%20All</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="7" controlTypeID="com.balsamiq.mockups::TextInput" x="170" y="189" w="225" h="-1" measuredW="138" measuredH="27" zOrder="6" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Compare%20Set%20Name...</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="8" controlTypeID="com.balsamiq.mockups::Button" x="402" y="189" w="-1" h="-1" measuredW="45" measuredH="27" zOrder="7" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Add</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="10" controlTypeID="com.balsamiq.mockups::RoundButton" x="569" y="24" w="15" h="18" measuredW="32" measuredH="32" zOrder="8" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<icon>CircledXIcon%7Cxsmall</icon>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="11" controlTypeID="com.balsamiq.mockups::Label" x="48" y="62" w="387" h="-1" measuredW="180" measuredH="21" zOrder="9" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<color>10066329</color>
|
||||
<text>Drag%20and%20drop%20intervals%20here%20...</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
</controls>
|
||||
</mockup>
|
||||
|
Before Width: | Height: | Size: 22 KiB |
@@ -1,610 +0,0 @@
|
||||
<mockup version="1.0" skin="sketch" fontFace="Balsamiq Sans" measuredW="1997" measuredH="568" mockupW="1935" mockupH="553">
|
||||
<controls>
|
||||
<control controlID="0" controlTypeID="com.balsamiq.mockups::TitleWindow" x="62" y="61" w="355" h="400" measuredW="450" measuredH="400" zOrder="0" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<bottomheight>0</bottomheight>
|
||||
<dragger>false</dragger>
|
||||
<text>Chart%20Controls%20%5BLTM%20Chart%5D</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="1" controlTypeID="com.balsamiq.mockups::TabBar" x="84" y="101" w="312" h="284" measuredW="219" measuredH="100" zOrder="1" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Basic%2C%20Preset%2C%20Custom*</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="2" controlTypeID="com.balsamiq.mockups::Button" x="321" y="413" w="75" h="27" measuredW="53" measuredH="27" zOrder="2" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Done</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="3" controlTypeID="com.balsamiq.mockups::List" x="101" y="164" w="-1" h="-1" measuredW="100" measuredH="126" zOrder="3" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Best%0AFormula%0AMetric%0AMeasure</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="4" controlTypeID="com.balsamiq.mockups::List" x="201" y="164" w="171" h="126" measuredW="100" measuredH="126" zOrder="4" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Power%205s%0A%3D60m%20WPK%20*%20RPE%0AAverage_Power%0AWeight</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="5" controlTypeID="com.balsamiq.mockups::TextInput" x="100" y="140" w="101" h="-1" measuredW="44" measuredH="27" zOrder="5" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Type</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="6" controlTypeID="com.balsamiq.mockups::TextInput" x="201" y="140" w="171" h="-1" measuredW="56" measuredH="27" zOrder="6" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Details</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="7" controlTypeID="com.balsamiq.mockups::Button" x="101" y="298" w="75" h="27" measuredW="46" measuredH="27" zOrder="7" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Edit</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="8" controlTypeID="com.balsamiq.mockups::Button" x="294" y="298" w="36" h="27" measuredW="31" measuredH="27" zOrder="8" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>+</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="9" controlTypeID="com.balsamiq.mockups::Button" x="336" y="298" w="36" h="27" measuredW="27" measuredH="27" zOrder="9" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>-</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="12" controlTypeID="com.balsamiq.mockups::Arrow" x="345" y="15" w="225" h="143" measuredW="150" measuredH="100" zOrder="10" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<backgroundAlpha>1</backgroundAlpha>
|
||||
<direction>bottom</direction>
|
||||
<rightArrow>false</rightArrow>
|
||||
<text>Lists%20all%20data%20series%20that%20will%20be%20available%20on%20the%20chart</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="13" controlTypeID="com.balsamiq.mockups::TitleWindow" x="481" y="55" w="489" h="507" measuredW="450" measuredH="400" zOrder="11" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Edit%20Data%20Series%20%5BMetric/Measure%5D</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="14" controlTypeID="com.balsamiq.mockups::RadioButton" x="497" y="156" w="136" h="22" measuredW="53" measuredH="22" zOrder="12" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<state>selected</state>
|
||||
<text>Metric</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="15" controlTypeID="com.balsamiq.mockups::RadioButton" x="497" y="184" w="136" h="22" measuredW="43" measuredH="22" zOrder="13" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Best</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="16" controlTypeID="com.balsamiq.mockups::RadioButton" x="497" y="212" w="136" h="22" measuredW="63" measuredH="22" zOrder="14" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Formula</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="17" controlTypeID="com.balsamiq.mockups::RadioButton" x="497" y="130" w="136" h="22" measuredW="68" measuredH="22" zOrder="15" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<state>selected</state>
|
||||
<text>Measure</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="18" controlTypeID="com.balsamiq.mockups::Arrow" x="155" y="242" w="326" h="69" measuredW="150" measuredH="100" zOrder="16" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<backgroundAlpha>0.25</backgroundAlpha>
|
||||
<direction>bottom</direction>
|
||||
<leftArrow>false</leftArrow>
|
||||
<rightArrow>true</rightArrow>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="19" controlTypeID="com.balsamiq.mockups::Arrow" x="306" y="242" w="175" h="69" measuredW="150" measuredH="100" zOrder="17" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<backgroundAlpha>0.25</backgroundAlpha>
|
||||
<direction>bottom</direction>
|
||||
<leftArrow>false</leftArrow>
|
||||
<rightArrow>false</rightArrow>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="20" controlTypeID="com.balsamiq.mockups::List" x="615" y="126" w="317" h="113" measuredW="100" measuredH="132" zOrder="18" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Peak%201m%20Power%0APeak%201m%20WPK%0APeak%201s%20Power%0APeak%201s%20WPK%0APeak%205s%20Power%0APeak%205s%20WPK</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="21" controlTypeID="com.balsamiq.mockups::TextInput" x="615" y="102" w="317" h="-1" measuredW="58" measuredH="27" zOrder="19" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Metrics</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="22" controlTypeID="com.balsamiq.mockups::VerticalScrollBar" x="916" y="126" w="-1" h="113" measuredW="16" measuredH="100" zOrder="20" locked="false" isInGroup="-1"/>
|
||||
<control controlID="24" controlTypeID="com.balsamiq.mockups::Label" x="498" y="101" w="-1" h="-1" measuredW="30" measuredH="21" zOrder="21" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Type</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="26" controlTypeID="com.balsamiq.mockups::Label" x="497" y="264" w="104" h="-1" measuredW="35" measuredH="21" zOrder="22" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Name</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="27" controlTypeID="com.balsamiq.mockups::Label" x="497" y="304" w="131" h="-1" measuredW="106" measuredH="21" zOrder="23" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Axis%20Label%20/%20Units</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="28" controlTypeID="com.balsamiq.mockups::Label" x="497" y="342" w="131" h="-1" measuredW="36" measuredH="21" zOrder="24" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Curve</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="29" controlTypeID="com.balsamiq.mockups::Label" x="497" y="378" w="131" h="-1" measuredW="44" measuredH="21" zOrder="25" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Symbol</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="30" controlTypeID="com.balsamiq.mockups::Label" x="499" y="416" w="131" h="-1" measuredW="35" measuredH="21" zOrder="26" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Stack</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="31" controlTypeID="com.balsamiq.mockups::Label" x="499" y="448" w="131" h="-1" measuredW="32" measuredH="21" zOrder="27" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Color</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="32" controlTypeID="com.balsamiq.mockups::Label" x="499" y="484" w="111" h="-1" measuredW="55" measuredH="21" zOrder="28" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Fill%20Curve</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="33" controlTypeID="com.balsamiq.mockups::TextInput" x="618" y="261" w="97" h="-1" measuredW="79" measuredH="26" zOrder="29" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="34" controlTypeID="com.balsamiq.mockups::TextInput" x="616" y="301" w="97" h="-1" measuredW="79" measuredH="26" zOrder="30" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="35" controlTypeID="com.balsamiq.mockups::ComboBox" x="618" y="340" w="95" h="-1" measuredW="55" measuredH="24" zOrder="31" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Line</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="36" controlTypeID="com.balsamiq.mockups::ComboBox" x="618" y="378" w="95" h="-1" measuredW="64" measuredH="24" zOrder="32" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Circle</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="37" controlTypeID="com.balsamiq.mockups::CheckBox" x="627" y="417" w="-1" h="-1" measuredW="20" measuredH="21" zOrder="33" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="38" controlTypeID="com.balsamiq.mockups::CheckBox" x="627" y="483" w="-1" h="-1" measuredW="20" measuredH="21" zOrder="34" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="39" controlTypeID="com.balsamiq.mockups::ColorPicker" x="620" y="447" w="-1" h="-1" measuredW="26" measuredH="28" zOrder="35" locked="false" isInGroup="-1"/>
|
||||
<control controlID="40" controlTypeID="com.balsamiq.mockups::Label" x="738" y="264" w="104" h="-1" measuredW="52" measuredH="21" zOrder="36" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Highlight</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="41" controlTypeID="com.balsamiq.mockups::Label" x="736" y="304" w="104" h="-1" measuredW="47" measuredH="21" zOrder="37" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Outliers</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="42" controlTypeID="com.balsamiq.mockups::Label" x="738" y="342" w="104" h="-1" measuredW="50" measuredH="21" zOrder="38" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Baseline</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="43" controlTypeID="com.balsamiq.mockups::Label" x="738" y="416" w="104" h="-1" measuredW="84" measuredH="21" zOrder="39" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Smooth%20Curve</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="44" controlTypeID="com.balsamiq.mockups::Label" x="738" y="446" w="104" h="-1" measuredW="63" measuredH="21" zOrder="40" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Trend%20Line</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="45" controlTypeID="com.balsamiq.mockups::CheckBox" x="842" y="417" w="-1" h="-1" measuredW="20" measuredH="21" zOrder="41" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="46" controlTypeID="com.balsamiq.mockups::CheckBox" x="842" y="448" w="20" h="21" measuredW="20" measuredH="21" zOrder="42" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="47" controlTypeID="com.balsamiq.mockups::NumericStepper" x="837" y="263" w="95" h="-1" measuredW="41" measuredH="24" zOrder="43" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>0</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="48" controlTypeID="com.balsamiq.mockups::NumericStepper" x="837" y="301" w="95" h="-1" measuredW="41" measuredH="24" zOrder="44" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>0</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="49" controlTypeID="com.balsamiq.mockups::NumericStepper" x="837" y="341" w="95" h="-1" measuredW="61" measuredH="24" zOrder="45" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>-999</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="50" controlTypeID="com.balsamiq.mockups::TitleWindow" x="991" y="57" w="489" h="507" measuredW="450" measuredH="400" zOrder="46" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Edit%20Data%20Series%20%5BFormula%5D</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="51" controlTypeID="com.balsamiq.mockups::RadioButton" x="1007" y="158" w="136" h="22" measuredW="53" measuredH="22" zOrder="47" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<state>up</state>
|
||||
<text>Metric</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="52" controlTypeID="com.balsamiq.mockups::RadioButton" x="1007" y="186" w="136" h="22" measuredW="43" measuredH="22" zOrder="48" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Best</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="53" controlTypeID="com.balsamiq.mockups::RadioButton" x="1007" y="214" w="136" h="22" measuredW="63" measuredH="22" zOrder="49" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<state>selected</state>
|
||||
<text>Formula</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="54" controlTypeID="com.balsamiq.mockups::RadioButton" x="1007" y="132" w="136" h="22" measuredW="68" measuredH="22" zOrder="50" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Measure</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="58" controlTypeID="com.balsamiq.mockups::Label" x="1008" y="103" w="-1" h="-1" measuredW="30" measuredH="21" zOrder="51" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Type</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="59" controlTypeID="com.balsamiq.mockups::Label" x="1007" y="266" w="104" h="-1" measuredW="35" measuredH="21" zOrder="52" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Name</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="60" controlTypeID="com.balsamiq.mockups::Label" x="1007" y="306" w="131" h="-1" measuredW="106" measuredH="21" zOrder="53" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Axis%20Label%20/%20Units</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="61" controlTypeID="com.balsamiq.mockups::Label" x="1007" y="344" w="131" h="-1" measuredW="36" measuredH="21" zOrder="54" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Curve</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="62" controlTypeID="com.balsamiq.mockups::Label" x="1007" y="380" w="131" h="-1" measuredW="44" measuredH="21" zOrder="55" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Symbol</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="63" controlTypeID="com.balsamiq.mockups::Label" x="1009" y="418" w="131" h="-1" measuredW="35" measuredH="21" zOrder="56" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Stack</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="64" controlTypeID="com.balsamiq.mockups::Label" x="1009" y="450" w="131" h="-1" measuredW="32" measuredH="21" zOrder="57" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Color</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="65" controlTypeID="com.balsamiq.mockups::Label" x="1009" y="486" w="111" h="-1" measuredW="55" measuredH="21" zOrder="58" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Fill%20Curve</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="66" controlTypeID="com.balsamiq.mockups::TextInput" x="1128" y="263" w="97" h="-1" measuredW="79" measuredH="26" zOrder="59" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="67" controlTypeID="com.balsamiq.mockups::TextInput" x="1126" y="303" w="97" h="-1" measuredW="79" measuredH="26" zOrder="60" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="68" controlTypeID="com.balsamiq.mockups::ComboBox" x="1128" y="342" w="95" h="-1" measuredW="55" measuredH="24" zOrder="61" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Line</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="69" controlTypeID="com.balsamiq.mockups::ComboBox" x="1128" y="380" w="95" h="-1" measuredW="64" measuredH="24" zOrder="62" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Circle</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="70" controlTypeID="com.balsamiq.mockups::CheckBox" x="1137" y="419" w="-1" h="-1" measuredW="20" measuredH="21" zOrder="63" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="71" controlTypeID="com.balsamiq.mockups::CheckBox" x="1137" y="485" w="-1" h="-1" measuredW="20" measuredH="21" zOrder="64" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="72" controlTypeID="com.balsamiq.mockups::ColorPicker" x="1130" y="449" w="-1" h="-1" measuredW="26" measuredH="28" zOrder="65" locked="false" isInGroup="-1"/>
|
||||
<control controlID="73" controlTypeID="com.balsamiq.mockups::Label" x="1248" y="266" w="104" h="-1" measuredW="52" measuredH="21" zOrder="66" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Highlight</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="74" controlTypeID="com.balsamiq.mockups::Label" x="1246" y="306" w="104" h="-1" measuredW="47" measuredH="21" zOrder="67" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Outliers</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="75" controlTypeID="com.balsamiq.mockups::Label" x="1248" y="344" w="104" h="-1" measuredW="50" measuredH="21" zOrder="68" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Baseline</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="76" controlTypeID="com.balsamiq.mockups::Label" x="1248" y="418" w="104" h="-1" measuredW="84" measuredH="21" zOrder="69" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Smooth%20Curve</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="77" controlTypeID="com.balsamiq.mockups::Label" x="1248" y="448" w="104" h="-1" measuredW="63" measuredH="21" zOrder="70" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Trend%20Line</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="78" controlTypeID="com.balsamiq.mockups::CheckBox" x="1352" y="419" w="-1" h="-1" measuredW="20" measuredH="21" zOrder="71" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="79" controlTypeID="com.balsamiq.mockups::CheckBox" x="1352" y="450" w="20" h="21" measuredW="20" measuredH="21" zOrder="72" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="80" controlTypeID="com.balsamiq.mockups::NumericStepper" x="1347" y="265" w="95" h="-1" measuredW="41" measuredH="24" zOrder="73" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>0</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="81" controlTypeID="com.balsamiq.mockups::NumericStepper" x="1347" y="303" w="95" h="-1" measuredW="41" measuredH="24" zOrder="74" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>0</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="82" controlTypeID="com.balsamiq.mockups::NumericStepper" x="1347" y="343" w="95" h="-1" measuredW="61" measuredH="24" zOrder="75" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>-999</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="83" controlTypeID="com.balsamiq.mockups::SearchBox" x="1128" y="103" w="315" h="-1" measuredW="120" measuredH="25" zOrder="76" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>%3D%20Formula...</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="84" controlTypeID="com.balsamiq.mockups::TextArea" x="1135" y="125" w="293" h="124" measuredW="200" measuredH="140" zOrder="77" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="85" controlTypeID="com.balsamiq.mockups::VerticalScrollBar" x="1412" y="126" w="-1" h="123" measuredW="16" measuredH="100" zOrder="78" locked="false" isInGroup="-1"/>
|
||||
<control controlID="87" controlTypeID="com.balsamiq.mockups::Label" x="1147" y="130" w="-1" h="-1" measuredW="35" measuredH="21" zOrder="79" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Fields</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="88" controlTypeID="com.balsamiq.mockups::Label" x="1308" y="131" w="70" h="-1" measuredW="59" measuredH="21" zOrder="80" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Operators</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="89" controlTypeID="com.balsamiq.mockups::Button" x="1147" y="151" w="-1" h="-1" measuredW="107" measuredH="27" zOrder="81" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>1s%20Peak%20Power</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="90" controlTypeID="com.balsamiq.mockups::Button" x="1149" y="183" w="-1" h="-1" measuredW="107" measuredH="27" zOrder="82" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>1s%20Peak%20Power</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="91" controlTypeID="com.balsamiq.mockups::Button" x="1149" y="215" w="-1" h="-1" measuredW="107" measuredH="27" zOrder="83" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>1s%20Peak%20Power</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="92" controlTypeID="com.balsamiq.mockups::Button" x="1301" y="152" w="85" h="27" measuredW="49" measuredH="27" zOrder="84" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>AND</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="93" controlTypeID="com.balsamiq.mockups::Button" x="1303" y="184" w="85" h="27" measuredW="42" measuredH="27" zOrder="85" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>OR</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="94" controlTypeID="com.balsamiq.mockups::Button" x="1305" y="216" w="85" h="27" measuredW="40" measuredH="27" zOrder="86" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>%3E%3D</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="95" controlTypeID="com.balsamiq.mockups::VerticalScrollBar" x="1266" y="126" w="-1" h="123" measuredW="16" measuredH="100" zOrder="87" locked="false" isInGroup="-1"/>
|
||||
<control controlID="96" controlTypeID="com.balsamiq.mockups::TitleWindow" x="1508" y="61" w="489" h="507" measuredW="450" measuredH="400" zOrder="88" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Edit%20Data%20Series%20%5BBests%5D</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="97" controlTypeID="com.balsamiq.mockups::RadioButton" x="1524" y="162" w="136" h="22" measuredW="53" measuredH="22" zOrder="89" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<state>up</state>
|
||||
<text>Metric</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="98" controlTypeID="com.balsamiq.mockups::RadioButton" x="1524" y="190" w="136" h="22" measuredW="43" measuredH="22" zOrder="90" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<state>selected</state>
|
||||
<text>Best</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="99" controlTypeID="com.balsamiq.mockups::RadioButton" x="1524" y="218" w="136" h="22" measuredW="63" measuredH="22" zOrder="91" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<state>up</state>
|
||||
<text>Formula</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="100" controlTypeID="com.balsamiq.mockups::RadioButton" x="1524" y="136" w="136" h="22" measuredW="68" measuredH="22" zOrder="92" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Measure</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="101" controlTypeID="com.balsamiq.mockups::Label" x="1525" y="107" w="-1" h="-1" measuredW="30" measuredH="21" zOrder="93" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Type</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="102" controlTypeID="com.balsamiq.mockups::Label" x="1524" y="270" w="104" h="-1" measuredW="35" measuredH="21" zOrder="94" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Name</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="103" controlTypeID="com.balsamiq.mockups::Label" x="1524" y="310" w="131" h="-1" measuredW="106" measuredH="21" zOrder="95" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Axis%20Label%20/%20Units</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="104" controlTypeID="com.balsamiq.mockups::Label" x="1524" y="348" w="131" h="-1" measuredW="36" measuredH="21" zOrder="96" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Curve</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="105" controlTypeID="com.balsamiq.mockups::Label" x="1524" y="384" w="131" h="-1" measuredW="44" measuredH="21" zOrder="97" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Symbol</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="106" controlTypeID="com.balsamiq.mockups::Label" x="1526" y="422" w="131" h="-1" measuredW="35" measuredH="21" zOrder="98" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Stack</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="107" controlTypeID="com.balsamiq.mockups::Label" x="1526" y="454" w="131" h="-1" measuredW="32" measuredH="21" zOrder="99" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Color</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="108" controlTypeID="com.balsamiq.mockups::Label" x="1526" y="490" w="111" h="-1" measuredW="55" measuredH="21" zOrder="100" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Fill%20Curve</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="109" controlTypeID="com.balsamiq.mockups::TextInput" x="1645" y="267" w="97" h="-1" measuredW="79" measuredH="26" zOrder="101" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="110" controlTypeID="com.balsamiq.mockups::TextInput" x="1643" y="307" w="97" h="-1" measuredW="79" measuredH="26" zOrder="102" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="111" controlTypeID="com.balsamiq.mockups::ComboBox" x="1645" y="346" w="95" h="-1" measuredW="55" measuredH="24" zOrder="103" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Line</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="112" controlTypeID="com.balsamiq.mockups::ComboBox" x="1645" y="384" w="95" h="-1" measuredW="64" measuredH="24" zOrder="104" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Circle</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="113" controlTypeID="com.balsamiq.mockups::CheckBox" x="1654" y="423" w="-1" h="-1" measuredW="20" measuredH="21" zOrder="105" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="114" controlTypeID="com.balsamiq.mockups::CheckBox" x="1654" y="489" w="-1" h="-1" measuredW="20" measuredH="21" zOrder="106" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="115" controlTypeID="com.balsamiq.mockups::ColorPicker" x="1647" y="453" w="-1" h="-1" measuredW="26" measuredH="28" zOrder="107" locked="false" isInGroup="-1"/>
|
||||
<control controlID="116" controlTypeID="com.balsamiq.mockups::Label" x="1765" y="270" w="104" h="-1" measuredW="52" measuredH="21" zOrder="108" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Highlight</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="117" controlTypeID="com.balsamiq.mockups::Label" x="1763" y="310" w="104" h="-1" measuredW="47" measuredH="21" zOrder="109" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Outliers</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="118" controlTypeID="com.balsamiq.mockups::Label" x="1765" y="348" w="104" h="-1" measuredW="50" measuredH="21" zOrder="110" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Baseline</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="119" controlTypeID="com.balsamiq.mockups::Label" x="1765" y="422" w="104" h="-1" measuredW="84" measuredH="21" zOrder="111" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Smooth%20Curve</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="120" controlTypeID="com.balsamiq.mockups::Label" x="1765" y="452" w="104" h="-1" measuredW="63" measuredH="21" zOrder="112" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Trend%20Line</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="121" controlTypeID="com.balsamiq.mockups::CheckBox" x="1869" y="423" w="-1" h="-1" measuredW="20" measuredH="21" zOrder="113" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="122" controlTypeID="com.balsamiq.mockups::CheckBox" x="1869" y="454" w="20" h="21" measuredW="20" measuredH="21" zOrder="114" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text/>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="123" controlTypeID="com.balsamiq.mockups::NumericStepper" x="1864" y="269" w="95" h="-1" measuredW="41" measuredH="24" zOrder="115" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>0</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="124" controlTypeID="com.balsamiq.mockups::NumericStepper" x="1864" y="307" w="95" h="-1" measuredW="41" measuredH="24" zOrder="116" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>0</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="125" controlTypeID="com.balsamiq.mockups::NumericStepper" x="1864" y="347" w="95" h="-1" measuredW="61" measuredH="24" zOrder="117" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>-999</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="126" controlTypeID="com.balsamiq.mockups::NumericStepper" x="1694" y="147" w="95" h="-1" measuredW="41" measuredH="24" zOrder="118" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>5</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="127" controlTypeID="com.balsamiq.mockups::ComboBox" x="1797" y="145" w="95" h="-1" measuredW="69" measuredH="24" zOrder="119" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Minute</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="128" controlTypeID="com.balsamiq.mockups::Label" x="1694" y="177" w="95" h="-1" measuredW="30" measuredH="21" zOrder="120" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Peak</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
<control controlID="129" controlTypeID="com.balsamiq.mockups::ComboBox" x="1797" y="175" w="95" h="-1" measuredW="66" measuredH="24" zOrder="121" locked="false" isInGroup="-1">
|
||||
<controlProperties>
|
||||
<text>Power</text>
|
||||
</controlProperties>
|
||||
</control>
|
||||
</controls>
|
||||
</mockup>
|
||||
|
Before Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 2.2 MiB |
|
Before Width: | Height: | Size: 173 KiB |
|
Before Width: | Height: | Size: 141 KiB |
@@ -11,15 +11,12 @@ Installing dependencies
|
||||
</font></big>
|
||||
|
||||
<p>GC requires a number of libraries. On Mac OS X, you can get most of these
|
||||
through <a href="http://www.macports.org/">Mac Ports</a> or
|
||||
<a href="http://www.brew.sh/">Homebrew</a>. On Linux and other
|
||||
through <a href="http://www.macports.org/">Mac Ports</a>. On Linux and other
|
||||
Unixes, you can use whatever package manager your distribution provides. (We
|
||||
list the package names for MacPorts and Ubuntu below.) On Windows, you'll
|
||||
probably need to download and install everything by hand. You might also want
|
||||
to read <a href="old-mailing-list-archives/2009-September/002502.html">this
|
||||
mailing list message</a> or check the
|
||||
<a href="https://github.com/GoldenCheetah/GoldenCheetah">INSTALL</a> documents
|
||||
on GitHub.</p>
|
||||
mailing list message</a>.</p>
|
||||
|
||||
<p>You'll need the following:</p>
|
||||
<table align="center" width="500">
|
||||
@@ -31,10 +28,16 @@ on GitHub.</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://qt.nokia.com/downloads">Qt</a></td>
|
||||
<td>4.8.0 or later</td>
|
||||
<td>4.5.0 or later</td>
|
||||
<td>qt4-mac</td>
|
||||
<td>libqt4-dev</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://www.boost.org/users/download/">Boost</a></td>
|
||||
<td>1.38.0 or later</td>
|
||||
<td>boost</td>
|
||||
<td>libboost-dev</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://git-scm.com/download">git</a></td>
|
||||
<td>any</td>
|
||||
@@ -60,7 +63,7 @@ checkout the code, execute this command:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
git clone git://github.com/GoldenCheetah/GoldenCheetah.git
|
||||
git clone git://github.com/srhea/GoldenCheetah.git
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
@@ -100,9 +103,9 @@ make
|
||||
for the build process. We would too, but none of us know
|
||||
<a href="http://www.gnu.org/software/autoconf/">autoconf</a> well
|
||||
enough to integrate it with Qt on Mac, Linux, and Windows. If you can help
|
||||
us out with that, please post a message on the
|
||||
<a href="https://groups.google.com/forum/?fromgroups&hl=en#!forum/golden-cheetah-users">GoldenCheetah User's
|
||||
Google Group</a>.</p>
|
||||
us out with that, please email the
|
||||
<a href="cgi-bin/mailman/listinfo/golden-cheetah-users">GoldenCheetah User's
|
||||
Mailing List</a>.</p>
|
||||
|
||||
<big><font face="arial,helvetica,sanserif">
|
||||
Making changes
|
||||
@@ -132,16 +135,18 @@ git show --color abcd0123
|
||||
variable, declare it <code>static</code> within a .cpp file.
|
||||
|
||||
<li>Only call C++'s operator <code>new</code> within the constructors and
|
||||
<code>reset</code> functions of <code>std::auto_ptr</code> etc.
|
||||
or when passing a parent pointer to a Qt class (so that the parent
|
||||
deletes the child). Never call <code>delete</code> explicitly.
|
||||
<code>reset</code> functions of <code>std::auto_ptr</code>,
|
||||
<code>boost::scoped_pointer</code>, etc. or when passing a parent pointer to a
|
||||
Qt class (so that the parent deletes the child). Never call
|
||||
<code>delete</code> explicitly.
|
||||
|
||||
<li>Do not use <code>malloc</code> or <code>free</code> unless forced to by an
|
||||
external C library.
|
||||
|
||||
<li>Allocate large buffers on the heap, not on the stack.
|
||||
|
||||
<li>When the Qt or C++ standard library has an appropriate function, use it.
|
||||
<li>When the C++ standard library has an appropriate function, use it.
|
||||
Likewise for Qt and Boost.
|
||||
|
||||
<li>Only use external libraries with GPL-compatible licenses.
|
||||
|
||||
@@ -481,13 +486,11 @@ file</em>, <code>0001-don-t-include-zero-metrics-in-ride-summary.patch</code>,
|
||||
that other people can use to include my change in their own local git
|
||||
repositories.</p>
|
||||
|
||||
<p>If you have a patch you'd like to share with others, we recommend that you
|
||||
<a href="https://help.github.com/articles/fork-a-repo">fork</a> the main GIT
|
||||
repository and submit a
|
||||
<a href="https://help.github.com/articles/creating-a-pull-request">pull request</a>
|
||||
with your patch. Alternatively you can join the
|
||||
<a href="https://groups.google.com/forum/?fromgroups#!forum/golden-cheetah-developers">
|
||||
Golden Cheetah Developer's Group</a> and post a patch there.</p>
|
||||
<p>If you have a patch you'd like to share with others, you can email it to
|
||||
the <a href="cgi-bin/mailman/listinfo/golden-cheetah-users">GoldenCheetah
|
||||
User's Mailing List</a>, and it will be considered for inclusion in the next
|
||||
release of GoldenCheetah. In fact, if you join the mailing list, you'll see
|
||||
lots of patches like this. You may even want to try some of them.</p>
|
||||
|
||||
<big><font face="arial,helvetica,sanserif">
|
||||
Applying patches
|
||||
316
doc/download.content
Normal file
@@ -0,0 +1,316 @@
|
||||
<!-- $Id: download.content,v 1.6 2009/01/09 20:45:03 rcarlsen Exp $ -->
|
||||
|
||||
<p>
|
||||
Golden Cheetah is available as source code and in binary form for
|
||||
Mac OS X Universal Binary, Linux on x86 processors and Windows 32-bit.
|
||||
</p>
|
||||
<p>
|
||||
Depending on your operating system, you may need to install the <a
|
||||
href="http://www.ftdichip.com/Drivers/D2XX.htm">FTDI USB
|
||||
driver</a> if you're using the PowerTap's new USB download cradle. The FTDI USB drivers are an optional install if you do not plan on downloading from your device using Golden Cheetah.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<font face="arial,helvetica,sanserif">
|
||||
<big><strong>Source Code</strong></big>
|
||||
</font>
|
||||
|
||||
<p>
|
||||
The Golden Cheetah source code is available via git. See the
|
||||
<a href="developers-guide.html">Developer's Guide</a> for more information.
|
||||
You can also <a href="http://github.com/srhea/GoldenCheetah/tree/master/">browse
|
||||
the source on github</a>.
|
||||
|
||||
<p>
|
||||
<font face="arial,helvetica,sanserif">
|
||||
<big><strong>Binaries</strong></big>
|
||||
</font>
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table width="100%" cellspacing="5">
|
||||
<tr>
|
||||
<td width="15%"><i>Version</i></td>
|
||||
<td width="25%"><i>Files</i></td>
|
||||
<td><i>Description</i></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">1.2.0</td>
|
||||
<td valign="top">
|
||||
<a href="GoldenCheetah_1.2.0_Linux_x86.tgz">Linux x86</a><br>
|
||||
<a href="GoldenCheetah_1.2.0_Linux_x86_64.tgz">Linux x86_64</a><br>
|
||||
<a href="GoldenCheetah_1.2.0_Darwin_Universal.dmg">Mac OS X Universal</a><br>
|
||||
<a href="GoldenCheetah_1.2.0_Windows_Installer.exe">Windows 32-bit</a>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<p>
|
||||
Lots of new features in this release, including:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Direct download from SRM (R. Clasen and S. Rhea)
|
||||
<li>WKO+ file import (M. Liversedge)
|
||||
<li>Qollector support (M. Rages)
|
||||
<li>Altitude plotting (T. Weichmann)
|
||||
<li>Manual ride entry (E. Murray)
|
||||
<li>Power zones shading (D. Connell)
|
||||
<li>Weekly summary histograms (R. Carlsen)
|
||||
<li>Automatic CP estimation from CP graph (D. Connell)
|
||||
<li>Support for running off a USB stick (J. Knotzke)
|
||||
<li>OS-specific directory layout (J. Simioni)
|
||||
<li>PF/PV plot improvements (B. de Schouwer)
|
||||
<li>Memory leak fixes (G. Lonnon)
|
||||
</ul>
|
||||
<p>Thanks also to Jamie Kimberley for extensive testing.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">1.1.325</td>
|
||||
<td valign="top">
|
||||
<a href="GoldenCheetah_1.1.325_Linux_x86.gz">Linux x86</a><br>
|
||||
<a href="GoldenCheetah_1.1.325_Linux_x86_64.gz">Linux x86_64</a><br>
|
||||
<a href="GoldenCheetah_1.1.325_Darwin_Universal.dmg">Mac OS X Universal</a><br>
|
||||
<a href="GoldenCheetah_1.1.325_Windows_Installer.exe">Windows 32-bit</a>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<p>
|
||||
First official Windows release courtesy of Ned Harding. Ned put much effort into the port to make the download reliable and created a nice installer, too (Thanks Ned!). He also provided the long-awaited Split Ride feature - break up a ride file into separate rides easily using long time gaps and intervals.
|
||||
<ul>
|
||||
<li>Ant+Sport PowerTap support.
|
||||
<li>Split Rides by time gaps or intervals.
|
||||
<li>Delete ride from list.
|
||||
<li>Use distance or time for x-axis in Ride Plot (Thanks Damain).
|
||||
<li>Numerous bug fixes (Thanks Tom, Dan).
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">1.0.277</td>
|
||||
<td valign="top">
|
||||
<a href="GoldenCheetah_1.0.277_Linux_x86.gz">Linux x86</a>,<br>
|
||||
<a href="GoldenCheetah_1.0.277_Linux_x86_64.tar.gz">Linux x86_64</a>,<br>
|
||||
<a href="GoldenCheetah_1.0.277_Darwin_Universal.dmg">Mac OS X Universal</a>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<p>*Note: Beginning with this release we are changing to a numbered versioning system. Minor point releases will generally indicate builds with new features, while bugfix releases will increment the final number, which represents the svn revision*</p>
|
||||
<p>Several new features in this release: Critical Power calculator, find best intervals utility, Pedal Force / Pedal Velocity chart, iBike and Ergomo CSV import, GUI power zones creator, separate vertical axes for Power / HR / Cadence and Speed in the Ride plot, sorting rides with the most recent at the top of the list, and many bug fixes courtesy of JT Conklin.
|
||||
</p>
|
||||
<p>You may need to install <a href="http://www.ftdichip.com/Drivers/D2XX.htm">USB drivers</a> from FTDI.
|
||||
</p>
|
||||
<p>
|
||||
For posterity, the <a href="http://robertcarlsen.net/blog/?page_id=49">beta version</a> for Windows, based on r295.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Mar 10, 2008</td>
|
||||
<td valign="top">
|
||||
<a href="GoldenCheetah_2008-03-10_Linux_x86.tgz">Linux x86</a>,<br>
|
||||
<a href="GoldenCheetah_2008-03-10_Darwin_Universal.dmg">Mac OS X Universal</a>
|
||||
</td>
|
||||
<td valign="top">
|
||||
This release introduces <a href="http://www.physfarm.com/Analysis%20of%20Power%20Output%20and%20Training%20Stress%20in%20Cyclists-%20BikeScore.pdf">BikeScore™</a>,
|
||||
a metric of training stress developed by Dr. Philip Skiba. It also
|
||||
fixes several small bugs in earlier releases.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Sep 23, 2007</td>
|
||||
<td valign="top">
|
||||
<a href="GoldenCheetah_2007-09-23_Linux_x86.tgz">Linux x86</a>,<br>
|
||||
<a href="GoldenCheetah_2007-09-23_Darwin_i386.dmg">Mac OS X x86</a>,<br>
|
||||
<a href="GoldenCheetah_2007-09-23_Darwin_powerpc.dmg">Mac OS X PowerPC</a>
|
||||
</td>
|
||||
<td valign="top">
|
||||
Bug fix release. CVS imports weren't quite working in the last one.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Sep 18, 2007</td>
|
||||
<td valign="top">
|
||||
<a href="GoldenCheetah_2007-09-18_Linux_x86.tgz">Linux x86</a>,<br>
|
||||
<a href="GoldenCheetah_2007-09-18_Darwin_powerpc.dmg">Mac OS X PowerPC</a>
|
||||
</td>
|
||||
<td valign="top">
|
||||
This release adds two small, but excellent features from Justin Knotzke:
|
||||
CSV file imports and visual interval markers in the ride plot.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Aug 7, 2007</td>
|
||||
<td valign="top">
|
||||
<a href="GoldenCheetah_2007-08-07_Linux_x86.tgz">Linux x86</a>,<br>
|
||||
<a href="GoldenCheetah_2007-08-07_Darwin_powerpc.dmg">Mac OS X PowerPC</a>
|
||||
</td>
|
||||
<td valign="top">This release fixes a bug in the critical power
|
||||
intervals graph where you could get bad data if you started an interval
|
||||
after a long period of not moving. It also adds really basic zooming to
|
||||
the ride plot: use the left mouse button to zoom in and the right one to
|
||||
return to the previous zoom state. It's pretty crappy right now, but
|
||||
it's better than nothing.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Apr 26, 2007</td>
|
||||
<td valign="top">
|
||||
<a href="GoldenCheetah_2007-04-26_Linux_x86.tgz">Linux x86</a>,<br>
|
||||
<a href="GoldenCheetah_2007-04-26_Darwin_powerpc.dmg">Mac OS X PowerPC</a>
|
||||
</td>
|
||||
<td valign="top">This release fixes some bugs and adds a whole bunch of
|
||||
new features:
|
||||
<ul>
|
||||
<li>Now imports .srm files (direct download from SRM hopefully coming
|
||||
soon)
|
||||
<li>New "Weekly Summary" tab shows total weekly hours, miles, and work
|
||||
<li>Power zones can now be entered into a text file, after which GC will
|
||||
display time in each zone in the ride and weekly summaries; for more
|
||||
information on the zone file format, <a href="zones.html">see this
|
||||
page</a>.
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Apr 1, 2007</td>
|
||||
<td valign="top">
|
||||
<a href="GoldenCheetah_2007-04-01_Linux_x86.tgz">Linux x86</a>,<br>
|
||||
<a href="GoldenCheetah_2007-04-01_Darwin_powerpc.dmg">Mac OS X PowerPC</a>
|
||||
</td>
|
||||
<td valign="top">This release fixes a bug that was introduced with the
|
||||
hardware echo detection code. If you're using the CycleOps-supplied USB
|
||||
cable to download from your PowerTap unit, this release should make
|
||||
downloads more reliable. (Those using the KeySpan USB-to-serial adaptor
|
||||
or a plain-old serial port shouldn't see any difference.)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Feb 22, 2007</td>
|
||||
<td valign="top">
|
||||
<a href="GoldenCheetah_2007-02-22_Linux_x86.tgz">Linux x86</a>,<br>
|
||||
<a href="GoldenCheetah_2007-02-22_Darwin_powerpc.dmg">Mac OS X PowerPC</a>
|
||||
</td>
|
||||
<td valign="top">Clicking on the Critical Power Plot now displays the
|
||||
interval duration, maximum power for that ride, and maximum power for all
|
||||
rides below the plot. Also fixes a bug for recording intervals longer than
|
||||
two seconds.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Feb 12, 2007</td>
|
||||
<td valign="top">
|
||||
<a href="GoldenCheetah_2007-02-12_Linux_x86.tgz">Linux x86</a>,<br>
|
||||
<a href="GoldenCheetah_2007-02-12_Darwin_powerpc.dmg">Mac OS X PowerPC</a>
|
||||
</td>
|
||||
<td valign="top">Interval information now included in ride summary, rides can
|
||||
now be exported as comma-separated values for import into Excel, and better
|
||||
automatic detection of hardware echo. Also includes a number of bux
|
||||
fixes.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Jan 30, 2007</td>
|
||||
<td valign="top">
|
||||
<a href="GoldenCheetah_2007-01-30_Linux_x86.tgz">Linux x86</a>,<br>
|
||||
<a href="GoldenCheetah_2007-01-30_Darwin_powerpc.dmg">Mac OS X PowerPC</a>
|
||||
</td>
|
||||
<td valign="top">Bug fix release.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Jan 6, 2007</td>
|
||||
<td valign="top"><a href="GoldenCheetah_2007-01-06_Linux_x86.tgz">Linux
|
||||
x86</a></td>
|
||||
<td valign="top">First release for Linux.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Dec 25, 2006</td>
|
||||
<td valign="top"><a href="GoldenCheetah_2006-12-25_Darwin_powerpc.dmg">Mac OS
|
||||
X PowerPC</a></td>
|
||||
<td valign="top">Adds the Power Histogram, which shows how much time a rider
|
||||
spent at each particular power level during a ride.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Sep 19, 2006</td>
|
||||
<td valign="top"><a href="GoldenCheetah_2006-09-19_Darwin_powerpc.dmg">Mac OS
|
||||
X PowerPC</a></td>
|
||||
<td valign="top">Adds the Critical Power Plot, which shows the highest average
|
||||
power you've achieved for every interval length over all your rides and the
|
||||
selected ride. Also shows download progress in minutes of ride data
|
||||
downloaded.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Sep 7, 2006</td>
|
||||
<td valign="top"><a href="GoldenCheetah_2006-09-07_Darwin_powerpc.dmg">Mac OS
|
||||
X PowerPC</a></td>
|
||||
<td valign="top">Adds speed and cadence to the ride plot. Fixes a bug
|
||||
found by George Gilliland where reseting the time during a ride could cause
|
||||
the GUI to crash.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Sep 6, 2006</td>
|
||||
<td valign="top"><a href="GoldenCheetah_2006-09-06_Darwin_powerpc.dmg">Mac OS
|
||||
X PowerPC</a></td>
|
||||
<td valign="top">The first release of the Golden Cheetah GUI.</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<p>
|
||||
<hr width="50%">
|
||||
|
||||
<p>
|
||||
<font face="arial,helvetica,sanserif">
|
||||
<big><strong>Older Stuff</strong></big>
|
||||
</font>
|
||||
|
||||
<p>
|
||||
These are the older, source-only, command-line distributions. I've left them
|
||||
up for historical purposes only; I don't recommend using them.
|
||||
|
||||
<center>
|
||||
<table width="100%" cellspacing="10">
|
||||
<tr>
|
||||
<td width="20%"><i>Date</i></td>
|
||||
<td width="30%"><i>File</i></td>
|
||||
<td><i>Description</i></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">Aug 11, 2006</td>
|
||||
<td valign="top"><a href="gc_2006-08-11.tgz">gc_2006-08-11.tgz</a></td>
|
||||
<td valign="top">ptdl now works with Keyspan USB-to-serial adaptor, after
|
||||
debugging help from Rob Carlsen.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">May 27, 2006</td>
|
||||
<td valign="top"><a href="gc_2006-05-27.tgz">gc_2006-05-27.tgz</a></td>
|
||||
<td valign="top">Adds the <code>cpint</code> program for computing critical
|
||||
power intervals and the <code>ptpk</code> program for converting from
|
||||
PowerTuned data files (see the <a href="users-guide.html">User's
|
||||
Guide</a>).</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top">May 16, 2006</td>
|
||||
<td valign="top"><a href="gc_2006-05-16.tgz">gc_2006-05-16.tgz</a></td>
|
||||
<td valign="top">The first code release, containing <code>ptdl</code> and
|
||||
<code>ptunpk</code>.</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</center>
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
<!-- $Id: faq.content,v 1.4 2006/07/05 16:59:56 srhea Exp $ -->
|
||||
|
||||
<h2>Documentation</h2>
|
||||
<p>
|
||||
There is a <a href="https://github.com/GoldenCheetah/GoldenCheetah/blob/master/doc/user/GC3-Manual.pdf?raw=true">Manual</a>
|
||||
and a <a href="https://github.com/GoldenCheetah/GoldenCheetah/blob/master/doc/user/GC3-FAQ.pdf?raw=true">FAQ</a> that
|
||||
you can use to help you use the program.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b><i>GoldenCheetah doesn't find my PowerTap on Ubuntu Linux.</i></b>
|
||||
<p>
|
||||
@@ -54,14 +54,13 @@ body {
|
||||
<img src="logo.jpg" width="175" height="175" alt="Picture of Cheetah">
|
||||
|
||||
<p> <b><a href="index.html">Introduction</a></b>
|
||||
<br> <b><a href="download.html">Download</a></b>
|
||||
<br> <b><a href="screenshots.html">Screenshots</a>
|
||||
<br> <b><a href="wiki.html">Wiki</a>
|
||||
<br> <b><a href="users-guide.html">User's Guide</a>
|
||||
<br> <b><a href="developers-guide.html">Developer's Guide</a>
|
||||
<br> <b><a href="faq.html">FAQ</a>
|
||||
<br> <b><a href="wishlist.html">Wish List</a>
|
||||
<br> <b><a href="license.html">License</a></b>
|
||||
<br> <b><a href="download.html">Download</a></b>
|
||||
<br> <b><a href="contrib.html">Contributors</a></b>
|
||||
<br> <b><a href="search.html">Search</a></b>
|
||||
<br> <b><a href="mailing-list.html">Mailing List</a></b>
|
||||
|
Before Width: | Height: | Size: 203 KiB After Width: | Height: | Size: 203 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 135 KiB |
@@ -13,7 +13,7 @@ GoldenCheetah is a software package that:
|
||||
|
||||
<ul>
|
||||
<li>Downloads ride data directly from the CycleOps PowerTap and the SRM
|
||||
PowerControl V, VI and VII.</p>
|
||||
PowerControl.<p>
|
||||
|
||||
<li>Imports ride data downloaded with other programs, including TrainingPeaks
|
||||
WKO+ and the manufacturers' software for the Ergomo, Garmin, Polar, PowerTap,
|
||||
@@ -23,7 +23,8 @@ and SRM devices.<p>
|
||||
BikeScore calculation, histogram analysis, a best interval finder, and a pedal
|
||||
force versus pedal velocity chart, to name just a few.<p>
|
||||
|
||||
<li>Is available for Linux, Mac OS X, and Windows.<p>
|
||||
<li>Is available for Linux, Mac OS X, and Windows. (The Windows version
|
||||
does not yet support direct downloads from the SRM PowerControl.)<p>
|
||||
|
||||
<li>Is released under an Open Source license.
|
||||
</ul>
|
||||
BIN
doc/logo.jpg
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
doc/logo.png
Normal file
|
After Width: | Height: | Size: 229 B |
|
Before Width: | Height: | Size: 203 KiB After Width: | Height: | Size: 203 KiB |
|
Before Width: | Height: | Size: 197 KiB After Width: | Height: | Size: 197 KiB |
BIN
doc/ride-plot.png
Normal file
|
After Width: | Height: | Size: 197 KiB |
BIN
doc/ride-summary.png
Normal file
|
After Width: | Height: | Size: 179 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
50
doc/screenshots.content
Normal file
@@ -0,0 +1,50 @@
|
||||
<!-- $Id: faq.content,v 1.4 2006/07/05 16:59:56 srhea Exp $ -->
|
||||
|
||||
<p>
|
||||
<center>
|
||||
|
||||
<p>
|
||||
<big><font face="arial,helvetica,sanserif">
|
||||
Ride Summary
|
||||
</font></big>
|
||||
<p>
|
||||
<img src="ride-summary.png" alt="Ride Summary Screen" align="center">
|
||||
|
||||
<p>
|
||||
<big><font face="arial,helvetica,sanserif">
|
||||
Plotting Altitude, Cadence, Heart Rate, Power, and Speed
|
||||
</font></big>
|
||||
<p>
|
||||
<img src="ride-plot.png" alt="Power and HR Plot" align="center">
|
||||
|
||||
<p>
|
||||
<big><font face="arial,helvetica,sanserif">
|
||||
Plotting Critical Power
|
||||
</font></big>
|
||||
<p>
|
||||
<img src="critical-power-plot.png" alt="The Critical Power Plot" align="center">
|
||||
|
||||
<p>
|
||||
<big><font face="arial,helvetica,sanserif">
|
||||
Histogram Analysis
|
||||
</font></big>
|
||||
<p>
|
||||
<img src="histogram-analysis.png" alt="The Power Histogram" align="center">
|
||||
|
||||
<p>
|
||||
<big><font face="arial,helvetica,sanserif">
|
||||
Plotting Pedal Force Versus Pedal Velocity
|
||||
</font></big>
|
||||
<p>
|
||||
<img src="pf-pv-plot.png" alt="The Power Histogram" align="center">
|
||||
|
||||
<p>
|
||||
<big><font face="arial,helvetica,sanserif">
|
||||
The Weekly Summary
|
||||
</font></big>
|
||||
<p>
|
||||
<img src="weekly-summary.png" alt="The Weekly Summary" align="center">
|
||||
|
||||
</center>
|
||||
|
||||
|
||||
10
doc/user/.gitignore
vendored
@@ -1,10 +0,0 @@
|
||||
*.aux
|
||||
*.cp
|
||||
*.cps
|
||||
*.fn
|
||||
*.ky
|
||||
*.log
|
||||
*.pg
|
||||
*.toc
|
||||
*.tp
|
||||
*.vr
|
||||
@@ -1,833 +0,0 @@
|
||||
This is GC3-FAQ.info, produced by makeinfo version 5.2 from
|
||||
GC3-FAQ.texinfo.
|
||||
|
||||
This manual is for Golden Cheetah, version 3.1.
|
||||
|
||||
Copyright (C) 2013 Mark Liversedge
|
||||
|
||||
|
||||
File: GC3-FAQ.info, Node: Top, Next: Top, Prev: Top
|
||||
|
||||
title
|
||||
*****
|
||||
|
||||
This manual is for GoldenCheetah, version 3.1.
|
||||
|
||||
* Menu:
|
||||
|
||||
* MOST COMMON QUESTIONS OF ALL:: Most common questions
|
||||
* GENERAL:: General Questions
|
||||
* DATA:: Working with Data
|
||||
* METRICS:: Working with Metrics
|
||||
* UPLOADING AND DOWNLOADING:: Uploading and Downloading Data
|
||||
* SEASONS AND EVENTS:: Seasons and Events
|
||||
* CHARTS:: Configuring and Using Charts
|
||||
* INDEX:: Index
|
||||
|
||||
|
||||
File: GC3-FAQ.info, Node: MOST COMMON QUESTIONS OF ALL, Next: GENERAL, Prev: INDEX, Up: Top
|
||||
|
||||
1 MOST COMMON QUESTIONS OF ALL
|
||||
******************************
|
||||
|
||||
1.1 How do I override / manually enter TSS for a ride?
|
||||
======================================================
|
||||
|
||||
The details chart on the analysis view allows you to override metrics on
|
||||
the metrics tab. By default the most common metrics are listed,
|
||||
including average HR, distance and so on. From v3.1 the default setup
|
||||
will also include TSS as a metric you can override here.
|
||||
|
||||
If the metric is not there you will need to configure GoldenCheetah to
|
||||
allow it to be shown. This is simple to do and described in 3.9 below.
|
||||
The 3.1 upgrade process should have added it to the Metric tab if it was
|
||||
not already there.
|
||||
|
||||
1.2 How do I add or remove a chart?
|
||||
===================================
|
||||
|
||||
To add a new chart to the view you can select from the hamburger menu on
|
||||
the right hand side of the chart bar.
|
||||
|
||||
Depending upon which view you are on the charts available will differ.
|
||||
For example realtime plots only appear on the Train view, whilst charts
|
||||
that work with individual rides will only appear on the analysis view.
|
||||
|
||||
To remove a chart, when you mouse over a chart (in tabbed or tiled mode)
|
||||
the word 'More...' will appear in the top left of the chart. This is a
|
||||
menu drop down, if you click on it you will see a 'Close' option. This
|
||||
is the option to remove (close) the chart.
|
||||
|
||||
1.3 Can I enter my weight and track/plot it?
|
||||
============================================
|
||||
|
||||
Weight can be maintained in 3 ways;
|
||||
|
||||
* Every athlete is setup with a weight value - this is the fallback
|
||||
value should no other weight measure be available. It can be found
|
||||
under preferences and athlete.
|
||||
|
||||
* The 'Weight' field can be maintained in the details screen. This
|
||||
is found on the 'Workout' tab in the details screen by default.
|
||||
Any entry here will be used for this ride ONLY.
|
||||
|
||||
* You can download weight from a withings scale. This is performed
|
||||
manually via the menu option Tools->Get Withings Data. This is
|
||||
then used to update the local measures database.
|
||||
|
||||
When calculating W/KG the Activity value is used if present, if not we
|
||||
then fall back to the last Withing measure that was collected, and if
|
||||
that is not available we then fall back to the default value for the
|
||||
athlete.
|
||||
|
||||
The weight from withings and weight from the activity can both be
|
||||
plotted separately in the LTM plots.
|
||||
|
||||
1.4 How do I plot x sec power best?
|
||||
===================================
|
||||
|
||||
In v3.1 it is now possible to plot custom durations for any data series
|
||||
on a metric trends chart in the Trends view. You will need to add a
|
||||
curve for the data series and select 'Best' instead of 'Metric' or
|
||||
'Estimate' on the curve settings.
|
||||
|
||||
For v3.0 or earlier it is still not possible to plot custom durations
|
||||
for power bests. We are looking to add this in version 3.1, but for now
|
||||
you can only plot 1s, 5s, 10s, 15s, 20s, 30s, 1min, 2min, 5min, 10min,
|
||||
20min, 30min and 60min bests.
|
||||
|
||||
1.5 I can't find Aerolab / Performance Manager?
|
||||
===============================================
|
||||
|
||||
By default we do not add these charts to the layout. Aerolab can be
|
||||
added to the Analysis view via the '+' menu found to the right hand side
|
||||
of the GoldenCheetah scope bar.
|
||||
|
||||
Similarly, the Performance manager can be added to the Home layout via
|
||||
the '+' menu. We may deprecate this chart in the near future since the
|
||||
LTM charts can be used to plot a PMC and we expect to implement an
|
||||
interactive PMC for planning in v3.1.
|
||||
|
||||
1.6 What happened to weekly summary?
|
||||
====================================
|
||||
|
||||
It has been deprecated since the Diary view allows you to summarise by
|
||||
day, week and month and add charts to the view that summarise for the
|
||||
selection. As the weekly summary was fixed on specific charts and did
|
||||
not handle other selections (e.g. monthly) it has been deprecated in
|
||||
view of the diary view.
|
||||
|
||||
At present you can treat the Diary view as you would have the weekly
|
||||
summary - they offer the same functionality. We expect the diary view
|
||||
to extend to planned workouts when we implement planning functionality
|
||||
in v3.1.
|
||||
|
||||
1.7 Where are all the chart settings?
|
||||
=====================================
|
||||
|
||||
All chart settings can be found under the drop down menu that appears in
|
||||
the top left hand corner of a chart when you mouse over it, titled
|
||||
'More...'. They will appear as a popup dialog box.
|
||||
|
||||
Additionally, when you move the cursor towards the title of a chart in a
|
||||
view that is tabbed (not tiled) then a small selection of the most
|
||||
important settings for the chart will appear for convenience.
|
||||
|
||||
1.8 Where is the preferences / options panel?
|
||||
=============================================
|
||||
|
||||
On a Mac the configurations page can be found under 'GoldenCheetah ->
|
||||
Preferences' on the main menu. Whilst on all other platforms it is
|
||||
found via 'Tools -> Options'.
|
||||
|
||||
We do this to match the general guidelines for the operating system.
|
||||
|
||||
1.9 How do I change the colour of the rides on the calendar/list?
|
||||
=================================================================
|
||||
|
||||
Activities are coloured according to keywords embedded in their details
|
||||
(metadata) you can configure the field that is used and the values that
|
||||
are matched and the colours they are shown in from the preferences pane
|
||||
via the 'Data Fields' toolbar option then select Notes Processing. The
|
||||
keywords and related words are scanned for to determine if the
|
||||
associated colour should be used for this ride.
|
||||
|
||||
They are processed in the order they are defined with the first match
|
||||
being returned. Take care when using values such as 'TT' and 'race'
|
||||
since these can also be part of an English word (e.g. ATTEMPT contains
|
||||
'TT' and graceful contains 'race'.
|
||||
|
||||
1.10 GoldenCheetah doesn't find my PowerTap on Ubuntu Linux.
|
||||
============================================================
|
||||
|
||||
If you're using the USB cradle (as opposed to the older, serial one),
|
||||
the FTDI driver sometimes conflicts with the braille terminal in the
|
||||
default Ubuntu installation. Try unplugging the PT cradle from the
|
||||
computer and uninstalling brltty: sudo apt-get remove brltty Then plug
|
||||
the device back in and it should work.
|
||||
|
||||
1.11 GoldenCheetah.dmg installation didn't seem to work.
|
||||
========================================================
|
||||
|
||||
Are you running OS X Snow Leopard (10.6) or later? You need to be. If
|
||||
you are, and you're still having this problem, open Terminal (in
|
||||
Applications -> Utilities) and type this at the prompt:
|
||||
|
||||
/Applications/GoldenCheetah.app/Contents/MacOS/GoldenCheetah then press
|
||||
<return> and send an email to the mailing list with whatever it prints
|
||||
out. We'll help you debug it.
|
||||
|
||||
|
||||
File: GC3-FAQ.info, Node: GENERAL, Next: METRICS, Prev: MOST COMMON QUESTIONS OF ALL, Up: Top
|
||||
|
||||
2 GENERAL
|
||||
*********
|
||||
|
||||
2.1 What is GoldenCheetah?
|
||||
==========================
|
||||
|
||||
GoldenCheetah is primarily a program for cyclists that own a power
|
||||
meter. It allows them to record, track and review their performance
|
||||
against recorded data. It also allows you to ride your turbo and
|
||||
collect data as you ride.
|
||||
|
||||
If you do not have a power meter then some of the functionality will not
|
||||
be of use to you as a cyclist. But you can still record and track
|
||||
progress. We support HR based TRIMP metrics for a HR based PMC for
|
||||
example.
|
||||
|
||||
2.2 What is a good book or resource on training with power?
|
||||
===========================================================
|
||||
|
||||
Unquestionably the bible for working with a power meter is Training and
|
||||
Racing with a Power Meter by Hunter Allan and Andy Coggan. Make sure
|
||||
you look at the 2nd edition since it is revised quite dramatically.
|
||||
Whilst it is heavily biased towards WKO+ as a software package most of
|
||||
the functions of note are also available in GoldenCheetah.
|
||||
|
||||
2.3 Where can I download the installer for GoldenCheetah ?
|
||||
==========================================================
|
||||
|
||||
Stable releases are available from <http://www.goldencheetah.org> whilst
|
||||
the latest and greatest code build is available from
|
||||
<http://goldencheetah.stand2surf.net>. Development builds are for the
|
||||
brave, since they may contain bugs. In reality the development builds
|
||||
are a changing feast and often contain latest fixes too.
|
||||
|
||||
2.4 Where can I get the source code?
|
||||
====================================
|
||||
|
||||
The GoldenCheetah source code is hosted on github and can be cloned
|
||||
using the following url;
|
||||
'git://github.com/GoldenCheetah/GoldenCheetah.git'
|
||||
|
||||
2.5 I am a triathlete is GoldenCheetah appropriate for me?
|
||||
==========================================================
|
||||
|
||||
GoldenCheetah is not a multi-sport program. For tracking cycling
|
||||
performance it is a good choice. But if you are looking for running and
|
||||
swimming metrics and tracking then these features are not available at
|
||||
present. It is an excellent choice for analysing cycling aspects of
|
||||
triathlon, or working on the trainer.
|
||||
|
||||
2.6 Is there a mailing list?
|
||||
============================
|
||||
|
||||
The mailing list for GoldenCheetah users is maintained via Google Groups
|
||||
at
|
||||
<http://groups.google.com/forum/?fromgroups=#forum/golden-cheetah-users>
|
||||
the first post you make is moderated and may take a while to appear.
|
||||
Once your first post is made you can make future posts without
|
||||
moderation.
|
||||
|
||||
2.7 How do I report a bug or request a new feature?
|
||||
===================================================
|
||||
|
||||
We use Github issues to record bugs and feature requests. You will need
|
||||
to create an account on github and then post a new request or bug at
|
||||
<http://www.github.com/GoldenCheetah/GoldenCheetah/issues>
|
||||
|
||||
2.8 How can I contribute?
|
||||
=========================
|
||||
|
||||
Patches are most welcome via the mailing list or a pull request in
|
||||
github. Of equal importance is the timely reporting of bugs and help in
|
||||
testing fixes. We also desperately need volunteers to translate into
|
||||
non-English languages and help with writing documentation including the
|
||||
maintenance of this FAQ.
|
||||
|
||||
If you want to help, post a note on the golden-cheetah-users mailing
|
||||
list.
|
||||
|
||||
2.9 Can I donate to the project?
|
||||
================================
|
||||
|
||||
We are an open source project. Our software is developed by a
|
||||
community. We do not have any facility to collect funding or spend it!
|
||||
We would rather you spread the word if you think our software is good,
|
||||
and maybe help out with documentation, tutorials or translations if you
|
||||
can.
|
||||
|
||||
|
||||
File: GC3-FAQ.info, Node: METRICS, Next: DATA, Prev: GENERAL, Up: Top
|
||||
|
||||
3 METRICS
|
||||
*********
|
||||
|
||||
3.1 What is the difference between xPower, NP and Daniels EqP?
|
||||
==============================================================
|
||||
|
||||
They all serve the same purpose - to express the variable power you have
|
||||
generated over a given period of time as a single value. This is so you
|
||||
can quantify the intensity of the ride and therefore the training stress
|
||||
of the ride.
|
||||
|
||||
In practice, NP and xPower are largely the same, whilst Daniels EqP
|
||||
place much higher emphasise on upper intensity work. For more info on
|
||||
xPower see Dr Skiba's paper on BikeScore
|
||||
<http://www.physfarm.com/bikescore.pdf>
|
||||
|
||||
3.2 What is the difference between CP and FTP?
|
||||
==============================================
|
||||
|
||||
CP is a shorthand for CP60 in GoldenCheetah, and is computed using the
|
||||
Scherer/Monod protocol using 3 and 20 minutes. Functional Threshold
|
||||
Power (FTP) is an actual measure of the power an athlete sustains for 60
|
||||
minutes.
|
||||
|
||||
Since it is very difficult for an athlete to maintain the desired
|
||||
intensity FTP 'reality' tends to result in a number that is much lower
|
||||
than CP 'theory'. Often users will consider the two as the same.
|
||||
|
||||
In GC we compute TSS and BikeScore using your 'CP' value. If you set it
|
||||
to your FTP value TSS will be accurate, BikeScore is likely to be lower.
|
||||
And if you set it to your CP value BikeScore will be accurate, but TSS
|
||||
will be overstated.
|
||||
|
||||
3.3 Why does my CP chart show higher watts for a longer duration?
|
||||
=================================================================
|
||||
|
||||
A higher power average for a longer time is possible if an effort has
|
||||
been "book ended". If, for example, you did a massive 30 second effort,
|
||||
followed by freewheeling for 29:30 then another massive 30 second
|
||||
effort, then your best average for a continuous 30 minutes would in fact
|
||||
be lower that your best average for a continuous 30minutes and 30
|
||||
seconds. (Thanks for Jon Hill from the Golden Cheetah Users mailing
|
||||
list for this example).
|
||||
|
||||
3.4 Can I set a different CP/FTP for different reasons e.g. CP/FTP on a trainer?
|
||||
================================================================================
|
||||
|
||||
We allow you to override the CP value for a specific ride by setting the
|
||||
"CP" field to the value you wish to use for the ride in question. We do
|
||||
not have a concept of 'separate' Cps for different purposes - you will
|
||||
need to specify the CP when the data is imported into GC. But this
|
||||
allows you to make manual adjustments.
|
||||
|
||||
We provide this functionality at user request - we do not endorse the
|
||||
concept of multiple CP values. But we do recognise the ongoing debate
|
||||
regarding physiological stress from working on a trainer vs on the road.
|
||||
|
||||
3.5 How do I seed the CTL for my PMC?
|
||||
=====================================
|
||||
|
||||
You can seed the starting CTL (we call it LTS, for long term stress)
|
||||
when you define a season. That way it is re-usable in a number of
|
||||
places. To do this you edit the season (date range) in the Home View
|
||||
and can set the Starting LTS.
|
||||
|
||||
3.6 Why is elevation different in GoldenCheetah to my other training software / website?
|
||||
========================================================================================
|
||||
|
||||
Different programs will use different hysteresis values to smooth the
|
||||
small changes in altitude. In GC we use a hysteresis value of 3m.
|
||||
|
||||
If this is of great concern you can adjust the hysteresis value in
|
||||
preferences under the general tab.
|
||||
|
||||
3.7 Why is a metric e.g. TSS or average power different in GoldenCheetah to Garmin Connect?
|
||||
===========================================================================================
|
||||
|
||||
The algorithms for calculating TSS, AP etc are static. They are
|
||||
implemented exactly the same way in GoldenCheetah, Garmin Connect,
|
||||
TrainingPeaks etc. The algorithms are extremely simple and not prone to
|
||||
difficulty in implementation.
|
||||
|
||||
However, how each application treats pauses and stops or loss of data
|
||||
accounts for most differences. In GoldenCheetah we always calculate
|
||||
AP,TSS etc including stop time. Other applications choose to ignore or
|
||||
smooth segments of short duration.
|
||||
|
||||
In addition, if there are anomalies in your data, with large gaps or
|
||||
even time going backwards, this will drastically affect GoldenCheetah's
|
||||
calculations.
|
||||
|
||||
We NEVER attempt to interpret data anomalies - if the results are not as
|
||||
you would expect you will need to correct the data. We do not
|
||||
'silently' fix the data for you. There is no secret sauce in
|
||||
GoldenCheetah, we are open and transparent with your data.
|
||||
|
||||
3.8 How do I set the metrics shown for intervals in the various summaries?
|
||||
==========================================================================
|
||||
|
||||
In the GoldenCheetah preference pane under the Metrics tab you can
|
||||
choose the metrics that will be shown in the ride summary charts and the
|
||||
metrics that will be shown in the interval summary in the analysis
|
||||
sidebar.
|
||||
|
||||
3.9 How do I add a metric to the details screen (so I can override it) ?
|
||||
========================================================================
|
||||
|
||||
If the metric you want (e.g. TSS) is not shown then you will need to
|
||||
add it via the GoldenCheetah preferences pane. On Mac this is from the
|
||||
menu option GoldenCheetah->Preferences whilst on Windows and Linux it is
|
||||
under Tools->Options.
|
||||
|
||||
You will need to select 'Data Fields' option from preferences toolbar
|
||||
and then the 'fields' tab. You will see a list of fields that are
|
||||
associated with a particular screen tab. If you scroll down you should
|
||||
find entries for the 'Metrics' screen tab, you can insert a new entry
|
||||
here with the '+' button. You should make sure the new entry is called
|
||||
exactly the same thing as the metric in question.
|
||||
|
||||
For 'TSS' this is relatively straight forward. For others, e.g.
|
||||
'Average Heart Rate' you must make sure that the name includes spaces
|
||||
etc. Once your metric has been added to the configuration you should
|
||||
save that and return to the details screen where you can now maintain
|
||||
it.
|
||||
|
||||
If you are creating a manual entry then there is no 'details' tab in the
|
||||
dialog. Once you have created the entry (and again in this case TSS can
|
||||
be entered in the dialog) you should go to the details tab to maintain
|
||||
any other specific fields. The manual entry dialog is designed to be
|
||||
simple and accept only the most common of entries.
|
||||
|
||||
3.10 Can you calculate gradient, virtual power or other derived series from the ride data?
|
||||
==========================================================================================
|
||||
|
||||
Not in 3.1. We plan to extend this functionality in v3.2.
|
||||
|
||||
3.11 Can I export metrics or access the metric database GC uses?
|
||||
================================================================
|
||||
|
||||
The metrics are stored within a Sqlite 3 Database called 'metricDBv3'
|
||||
that can be found in the athlete directory. You can use any Sqlite 3
|
||||
tools to query and work with the db.
|
||||
|
||||
Alternatively you can export the db in its entirety using the
|
||||
Activity->Export Metrics as CSV to export to a format you can use in a
|
||||
spreadsheet program.
|
||||
|
||||
|
||||
File: GC3-FAQ.info, Node: DATA, Next: UPLOADING AND DOWNLOADING, Prev: METRICS, Up: Top
|
||||
|
||||
4 DATA
|
||||
******
|
||||
|
||||
4.1 How do I split, merge or join files?
|
||||
========================================
|
||||
|
||||
You can split a file by time using the activity->split ride menu item
|
||||
(or toolbar button).
|
||||
|
||||
To join two rides together (making one longer ride from two rides) you
|
||||
can copy rows in the activity editor and paste special in the ride
|
||||
editor (right click) and then select append mode.
|
||||
|
||||
If you wish to merge rides, in v3.1 there is a new Activity->Merge
|
||||
wizard that will walk you through merging ride files and also provide
|
||||
the ability to synchronise timestamps.
|
||||
|
||||
4.2 How can I find 'spikes' or specific values in activity data?
|
||||
================================================================
|
||||
|
||||
The activity editor has a function to find data on its toolbar. You can
|
||||
specify a range or upper or lower limit and find values less than,
|
||||
greater than or between a range of values.
|
||||
|
||||
Additionally, the editor will scan the file looking for anomalies -
|
||||
where the data appears to be out of normal ranges. These are shown with
|
||||
a wiggly red line in the editor and can also be listed by clicking on
|
||||
the anomalies icon on the editor toolbar.
|
||||
|
||||
If the anomalies icon is not enabled on the toolbar then there are no
|
||||
anomalies in the currently selected ride.
|
||||
|
||||
4.3 How can I fix 'spikes' or 'anomalies' in activity data?
|
||||
===========================================================
|
||||
|
||||
You can either manually edit the values in the activity editor (there is
|
||||
full undo and redo in the editor). Or you can use the fix tools that
|
||||
are listed under the tool menu option (fix power spikes, fix gaps in
|
||||
recording, fix gps errors, fix torque.
|
||||
|
||||
Each of the fix tools opens a dialog that displays texts to explain what
|
||||
the fix tool does.
|
||||
|
||||
4.4 How can I add/remove a field to edit on the details screen?
|
||||
===============================================================
|
||||
|
||||
The fields (metadata) that is editable can be configured in the
|
||||
preferences pane under the data fields tab. Where no screen is
|
||||
specified (its left blank) it will not be made available.
|
||||
|
||||
GoldenCheetah ships with a number of fields defined in the config but
|
||||
with no screen set. If you wish to use them simply set the screen tab
|
||||
to the tab you would like it to be shown on. To remove a field set the
|
||||
field tab to blank.
|
||||
|
||||
4.5 What are 'special fields' ?
|
||||
===============================
|
||||
|
||||
There are a number of fields that when maintained in the details screen
|
||||
will be used elsewhere in the code to calculate metrics or for other
|
||||
purposes.
|
||||
|
||||
Some examples include;
|
||||
|
||||
Weight - used in W/KG calculations, Sport and Workout code are used when
|
||||
exporting to other file formats, Identifier is used to assign a UUID to
|
||||
the activity when it is uploaded to online services and so on.
|
||||
|
||||
There is a full list of special fields and their meaning in the Golden
|
||||
Cheetah user guide appendices.
|
||||
|
||||
4.6 How do I find/add/sort/delete/edit intervals ?
|
||||
==================================================
|
||||
|
||||
The context menu (on the right hand side of the splitter handle) for the
|
||||
interval sidebar in Analysis view contains a number of options for
|
||||
working with intervals.
|
||||
|
||||
Additionally, you can click and drag on the performance (aka ride) plot
|
||||
to visually define an interval.
|
||||
|
||||
4.7 How can I export to a specific file format?
|
||||
===============================================
|
||||
|
||||
Activity->Export allows you to export the activity to csv, fitlog, gc
|
||||
(xml), json, Training Peaks PWX or Garmin TCX format.
|
||||
|
||||
4.8 Can I use GC to convert data from one format to another on the command line?
|
||||
================================================================================
|
||||
|
||||
No. It is something we may add in v3.2
|
||||
|
||||
4.9 Can I delete an athlete and all his/her data?
|
||||
=================================================
|
||||
|
||||
No. It must be done manually by removing the athlete directory via the
|
||||
operating system. Please ensure you do this when GoldenCheetah is not
|
||||
running.
|
||||
|
||||
|
||||
File: GC3-FAQ.info, Node: UPLOADING AND DOWNLOADING, Next: SEASONS AND EVENTS, Prev: DATA, Up: Top
|
||||
|
||||
5 UPLOADING AND DOWNLOADING
|
||||
***************************
|
||||
|
||||
5.1 Why does upload to TrainingPeaks keep failing?
|
||||
==================================================
|
||||
|
||||
The Sport field in TrainingPeaks must have very specific values,
|
||||
although this is not documented in the XML Schema. We recommend using a
|
||||
sport of "Bike" if you plan on uploading rides to training peaks.
|
||||
|
||||
5.2 Why does download from TrainingPeaks say I need a premium account?
|
||||
======================================================================
|
||||
|
||||
Training Peaks only allow paid up members to get access to their data.
|
||||
If you are using a free service they do not let you retrieve your data.
|
||||
|
||||
5.3 What settings do I need to get GoldenCheetah to upload to my Google Calendar?
|
||||
=================================================================================
|
||||
|
||||
The upload to Google Calendar uses their CalDAV API, and as such needs
|
||||
to specify a collection. This means when entering the details in the
|
||||
passwords pane of preferences you should use the following for the
|
||||
caldav url:
|
||||
|
||||
<https://www.google.com/calendar/dav/xxxx@gmail.com/events/>
|
||||
|
||||
Where xxxx is your username. The username will need to be repeated in
|
||||
the username field and obviously set the password too.
|
||||
|
||||
5.4 When setting up my Withings wifi scales where do I get the userid and key ?
|
||||
===============================================================================
|
||||
|
||||
You will need to login to your Withings account
|
||||
(<http://my.withings.com>) and click on the 'share' button at the top of
|
||||
the dashboard. From there you will get a popup box with lots of
|
||||
options.
|
||||
|
||||
If you click on 'share on my website' you will be greeted with a number
|
||||
of code snippets you can embed in a web page. If you look closely in
|
||||
the top right hand corner there will be a box containing the user id and
|
||||
public key. These are the two values you need to enter into the options
|
||||
dialog.
|
||||
|
||||
You will now be able to retrieve withings data via the tools menu.
|
||||
|
||||
|
||||
File: GC3-FAQ.info, Node: SEASONS AND EVENTS, Next: CHARTS, Prev: UPLOADING AND DOWNLOADING, Up: Top
|
||||
|
||||
6 SEASONS AND EVENTS
|
||||
********************
|
||||
|
||||
6.1 Why are there different types of seasons?
|
||||
=============================================
|
||||
|
||||
This is to help with planning functions. As of v3 there is no real
|
||||
distinction made. Adhoc seasons are expected to be used solely as date
|
||||
ranges and have no associated plan. Whilst other season types may
|
||||
contain plans. This is only relevant for planning functions that are
|
||||
not available yet.
|
||||
|
||||
6.2 What is event used for?
|
||||
===========================
|
||||
|
||||
It is only used to annotate a LTM chart - so you can show an 'event'
|
||||
that happened at a particular date. There are no rules about what
|
||||
constitutes and event. It could be a race, a training camp or just a
|
||||
day that was particularly meaningful e.g. illness, crash.
|
||||
|
||||
6.3 How do create/edit/delete seasons and events?
|
||||
=================================================
|
||||
|
||||
Seasons and Events are created and edited in the sidebar for the Home
|
||||
view. Seasons are listed under date ranges, whilst events are listed
|
||||
under the events sidebar item. In both cases they can be created and
|
||||
deleted from the sidebar item's drop down menu.
|
||||
|
||||
Please note that in v3.1 events can only be created when a user season
|
||||
is selected, since events are associated with a particular season. This
|
||||
constraint will be removed in v3.2.
|
||||
|
||||
|
||||
File: GC3-FAQ.info, Node: CHARTS, Next: INDEX, Prev: SEASONS AND EVENTS, Up: Top
|
||||
|
||||
7 CHARTS
|
||||
********
|
||||
|
||||
7.1 I want to plot month -1,-2 and -3 how do I do that?
|
||||
=======================================================
|
||||
|
||||
Assuming the chart allows you to specify a date range you can select
|
||||
'This' 'month' and select prior '3' to specify a month 3 years prior,
|
||||
similarly 'This' 'month' and prior '2' is a month 2 months ago, whilst
|
||||
'This' 'month' and prior '1' is last month.
|
||||
|
||||
'This' 'month' prior and 0 is just this month.
|
||||
|
||||
7.2 How should I use Aerolab?
|
||||
=============================
|
||||
|
||||
The following is a brief piece of advice from Robert Chung, from a
|
||||
discussion on the Golden Cheetah Users mailing list:
|
||||
|
||||
Ideally, you'll want calm conditions (both in terms of wind and traffic)
|
||||
but here's a quickie test you can do just to get a handle on what to do.
|
||||
Try to find a loop without stop signs, or an out-and-back with maybe a
|
||||
little dip or something in the middle. Make sure you won't get hit by a
|
||||
car and have good sight lines. I just go around my block a few times.
|
||||
Do a loop in the drops, then another loop faster, then a loop slower;
|
||||
then repeat with your hands on the hoods.
|
||||
|
||||
Weigh yourself and the bike and ballpark the air density.
|
||||
|
||||
See whether you can come close to modeling the "true" elevation profile
|
||||
by sliding the CdA slider around. Even with this informal test, as long
|
||||
as the wind isn't blowing too hard, you ought to be able to see a
|
||||
difference between the loops where you were in the drops and the loops
|
||||
where you on the hoods, and to spot little bumps and dips in the road.
|
||||
|
||||
There is also an overview of Virtual Elevation to measure aerodynamics
|
||||
in this YouTube video from the power seminar at Interbike 2011 given by
|
||||
Jim Meyer the founder of Quarq:
|
||||
|
||||
<http://www.youtube.com/watch?v=b8tJnFE_BFg&feature=youtu.be&t=27m58s>
|
||||
|
||||
Finally, Robert Chung's original paper is included in the docs section
|
||||
of the GoldenCheetah repository, you can it up here (click on 'View Raw'
|
||||
to download):
|
||||
|
||||
<https://github.com/GoldenCheetah/GoldenCheetah/blob/master/doc/contrib/ChungVE.pdf>
|
||||
|
||||
7.3 My map doesn't show?
|
||||
========================
|
||||
|
||||
This is most likely because you have a proxy that requires
|
||||
authentication or session details. We do not have sophisticated support
|
||||
for internet proxy servers. We will re-use the operating system
|
||||
settings where they are configured.
|
||||
|
||||
7.4 What is the treemap plot used for?
|
||||
======================================
|
||||
|
||||
Typically it is used to visualise where you spend your time or where you
|
||||
get best results. It is not particularly useful if you do not maintain
|
||||
details for each ride e.g. workout code, sport et al.
|
||||
|
||||
7.5 Can I change the colors in plot x ?
|
||||
=======================================
|
||||
|
||||
With the exception of the Long Term Metric plots the colours on the
|
||||
charts are configured in the GoldenCheetah preferences pane. It is
|
||||
possible to apply a theme or change each individual color.
|
||||
|
||||
We want to use the same colours to plot each data series across the
|
||||
charts, so you can change them globally.
|
||||
|
||||
The only colours you cannot change are the colours assigned to intervals
|
||||
when plotting them on scatterplot or PfPv. These colours are assigned
|
||||
according to their sequence.
|
||||
|
||||
7.6 How do you zoom in on a chart?
|
||||
==================================
|
||||
|
||||
You can zoom in on the distribution, scatterplot and PfPv charts by
|
||||
selecting the zoom area with the left click of the mouse.
|
||||
|
||||
On the performance (ride) plot you can zoom with the span slider at the
|
||||
bottom of the chart (if you select the full plot in the chart settings).
|
||||
|
||||
There are no other zoom options for the other charts.
|
||||
|
||||
7.7 I zoomed in but can't zoom out?
|
||||
===================================
|
||||
|
||||
Right click will zoom back out to the previous zoom level (in the case
|
||||
of zooming multiple times). If you select another activity the chart
|
||||
will return to fully zoomed out.
|
||||
|
||||
7.8 GoldenCheetah is saying there is no data for a chart, but I'm sure there is?
|
||||
================================================================================
|
||||
|
||||
You should check in the editor if the data series is present. if the
|
||||
activity is a manual activity entry it will contain no data.
|
||||
|
||||
|
||||
File: GC3-FAQ.info, Node: INDEX, Next: MOST COMMON QUESTIONS OF ALL, Prev: CHARTS, Up: Top
|
||||
|
||||
Index
|
||||
*****
|
||||
|
||||
| ||||