private static function equivalencyInfo() { $items = array(array('field' => 'activity_calories', 'unit' => 'cupcake', 'prefix' => t('Our community burnt')), array('field' => 'activity_calories', 'unit' => 'huskydogs', 'prefix' => t('Our community burnt')), array('field' => 'activity_calories', 'unit' => 'gallonofgas', 'prefix' => t('Our community burnt')), array('field' => 'activity_duration', 'unit' => 'fortnight', 'prefix' => t('Our community recorded')), array('field' => 'activity_duration', 'unit' => 'dogyear', 'prefix' => t('Our community recorded')), array('field' => 'activity_distance', 'unit' => 'furlong', 'prefix' => t('Our community travelled')), array('field' => 'activity_distance', 'unit' => 'tripmoon', 'prefix' => t('Our community travelled')), array('field' => 'activity_distance', 'unit' => 'tripearth', 'prefix' => t('Our community travelled')), array('field' => 'activity_distance', 'unit' => 'nauticalmile', 'prefix' => t('Our community travelled'))); $valid = false; $message = null; $value = null; while (!$valid && count($items) > 0) { shuffle($items); $message = array_pop($items); if (!empty($message['field'])) { $query = db_select('node', 'n'); $query->innerJoin(OpenFitActivity::TABLE_NODE_ACTIVITY_ASSOC, 'na', 'n.nid = na.nid'); $query->innerJoin(OpenFitActivity::TABLE_ACTIVITY, 'a', 'a.activity_id = na.activity_id'); $query->innerJoin(OpenFitActivity::TABLE_ACTIVITY_CATEGORY, 'c', 'a.activity_category_id = c.category_id'); $query->addExpression('SUM(a.' . $message['field'] . ')', 'value'); $value = $query->execute()->fetchField(); $value = empty($value) ? 0 : round($value) * 9; $value = OpenFitMeasurement::convert($value, null, $message['unit'], OpenFitMeasurement::FORMAT_TYPE_LABEL); $value_split = preg_split('/\\s/', $value); if (intval(preg_replace('/\\D/', '', $value_split[0])) >= 1) { $valid = true; } } } if (!$valid) { return ''; } return $message['prefix'] . ' ' . $value . '.'; }
private static function exportTcx($activity) { $info = $activity->openfit_info; $utc = new DateTimeZone('UTC'); $filename = str_replace(' ', '_', $info['activity']->activity_start) . '.tcx'; header("Content-Type: text/tcx/force-download"); header("Content-Disposition: attachment; filename={$filename}"); $startTime = new DateTime($info['activity']->activity_start, $utc); $reader = new ActivityDataTrackReader($info['activity']->activity_id, 'full'); $supportedTracks = array(ActivityDataTrackAccess::LOCATION, ActivityDataTrackAccess::ELEVATION, ActivityDataTrackAccess::DISTANCE, ActivityDataTrackAccess::HEARTRATE); $data = $reader->readTracks($supportedTracks); //find the start and end times for each lap. Do some formatting $lap_times = array(); $laps = array(); foreach ($info['laps'] as $lap_num => $lap) { $time = new DateTime($info['laps'][$lap_num]->lap_start, $utc); $lap->lap_calories = intval(OpenFitMeasurement::convert($lap->lap_calories, null, OpenFitMeasurement::MEASUREMENT_CALORIE)); $lap->lap_start = $time->format('Y-m-d\\TH:i:s\\Z'); $lap->points = array(); $laps[$lap_num] = $lap; $endTime = clone $time; $lap_times[$lap_num] = array($time, $endTime->add(new DateInterval('PT' . intval($info['laps'][$lap_num]->lap_duration) . 'S'))); } //Store hash counters in array to allow for multiple single-timestamp points $counters = array(); foreach ($data as $type => $track) { $iter = new OpenFitTrackIterator($track, $startTime); $current_lap = array_shift(array_keys($laps)); foreach ($iter as $offsetS => $value) { $time = clone $startTime; $time->add(new DateInterval('PT' . $offsetS . 'S')); if (is_object($time)) { $formatted_time = $time->format('Y-m-d\\TH:i:s\\Z'); //Ensure point is inside some lap, figure out which one if so if ($time > $lap_times[$current_lap][1]) { if (isset($lap_times[$current_lap + 1])) { if ($time > $lap_times[$current_lap + 1][0]) { ++$current_lap; //Advance lap } else { continue; //Drop point } } else { continue; //Drop point } } else { if ($time < $lap_times[$current_lap][0]) { throw new RuntimeException("Something went wrong, time: " . $time->format('Y-m-d\\TH:i:s\\Z') . ' is before start of lap.'); } } //Handles sequentiality for non-timestamped data if (isset($laps[$current_lap]->points[$formatted_time]) && isset($laps[$current_lap]->points[$formatted_time][$type])) { if (!isset($counters[$formatted_time])) { $counters[$formatted_time] = 1; } $formatted_time = $formatted_time . $counters[$formatted_time]; $counters[$formatted_time]++; } if (isset($laps[$current_lap]->points[$formatted_time])) { $laps[$current_lap]->points[$formatted_time][$type] = $value; } else { $laps[$current_lap]->points[$formatted_time] = array($type => $value, 'time' => $formatted_time); } } } } //For debugging purposes, //probably won't matter that points aren't in proper order when really exporting. foreach (array_keys($laps) as $lap_num) { ksort($laps[$lap_num]->points); } //die(print_r($laps, true)); $out = new XMLWriter(); $out->openURI('php://output'); $out->startDocument('1.0', 'UTF-8', 'no'); $out->setIndent(true); $out->setIndentString(' '); $out->startElement('TrainingCenterDatabase'); $out->writeAttribute('xsi:schemaLocation', 'http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd'); $out->writeAttribute('xmlns', 'http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2'); $out->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); $out->startElement('Activities'); $out->startElement('Activity'); $out->writeAttribute('Sport', $info['activity']->category_name); $out->writeElement('Id', $startTime->format('Y-m-d\\TH:i:s\\Z')); if (!empty($info['activity']->activity_notes)) { $out->writeElement('Notes', $info['activity']->activity_notes); } foreach ($laps as $lap_num => $lap) { $out->startElement('Lap'); $out->writeAttribute('StartTime', $lap->lap_start); $out->writeElement('TotalTimeSeconds', $lap->lap_duration); $out->writeElement('DistanceMeters', $lap->lap_distance); //$out->writeElement('MaximumSpeed', $lap->lap_max_speed); $out->writeElement('Calories', $lap->lap_calories); $out->startElement('AverageHeartRateBpm'); $out->writeAttribute('xsi:type', 'HeartRateInBeatsPerMinute_t'); $out->writeElement('Value', $lap->lap_avg_heartrate); $out->endElement(); $out->startElement('MaximumHeartRateBpm'); $out->writeAttribute('xsi:type', 'HeartRateInBeatsPerMinute_t'); $out->writeElement('Value', $lap->lap_max_heartrate); $out->endElement(); $out->writeElement('Intensity', ucwords(strtolower($lap->lap_type))); $out->startElement('Track'); foreach ($lap->points as $point) { $out->startElement('Trackpoint'); $out->writeElement('Time', $point['time']); if (isset($point[ActivityDataTrackAccess::LOCATION])) { $out->startElement('Position'); $out->writeElement('LatitudeDegrees', $point[ActivityDataTrackAccess::LOCATION][1]); $out->writeElement('LongitudeDegrees', $point[ActivityDataTrackAccess::LOCATION][2]); $out->endElement(); } if (isset($point[ActivityDataTrackAccess::ELEVATION])) { $out->writeElement('AltitudeMeters', $point[ActivityDataTrackAccess::ELEVATION]); } if (isset($point[ActivityDataTrackAccess::DISTANCE])) { $out->writeElement('DistanceMeters', $point[ActivityDataTrackAccess::DISTANCE]); } if (isset($point[ActivityDataTrackAccess::HEARTRATE])) { $out->startElement('HeartRateBpm'); $out->writeAttribute('xsi:type', 'HeartRateInBeatsPerMinute_t'); $out->writeElement('Value', $point[ActivityDataTrackAccess::HEARTRATE]); $out->endElement(); } $out->endElement(); } $out->endElement(); $out->endElement(); } $out->endElement(); $out->endElement(); $out->endElement(); $out->endDocument(); $out->flush(); }