"; file_put_contents($file, $geojson_fingerprint_str, LOCK_EX); if(!$localhost) { if ( !file_exists('/var/www/html/live/www2.php') || !file_exists('/var/www/html/live/www3.php') || !isset($_GET['force_remote_rebuild']) ) { // IF WWW AND NOT WWW2/WWW3 execute remote clear cache /***************************************/ /* Rebuild Cache www 2 */ /***************************************/ $link = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; $link = str_replace("www", "www2", $link) . '&force_remote_rebuild='.date("jnY").'uyULaDBe6GY5Hd7JhR7Cc33rJMTVL6aR'; // Update url - Replace www with www2 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$link); // Receive server response ... curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $server_output = curl_exec($ch); curl_close ($ch); /***************************************/ /* Rebuild Cache www 3 */ /***************************************/ $link = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; $link = str_replace("www", "www3", $link) . '&force_remote_rebuild='.date("jnY").'uyULaDBe6GY5Hd7JhR7Cc33rJMTVL6aR'; // Update url - Replace www with www2 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$link); // Receive server response ... curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $server_output = curl_exec($ch); curl_close ($ch); } } } } } $start = microtime(true); $mem = memory_get_usage(); $actual_link_full = 'https: //' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']; $actual_link = strtr($actual_link_full, "/index.php", ""); $FBurl = strtok('https://' . $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"], '?'); $data = array(); $ridersArray = array(); $ridersArrayPreRace = array(); $coArray = array("data" => ""); $raceData = FALSE; //$ridersArrayLeaderboard = array(); $cpArray = array(); $i = 0; if ($config_sortActive == 'cpCount') { $ridersArrayJsonFile = file_get_contents('./data/ridersArray.json'); $ridersArrayJsonFile = json_decode($ridersArrayJsonFile, true); } $startTimelog = ''; $sql = "SELECT ".$eventTable_rc.".*, ".$eventTable.".* FROM ".$eventTable_rc." LEFT JOIN ".$eventTable." ON ".$eventTable_rc.".imei = ".$eventTable.".imei WHERE ".$eventTable_rc.".active=1;"; $res = mysqli_query($conn, $sql); while ($deviceData = mysqli_fetch_array($res)) { if ($deviceData['fixUnix']) { // if there is a fixUnix value then the device is active, otherwise, put it in pre-race loop. $raceData = true; if (!$deviceData['scratched']) { if($grouppedEvent && $groupColors[$deviceData['groupId']]){ $deviceData['color'] = $groupColors[$deviceData['groupId']]; // Groups get same color } } else { if ($deviceData['scratched'] == '4') { $deviceData['color'] = "#ff0000"; // Crew Color } else { $deviceData['color'] = "#000000"; // Scratched color } } if( isset($deviceData['nameExt']) && !empty($deviceData['nameExt']) ) { $rider = preg_replace("/[^A-Za-z0-9]/", "", $deviceData['nameExt']); } else { $rider = preg_replace("/[^A-Za-z0-9]/", "", "Participant " . $deviceData['deviceId']); } // put rider data into php array if (!empty($rider)) { if ($debug) { $rider = $rider . "" . $i; } $lastReportSec = (time() - $deviceData['fixUnix']) - ($viewDelay * 60); $lastReportMins = $lastReportSec / 60; $lastReport = lastReport($lastReportSec); //$lastPingReportSec = (time() - strtotime($deviceData['dateTime'])) - ($viewDelay * 60); //$lastPingReport = lastReport($lastPingReportSec); // check if the last know unixtimestamp is todays otherwise todays data is null $date = date('Y-m-d', $deviceData['fixUnix']); $today = date('Y-m-d'); $attributes = json_decode($deviceData['attributes'], true); // create rider data array for mainpage view if ($debug) { $ridersArray[$rider]['latitude'] = '4.457832'; $ridersArray[$rider]['longitude'] = '52.147147'; } else { $ridersArray[$rider]['latitude'] = floatval($deviceData['latitude']); $ridersArray[$rider]['longitude'] = floatval($deviceData['longitude']); } $ridersArray[$rider]['lastReport'] = $lastReport; $ridersArray[$rider]['lastReportMins'] = round($lastReportMins); $ridersArray[$rider]['teamNumber'] = '-'; if( isset($deviceData['teamNumber']) && !empty($deviceData['teamNumber']) ) { $ridersArray[$rider]['teamNumber'] = $deviceData['teamNumber']; } $ridersArray[$rider]['startDelay'] = $deviceData['startDelay']; $ridersArray[$rider]['country'] = 'Unknown.png'; if( isset($deviceData['country']) && !empty($deviceData['country']) ) { $ridersArray[$rider]['country'] = $deviceData['country']; } $ridersArray[$rider]['scratched'] = floatval($deviceData['scratched']); $ridersArray[$rider]['dtf'] = ($deviceData['dtf'] * 1000); $ridersArray[$rider]['dtfKM'] = round($deviceData['dtf']); if(empty($deviceData['groupId']) ) { $deviceData['groupId'] = '1'; } if(!$grouppedEvent){ $deviceData['groupId'] = '1'; } // If no groupped event, force all riders in group 1 to perform ranking and sorting. $ridersArray[$rider]['groupId'] = $deviceData['groupId']; if(isset($groupHeaderLabels)) { $ridersArray[$rider]['groupHeaderLabel'] = $groupHeaderLabels[$deviceData['groupId']]; } if(isset($groupHeaderMarkerLabels)) { $ridersArray[$rider]['groupHeaderMarkerLabels'] = $groupHeaderMarkerLabels[$deviceData['groupId']]; } if( isset($groupFinishCPs) ) { $ridersArray[$rider]['groupFinish'] = $groupFinishCPs[$deviceData['groupId']]; } if(!$grouppedEvent){ $ridersArray[$rider]['startTimeUnix'] = $groupStartTimes[$deviceData['groupId']] + ($deviceData['startDelay']*60); } else { $ridersArray[$rider]['startTimeUnix'] = $startTimeUnix; } // DO WE STILL USE THIS ?? /*if ($date == $today) { $ridersArray[$rider]['avgSpeedToday'] = round($deviceData['speedAvgToday'], 2); if($deviceData['distanceToday']) { $ridersArray[$rider]['todaysDistance'] = round(($deviceData['distanceToday'] * $correctionPercentage), 2); } else { $ridersArray[$rider]['todaysDistance'] = 0; } } else { $ridersArray[$rider]['avgSpeedToday'] = '0'; $ridersArray[$rider]['todaysDistance'] = '0'; }*/ $ridersArray[$rider]['totalDistance'] = round((floatval($deviceData['totalDistance']) * floatval($correctionPercentage)), 2); if(isset($deviceData['speed'])){ $ridersArray[$rider]['currentSpeed'] = round(floatval($deviceData['speed']), 2); // LEGACY ?? } //$ridersArray[$rider]['dbtable'] = $eventTable; $ridersArray[$rider]['riderNameClean'] = $rider; $ridersArray[$rider]['riderColor'] = $deviceData['color']; $ridersArray[$rider]['attributes'] = $deviceData['attributes']; $ridersArray[$rider]['fixTimeUnix'] = $lastReport; $ridersArray[$rider]['fixUnix'] = $deviceData['fixUnix']; $ridersArray[$rider]['firstFixUnix'] = $deviceData['firstFixUnix']; $ridersArray[$rider]['timeIdle'] = $deviceData['timeIdle']; if ( ($deviceData['timeIdle']) && ($deviceData['fixUnix'] != $deviceData['firstFixUnix']) ) { $movingTime = ($deviceData['fixUnix'] - $deviceData['firstFixUnix']) - $deviceData['timeIdle']; $stoppedTime = $deviceData['timeIdle']; $stoppedPercentage = round(($deviceData['timeIdle'] * 100) / ($deviceData['fixUnix'] - $deviceData['firstFixUnix'])); $movingTimePercentage = round(100 - $stoppedPercentage); $ridersArray[$rider]['movingTime'] = $movingTime; $ridersArray[$rider]['movingTimeText'] = sec2elapsed($movingTime); $ridersArray[$rider]['timeIdleText'] = sec2elapsed($deviceData['timeIdle']); $ridersArray[$rider]['stoppedPercentage'] = $stoppedPercentage; $ridersArray[$rider]['movingTimePercentage'] = $movingTimePercentage; } elseif ($deviceData['fixUnix'] != $deviceData['firstFixUnix']) { // No idle time yet so 100% moving time. $movingTime = ($deviceData['fixUnix'] - $deviceData['firstFixUnix']); $stoppedTime = 0; $stoppedPercentage = round(($deviceData['timeIdle'] * 100) / ($deviceData['fixUnix'] - $deviceData['firstFixUnix'])); $movingTimePercentage = round(100 - $stoppedPercentage); $ridersArray[$rider]['movingTime'] = $movingTime; $ridersArray[$rider]['movingTimeText'] = sec2elapsed($movingTime); $ridersArray[$rider]['timeIdleText'] = sec2elapsed($deviceData['timeIdle']); $ridersArray[$rider]['stoppedPercentage'] = $stoppedPercentage; $ridersArray[$rider]['movingTimePercentage'] = $movingTimePercentage; } //$ridersArray[$rider]['dateTimeUnix'] = $lastPingReport; $ridersArray[$rider]['address'] = $deviceData['address']; $ridersArray[$rider]['imei'] = $deviceData['imei']; $ridersArray[$rider]['deviceId'] = $deviceData['deviceId']; $ridersArray[$rider]['course'] = $deviceData['course']; $ridersArray[$rider]['finishTime'] = ''; // Start with a blanco finish time key value $finishTime = $deviceData['finished']; // Set the finish time in case a rider has a detected finish // In case of a finishOverrule (unix), update or set the finishTime variable if ($deviceData['finishOverrule']) { $finishTime = $deviceData['finishOverrule']; } if($finishTime) { // Apply any correction in case to the finish time if($deviceData['finishCorrection']) { $finishTime = $finishTime + intval($deviceData['finishCorrection']*60); } if($grouppedEvent) { $finishCheckpoint = $groupFinishCPs[$deviceData['groupId']]; } else { $finishCheckpoint = $finishCP; } if($startRandomTrackpoint && $startRandomTrackpointSameFinish) { $finishCheckpoint = 'CP_FIN_FORCED'; } // Check if there is a correction on the finish checkpoint, if so, apply here as a correction on the finish timestamp $cpCorrections = array(); if(isset($deviceData['cpCorrections'])) { $cpCorrections = json_decode($deviceData['cpCorrections'],true); } if(isset($cpCorrections[$finishCheckpoint]) && !empty($cpCorrections[$finishCheckpoint])) { $finishTime = $finishTime + ($cpCorrections[$finishCheckpoint] * 60); } // Push back the finished/overruled/corrected time into the ridersArray to sort upon. $ridersArray[$rider]['finishTime'] = $finishTime; // Push back the elapsed time $ridersArray[$rider]['finishTimeElapsed'] = $finishTime-$deviceData['firstFixUnix']; // Create a readable finish string $minutes = $ridersArray[$rider]['finishTimeElapsed'] / 60; $day = floor($minutes / 1440); $hour = floor(($minutes - $day * 1440) / 60); $min = floor($minutes - ($day * 1440) - ($hour * 60)); $ridersArray[$rider]['finishedInString'] = $day . " d " . $hour . " h " . $min . " m"; } /* Speed the new way */ $ridersArray[$rider]['speedJSON'] = $deviceData['speedJSON']; $speedJSON = json_decode($deviceData['speedJSON'], true); $ridersArray[$rider]['routeSpeed'] = 0; if(isset($speedJSON['rs'])) { $ridersArray[$rider]['routeSpeed'] = $speedJSON['rs']; } $ridersArray[$rider]['routeSpeedMoving'] = 0; if(isset($speedJSON['rsm'])) { $ridersArray[$rider]['routeSpeedMoving'] = $speedJSON['rsm']; } $ridersArray[$rider]['altitude'] = $deviceData['altitude']; $ridersArray[$rider]['elevation'] = $deviceData['elevation']; // We don't want to overwrite the tracktable var if( isset($trackTable) ) { $trackTable_elevation = $trackTable; if ($grouppedEvent) { $trackTable_elevation = $groupTrackTables[$deviceData['groupId']]; } } if( isset($trackTable_elevation) ) { $ridersArray[$rider]['totalElevation'] = $track_summary[$trackTable_elevation]['totalElevation']; } $ridersArray[$rider]['weather'] = $deviceData['weather']; $ridersArray[$rider]['city'] = $deviceData['city']; $ridersArray[$rider]['website'] = $deviceData['website']; // Distance switch depending on data $ridersArray[$rider]['onTrackStatusBoolean'] = false; if ( isset($trackTable) || $groupDistanceOnTrack) { if($groupDistanceOnTrack) { if ( isset($totalTrackDistanceGroup[$deviceData['groupId']]) ) { $ridersArray[$rider]['totalTrackDistance'] = $totalTrackDistanceGroup[$deviceData['groupId']]; $totalTrackDistance = $totalTrackDistanceGroup[$deviceData['groupId']]; } else { $ridersArray[$rider]['totalTrackDistance'] = 0; $totalTrackDistance = 0; } } else { $ridersArray[$rider]['totalTrackDistance'] = $totalTrackDistance; } if($startRandomTrackpoint) { if( empty(floatval($deviceData['distanceOnTrack'])-floatval($deviceData['firstDistanceOnTrack'])) ){ // if the distance on track happends to be zero, he's on the exact start point $deviceData['distanceOnTrack'] = abs( (floatval($deviceData['distanceOnTrack'])-floatval($deviceData['firstDistanceOnTrack']))); } else if ( floatval($deviceData['distanceOnTrack']) > floatval($deviceData['firstDistanceOnTrack']) ) { $deviceData['distanceOnTrack'] = abs( floatval($deviceData['distanceOnTrack'])-floatval($deviceData['firstDistanceOnTrack'])); } else { $deviceData['distanceOnTrack'] = abs( $totalTrackDistance - floatval($deviceData['firstDistanceOnTrack'])+floatval($deviceData['distanceOnTrack'])); } } if (($deviceData['distanceOnTrack'] != "false") && (!empty($deviceData['distanceOnTrack'])) || (!empty($deviceData['distanceOnTrackId']))) { $ridersArray[$rider]['onTrackStatus'] = "On Track"; $ridersArray[$rider]['onTrackStatusBoolean'] = true; $ridersArray[$rider]['onTrackDistance'] = $deviceData['distanceOnTrack']; if(!empty($totalTrackDistance)) { $ridersArray[$rider]['onTrackPercentage'] = round(((floatval($deviceData['distanceOnTrack']) / floatval($totalTrackDistance)) * 100), 2); } else { $ridersArray[$rider]['onTrackPercentage'] = 0; } if($deviceData['finished'] || $deviceData['finishOverrule']) { $deviceData['distanceOnTrack'] = $ridersArray[$rider]['totalTrackDistance']; } if( is_infinite($ridersArray[$rider]['onTrackPercentage']) || is_nan($ridersArray[$rider]['onTrackPercentage']) ) { // JSON Encode fails on INF values. $ridersArray[$rider]['onTrackPercentage'] = 0; } // push distance on track value into the totaldistance value for riders who are on track $ridersArray[$rider]['totalDistance'] = round((floatval($deviceData['distanceOnTrack']) * $correctionPercentage), 3); } else { $ridersArray[$rider]['onTrackStatus'] = "Off Track"; $ridersArray[$rider]['onTrackStatusBoolean'] = false; $ridersArray[$rider]['onTrackDistance'] = ''; // off track - no distance known - fallback on calculated distance } } /***********************/ /* FINISH RECALC */ /***********************/ if($finishTime || $deviceData['finishOverrule']) { // If the device is finished, we need to re-calculate a few final variables, based upon total track distance and/or corrections on finish time or finish overrule // First, check if finish time - firstfix is not zero, this happens if the rider finished on his start point by mistake, causing division by zero resulting in error 500 if(!empty($finishTime-$deviceData['firstFixUnix'])) { $speedJSON['rs'] = round($totalTrackDistance / (($finishTime-$deviceData['firstFixUnix'])/3600),2); // Route Speed } /* ROUTE SPEED RE-CALCULATION AFTER ADJUSTMENTS */ if(is_nan($speedJSON['rs'])){ $ridersArray[$rider]['rs'] = 0; } else { $ridersArray[$rider]['rs'] = $speedJSON['rs']; $ridersArray[$rider]['routeSpeed'] = $speedJSON['rs']; // legacy? } /* MOVING TIME RE-CALCULATION AFTER ADJUSTMENTS */ if($deviceData['finishCorrection']) { $movingTime = ($deviceData['fixUnix'] - $deviceData['firstFixUnix']) - $deviceData['timeIdle'] + ($deviceData['finishCorrection']*60); $stoppedTime = $deviceData['timeIdle']; $stoppedPercentage = round(($deviceData['timeIdle'] * 100) / ($deviceData['fixUnix'] - $deviceData['firstFixUnix'] + ($deviceData['finishCorrection']*60))); $movingTimePercentage = round(100 - $stoppedPercentage); $ridersArray[$rider]['movingTime'] = $movingTime; $ridersArray[$rider]['movingTimeText'] = sec2elapsed($movingTime); $ridersArray[$rider]['timeIdleText'] = sec2elapsed($deviceData['timeIdle']); $ridersArray[$rider]['stoppedPercentage'] = $stoppedPercentage; $ridersArray[$rider]['movingTimePercentage'] = $movingTimePercentage; // Recalculate with the finished distance on track (100%) and the adjusted moving time after the finish correction. We assume the correction is on moving time as he passes the finish. $speedJSON['rsm'] = round((floatval($deviceData['distanceOnTrack']) / floatval($movingTime / 3600)), 2); if(is_nan($speedJSON['rs'])){ $ridersArray[$rider]['rsm'] = 0; } else { $ridersArray[$rider]['rsm'] = $speedJSON['rsm']; $ridersArray[$rider]['routeSpeedMoving'] = $speedJSON['rsm']; // legacy? } } // Update the Speed JSON var after correcting the finish time. $ridersArray[$rider]['speedJSON'] = json_encode($speedJSON); } if ($debug) { $ridersArray[$rider]['riderName'] = $rider; } else { $ridersArray[$rider]['riderName'] = "Participant " . $deviceData['einsteinDeviceId']; if( isset($deviceData['nameExt']) && !empty($deviceData['nameExt']) ) { $ridersArray[$rider]['riderName'] = $deviceData['nameExt']; } } } if ($config_sortActive == 'cpCount') { if( isset($ridersArrayJsonFile[$rider]['cpCount']) && isset($ridersArrayJsonFile[$rider]['cpLastCP']) && !empty($ridersArrayJsonFile[$rider]['cpLastCP']) && isset($ridersArrayJsonFile[$rider]['cpLastHitUnix']) && !empty($ridersArrayJsonFile[$rider]['cpLastHitUnix'])){ $ridersArray[$rider]['cpCount'] = $ridersArrayJsonFile[$rider]['cpCount']; $ridersArray[$rider]['cpLastCP'] = $ridersArrayJsonFile[$rider]['cpLastCP']; $ridersArray[$rider]['cpLastHitUnix'] = $ridersArrayJsonFile[$rider]['cpLastHitUnix']; $ridersArray[$rider]['cpLastHitTimeSinceStart'] = $ridersArrayJsonFile[$rider]['cpLastHitTimeSinceStart']; } else { $ridersArray[$rider]['cpCount'] = 0; $ridersArray[$rider]['cpLastCP'] = ""; // default values if ($deviceData['scratched']) { if( is_int($deviceData['teamNumber']) ) { $ridersArray[$rider]['cpLastHitUnix'] = $deviceData['teamNumber'] * 100000; // bring down the scratchers } else { $ridersArray[$rider]['cpLastHitUnix'] = $deviceData['deviceId'] * 100000; // bring down the scratchers } } else { $number = $deviceData['teamNumber']; $length = 10; $string = substr(str_repeat(0, $length).$number, - $length); $ridersArray[$rider]['cpLastHitUnix'] = $string; } $sql = "SELECT cpName, MAX(id) as maxId FROM " . $dataEventTable . " WHERE cpName != 'nocp' AND imei = '" . $deviceData['imei'] . "' GROUP BY cpName"; $result = mysqli_query($conn, $sql); $row = array(); while($data = mysqli_fetch_assoc($result)){ $row[$data['cpName']] = $data; } if($grouppedEvent) { $finishCheckpoint = $groupFinishCPs[$deviceData['groupId']]; } else { $finishCheckpoint = $finishCP; } if($startRandomTrackpoint && $startRandomTrackpointSameFinish) { $finishCheckpoint = 'CP_FIN_FORCED'; } if(isset($cpOverrules)) { foreach ($cpOverrules as $key => $value) { $resArrSearch = array_search($key, array_column($row, 'cpName')); if(empty($resArrSearch)) { // The overrule checkpoint has not been checked before by the participant - add it to include $row[$key]['cpName'] = $key; } } } foreach ($row as $x => $cpData) { $sql2 = "SELECT rowID, deviceName, fixUnix, cpName, cpDistance FROM " . $dataEventTable . " WHERE cpName = '" . $cpData['cpName'] . "' AND imei = '" . $deviceData['imei'] . "' LIMIT 3"; if(isset($cpOverrules[$cpData['cpName']])) { $sql2 = "SELECT rowID, deviceName, fixUnix, '".$cpData['cpName']."' as cpName, 1 as cpDistance FROM " . $dataEventTable . " WHERE id = '" . $cpOverrules[$cpData['cpName']] . "'"; } $result2 = mysqli_query($conn, $sql2); $arr = array(); while ($data = mysqli_fetch_array($result2)) { $arr[] = $data; } // Sort to get the best match array_multisort( array_column($arr, 'cpDistance'), array_column($arr, 'fixUnix'), $arr); if( isset($arr) && !empty($arr) ){ $cpDataResult = $arr[array_key_first($arr)]; } else { $cpDataResult; } if ( isset($cpDataResult['fixUnix']) && !empty($cpDataResult['fixUnix']) ) { $cpName = $cpDataResult['cpName']; if ($cpDataResult['cpName'] == $finishCheckpoint) { // The clean finish time to start with $finishTime = $deviceData['finished']; if($deviceData['finishOverrule']) { $finishTime = $deviceData['finishOverrule']; } if($deviceData['finishCorrection']) { $finishTime = $finishTime + intval($deviceData['finishCorrection']*60); } $cpCorrections = array(); if(isset($deviceData['cpCorrections'])) { $cpCorrections = json_decode($deviceData['cpCorrections'],true); } } if( isset($checkpoints) ) { foreach ($checkpoints as $cpArr) { if( isset($cpArr['uniqueid']) ) { if($cpArr['uniqueid'] == $cpName) { if(!isset($cpArr['offset'])){ // if no offset, the offset is equal to the server. $cpArr['offset'] = $timezoneCorrection; } $timezone_offset_cp = $cpArr['offset'] - $timezoneCorrection; } } } if( isset($cpCorrections[$cpName]) && is_int(intval($cpCorrections[$cpName])) ) { $cpCorrection = $cpCorrections[$cpName] * 60; // Correction is in minutes, convert to seconds. } else { $cpCorrection = 0; } if(!isset($timezone_offset_cp)){ $timezone_offset_cp = 0; } $unixTime = $cpDataResult['fixUnix'] + $timezone_offset_cp + $cpCorrection; // Push back into row array $row[$x]['fixUnix'] = $unixTime; } } } // Sort on actual order from the manager usort($row, function($x, $y) { return $x['fixUnix'] <=> $y['fixUnix']; }); $cpCounter = 0; $cpCounter = count($row); // Defaults $ridersArray[$rider]['cpLastCP'] = ''; //$ridersArray[$rider]['cpLastHitUnix'] = ''; $lastCheckpointHit = end($row); if($lastCheckpointHit) { $ridersArray[$rider]['cpCount'] = $cpCounter; $ridersArray[$rider]['cpLastCP'] = $lastCheckpointHit['cpName']; $ridersArray[$rider]['cpLastHitUnix'] = $lastCheckpointHit['fixUnix']; } unset($row); unset($lastCheckpointHit); unset($cpCounter); } } if ($config_sortActive == 'cpScore') { // default values if ($deviceData['scratched']) { if( is_int($deviceData['teamNumber']) ) { $ridersArray[$rider]['cpLastHitUnix'] = $deviceData['teamNumber'] * 100000; // bring down the scratchers } else { $ridersArray[$rider]['cpLastHitUnix'] = $deviceData['deviceId'] * 100000; // bring down the scratchers } } else { $ridersArray[$rider]['cpLastHitUnix'] = $deviceData['teamNumber']; } $ridersArray[$rider]['cpScore'] = 0; $ridersArray[$rider]['cpLastCP'] = ""; // Get all checked checkpoints, no need to dive deep into timestamps, we just need to know which CP for the score. $cp_sql = "SELECT cpName, MAX(id) FROM " . $dataEventTable . " WHERE cpName != 'nocp' AND imei = '" . $ridersArray[$rider]['imei'] . "' GROUP BY cpName ORDER BY MAX(id)"; $cp_result = mysqli_query($conn, $cp_sql); $cp_checked_rider = array(); while ($data = mysqli_fetch_array($cp_result)) { $cp_checked_rider[] .= $data['cpName']; if( isset($checkpoint_values[$data['cpName']]) ) { $ridersArray[$rider]['cpScore'] = $ridersArray[$rider]['cpScore'] + $checkpoint_values[$data['cpName']]; } else { $ridersArray[$rider]['cpScore'] = $ridersArray[$rider]['cpScore'] + 0; } } $cpCounter = mysqli_num_rows($cp_result); $ridersArray[$rider]['cpCount'] = $cpCounter; if(empty($ridersArray[$rider]['cpScore'])){ $ridersArray[$rider]['cpScore'] = 0; } // If empty, set zero points. // Get latest CP hit: $last_cp_sql = "SELECT sub.* FROM ( SELECT cpName, cpDistance, fixUnix, fixTime FROM " . $dataEventTable . " WHERE cpName='".end($cp_checked_rider)."' AND imei = '" . $ridersArray[$rider]['imei'] . "' order by fixUnix ASC LIMIT 5) sub ORDER BY CAST(cpDistance as SIGNED INTEGER), fixUnix ASC LIMIT 1"; $last_cp_result = mysqli_query($conn, $last_cp_sql); while ($last_cpDataResult = mysqli_fetch_array($last_cp_result)) { $ridersArray[$rider]['cpLastCP'] = $last_cpDataResult['cpName']; $ridersArray[$rider]['cpLastHitUnix'] = $last_cpDataResult['fixUnix']; } } $i++; } else { //$sql_name = "SELECT * FROM " . $eventTable . "_rc WHERE imei = '" . $data['imei'] . "'"; //$resultName = mysqli_query($conn, $sql_name); //$deviceData = mysqli_fetch_assoc($resultName); $rider = preg_replace("/[^A-Za-z0-9]/", "", $deviceData['nameExt']); $randomOffset = rand(0, 1000) / 2000; if (!$deviceData['scratched']) { if($grouppedEvent && $groupColors[$deviceData['groupId']]){ $deviceData['color'] = $groupColors[$deviceData['groupId']]; // Groups get same color } } else { if ($deviceData['scratched'] == '4') { $deviceData['color'] = "#ff0000"; // Crew Color } else { $deviceData['color'] = "#000000"; // Scratched color } } if($grouppedEvent){ $startpointLat = $groupStartLocation[$deviceData['groupId']]['latitude']; $startpointLng = $groupStartLocation[$deviceData['groupId']]['longitude']; } $ridersArrayPreRace[$rider]['lastReport'] = 'Start '; $ridersArrayPreRace[$rider]['positionAbbrev'] = '-'; $ridersArrayPreRace[$rider]['teamNumber'] = '-'; if( isset($deviceData['teamNumber']) && !empty($deviceData['teamNumber']) ) { $ridersArrayPreRace[$rider]['teamNumber'] = $deviceData['teamNumber']; } $ridersArrayPreRace[$rider]['country'] = $deviceData['country']; $ridersArrayPreRace[$rider]['riderName'] = "Participant " . $deviceData['einsteinDeviceId']; if( isset($deviceData['nameExt']) && !empty($deviceData['nameExt']) ) { $ridersArrayPreRace[$rider]['riderName'] = $deviceData['nameExt']; } $ridersArrayPreRace[$rider]['riderNameClean'] = $rider; $ridersArrayPreRace[$rider]['riderColor'] = $deviceData['color']; $ridersArrayPreRace[$rider]['dtf'] = floatval(0); $ridersArrayPreRace[$rider]['dtfKM'] = floatval(0); $ridersArrayPreRace[$rider]['deviceId'] = $deviceData['einsteinDeviceId']; $ridersArrayPreRace[$rider]['preraceCheck'] = $deviceData['preraceCheck']; $ridersArrayPreRace[$rider]['startDelay'] = $deviceData['startDelay']; $ridersArrayPreRace[$rider]['startTimeUnix'] = $groupStartTimes[$deviceData['groupId']] + ($deviceData['startDelay']*60); if(empty($deviceData['groupId']) ) { $deviceData['groupId'] = '1'; } $ridersArrayPreRace[$rider]['groupId'] = $deviceData['groupId']; if( isset($groupFinishCPs)){ $ridersArrayPreRace[$rider]['groupFinish'] = $groupFinishCPs[$deviceData['groupId']]; } // Default start position. Overwrite in case of pre race dots, see below. $ridersArrayPreRace[$rider]['latitude'] = $startpointLat; $ridersArrayPreRace[$rider]['longitude'] = $startpointLng + ((($randomOffset - 0.5) / 350) * 1.1); if( isset($config_showDotsPreRace) && !empty($config_showDotsPreRace) ) { // Make the dot visible x minutes before the start of the participant $timeToStartParticipant = ($ridersArrayPreRace[$rider]['startTimeUnix'] - time()) /60; // in MINUTES if ($timeToStartParticipant <= $config_showDotsPreRace) { // 24 HRS before the race, show dots. $timeToRequest = $ridersArrayPreRace[$rider]['startTimeUnix']; $timeToRequest = $timeToRequest - ($config_showDotsPreRace*60); // Check if the array is made and filled, if so there is no need to call Traccar again. if( isset($traccar_data_array) && !empty($traccar_data_array) ) { } else { $traccar_data_array = array(); // Request al last known device positions at once from Traccer require_once './config/config.db.einstein.php'; $sql = "SELECT a.id as devices_deviceid, a.*, b.* FROM einstein2.tc_devices a LEFT JOIN einstein2.tc_positions b ON b.id = a.positionid WHERE lastupdate IS NOT NULL AND fixtime >= '".gmdate("Y-m-d\TH:i:s", $timeToRequest)."'"; $result_prerace = mysqli_query($einstein_conn, $sql); while ($device = $result_prerace->fetch_assoc()) { $traccar_data_array[$device['uniqueid']] = $device; } if($einstein_conn) { $einstein_conn->close(); } } // If there is data for this device, we are going to put the dot on the map. if( isset($traccar_data_array[$deviceData[1]]) && !empty($traccar_data_array[$deviceData[1]]) ) { $this_device = $traccar_data_array[$deviceData[1]]; // Why do I need to use 1 and don't I just have the imei field filled like in race mode? ??? $ridersArrayPreRace[$rider]['latitude'] = $this_device['latitude']; $ridersArrayPreRace[$rider]['longitude'] = $this_device['longitude']; } else { // If there is no data in the pre-race window, don't display at 0,0 and don't display at the start as it is confusion so unset the location. unset($ridersArrayPreRace[$rider]['latitude']); unset($ridersArrayPreRace[$rider]['longitude']); } } else { $ridersArrayPreRace[$rider]['latitude'] = $startpointLat; $ridersArrayPreRace[$rider]['longitude'] = $startpointLng + ((($randomOffset - 0.5) / 350) * 1.1); } } if(isset($groupHeaderLabels)){ $ridersArrayPreRace[$rider]['groupHeaderLabel'] = $groupHeaderLabels[$deviceData['groupId']]; } if(isset($groupHeaderMarkerLabels)) { $ridersArrayPreRace[$rider]['groupHeaderMarkerLabels'] = $groupHeaderMarkerLabels[$deviceData['groupId']]; } } } /************************************************/ /* Overall Ranking */ /************************************************/ $overallRidersArray = []; $overallFinishers = []; $overallNotFinishers = []; // Split finishers and non-finishers foreach ($ridersArray as $rider) { if($rider['scratched'] <= 1 ) { // Only use active riders and DNF in overall ranking, not DNS DSQ & Crew if (!empty($rider['finishTime'])) { $overallFinishers[$rider['riderNameClean']] = $rider; } else { $overallNotFinishers[$rider['riderNameClean']] = $rider; } } } // OVERALL SORTING -> FINISHERS $col = array_column( $overallFinishers, $config_sortFinished ); if($config_sortFinishedOrder == "SORT_DESC") { array_multisort($col, SORT_DESC, $overallFinishers ); } else { array_multisort($col, SORT_ASC, $overallFinishers ); } // OVERALL SORTING -> NON FINISHERS $col = array_column( $overallNotFinishers, $config_sortActive ); if($config_sortActiveOrder == "SORT_DESC") { array_multisort($col, SORT_DESC, $overallNotFinishers ); } else { array_multisort($col, SORT_ASC, $overallNotFinishers ); } // MERGE FINISHERS AND NON FINISHERS BACK TO OVERALL ARRAY $overallRidersArray = array_merge($overallFinishers, $overallNotFinishers); // Add rank and label to each participant and put back in the original ridersarray for further use $i = 1; foreach ($overallRidersArray as $rider) { $ridersArray[$rider['riderNameClean']]['position_overall'] = $i; $ends = array( 'th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th'); if (($i % 100) >= 11 && ($i % 100) <= 13) { $ridersArray[$rider['riderNameClean']]['position_overall_abbrev'] = $i . 'th'; } else { $ridersArray[$rider['riderNameClean']]['position_overall_abbrev'] = $i . $ends[$i % 10]; } $i++; } /*************************************************************/ /* Split Riders up in Group Arrays */ /*************************************************************/ $groupRidersArray = array(); foreach ($ridersArray as $key => $item) { $groupRidersArray[$item['groupId']][$key] = $item; } ksort($groupRidersArray, SORT_NUMERIC); // Splits riders into subarrays based on group ID $arr_counter = 1; foreach ($groupRidersArray as $ridersArray) { /************************************************/ /* Prepare Sort Array */ /************************************************/ // Main Arrays $finishers = []; $notFinishers = []; foreach ($ridersArray as $rider) { if (!empty($rider['finishTime'])) { $finishers[$rider['riderNameClean']] = $rider; } else { $notFinishers[$rider['riderNameClean']] = $rider; } } /************************************************/ /* Sort Finishers on time */ /************************************************/ $col = array_column( $finishers, $config_sortFinished ); if($config_sortFinishedOrder == "SORT_DESC") { array_multisort($col, SORT_DESC, $finishers ); } else { array_multisort($col, SORT_ASC, $finishers ); } /***********************************************************/ /* Sort on CP Count (Free Route) */ /***********************************************************/ if ($config_sortActive == 'cpCount') { $col_a = array_column( $notFinishers, 'cpCount' ); $col_b = array_column( $notFinishers, 'cpLastHitUnix' ); array_multisort($col_a, SORT_DESC, $col_b, SORT_ASC, $notFinishers ); } else if ($config_sortActive == 'cpScore') { /************************************************/ /* Sortin on CP Score */ /************************************************/ foreach ($notFinishers as $key => $value) { if( empty($value['cpLastHitUnix']) ) { $notFinishers['riderNameClean']['cpLastHitUnix'] = $value['teamNumber']; // If no CP's yet, keep sorting on start number $notFinishers['riderNameClean']['cpScore'] = 0; $notFinishers['riderNameClean']['cpLastCP'] = ""; } } $col_a = array_column( $notFinishers, 'cpScore' ); $col_b = array_column( $notFinishers, 'cpLastHitUnix' ); array_multisort($col_a, SORT_DESC, $col_b, SORT_ASC, $notFinishers ); } else { /************************************************/ /* Default Sorting */ /************************************************/ $col = array_column( $notFinishers, $config_sortActive ); if($config_sortActiveOrder == "SORT_DESC") { array_multisort($col, SORT_DESC, $notFinishers ); } else { array_multisort($col, SORT_ASC, $notFinishers ); } } /************************************************/ /* Merge Sorted Arrays */ /************************************************/ $ridersArray = array_merge($finishers, $notFinishers); /************************************************/ /* Drop DNS & Crew visually */ /************************************************/ foreach ($ridersArray as $rider) { if($rider['scratched'] == '2') { unset($ridersArray[ $rider['riderNameClean']]); // Remove DNS rider $ridersArray[ $rider['riderNameClean']] = $rider; // re-add crew DNS to array to make them drop in position visually } } foreach ($ridersArray as $rider) { if($rider['scratched'] == '4') { unset($ridersArray[ $rider['riderNameClean']]); // Remove crew rider $ridersArray[ $rider['riderNameClean']] = $rider; // re-add crew rider to array to make them drop in position visually } $arr_counter = $rider['groupId']; // HACK RADX } $groupRidersArray[$arr_counter] = $ridersArray; // put updated array back in group array $arr_counter++; } /********************************************/ /* Sort Pre-Race */ /********************************************/ $col = array_column( $ridersArrayPreRace, $config_sortPreRace ); if($config_sortPreRaceOrder == "SORT_DESC") { array_multisort($col, SORT_DESC, $ridersArrayPreRace ); } else { array_multisort($col, SORT_ASC, $ridersArrayPreRace ); } /************************************************/ /* Add ranking and data */ /************************************************/ $firstKey = array_key_first($groupRidersArray); if( isset($groupRidersArray[$firstKey]) ) { $leaderArray = array_shift(array_values($groupRidersArray[$firstKey])); // hack to focus on leader $leaderPosition = "" . $leaderArray['longitude'] . "," . $leaderArray['latitude'] . ""; } foreach ($groupRidersArray as $ridersArray) { $i = 1; $distanceLeader = 0; $distancePreviousParticipant = 0; foreach ($ridersArray as $rider) { // Distance to leader $distanceLeader = $ridersArray[array_key_first($ridersArray)]['totalDistance']; $distanceToLeader = round($distanceLeader-$rider['totalDistance'],2); $ridersArray[$rider['riderNameClean']]['distanceToLeader'] = $distanceToLeader; // Distance to next participant up ahead if($distancePreviousParticipant){ $distanceToNextParticipant = round($distancePreviousParticipant-$rider['totalDistance'],2); $ridersArray[$rider['riderNameClean']]['distanceToNextParticipant'] = $distanceToNextParticipant; } // ETA if(isset($rider['routeSpeedMoving'])) { //if ($rider['lastReportMins'] >= 1440){ if( isset($rider['totalTrackDistance']) ) { $distanceToGo = round($rider['totalTrackDistance']-$rider['totalDistance'],2); $eta_sec = calculate_eta($distanceToGo,$rider['routeSpeedMoving']); $eta = sec2elapsed($eta_sec); $eta = str_replace('0 d ', '', $eta); $eta = str_replace('00 h ', '', $eta); $ridersArray[$rider['riderNameClean']]['eta'] = $eta; $ridersArray[$rider['riderNameClean']]['eta_sec'] = $eta_sec; } //} } $ridersArray[$rider['riderNameClean']]['position'] = $i; $ends = array( 'th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th'); $arr_counter = $rider['groupId']; // HACK RADX if (($i % 100) >= 11 && ($i % 100) <= 13) { $ridersArray[$rider['riderNameClean']]['positionAbbrev'] = $i . 'th'; } else { $ridersArray[$rider['riderNameClean']]['positionAbbrev'] = $i . $ends[$i % 10]; } $ridersArrayRebuild[] = $ridersArray[$rider['riderNameClean']]; $groupRidersArray[$arr_counter] = $ridersArray; // Put updated array back in the group array. $distancePreviousParticipant = $rider['totalDistance']; unset($eta); $i++; } } if( isset($ridersArrayRebuild) ) { foreach ($ridersArrayRebuild as $value) { $ridersArrayRebuildNew[$value['riderNameClean']] = $value; } $ridersArray = $ridersArrayRebuildNew; // Rebuild the original riderArray again. } // get the leader array to be used on the replay iframe include $riderKeys = array_keys($ridersArray); $groupPreRaceRidersArray = array(); foreach ($ridersArrayPreRace as $key => $item) { $groupPreRaceRidersArray[$item['groupId']][$key] = $item; } ksort($groupPreRaceRidersArray, SORT_NUMERIC); ?>