City Cycle Race (with STRAVA) - Compare the cycling speed of cities
This shiny app allows to compare how fast people cycle in your city. This app uses data from strava to compare the cyclists in two cities. How is this possible? Strava is a sports tracking app. Basically whenever people cycle they can track themselves using GPS. Afterwards they will know how fast they went on their track. This is not comparable. Though, strava build in a feature called segments. These segments are tracks of any length all around the world. On each of these segments strava the users can have a virtual race. The time they needed for the segment is stored on a leaderboard. The fastest cyclist is the King of the Mountain on this segment. The data is available for everybody having a strava account via the strava API. This package ( + app) includes the data and allows to crawl it by certain features. A short summary of the data is given here:
| cities | 4 | | segments | 421,685 | | segments with average speed | 22,589 | | Average speed per segment | 28.76 km/h | | Average speed per segment (men) | 32.7 km/h | | Average speed per segment (women) | 23.49 km/h | | Average length of a segment | 2162.3 m | | Variables measured per segment | 23 |
What the app can do will be shown in the next section. To read more about the process of how to get the data, just start the app on
shinyapps.io and go to the "About" section.
The app now first allows to select a city by radius and see the segments in a map. The map highlights each segment by the average speed on the segment. The city radius gets drawn into the map such that you can see how much of e.g. London you covered with 20 km radius.
Every single segment on the map can be chosen and the leaderboard for the segment can be explored on STRAVA.
To show that there is a race going on, the app animates all bar charts. Meaning whenever you change the Race settings of two cities some bar charts will get updated as an animation. This function was implemented as a
JSON to be rendered under each other and have a maximum length of the maximum of all bars.
Just for the selection of the gender, I built an R-package to construct a candle-stick input. The package can be found under https://github.com/zappingseb/shinycandlestick.
Data Filtering with URL Parameters
The data for the race can be filtered by several parameters. Gender of Cyclists, if the speed per segment
shall be calculated by average or median, length of the segments, elevation calculations, and the number
of athletes per segment.
To allow storing and sharing those settings the users have a button to produce a link to the app
including all their settings. If the app is called with those settings they will immediately be the
default "Race Settings".
Landing Page Module
The Landing Page allows to automatically guide the user into the right place. If he wants to already change the
setup of the app he/she can navigate to the "Race Settings" immediately.
The app was programmed in a fully responsive way. All features work on a mobile phone.
inside the R-package
CSS was used to modify most input elements, even standard shiny based input elements. The "Race Setting" button was taken from
shinyWidgests::dropdownButton and also modified via CSS.
CSS helped a lot to make the app responsive and let the animated bars look the way they do.
I'm a huge fan of modularization. Actually, the map and the select input are rendered twice. So I thought these have to be modules. I wanted to keep the app itself really clean. the UI function has actually just 60 lines of code thanks to modularization. I wrote an article about why and how to modularize shiny on Medium. If you are interested to go through it.
Custom shiny inputs
I used a custom shiny input for the candlestick as described in these two tutorials: