Te voet naar Santa’s House

Bij Unit-T, waar ik werk, hebben ze fantastische ideeën.
Na de virtuele dodentocht, waarin ik 300 km aflegde in 4 weken, kwam het feestcomité met het idee om eens zelf intern een challenge te organiseren:

Samen virtueel te voet naar Rovaniemi, de hoofdstad van Lapland en woonplaats van de Kerstman. Welgeteld 2505 km vanaf thuishaven Mechelen.

Afhankelijk van hoeveel collega’s zich inschreven zou dat ofwel een makkie, ofwel een onmogelijke opdracht worden.

Om de technische kant te faciliteren werd mijn hulp ingeroepen. Op één of andere manier moeten de kilometers kunnen geregistreerd worden en moet de voortgang kunnen bijgehouden worden.
In Strava is er helaas geen mogelijkheid om een ‘wandel- & loopclub’ aan te maken. In de loopclub worden geen wandelactiviteiten meegeteld en in een algemene club zou fietsen ook meetellen (en dan wordt het te makkelijk).

Ik besloot dus gebruik te maken van de Strava API. Dat bleek makkelijker dan verwacht. In enkele tellen was die actief.

Een API

Dankzij wat copy/paste werk vanuit github.com/iamstuartwilson kreeg ik in no time activiteiten binnen en kon ik die importeren in een database.

$yesterdaysepoch = mktime(0, 0, 0, date("m"), date("d")-8, date("Y")); // niet yesterday, maar laatste week :)

if ($yesterdaysepoch < $challengestart) $yesterdaysepoch = $challengestart; // niets opvragen vóór de startdatum

$response = $api->get(
	'clubs/772000/activities',
	[
		'page' => 1,
		'per_page' => 200,
		'after' => $yesterdaysepoch
	]
);
		
$i = $t = $a = $b = 0;
 //vars voor logging

foreach($response as $activity) {
	$t++;
	if (is_object($activity)) {
		$activityname = $activity->name;
		$activitytype = $activity->type;
		$activitydistance = $activity->distance;
		$activitymovingtime = $activity->moving_time;
		$athletename = $activity->athlete->firstname." ".$activity->athlete->lastname;
			
		$stmt = $db->prepare("INSERT IGNORE INTO `strava_walkchallenge` (`actvityname`, `activitytype`, `activitydistance`, `activitymovingtime`, `athletename`) VALUES (?,?,?,?,?);")
		$stmt->bind_param("ssdis", $activityname, $activitytype, $activitydistance, $activitymovingtime, $athletename);
		$stmt->execute();
		if ($stmt->affected_rows > 0) {
			if ($activitytype == 'Walk' || $activitytype == 'Run' || $activitytype == 'Hike') {
				$a = $a + $stmt->affected_rows;
			}
			else {
				$b = $b + $stmt->affected_rows;
			}
		}
		$stmt->close();
				
		$allownaam = str_replace(' ', '%', $athletename);
		$stmt = $db->prepare("INSERT IGNORE INTO `strava_allowlist` (`naam`, `allow`) VALUES (?,0);");
		$stmt->bind_param("s", $allownaam);
		$stmt->execute();
		$stmt->close();
				
		$stmt = $db->prepare("UPDATE `swatweb`.`strava_settings` SET `value`='".date("Y-m-d H:i:s")."' WHERE  `key`='lastupdate';");
		$stmt->execute();
		if ($stmt->affected_rows != 1) {
			
		}
		$stmt->close();
			
		$i++;
	}
}

Dan was het enkel kwestie om deze te filteren op “hike, run, walk”, een cronjob op te zetten en een mooi tellertje tonen.

