Bicycle Ride Speed Calculator
Bicycle club ride speed calculator based on a specific reference course. On GitHub at https://github.com/apperceive/SpeedCalculator/
by Markus Sandy
HTML
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<div class='block'>
<h2 class='block-title title'>Unsure which Ride to join?</h2>
<ul>
<li>Assess your cruising speed by timing yourself.</li>
<li>Time a four-lap ride of the complete oval in Central Park.</li>
<li>That's 24.4 miles total.</li>
<li>Ride at a comfortable, sustainable pace.</li>
<li>Fewer than four laps will give a false assessment.</li>
<li>Position your time on the slider below (1.5 hrs = 90 min).</li>
<li>Note the cruising speed.</li>
</ul>
<input id="coursetime" class='coursetime' type ="range" min ="0.0" max="3.0" step ="0.001" value='1.5' onchange='changetime();' onmousemove='mousetime();' />
<div id='range'><span id='timemin'>0</span><span id='timeset'></span><span id='timemax'>3</div>
<div class='results'>
<div id='comment'>There <strong id='ridenum'>6</strong> with this speed available to club members.</div>
<h2 id='time'></h1>
<h2 id='speed'></h1>
</div>
<ul>
<li>Pick a ride that matches your cruising speed.</li>
<li>It's that easy!</li>
<li>Most ride speeds are in the range of 10mph - 23mph.</li>
<li><a href='/join' title='Click to join and view upcoming rides listing...'>Click here to join or view rides.</a></li>
</ul>
</div>
CSS
.block {
background: #aaa url("http://apperceive.com/img/nycc-speed-calc.jpg"); /* https://www.flickr.com/photos/skinnylawyer/7174938930/ */
background-size: 100% 100%;
width: 480px;
margin: 0 auto;
border: solid thin gray;
padding: 10px;
color: #333;
}
#range {
width: 460px;
}
.coursetime {
width: 400px;
color: coursetime;
text-align: center;
}
#timeset,
#timemax,
#timemin {
display: inline-block;
width: 33%;
}
#timemax {
text-align: right;
}
#timeset,
.block-title,
.results {
text-align: center;
}
#comment {
padding-top: 25px;
font-style: italic;
}
.block a,
.block a:visited {
color: #111;
font-weight: bold;
}
.block a:hover {
color: #888;
}
.block a.wikipedia {
color: #333;
font-weight: normal;
}
input[type=range] {
-webkit-appearance: none;
width: 100%;
margin: 13.8px 0;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 8.4px;
cursor: pointer;
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
background: #3071a9;
border-radius: 1.3px;
border: 0.2px solid #010101;
}
input[type=range]::-webkit-slider-thumb {
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
border: 1px solid #000000;
height: 36px;
width: 16px;
border-radius: 3px;
background: #ffffff;
cursor: pointer;
-webkit-appearance: none;
margin-top: -14px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: #367ebd;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 8.4px;
cursor: pointer;
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
background: #3071a9;
border-radius: 1.3px;
border: 0.2px solid #010101;
}
input[type=range]::-moz-range-thumb {
box-shadow: 1px 1px 1px #000000, 0px...
JavaScript
function mousetime() {
change();
}
function changetime() {
var ctval = document.getElementById('coursetime').value;
var speed = (ctval > 0.000001) ? (Math.round(24.4 / ctval)) : -1;
var rides = (speed < 25) ? getRandomIntInclusive(1, 10) : 0;
document.getElementById('ridenum').innerHTML = (ctval > .0001 ? ((rides == 1) ? 'is 1 ride' : 'are ' + rides + ' rides') : 'no rides');
document.getElementById('comment').innerHTML = getMessage(speed);
change();
}
function change() {
var ctval = Math.round(document.getElementById('coursetime').value * 100)/100;
var speed = (ctval > 0.000001) ? (Math.round(24.4 / ctval)) : -1;
// display hours : min
var hours = Math.floor(ctval);
var min = ctval - hours;
document.getElementById('timeset').innerHTML = (hours ? (hours + (hours == 1 ? " hour " : " hours ")) : "") + (min ? Math.round(min * 60) + " min" : ( !hours && !min ? "0 min" : ""));
document.getElementById('speed').innerHTML = 'Crusing Speed: ' + (speed > 0 ? speed + ' mph' : 'Infinite!');
}
// ToDo: make this a jsonp service
function getMessage(speed) {
var rides = (speed < 25) ? getRandomIntInclusive(1, 6) : 0;
var messagedef = "There "+(rides == 1 ? "is" : "are")+" <strong id='ridenum'>" + rides + "</strong> <a href='/upcoming-rides' title='Click to view upcoming rides listing...'>upcoming "+(rides == 1 ? "ride" : "rides")+"</a> with this speed available to club members.";
var message = messagedef;
var speeds = [
{'speed': 31, 'text': "Typical speed of road-race cyclist"},
{'speed': 37, 'text': "Typical speed of thoroughbred racehorse or racing greyhound"},
{'speed': 55.2, 'text': "Barton Mawer, Solar powered bicycle speed record holder"},
{'speed': 83.13, 'text': "Sebastiaan Bowier, Human powered bicycle speed record holder"},
{'speed': 139.85, 'text': "Charles Burnett III, Steam powered speed record holder"},
{'speed': 167.044, 'text': "Fred Rompelberg, Paced bicycle speed record holder"},
{'speed':...