Files
endurain/frontend/inc/func/activities-funcs.php
2023-12-01 23:02:18 +00:00

446 lines
16 KiB
PHP

<?php
/* ************************************************************************** */
/* Activies */
/* ************************************************************************** */
/* Get all activities */
function getActivities(){
$response = callAPIRoute("/activities/all", 1, 0, NULL);
if ($response[0] === false) {
return -1;
} else {
if ($response[1] === 200) {
return json_decode($response[0], true);
} else {
return -2;
}
}
}
/* Get user activities */
function getUserActivities(){
$response = callAPIRoute("/activities/useractivities", 1, 0, NULL);
if ($response[0] === false) {
return -1;
} else {
if ($response[1] === 200) {
return json_decode($response[0], true);
} else {
return -2;
}
}
}
/* Get user activities */
function getUserActivitiesThisWeekDistances($userID){
$response = callAPIRoute("/activities/useractivities/$userID/thisweek/distances", 0, 0, NULL);
if ($response[0] === false) {
return -1;
} else {
if ($response[1] === 200) {
return json_decode($response[0], true);
} else {
return -2;
}
}
}
/* Get all gear activities */
function getGearActivities($gearID){
$response = callAPIRoute("/activities/gear/$gearID", 1, 0, NULL);
if ($response[0] === false) {
return -1;
} else {
if ($response[1] === 200) {
return json_decode($response[0], true);
} else {
return -2;
}
}
}
/* Get all activities with pagination */
function getActivitiesPagination($pageNumber, $numRecords){
$response = callAPIRoute("/activities/all/pagenumber/$pageNumber/numRecords/$numRecords", 1, 0, NULL);
if ($response[0] === false) {
return -1;
} else {
if ($response[1] === 200) {
return json_decode($response[0], true);
} else {
return -2;
}
}
}
/* Get user activities with pagination */
function getUserActivitiesPagination($pageNumber, $numRecords){
$response = callAPIRoute("/activities/useractivities/pagenumber/$pageNumber/numRecords/$numRecords", 1, 0, NULL);
if ($response[0] === false) {
return -1;
} else {
if ($response[1] === 200) {
return json_decode($response[0], true);
} else {
return -2;
}
}
}
/* Get number of activities */
function numActivities(){
$response = callAPIRoute("/activities/all/number", 0, 0, NULL);
if ($response[0] === false) {
return -1;
} else {
if ($response[1] === 200) {
$data = json_decode($response[0], true);
return $data[0];
} else {
return -2;
}
}
}
/* Get user number of activities */
function numUserActivities(){
$response = callAPIRoute("/activities/useractivities/number", 0, 0, NULL);
if ($response[0] === false) {
return -1;
} else {
if ($response[1] === 200) {
$data = json_decode($response[0], true);
return $data[0];
} else {
return -2;
}
}
}
/* Get gear from id */
function getActivityFromId($id){
$response = callAPIRoute("/activities/$id/activityfromid", 1, 0, NULL);
if ($response[0] === false) {
return -1;
} else {
if ($response[1] === 200) {
return json_decode($response[0], true);
} else {
return -2;
}
}
}
/* adds gear_id to activity */
function addGearToActivity($activityID, $gearID){
$response = callAPIRoute("/activities/$activityID/addgear/$gearID", 0, 3, NULL);
if ($response[0] === false) {
return -1;
} else {
if ($response[1] === 200) {
return 0;
} else {
return -2;
}
}
}
/* Creates a new activity */
function newActivity($distance, $name, $type, $starttime, $endtime, $town, $country, $city, $waypoints, $elevationGain, $elevationLoss, $pace, $averageSpeed, $averagePower, $strava_id){
$response = callAPIRoute("/activities/create", 0, 4, json_encode(array(
'distance' => $distance,
'name' => $name,
'type' => $type,
'starttime' => $starttime,
'endtime' => $endtime,
'city' => $city,
'town' => $town,
'country' => $country,
'waypoints' => $waypoints,
'elevationGain' => $elevationGain,
'elevationLoss' => $elevationLoss,
'pace' => $pace,
'averageSpeed' => $averageSpeed,
'averagePower' => $averagePower,
'strava_id' => $strava_id,
)));
if ($response[0] === false) {
return -1;
} else {
if ($response[1] === 200) {
return 0;
// $data = json_decode($response[0], true);
// if (isset($data['id'])) {
// return $data['id']; // Return the activity ID.
// } else {
// return -2; // Response doesn't contain the ID.
// }
} else {
return -2;
}
}
}
function parseActivityGPX($gpx_file){
try {
$xml = simplexml_load_file($gpx_file);
if ($xml === false) {
throw new Exception("Invalid GPX file or could not load the file.");
}
if ((string)$xml['creator'] != 'StravaGPX' && (string)$xml['creator'] != 'Garmin Connect') {
return -5;
}
// Extract metadata
$activityType = (string)($xml->trk->type ?? "Workout"); // Extract activity type
$activityName = (string)($xml->trk->name ?? "Workout" ); // Extract activity name
$distance = 0; // Initialize total distance to 0
$firstWaypointTime = null; // Variable to store the first waypoint time
$lastWaypointTime = null; // Variable to store the last waypoint time
$city = null; // Variable to store the last waypoint time
$town = null; // Variable to store the last waypoint time
$country = null; // Variable to store the last waypoint time
$processOneTimeFields = 0;
$elevationGain = 0;
$elevationLoss = 0;
$pace = 0;
// Extract the start time from metadata
#$startTime = (string)$xml->metadata->time;
$waypoints = [];
$prevLatitude = null;
$prevLongitude = null;
// Iterate through track segments and track points
foreach ($xml->trk->trkseg->trkpt as $point) {
$latitude = (float)$point['lat'];
$longitude = (float)$point['lon'];
if ($prevLatitude !== null && $prevLongitude !== null) {
// Calculate distance between waypoints (Haversine formula) and add to total distance
$distance += calculateDistance($prevLatitude, $prevLongitude, $latitude, $longitude);
}
$elevation = (float)$point->ele;
// You can access other data like time, heart rate, cadence, etc. from the extensions as needed
$time = (string)$point->time;
// Store the first and last waypoint times
if ($firstWaypointTime === null) {
$firstWaypointTime = $time;
}
// Store the town and country
if($processOneTimeFields == 0){
$url = "https://geocode.maps.co/reverse?lat=$latitude&lon=$longitude";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
try {
$response = curl_exec($ch);
#echo $response;
if ($response !== false) {
// Parse the JSON response
$data = json_decode($response);
#echo $data;
// Extract the town and country from the address components
if(isset($data->address->city)){
$city = (string)$data->address->city;
}
if(isset($data->address->town)){
$town = (string)$data->address->town;
}
if(isset($data->address->country)){
$country = (string)$data->address->country;
}
}
} catch (Exception $e) {
echo "An error occurred: " . $e->getMessage();
}
curl_close($ch);
$processOneTimeFields = 1;
}
if ((string)$xml['creator'] === 'StravaGPX') {
$heartRate = (int)$point->extensions->children('gpxtpx', true)->TrackPointExtension->hr;
$cadence = (int)$point->extensions->children('gpxtpx', true)->TrackPointExtension->cad;
}else{
$heartRate = (int)$point->extensions->children('ns3', true)->TrackPointExtension->hr;
$cadence = (int)$point->extensions->children('ns3', true)->TrackPointExtension->cad;
}
$power = (int)$point->extensions->power;
$instantSpeed = (float)calculateInstantSpeed($lastWaypointTime, $time, $latitude, $longitude, $prevLatitude, $prevLongitude);
if ($instantSpeed > 0) {
$instantPace = 1/$instantSpeed; // Calculate instant pace in s/m
} else {
$instantPace = 0; // Avoid division by zero for points with zero speed
}
$waypoints[] = [
'lat' => $latitude,
'lon' => $longitude,
'ele' => $elevation,
'time' => $time,
'hr' => $heartRate,
'cad' => $cadence,
'power' => $power,
'vel' => $instantSpeed,
'pace' => $instantPace,
];
// Update previous latitude and longitude for the next iteration
$prevLatitude = $latitude;
$prevLongitude = $longitude;
$lastWaypointTime = $time;
}
$elevationData = calculateElevationGainLoss($waypoints);
$elevationGain = $elevationData['elevationGain'];
$elevationLoss = $elevationData['elevationLoss'];
$pace = calculatePace($distance, $firstWaypointTime, $lastWaypointTime);
$averageSpeed = calculateAverageSpeed($distance, $firstWaypointTime, $lastWaypointTime);
$averagePower = calculateAveragePower($waypoints);
return newActivity(intval(number_format($distance, 0, '', '')), $activityName, $activityType, $firstWaypointTime, $lastWaypointTime, $town, $country, $city, $waypoints, $elevationGain, $elevationLoss, number_format($pace,10), number_format($averageSpeed,10), $averagePower, null);
} catch (Exception $e) {
// Handle the exception
#echo "Error: " . $e->getMessage();
// You can log the error, redirect the user, or take appropriate action.
return -4;
}
}
// Function to calculate distance
function calculateDistance($lat1, $lon1, $lat2, $lon2) {
// The radius of the Earth in meters (mean value)
$earthRadius = 6371000; // 6,371 km = 6,371,000 meters
// Convert latitude and longitude from degrees to radians
$lat1 = deg2rad($lat1);
$lon1 = deg2rad($lon1);
$lat2 = deg2rad($lat2);
$lon2 = deg2rad($lon2);
// Haversine formula
$latDiff = $lat2 - $lat1;
$lonDiff = $lon2 - $lon1;
$a = sin($latDiff / 2) * sin($latDiff / 2) + cos($lat1) * cos($lat2) * sin($lonDiff / 2) * sin($lonDiff / 2);
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
$distance = $earthRadius * $c;
return $distance;
}
// Add this function to calculate elevation gain and loss
function calculateElevationGainLoss($waypoints) {
$elevationGain = 0;
$elevationLoss = 0;
$prevElevation = null;
foreach ($waypoints as $waypoint) {
$elevation = $waypoint['ele'];
if ($prevElevation !== null) {
$elevationChange = $elevation - $prevElevation;
if ($elevationChange > 0) {
$elevationGain += $elevationChange;
} else {
$elevationLoss -= $elevationChange;
}
}
$prevElevation = $elevation;
}
return ['elevationGain' => $elevationGain, 'elevationLoss' => $elevationLoss];
}
// Add this function to calculate pace
function calculatePace($distance, $firstWaypointTime, $lastWaypointTime) {
// Convert the time strings to DateTime objects
$startDateTime = new DateTime($firstWaypointTime);
$endDateTime = new DateTime($lastWaypointTime);
// Calculate the time difference in seconds
$totalTimeInSeconds = $endDateTime->getTimestamp() - $startDateTime->getTimestamp();
// Calculate pace in seconds per meter
$paceInSecondsPerMeter = $totalTimeInSeconds / $distance;
return $paceInSecondsPerMeter;
}
function calculateInstantSpeed($prevTime, $time, $latitude, $longitude, $prevLatitude, $prevLongitude) {
$timeCalc = new DateTime($time);
$prevTimeCalc = new DateTime($prevTime);
if ($prevTimeCalc !== null) {
$timeDifference = $timeCalc->getTimestamp() - $prevTimeCalc->getTimestamp();
if ($timeDifference > 0) {
$distance = calculateDistance($prevLatitude, $prevLongitude, $latitude, $longitude);
$instantSpeed = $distance / $timeDifference;
}
}
return $instantSpeed; // output in m/s
}
function calculateAverageSpeed($distance, $firstWaypointTime, $lastWaypointTime) {
// Convert the time strings to DateTime objects
$startDateTime = new DateTime($firstWaypointTime);
$endDateTime = new DateTime($lastWaypointTime);
// Calculate the time difference in seconds
$totalTimeInSeconds = $endDateTime->getTimestamp() - $startDateTime->getTimestamp();
// Calculate average speed in meters per second
$averageSpeed = $distance / $totalTimeInSeconds;
return $averageSpeed;
}
function calculateAveragePower($waypoints) {
$totalPower = 0;
$numDataPoints = count($waypoints);
foreach ($waypoints as $waypoint) {
$totalPower += $waypoint['power'];
}
if ($numDataPoints > 0) {
$averagePower = $totalPower / $numDataPoints;
return $averagePower;
} else {
return 0; // Avoid division by zero in case of no data points
}
}
/* Unset activity gear */
function unsetActivityGear($id){
$response = callAPIRoute("/activities/$id/deletegear", 0, 3, NULL);
if ($response[0] === false) {
return -1;
} else {
if ($response[1] === 200) {
return 0;
} else {
return -2;
}
}
}
/* Deletes an activity based on its ID */
function deleteActivity($id){
$response = callAPIRoute("/activities/$id/delete", 0, 1, NULL);
if ($response[0] === false) {
return -1;
} else {
if ($response[1] === 200) {
return 0;
} else {
return -2;
}
}
}