if($stmt=$db->prepare("SELECT SUM(s.activitydistance) as walkeddistance, MAX(s.added) AS lastactivity, COUNT(DISTINCT s.athletename) AS actievedlns 
FROM strava_walkchallenge s 
WHERE s.activitytype IN ('Walk', 'Run', 'Hike')
AND s.del = 0
AND REPLACE(s.athletename,' ','%') IN (SELECT naam FROM strava_allowlist WHERE allow=1)
AND s.added > from_unixtime((SELECT `value` FROM strava_settings WHERE `key` = 'challenge_start'))")){
	$stmt->execute();
	$result = $stmt->get_result();
	while ($row = $result->fetch_assoc()) {
		$walkeddistance = number_format((($row['walkeddistance'])/1000),0,',', '');
		$kmtegaan = (int)2505-(int)$walkeddistance;
		$lastactivity = $row['lastactivity'];
		$actievedlns = $row['actievedlns'];
	}
	$stmt->close();
}

$t0 = new DateTime($startdate);
$t1 = new DateTime(date("Y-m-d"));
$t2 = new DateTime($stopdate);
$days2go = $t1->diff($t2)->format('%r%a');
		
		
if ($actievedlns > 0) {
	if (((int)$actievedlns>0) && ((int)$days2go > 0)) {
		$kmperdlnperdag = number_format(((int)$kmtegaan/(int)$actievedlns/(int)$days2go),0);
	}
}
else {
	$kmperdlnperdag = 9999;
}

$challengedays = $t0->diff($t2)->format('%r%a') +1; //+1 want de stopdatum zelf telt ook mee.
$schema_kmpd = $challenge_distance/$challengedays; 
$schema_dayspassed = $challengedays-$days2go;
$schema_targettoday = $schema_kmpd*$schema_dayspassed;
$schema = $walkeddistance-$schema_targettoday;

Visualisatie

Om het nog wat visueler te maken was er ook het idee de virtueel afgelegde afstand op een kaart te tonen.

De tracelijn heb ik op een alternatieve manier op de map getoverd. Ik plot gewoon alle trackpoints. Niet de ideale manier, wel de makkelijkste 🙂
Ik exporteerde daarvoor eerst de GPX file zodat ik alle trackpoints had. Omdat dit er veel te veel waren, heb ik die via een online Tracks optimizer (source op GitHub) verminderd tot een 2500-tal punten. Deze in een array gestoken en afhankelijk van de afgelegde afstand tot dat punt plotten in’t groen en vanaf daar de resterende array plotten in ’t rood met een interval van een 100-tal punten.

for (var i = 0; i < allPoints.length; i = i + jumper) {
	var iconcolor = 'green';

	var myLatlng = new google.maps.LatLng(allPoints[i][1], allPoints[i][0]);
	if (i > <?= $walkeddistance ?>) {
		iconcolor = 'red';
		jumper = 100;
		var marker = new google.maps.Marker({
			position : myLatlng,
			map : map,
			icon : {
				path: google.maps.SymbolPath.CIRCLE,
				scale: 3,
				strokeColor: iconcolor,
				fillColor: iconcolor,
				fillOpacity: 100
			}
		});
	}
	else {
		jumper = 2;
		var marker = new google.maps.Marker({
			position : myLatlng,
			map : map,
			icon : {
				path: google.maps.SymbolPath.CIRCLE,
				scale: 2,
				strokeColor: iconcolor,
				fillColor: iconcolor,
				fillOpacity: 100
			}
		});
	}
}

Natuurlijk mag javascriptvuurwerk ook niet ontbreken als de challenge werd gehaald 🙂

Google Maps

Om Google Maps te mogen gebruiken is er ook een API key nodig. Dit is gratis als je onder een bepaald aantal requests blijft. Gelukkig kan je onder Billing > Budgets & Alerts op voorhand instellen hoeveel euro je er voor over hebt.

https://developers.google.com/maps/documentation/javascript/get-api-key

De Challenge zelf

Uiteindelijk schreven meer dan dertig collega’s zich in. Elk 85 km in een maand zou een uitdaging worden, maar niet onmogelijk. Halverwege was het wat spannend, maar dankzij een eindsprintje haalden we het.

In deze 31 dagen durende challenge legde ik zelf 210 km te voet af. Soms onder een stralende zon, soms in de regen, maar vooral door de modder 🙃


Een infographic mag dan ook niet ontbreken 🙂

Reacties

Een reactie achterlaten

Je e-mailadres zal niet getoond worden. Vereiste velden zijn gemarkeerd met *