Compare commits

..

3 Commits

Author SHA1 Message Date
Eric Murray
b87aab0302 fix manual ride entry crash when no zones file
This is a partial patch based on code from Eric Murray.  It changes just
enough of ManyalRideDialog to fix a crash that otherwise occurs when the
user doesn't have a zones file.
2009-09-19 09:22:42 -07:00
Mark Liversedge
ecdc2288ff Optional padding data with value 0x8012 discovered 2009-09-12 21:30:17 -04:00
Berend De Schouwer
04bb484f8e SplitRide altitude matches CSV2 2009-09-12 21:30:09 -04:00
1939 changed files with 10915 additions and 1876252 deletions

29
.gitignore vendored
View File

@@ -1,33 +1,6 @@
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
profile

View File

@@ -1,116 +0,0 @@
branches:
- master
language:
- objective-c
compiler:
- clang
- gcc
env:
matrix:
## Test 4.8 or 5.4.2
- BRANCH=master QT=qt4 QT_PATH=qt
- BRANCH=master QT=qt5 QT_PATH=qt5
global:
- secure: iqYW7f3//ZkMVzeCEarYn0S0DqKjFU9juBh0KF6WTlUsKX902Jtsk7dFoJlNDYBf63HLgV+wW2Hc6MxI9sGiUkom0gY9/To/aeGIJFGEX2sLm/e0Ok3qN521FA0Q/OiCFsD0RC6J+yrHxzI+rf8Z1rujceUsz2KgsrfAjYYv+BY=
- secure: C6f58PXwvvHeVOjCLbyDRjgyF0tk+bXjCNUDur8VJLhJEGNdnrt+rH+d3azYaX0n348ZnQZ14as4M4rHjN1A/3DRbdUdOS7PQZrkj/n363ck1tvYOG/tzYqkEcVoQyjIJ7ZoTuBXDQry/VJmLxQjM0glTa2upNFHMOMwqZNkF+I=
- secure: mgf181ok4rJTHxAdSaeIb/OzUx7PQc6UjJYfhJQcZDjN1Nou+Um6OHpnooMHeEq0CdGuLSiv2xVmuQnRjI5MfG5re/a3l39hSzi9tPLWi1y7uOLCtQFooJw3H+LhiKZcgAtEnkTmEhUCEu5uZ7cp4lWhrQZWCR5mCDNtJrGHjiw=
- secure: UkW6SpgeACb6enGZADTAtPPRe23Tffne/SRQoBsZ3kGbKzgv8kTCLY0G5N71B1xEGdLB/36piOa0yji2SMW1jbflxR7tdOsiNpfd9R5qYqWVZRulY0qite8ZCwU5dqgy87pp4ECC1hNSOTq17aa4Sc4G4egg9AOy8cntLBTtxJA=
- secure: rb/MKPHEK8yOK5uYpXq2o+MQ7h65ft+c/xE9XmLFk1jLnK0oxe6+KeoSFlQ0n5UwLSsHrytMXVaUHex6EEt0TheXFlohi7BcNFWRWXr+wLucuaPjMnU49VErrSigjJ5VW/rcR7fORmnDwn5y06r3Rer9SC1hImCxf/pqF8hFZps=
- secure: FXJzm98lwbc1R2eh9/CvVReVRHEPLDm+sCRjiV9HJgeCveIUauLasp9Skamz0c6OKLmkjLY8JERPT491ZgCG8YcQ9x1bM8HGbmRqnn9xSUxINIRzVmyTiLMBoT/ibHHeFjFpyiGfukOAkHwMNNsrSrbaekhiJuekaXo7iTwYQB0=
before_install:
- date
- brew update
##- sh travis/install-qt.sh
- brew install $QT
- brew install libical
- brew install libusb libusb-compat
- brew install srmio
- brew install libsamplerate
## Disable KML for now
##- brew install --HEAD travis/libkml.rb
- sudo chmod -R +w /usr/local
- curl -O http://www.ftdichip.com/Drivers/D2XX/MacOSX/D2XX1.2.2.dmg
- git clone --depth 1 https://github.com/sintegrial/qwtplot3d.git qwtplot3d
- cd qwtplot3d
- CC=clang CXX=clang++ /usr/local/opt/$QT_PATH/bin/qmake -makefile -recursive QMAKE_CXXFLAGS_WARN_ON+=-Wno-unused-private-field
- CC=clang CXX=clang++ make -j2
- cd ..
- git clone --branch 0.98 https://github.com/kypeli/kQOAuth.git kQOAuth-0.98
- cd kQOAuth-0.98
- CC=clang CXX=clang++ /usr/local/opt/$QT_PATH/bin/qmake -makefile -recursive QMAKE_CXXFLAGS_WARN_ON+=-Wno-unused-private-field
- CC=clang CXX=clang++ make -j2 qmake_all
- CC=clang CXX=clang++ sudo make install
- cd ..
- hdiutil mount D2XX1.2.2.dmg
before_script:
- mkdir D2XX
- cp /Volumes/release/D2XX/Object/10.5-10.7/x86_64/libftd2xx.1.2.2.dylib D2XX
- sudo cp /Volumes/release/D2XX/Object/10.5-10.7/x86_64/libftd2xx.1.2.2.dylib /usr/local/lib
- cp /Volumes/release/D2XX/bin/*.h D2XX
- sed -i "" "s|libftd2xx.dylib|@executable_path/../Frameworks/libftd2xx.1.2.2.dylib|"
src/D2XX.cpp
- cp qwt/qwtconfig.pri.in qwt/qwtconfig.pri
- cp src/gcconfig.pri.in src/gcconfig.pri
- /usr/local/opt/$QT_PATH/bin/lupdate src/src.pro
- sed -i "" "s|#\(CONFIG += release.*\)|\1 static |" src/gcconfig.pri
- sed -i "" "s|#\(QMAKE_LRELEASE\).*|\1 += /usr/local/opt/$QT_PATH/bin/lrelease|"
src/gcconfig.pri
- sed -i "" "s|#\(QMAKE_CXXFLAGS\).*|\1_RELEASE += -mmacosx-version-min=10.7 -arch
x86_64|" src/gcconfig.pri
- sed -i "" "s|#\(SRMIO_INSTALL =.*\)|\1 /usr/local|" src/gcconfig.pri
- sed -i "" "s|#\(D2XX_INCLUDE =.*\)|\1 ../D2XX|" src/gcconfig.pri
- sed -i "" "s|#\(D2XX_LIBS =.*\)|\1 -L../D2XX -lftd2xx.1.2.2|" src/gcconfig.pri
- sed -i "" "s|#\(KQOAUTH_INSTALL =.*\)|\1 /usr/local|" src/gcconfig.pri
- sed -i "" "s|#\(KQOAUTH_INCLUDE =.*\)|\1 \$\$[QT_INSTALL_LIBS]/kqoauth.framework/Headers|"
src/gcconfig.pri
- sed -i "" "s|#\(KQOAUTH_LIBS =.*\)|\1 -F\$\$[QT_INSTALL_LIBS] -framework kqoauth|"
src/gcconfig.pri
- sed -i "" "s|#\(QWT3D_INSTALL =.*\)|\1 ../qwtplot3d|" src/gcconfig.pri
## Disable KML for now
##- sed -i "" "s|#\(KML_INSTALL =\).*|\1 /usr/local|" src/gcconfig.pri
##- sed -i "" "s|#\(KML_LIBS =.*\)|\1 -L/usr/local/lib -lkmlxsd -lkmlregionator -lkmldom
## -lkmlconvenience -lkmlengine -lkmlbase|" src/gcconfig.pri
- sed -i "" "s|#\(ICAL_INSTALL =.*\)|\1 /usr/local|" src/gcconfig.pri
- sed -i "" "s|#\(ICAL_LIBS =.*\)|\1 -L/usr/local/lib -lical|" src/gcconfig.pri
- sed -i "" "s|#\(LIBUSB_INSTALL =\).*|\1 /usr/local|" src/gcconfig.pri
- sed -i "" "s|#\(LIBUSB_LIBS =.*\)|\1 -L/usr/local/lib -lusb|" src/gcconfig.pri
- sed -i "" "s|#\(SAMPLERATE_INSTALL =\).*|\1 /usr/local|" src/gcconfig.pri
- sed -i "" "s|#\(SAMPLERATE_LIBS =\).*|\1 -L/usr/local/lib -lsamplerate|" src/gcconfig.pri
- sed -i "" "s|#\(DEFINES += GC_HAVE_LION*\)|\1|" src/gcconfig.pri
- sed -i "" "s|#\(HTPATH = ../httpserver.*\)|\1 |" src/gcconfig.pri
- sed -i "" "s|#\(DEFINES += GC_WANT_ROBOT.*\)|\1 |" src/gcconfig.pri
- sed -i "" "s|\(DEFINES += GC_VIDEO_NONE.*\)|#\1 |" src/gcconfig.pri
- sed -i "" "s|#\(DEFINES += GC_VIDEO_QUICKTIME.*\)|\1 |" src/gcconfig.pri
- echo "QMAKE_CFLAGS_RELEASE += -mmacosx-version-min=10.7 -arch x86_64" >> src/gcconfig.pri
- sed -i "" "s/__GC_GOOGLE_CALENDAR_CLIENT_SECRET__/"$GC_GOOGLE_CALENDAR_CLIENT_SECRET"/" src/Secrets.h
- sed -i "" "s/__GC_STRAVA_CLIENT_SECRET__/"$GC_STRAVA_CLIENT_SECRET"/" src/Secrets.h
- sed -i "" "s/__GC_DROPBOX_CLIENT_SECRET__/"$GC_DROPBOX_CLIENT_SECRET"/" src/Secrets.h
- sed -i "" "s/__GC_CYCLINGANALYTICS_CLIENT_SECRET__/"$GC_CYCLINGANALYTICS_CLIENT_SECRET"/" src/Secrets.h
- sed -i "" "s/__GC_TWITTER_CONSUMER_SECRET__/"$GC_TWITTER_CONSUMER_SECRET"/" src/Secrets.h
- cat src/gcconfig.pri
script:
- CC=clang CXX=clang++ /usr/local/opt/$QT_PATH/bin/qmake -makefile -recursive QMAKE_CXXFLAGS_WARN_ON+=-Wno-unused-private-field
- CC=clang CXX=clang++ make qmake_all
- CC=clang CXX=clang++ make -j4 sub-qwt --silent
- CC=clang CXX=clang++ make -j4 sub-src
after_success:
- cd src
- ls -laR GoldenCheetah.app
- GoldenCheetah.app/Contents/MacOS/GoldenCheetah --help
- /usr/local/opt/$QT_PATH/bin/macdeployqt GoldenCheetah.app -verbose=2 -dmg
## fix up the bundle with macdeployqtfix
- python ../travis/macdeployqtfix.py GoldenCheetah.app /usr/local/opt/$QT_PATH
- brew remove $QT
- mv GoldenCheetah.dmg GoldenCheetah_$QT.dmg
- hdiutil mount GoldenCheetah_$QT.dmg
- cd /Volumes/GoldenCheetah
- ls -laR GoldenCheetah.app
- GoldenCheetah.app/Contents/MacOS/GoldenCheetah --help
deploy:
provider: releases
api_key: $GH_OAUTH_TOKEN
file: GoldenCheetah_$QT.dmg
skip_cleanup: true
on:
tags: true

View File

@@ -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

View File

@@ -1,299 +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
- kQOAuth
- 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
wanting to build a particular release you need to checkout the release. To
build a release you need to checkout the code at the tag for the release.
A list of releases can be found at: https://github.com/GoldenCheetah/GoldenCheetah/tags
$ git checkout V3.3-RC1
$ 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
- kQOAuth
- 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 kQOAuth - For OAuth Authentication
--------------------------------------
kQOauth (0.98)
qmake
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

View File

@@ -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, youll 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.

View File

@@ -1,15 +0,0 @@
Golden Cheetah install and build instructions are documented
for each platform;
INSTALL-WIN32 For building on Microsoft Windows
INSTALL-LINUX For building on Ubuntu Linux
INSTALL-MAC For building on Apple OS X
[![Build Status](https://travis-ci.org/GoldenCheetah/GoldenCheetah.svg?branch=master)](https://travis-ci.org/GoldenCheetah/GoldenCheetah)
Alternatively official builds are available from http://www.goldencheetah.org
whilst latest developer builds are available from http://goldencheetah.stand2surf.net

View File

@@ -1,7 +0,0 @@
TEMPLATE = subdirs
SUBDIRS = qwt
unix:!macx {
SUBDIRS += kqoauth
}
SUBDIRS += src
CONFIG += ordered

View File

@@ -1,316 +0,0 @@
From 7be04e65a53b22ce382d640a6c409b5d3bfe5645 Mon Sep 17 00:00:00 2001
From: Joern <joern.rm@gmail.com>
Date: Sat, 20 Dec 2014 12:42:37 +0100
Subject: [PATCH] Patch-Windows-MingGW-subset for GC
... reduce the libs in Make to what GoldenCheetah needs
... add two functions missing in MingGW standard libs
---
Makefile.am | 2 +-
configure.ac | 44 -------------------
src/Makefile.am | 2 +-
src/kml/base/file_posix.cc | 102 ++++++++++++++++++++++++++++++++++++++++++++
src/kml/base/string_util.cc | 17 ++++++++
third_party/Makefile.am | 42 +++---------------
6 files changed, 126 insertions(+), 83 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 2be0803..e29201e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
ACLOCAL_AMFLAGS = -I m4
# Order is important:
-SUBDIRS = third_party src testdata examples msvc xcode
+SUBDIRS = third_party src
EXTRA_DIST = \
AUTHORS \
diff --git a/configure.ac b/configure.ac
index d5fa75f..033128b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -203,23 +203,6 @@ AC_CHECK_LIB(pthread, pthread_create,,
AC_CONFIG_FILES([
Makefile
- examples/Makefile
- examples/domviewer/Makefile
- examples/engine/Makefile
- examples/gpx/Makefile
- examples/gx/Makefile
- examples/hellonet/Makefile
- examples/helloworld/Makefile
- examples/java/Makefile
- examples/kml/Makefile
- examples/python/Makefile
- examples/regionator/Makefile
- examples/wxregionator/Makefile
- examples/wxviewer/Makefile
- examples/xsd/Makefile
- msvc/Makefile
- msvc/examples/Makefile
- msvc/tests/Makefile
src/Makefile
src/kml/Makefile
src/kml/convenience/Makefile
@@ -228,34 +211,7 @@ AC_CONFIG_FILES([
src/kml/regionator/Makefile
src/kml/base/Makefile
src/kml/xsd/Makefile
- src/swig/Makefile
- src/swig/java/Makefile
- src/swig/python/Makefile
- testdata/Makefile
- testdata/atom/Makefile
- testdata/balloon/Makefile
- testdata/csv/Makefile
- testdata/deprecated/Makefile
- testdata/gdata/Makefile
- testdata/gmaps/Makefile
- testdata/gpx/Makefile
- testdata/gx/Makefile
- testdata/kml/Makefile
- testdata/kmz/Makefile
- testdata/kmz/files/Makefile
- testdata/kmz/kmzfiles/Makefile
- testdata/kmz/rumsey/Makefile
- testdata/kmz/rumsey/kml/Makefile
- testdata/kmz/rumsey/imagery/Makefile
- testdata/links/Makefile
- testdata/style/Makefile
- testdata/style/weather/Makefile
- testdata/update/Makefile
- testdata/xal/Makefile
- testdata/xsd/Makefile
third_party/Makefile
- xcode/Makefile
- xcode/LibKML/Makefile
])
AC_OUTPUT
diff --git a/src/Makefile.am b/src/Makefile.am
index 0bf15ac..721209e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = kml swig
+SUBDIRS = kml
# TODO: use the phc files in msvc.
EXTRA_DIST = \
diff --git a/src/kml/base/file_posix.cc b/src/kml/base/file_posix.cc
index b9461c0..920a996 100644
--- a/src/kml/base/file_posix.cc
+++ b/src/kml/base/file_posix.cc
@@ -33,8 +33,110 @@
#include <sys/stat.h>
#include <unistd.h> // For unlink, close.
+// START PATCH
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+// END PATCH
+
namespace kmlbase {
+// START PATCH
+// Implementation of missing functions
+
+/* mkstemp extracted from libc/sysdeps/posix/tempname.c. Copyright
+ (C) 1991-1999, 2000, 2001, 2006 Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version. */
+
+static const char letters[] =
+"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+/* Generate a temporary file name based on TMPL. TMPL must match the
+ rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed
+ does not exist at the time of the call to mkstemp. TMPL is
+ overwritten with the result. */
+int
+mkstemp (char *tmpl)
+{
+ int len;
+ char *XXXXXX;
+ static unsigned long value;
+ unsigned long random_time_bits;
+ unsigned int count;
+ int fd = -1;
+ int save_errno = errno;
+
+ /* A lower bound on the number of temporary files to attempt to
+ generate. The maximum total number of temporary file names that
+ can exist for a given template is 62**6. It should never be
+ necessary to try all these combinations. Instead if a reasonable
+ number of names is tried (we define reasonable as 62**3) fail to
+ give the system administrator the chance to remove the problems. */
+#define ATTEMPTS_MIN (62 * 62 * 62)
+
+ /* The number of times to attempt to generate a temporary file. To
+ conform to POSIX, this must be no smaller than TMP_MAX. */
+#if ATTEMPTS_MIN < TMP_MAX
+ unsigned int attempts = TMP_MAX;
+#else
+ unsigned int attempts = ATTEMPTS_MIN;
+#endif
+
+ len = strlen (tmpl);
+ if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+/* This is where the Xs start. */
+ XXXXXX = &tmpl[len - 6];
+
+ /* Get some more or less random data. */
+ {
+ struct timeval tv;
+ gettimeofday (&tv, NULL);
+ random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec;
+ }
+ value += random_time_bits ^ getpid ();
+
+ for (count = 0; count < attempts; value += 7777, ++count)
+ {
+ unsigned long v = value;
+
+ /* Fill in the random bits. */
+ XXXXXX[0] = letters[v % 62];
+ v /= 62;
+ XXXXXX[1] = letters[v % 62];
+ v /= 62;
+ XXXXXX[2] = letters[v % 62];
+ v /= 62;
+ XXXXXX[3] = letters[v % 62];
+ v /= 62;
+ XXXXXX[4] = letters[v % 62];
+ v /= 62;
+ XXXXXX[5] = letters[v % 62];
+
+ fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, _S_IREAD | _S_IWRITE);
+ if (fd >= 0)
+ {
+ errno = save_errno;
+ return fd;
+ }
+ else if (errno != EEXIST)
+ return -1;
+ }
+
+ /* We got out of the loop because we ran out of combinations to try. */
+ errno = EEXIST;
+ return -1;
+}
+// END PATCH
+
// Internal to the POSIX File class.
static bool StatFile(const char* path, struct stat* stat_data) {
struct stat tmp;
diff --git a/src/kml/base/string_util.cc b/src/kml/base/string_util.cc
index b3a9654..3fdba2b 100644
--- a/src/kml/base/string_util.cc
+++ b/src/kml/base/string_util.cc
@@ -31,6 +31,23 @@
namespace kmlbase {
+// START PATCH
+int strncasecmp(const char *s1, const char *s2, size_t n) {
+ while (*s1 != 0 && tolower(*s1) == tolower(*s2)) {
+ ++s1;
+ ++s2;
+ }
+
+ return
+ (*s2 == 0)
+ ? (*s1 != 0)
+ : (*s1 == 0)
+ ? -1
+ : (tolower(*s1) - tolower(*s2));
+}
+
+// ENDPATCH
+
void b2a_hex(uint32_t i, char* out) {
char map[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f'};
diff --git a/third_party/Makefile.am b/third_party/Makefile.am
index b73dec3..fe34dea 100644
--- a/third_party/Makefile.am
+++ b/third_party/Makefile.am
@@ -12,7 +12,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/third_party/zlib-1.2.3/contrib \
-I$(top_srcdir)/third_party/gtest-1.7.0/include
lib_LTLIBRARIES = libminizip.la liburiparser.la
-noinst_LTLIBRARIES = libgtest.la libgtest_main.la
+#noinst_LTLIBRARIES = libgtest.la libgtest_main.la
libminizip_la_SOURCES = \
zlib-1.2.3/contrib/minizip/unzip.c \
@@ -83,11 +83,11 @@ libboostconfigplatforminclude_HEADERS = \
$(boost)/config/platform/linux.hpp \
$(boost)/config/platform/macos.hpp
-libgtest_la_SOURCES = \
- gtest-1.7.0/src/gtest-all.cc
+#libgtest_la_SOURCES = \
+# gtest-1.7.0/src/gtest-all.cc
-libgtest_main_la_SOURCES = gtest-1.7.0/src/gtest_main.cc
-libgtest_main_la_LIBADD = libgtest.la
+#libgtest_main_la_SOURCES = gtest-1.7.0/src/gtest_main.cc
+#libgtest_main_la_LIBADD = libgtest.la
# TODO: add the new gtest libs for windows.
# gtest-1.7.0.win32/debug/gtest.lib \
@@ -149,38 +149,6 @@ EXTRA_DIST = \
$(boost)/config/stdlib/sgi.hpp \
$(boost)/config/stdlib/stlport.hpp \
$(boost)/config/stdlib/vacpp.hpp \
- gtest-1.7.0/include/gtest/gtest-death-test.h \
- gtest-1.7.0/include/gtest/gtest-message.h \
- gtest-1.7.0/include/gtest/gtest-param-test.h \
- gtest-1.7.0/include/gtest/gtest-param-test.h.pump \
- gtest-1.7.0/include/gtest/gtest-printers.h \
- gtest-1.7.0/include/gtest/gtest-spi.h \
- gtest-1.7.0/include/gtest/gtest-test-part.h \
- gtest-1.7.0/include/gtest/gtest-typed-test.h \
- gtest-1.7.0/include/gtest/gtest.h \
- gtest-1.7.0/include/gtest/gtest_pred_impl.h \
- gtest-1.7.0/include/gtest/gtest_prod.h \
- gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
- gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
- gtest-1.7.0/include/gtest/internal/gtest-internal.h \
- gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
- gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
- gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h.pump \
- gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
- gtest-1.7.0/include/gtest/internal/gtest-port.h \
- gtest-1.7.0/include/gtest/internal/gtest-string.h \
- gtest-1.7.0/include/gtest/internal/gtest-tuple.h \
- gtest-1.7.0/include/gtest/internal/gtest-tuple.h.pump \
- gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
- gtest-1.7.0/include/gtest/internal/gtest-type-util.h.pump \
- gtest-1.7.0/src/gtest-death-test.cc \
- gtest-1.7.0/src/gtest-filepath.cc \
- gtest-1.7.0/src/gtest-internal-inl.h \
- gtest-1.7.0/src/gtest-port.cc \
- gtest-1.7.0/src/gtest-printers.cc \
- gtest-1.7.0/src/gtest-test-part.cc \
- gtest-1.7.0/src/gtest-typed-test.cc \
- gtest-1.7.0/src/gtest.cc \
uriparser-0.7.5/COPYING \
uriparser-0.7.5.win32/debug/uriparser.lib \
uriparser-0.7.5.win32/release/uriparser.lib \
--
1.9.5.github.0

View File

@@ -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

Binary file not shown.

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

View File

@@ -1,3 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
</lint>

View File

@@ -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

View File

@@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -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"
/>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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) {}
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}
}

View File

@@ -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() {}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

Binary file not shown.

Binary file not shown.

57
doc/Makefile Normal file
View File

@@ -0,0 +1,57 @@
CONTENT=$(wildcard *.content)
HTML=$(subst .content,.html,$(CONTENT))
TARBALLS=$(wildcard gc_*.tgz)
OTHER=logo.jpg sample.gp sample.png cpint.gp cpint.png \
screenshot-summary.png screenshot-plot.png \
screenshot-cpint.png screenshot-phist.png \
screenshot-download.png screenshot-weekly.png \
choose-a-cyclist.png main-window.png critical-power.png \
power.zones
all: $(HTML)
.PHONY: all clean install
clean:
rm -f $(HTML)
install:
rsync -avz -e ssh $(HTML) $(TARBALLS) $(OTHER) \
srhea.net:wwwroot/goldencheetah.org/
command-line.html: command-line.content genpage.pl
./genpage.pl "Legacy Command-Line Tools" $< > $@
contact.html: contact.content genpage.pl
./genpage.pl "Contact Us" $< > $@
contrib.html: contrib.content genpage.pl
./genpage.pl "Contributors" $< > $@
download.html: download.content genpage.pl
./genpage.pl "Download" $< > $@
faq.html: faq.content genpage.pl
./genpage.pl "Frequently Asked Questions" $< > $@
index.html: index.content genpage.pl
./genpage.pl "Introduction" $< > $@
license.html: license.content genpage.pl
./genpage.pl "License" $< > $@
screenshots.html: screenshots.content genpage.pl
./genpage.pl "Screenshots" $< > $@
search.html: search.content genpage.pl
./genpage.pl "Search" $< > $@
users-guide.html: users-guide.content genpage.pl
./genpage.pl "User's Guide" $< > $@
wishlist.html: wishlist.content genpage.pl
./genpage.pl "Wish List" $< > $@
zones.html: zones.content genpage.pl
./genpage.pl "Power Zones File Guide" $< > $@

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

32
doc/contrib.content Normal file
View File

@@ -0,0 +1,32 @@
<!-- $Id: contrib.content,v 1.4 2006/09/06 04:07:18 srhea Exp $ -->
Sean Rhea bought a PowerTap Pro on April 20, 2006, and immediately set to
figuring out how to use it from his Mac Powerbook without using Virtual PC.
Within a week, he was able to download the raw data. Shortly thereafter, Russ
Cox asked what he was up to, and the two worked together to figure out the
packing format used. By May 4, they could reproduce the numbers given by the
PowerTap software except for minor discrepancies in the time values. David
Easter then pointed out how the checksum bytes in the download protocol were
used, and Sean Rhea coded up their combined discoveries into the two
utilities, <code>ptdl</code> and <code>ptunpk</code>.
<p>
Later that year, Sean needed to learn QT for his real job, and he set about
writing a graphical version of <code>ptdl</code> and <code>ptunpk</code> for
practice. He released the first graphical version on September 6, 2006,
changing the name to GoldenCheetah in reference to an old legend from his days
as a runner.
<p>
Since then, a number of others have helped out in various ways.
Robert Carlsen helped get the serial port version of the PowerTap Pro working
with the Keyspan USB-to-serial adaptor. Robert also figured out how to build
universal binaries for Mac OS X. Scott Overfield helped figure out
that we should be using the <code>/dev/cu.*</code> devices instead of the
<code>/dev/tty.*</code> ones. Aldy Hernandez and Andrew Kruse helped get
things working under Linux.
Dan Connelly helped find and fix several core dumps.
Justin Knotzke contributed code to import comma-separated value files
and visually mark intervals on the ride plot. J.T. Conklin added the ability
to import TCX files. J.T. also added a pedal force vs. pedal velocity chart. Tom Montgomery added IBike 3 support and cleaned up the Import CSV tool, adding the default ride date when importing new files. Ned Harding resurrected the Windows builds of Golden Cheetah (fixing USB download inconsistencies in the process), then added slew of functions including the long-desired Split Ride feature. (available in version 1.0.305+).

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -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

View File

@@ -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:

File diff suppressed because it is too large Load Diff

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 149 KiB

View File

@@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

View File

@@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

297
doc/download.content Normal file
View File

@@ -0,0 +1,297 @@
<!-- $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
<a href="http://git-scm.com/">git</a>. You need to install
<a href="http://www.trolltech.com/products/qt">QT 4.5.x</a> and
<a href="http://qwt.sourceforge.net/">qwt 5.0.2</a> (as a static, not
dynamic, library) and
edit <code>goldencheetah/src/src.pro</code> to point to them
before building GoldenCheetah.
Use this command to check out the current version of the repository:
<pre>
git clone git://github.com/srhea/GoldenCheetah.git
</pre>
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="10">
<tr>
<td width="20%"><i>Version</i></td>
<td width="30%"><i>Files</i></td>
<td><i>Description</i></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&#8482;</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>

79
doc/faq.content Normal file
View File

@@ -0,0 +1,79 @@
<!-- $Id: faq.content,v 1.4 2006/07/05 16:59:56 srhea Exp $ -->
<p>
<b><i>GoldenCheetah doesn't find my PowerTap on Ubuntu Linux.</i></b>
<p>
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 <code>brltty</code>:
<blockquote>
<code>sudo apt-get remove brltty</code>
</blockquote>
Then plug the device back in and it should work.
<p>
<b><i>I downloaded a .dmg, opened it, dragged and dropped GoldenCheetah into
Applications, double-clicked on it, and nothing happened. What
gives?</i></b>
<p>
Are you running OS X Tiger? You need to be. If you are, and you're still
having this problem, open Terminal (in Applications -&gt; Utilities) and type
this at the prompt:
<blockquote><pre>
/Applications/GoldenCheetah.app/Contents/MacOS/GoldenCheetah
</pre></blockquote>
then press &lt;return&gt; and send an email to the mailing list with
whatever it prints out. We'll help you debug it.
<p>
<b><i>I've downloaded and unpacked the data. Now what do I do with
it?</i></b>
<p>
We highly recommend that you buy and read both Joe Friel's <i>The
Cyclist's Training Bible</i> and Allen and Coggan's <i>Training and
Racing with a Power Meter</i>. The former is the definitive book about all
aspects of cycling training (although we think he's off his rocker in the
chapter about diet), and the latter is the definitive book about power-based
training.
<p>
Also, if you buy either of these books through the links below, we'll get a
referral fee in return, helping us to support this web site. Thanks!
<center>
<iframe
src="http://rcm.amazon.com/e/cm?t=goldencheetah-20&o=1&p=8&l=as1&asins=B0006JHZ7Q&fc1=000000&IS2=1&lt1=_blank&lc1=0000ff&bc1=000000&bg1=ffffff&f=ifr"
style="width:120px;height:240px;" scrolling="no" marginwidth="0"
marginheight="0" frameborder="0"></iframe>
<iframe
src="http://rcm.amazon.com/e/cm?t=goldencheetah-20&o=1&p=8&l=as1&asins=1931382794&fc1=000000&IS2=1&lt1=_blank&lc1=0000ff&bc1=000000&bg1=ffffff&f=ifr"
style="width:120px;height:240px;" scrolling="no" marginwidth="0"
marginheight="0" frameborder="0"></iframe>
</center>
<p>
<b><i>Does the output of <code>ptunpk</code> exactly match that of the software
included with the PowerTap?</i></b>
<p>
Almost. If you run it in compatibility mode, using the <code>-c</code>
option, it matches the PowerTap software's output exactly on everything but
the time values, at least for the five sample rides we've tried it with.
The times are a little off, but not by more than 0.1%, so we don't consider it
a big deal.
<p>
That said, the PowerTap software does some weird things, like converting from
kilometers to miles by multiplying by 0.62, but then reporting the miles
values with five digits after the decimal place. If you run
<code>ptunpk</code> without the <code>-c</code> option, it will unpack the
data in the way we think it should. The results mostly match up with the
official ones, and are almost certainly identical within the range of accuracy
of the device.

View File

@@ -28,23 +28,14 @@ print<<EOF;
<head>
<title>Golden Cheetah: Cycling Performance Software for Linux, Mac OS X, and Windows</title>
<meta name="keywords" content="powertap srm linux mac cycling performance">
<style type='text/css'>
li {
margin: .5em 0
}
body {
color: #000000;
background: #ffffff;
}
:link {
color: #5e431b;
}
:visited {
color: #996e2d;
}
</style>
</head>
<body text="#000000"
link="#5e431b"
vlink="#996e2d"
alink="#000000"
bgcolor="#ffffff">
<table width="95%" border="0" width="100%" cellspacing="10">
<tr>
@@ -54,18 +45,33 @@ 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>
<br> <b><a href="bug-tracker.html">Bug Tracker</a></b>
<br> <b><a href="cgi-bin/mailman/listinfo/golden-cheetah-users">Mailing List</a></b>
<p>
<script type="text/javascript"><!--
google_ad_client = "pub-2993461533095312";
google_ad_width = 120;
google_ad_height = 240;
google_ad_format = "120x240_as";
google_ad_type = "text";
google_ad_channel ="";
google_color_border = "FFFFFF";
google_color_bg = "FFFFFF";
google_color_link = "5E431B";
google_color_url = "996E2D";
google_color_text = "000000";
//--></script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</center>
</td>
@@ -109,9 +115,9 @@ while (<FILE>) {
}
close (FILE);
#if (defined $last_mod) {
# print "<p><hr><em>Last modified $last_mod.</em>\n";
#}
if (defined $last_mod) {
print "<p><hr><em>Last modified $last_mod.</em>\n";
}
print<<EOF;

View File

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 203 KiB

26
doc/index.content Normal file
View File

@@ -0,0 +1,26 @@
<!-- $Id: index.content,v 1.1 2006/05/16 14:24:50 srhea Exp $ -->
<p>
GoldenCheetah is a software package that:
<ul>
<li>Downloads ride data directly from the CycleOps PowerTap, including the
newer Ant+Sport models.<p>
<li>Imports ride data from SRM, Garmin TCX, Polar HRM, and CSV files,
including those from Cycling Peaks&nbsp;(TM) and the ergomo.<p>
<li>Provides a rich set of analysis tools, including critial power,
BikeScore&nbsp;(TM), power histograms, a best interval finder, and pedal force
versus pedal velocity, to name just a few.<p>
<li>Works identically under Linux, Mac OS X, and Windows.<p>
<li>Is available under an Open Source license.
</ul>
<p>
We believe that cyclists should be able to download their power data
to the computer of their choice, analyze it in whatever way they see fit, and
share their methods of analysis with others.

BIN
doc/logo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
doc/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

View File

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 203 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

BIN
doc/screenshot-cpint.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
doc/screenshot-download.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
doc/screenshot-phist.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
doc/screenshot-plot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
doc/screenshot-summary.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
doc/screenshot-weekly.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

49
doc/screenshots.content Normal file
View File

@@ -0,0 +1,49 @@
<!-- $Id: faq.content,v 1.4 2006/07/05 16:59:56 srhea Exp $ -->
<p>
<center>
<big><font face="arial,helvetica,sanserif">
The Download Dialog
</font></big>
<p>
<img src="screenshot-download.png" alt="Download Dialog" align="center">
<p>
<big><font face="arial,helvetica,sanserif">
The Ride Summary
</font></big>
<p>
<img src="screenshot-summary.png" alt="Ride Summary Screen" align="center">
<p>
<big><font face="arial,helvetica,sanserif">
The Power, Heart Rate, Speed, and Cadence Plot
</font></big>
<p>
<img src="screenshot-plot.png" alt="Power and HR Plot" align="center">
<p>
<big><font face="arial,helvetica,sanserif">
The Critical Power Plot
</font></big>
<p>
<img src="screenshot-cpint.png" alt="The Critical Power Plot" align="center">
<p>
<big><font face="arial,helvetica,sanserif">
The Power Histogram
</font></big>
<p>
<img src="screenshot-phist.png" alt="The Power Histogram" align="center">
<p>
<big><font face="arial,helvetica,sanserif">
The Weekly Summary
</font></big>
<p>
<img src="screenshot-weekly.png" alt="The Weekly Summary" align="center">
</center>

10
doc/user/.gitignore vendored
View File

@@ -1,10 +0,0 @@
*.aux
*.cp
*.cps
*.fn
*.ky
*.log
*.pg
*.toc
*.tp
*.vr

View File

@@ -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
*****
[index]
* Menu:
* add: MOST COMMON QUESTIONS OF ALL.
(line 22)
* adhoc: SEASONS AND EVENTS. (line 9)
* Aerolab: MOST COMMON QUESTIONS OF ALL.
(line 75)
* Aerolab <1>: CHARTS. (line 19)
* anomalies: DATA. (line 23)
* anomalies <1>: DATA. (line 38)
* AP: METRICS. (line 80)
* best: MOST COMMON QUESTIONS OF ALL.
(line 62)
* bug: GENERAL. (line 66)
* cervo: MOST COMMON QUESTIONS OF ALL.
(line 136)
* Chung: CHARTS. (line 19)
* clone: GENERAL. (line 40)
* colour: MOST COMMON QUESTIONS OF ALL.
(line 121)
* colour <1>: CHARTS. (line 68)
* contribute: GENERAL. (line 73)
* CP: METRICS. (line 22)
* CP <1>: METRICS. (line 39)
* CP <2>: METRICS. (line 50)
* CSV: DATA. (line 87)
* CTL: METRICS. (line 63)
* cycle: SEASONS AND EVENTS. (line 9)
* Daniels: METRICS. (line 9)
* donate: GENERAL. (line 85)
* download: GENERAL. (line 31)
* download <1>: UPLOADING AND DOWNLOADING.
(line 16)
* elevation: METRICS. (line 71)
* EqP: METRICS. (line 9)
* event: SEASONS AND EVENTS. (line 18)
* event <1>: SEASONS AND EVENTS. (line 26)
* feature: GENERAL. (line 66)
* FITLOG: DATA. (line 87)
* FTP: METRICS. (line 22)
* FTP <1>: METRICS. (line 50)
* Garmin Connect: METRICS. (line 80)
* github: GENERAL. (line 40)
* Google: UPLOADING AND DOWNLOADING.
(line 22)
* install: GENERAL. (line 31)
* join: DATA. (line 9)
* JSON: DATA. (line 87)
* LTS: METRICS. (line 63)
* mail: GENERAL. (line 56)
* map: CHARTS. (line 53)
* merge: DATA. (line 9)
* month: CHARTS. (line 9)
* NP: METRICS. (line 9)
* options: MOST COMMON QUESTIONS OF ALL.
(line 112)
* override: METRICS. (line 110)
* PMC: MOST COMMON QUESTIONS OF ALL.
(line 75)
* PMC <1>: METRICS. (line 63)
* powertap: MOST COMMON QUESTIONS OF ALL.
(line 136)
* preferences: MOST COMMON QUESTIONS OF ALL.
(line 112)
* prior: CHARTS. (line 9)
* PWX: DATA. (line 87)
* remove: MOST COMMON QUESTIONS OF ALL.
(line 22)
* report: GENERAL. (line 66)
* season: SEASONS AND EVENTS. (line 9)
* season <1>: SEASONS AND EVENTS. (line 26)
* settings: MOST COMMON QUESTIONS OF ALL.
(line 101)
* source: GENERAL. (line 40)
* spikes: DATA. (line 23)
* spikes <1>: DATA. (line 38)
* split: DATA. (line 9)
* TCX: DATA. (line 87)
* trainer: METRICS. (line 50)
* TrainingPeaks: UPLOADING AND DOWNLOADING.
(line 9)
* TrainingPeaks <1>: UPLOADING AND DOWNLOADING.
(line 16)
* treemap: CHARTS. (line 61)
* triathlete: GENERAL. (line 47)
* TSS: MOST COMMON QUESTIONS OF ALL.
(line 9)
* TSS <1>: METRICS. (line 80)
* unzoom: CHARTS. (line 93)
* upload: UPLOADING AND DOWNLOADING.
(line 9)
* usb: MOST COMMON QUESTIONS OF ALL.
(line 136)
* VE: CHARTS. (line 19)
* weekly summary: MOST COMMON QUESTIONS OF ALL.
(line 87)
* weight: MOST COMMON QUESTIONS OF ALL.
(line 37)
* Withings: UPLOADING AND DOWNLOADING.
(line 35)
* xPower: METRICS. (line 9)
* zoom: CHARTS. (line 82)
* zoom <1>: CHARTS. (line 93)

Tag Table:
Node: Top163
Node: MOST COMMON QUESTIONS OF ALL608
Node: GENERAL7263
Node: METRICS10899
Node: DATA17912
Node: UPLOADING AND DOWNLOADING21867
Node: SEASONS AND EVENTS23922
Node: CHARTS25327
Node: INDEX29480

End Tag Table

Binary file not shown.

View File

@@ -1,771 +0,0 @@
\input texinfo @c -*-texinfo-*-
@ifnotinfo
@input palatino
@end ifnotinfo
@c %**start of header
@setfilename FAQ.texinfo
@settitle Golden Cheetah FAQ
@c %**end of header
@paragraphindent 0
@copying
This manual is for Golden Cheetah, version 3.1.
Copyright @copyright{} 2013 Mark Liversedge
@end copying
@titlepage
@title Golden Cheetah FAQ
@c @subtitle subtitle-if-any
@c @subtitle second-subtitle
@author Mark Liversedge
@c The following two commands
@c start the copyright page.
@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage
@c So the toc is printed at the start.
@contents
@ifnottex
@node Top,Top,Top,
@top title
This manual is for GoldenCheetah, version 3.1.
@end ifnottex
@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
@end menu
@node MOST COMMON QUESTIONS OF ALL,GENERAL,INDEX,Top
@chapter MOST COMMON QUESTIONS OF ALL
@section How do I override / manually enter TSS for a ride?
@cindex TSS
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.
@section How do I add or remove a chart?
@cindex add
@cindex remove
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.
@section Can I enter my weight and track/plot it?
@cindex weight
Weight can be maintained in 3 ways;
@itemize @bullet
@item 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.
@item 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.
@item 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.
@end itemize
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.
@section How do I plot x sec power best?
@cindex 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.
@section I can't find Aerolab / Performance Manager?
@cindex Aerolab
@cindex PMC
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.
@section What happened to weekly summary?
@cindex 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.
@section Where are all the chart settings?
@cindex 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.
@section Where is the preferences / options panel?
@cindex preferences
@cindex options
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.
@section How do I change the colour of the rides on the calendar/list?
@cindex colour
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'.
@section GoldenCheetah doesn't find my PowerTap on Ubuntu Linux.
@cindex powertap
@cindex cervo
@cindex usb
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.
@section 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.
@node GENERAL,METRICS,MOST COMMON QUESTIONS OF ALL,Top
@chapter GENERAL
@section 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.
@section 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.
@section Where can I download the installer for GoldenCheetah ?
@cindex download
@cindex install
Stable releases are available from @url{http://www.goldencheetah.org} whilst the latest and greatest
code build is available from @url{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.
@section Where can I get the source code?
@cindex source
@cindex github
@cindex clone
The GoldenCheetah source code is hosted on github and can be cloned using the following url;
@code{git://github.com/GoldenCheetah/GoldenCheetah.git}
@section I am a triathlete is GoldenCheetah appropriate for me?
@cindex triathlete
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.
@section Is there a mailing list?
@cindex mail
The mailing list for GoldenCheetah users is maintained via Google Groups at
@url{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.
@section How do I report a bug or request a new feature?
@cindex feature
@cindex bug
@cindex report
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
@url{http://www.github.com/GoldenCheetah/GoldenCheetah/issues}
@section How can I contribute?
@cindex 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.
@section Can I donate to the project?
@cindex donate
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.
@node METRICS,DATA,GENERAL,Top
@chapter METRICS
@section What is the difference between xPower, NP and Daniels EqP?
@cindex xPower
@cindex NP
@cindex Daniels
@cindex 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
@url{http://www.physfarm.com/bikescore.pdf}
@section What is the difference between CP and FTP?
@cindex CP
@cindex 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.
@section Why does my CP chart show higher watts for a longer duration?
@cindex CP
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).
@section Can I set a different CP/FTP for different reasons e.g. CP/FTP on a trainer?
@cindex CP
@cindex FTP
@cindex 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.
@section How do I seed the CTL for my PMC?
@cindex PMC
@cindex CTL
@cindex LTS
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.
@section Why is elevation different in GoldenCheetah to my other training software / website?
@cindex elevation
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.
@section Why is a metric e.g. TSS or average power different in GoldenCheetah to Garmin Connect?
@cindex TSS
@cindex AP
@cindex 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.
@section 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.
@section How do I add a metric to the details screen (so I can override it) ?
@cindex override
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.
@section 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.
@section 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.
@node DATA,UPLOADING AND DOWNLOADING,METRICS,Top
@chapter DATA
@section How do I split, merge or join files?
@cindex split
@cindex merge
@cindex join
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.
@section How can I find 'spikes' or specific values in activity data?
@cindex spikes
@cindex anomalies
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.
@section How can I fix 'spikes' or 'anomalies' in activity data?
@cindex spikes
@cindex anomalies
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.
@section 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.
@section 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.
@section 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.
@section How can I export to a specific file format?
@cindex PWX
@cindex JSON
@cindex TCX
@cindex CSV
@cindex FITLOG
Activity->Export allows you to export the activity to csv, fitlog, gc (xml), json,
Training Peaks PWX or Garmin TCX format.
@section 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
@section 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.
@node UPLOADING AND DOWNLOADING,SEASONS AND EVENTS,DATA,Top
@chapter UPLOADING AND DOWNLOADING
@section Why does upload to TrainingPeaks keep failing?
@cindex TrainingPeaks
@cindex upload
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.
@section Why does download from TrainingPeaks say I need a premium account?
@cindex TrainingPeaks
@cindex download
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.
@section What settings do I need to get GoldenCheetah to upload to my Google Calendar?
@cindex Google
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:
@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.
@section When setting up my Withings wifi scales where do I get the userid and key ?
@cindex Withings
You will need to login to your Withings account (@url{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.
@node SEASONS AND EVENTS,CHARTS,UPLOADING AND DOWNLOADING,Top
@chapter SEASONS AND EVENTS
@section Why are there different types of seasons?
@cindex season
@cindex adhoc
@cindex cycle
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.
@section What is event used for?
@cindex event
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.
@section How do create/edit/delete seasons and events?
@cindex event
@cindex season
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.
@node CHARTS,INDEX,SEASONS AND EVENTS,Top
@chapter CHARTS
@section I want to plot month -1,-2 and -3 how do I do that?
@cindex month
@cindex prior
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.
@section How should I use Aerolab?
@cindex Aerolab
@cindex Chung
@cindex VE
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:
@url{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):
@url{https://github.com/GoldenCheetah/GoldenCheetah/blob/master/doc/contrib/ChungVE.pdf}
@section My map doesn't show?
@cindex map
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.
@section What is the treemap plot used for?
@cindex treemap
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.
@section Can I change the colors in plot x ?
@cindex colour
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.
@section How do you zoom in on a chart?
@cindex zoom
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.
@section I zoomed in but can't zoom out?
@cindex zoom
@cindex unzoom
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.
@section 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.
@node INDEX,MOST COMMON QUESTIONS OF ALL,CHARTS,Top
@unnumbered Index
@printindex cp
@bye

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More