Exemplo n.º 1
0
 function viewUpload()
 {
     $form = new SessionUploadForm();
     $view = Core_View::factory('sessionsfileupload');
     $view->UploadStatusMsg = "";
     $view->UploadStatus = "Error";
     if ($form->validate()) {
         $timer = new Benchmark_Timer();
         $timer->start();
         $upload = $form->getSubmitValue('upload');
         $timer->setMarker('Decode Sessions - Start');
         exec('/usr/local/bin/fitdecode -s ' . $upload['tmp_name'], $xml_session);
         $xml_session = implode("\n", $xml_session);
         $sessions = parseSessions($xml_session);
         $timer->setMarker('Decode Sessions - End');
         /* There should only be one session */
         if (is_array($sessions)) {
             $session = $sessions[0];
             unset($sessions);
         }
         $db = Zend_Registry::get('db');
         $db->beginTransaction();
         try {
             $api = new Module_Sessions_API();
             /* Insert the session data into the database */
             $api->createSessionFull($session->start_time, 'E1', 'Untitled', $session->total_timer_time, $session->total_distance, $session->total_calories, $session->avg_heart_rate, $session->max_heart_rate, $session->avg_speed, $session->max_speed, $session->total_ascent, $session->total_descent, '');
             /* Find the seconds since epoch so we can do simple maths */
             $ftime = strptime($session->start_time, '%FT%T%z');
             $session_epoch = mktime($ftime['tm_hour'], $ftime['tm_min'], $ftime['tm_sec'], 1, $ftime['tm_yday'] + 1, $ftime['tm_year'] + 1900);
             $session_timestamp = $session->start_time;
             unset($session);
             unset($sessions);
             $timer->setMarker('Decode Records - Start');
             exec('/usr/local/bin/fitdecode -r ' . $upload['tmp_name'], $xml_records);
             $xml_records = implode("\n", $xml_records);
             $records_input = parseRecords($xml_records, $session_epoch);
             $timer->setMarker('Decode Records - End');
             if (is_array($records_input)) {
                 $record_prev = $records_input[0];
             }
             /* Get the array of records, removing duplicates */
             $records = array();
             foreach ($records_input as $record) {
                 if (!isset($record_last) || $record_last->interval != $record->interval) {
                     $records[] = $record;
                 }
                 $record_last = $record;
             }
             unset($records_input);
             unset($record_last);
             $UserAPI = Module_UserManagement_API::getInstance();
             $user = $UserAPI->getUser();
             /* Add the matching data points */
             foreach ($records as $record) {
                 /* Skip duplicates, they will cause issues in graphs */
                 if (!isset($record->power)) {
                     $record->power = $api->getPower($record->gradient, $record->temperature, $record->altitude, $record->speed, $record->speed - $record_prev->speed, $record->interval - $record_prev->interval, $user['rider_weight'], $user['bike_weight']);
                 }
                 $record_prev = $record;
             }
             unset($user);
             unset($UserAPI);
             $timer->setMarker('Record insertion - start');
             $api->insertAllSessionData($session_timestamp, $records);
             /* Insert all the data */
             $timer->setMarker('Record insertion - end');
             /* Calculate the climbs */
             $climbs = $api->getClimbCategories();
             $timer->setMarker('Climb - Start');
             $min_climb = $climbs[0];
             /* 500m with an average gradient of more than 3% (cat 5)*/
             /* Find the points that have a distance of 500m */
             $window_distance = 0;
             $window_altitude = 0;
             $cat = -1;
             $climb_num = 1;
             $num_records = count($records);
             $num_climbs = count($climbs);
             for ($front = 0, $back = 0; $front < $num_records; $front++) {
                 $window_distance += $records[$front]->delta_distance * 1000;
                 $window_altitude += $records[$front]->delta_altitude;
                 if ($window_distance > $min_climb['min_distance']) {
                     $window_gradient = $window_altitude / $window_distance * 100;
                     /* Check if we have found the start of a climb */
                     if ($cat == -1 && $window_gradient >= $climbs[$cat + 1]['min_gradient']) {
                         $cat++;
                         /* Go through and find the minimum height */
                         $min = $back;
                         for ($i = $back; $i < $front; $i++) {
                             if ($records[$i]->altitude <= $records[$min]->altitude) {
                                 $min = $i;
                             }
                         }
                         $climb['bottom'] = $records[$min]->interval;
                         $climb['min_altitude'] = $records[$min]->altitude;
                     }
                     /* Check if we have finished the climb */
                     if ($cat != -1 && $window_gradient < $climbs[$cat]['min_gradient']) {
                         /* Need to go back and find the maximum altitude */
                         $max = $back;
                         for ($i = $back; $i < $front; $i++) {
                             if ($records[$i]->altitude > $records[$max]->altitude) {
                                 $max = $i;
                             }
                         }
                         $climb['top'] = $records[$max]->interval;
                         $climb['max_altitude'] = $records[$max]->altitude;
                         /* Get the max gradient */
                         $climb['gradient_max'] = $records[$min]->gradient;
                         for ($i = $min; $i <= $max; $i++) {
                             if ($climb['gradient_max'] < $records[$i]->gradient) {
                                 $climb['gradient_max'] = $records[$i]->gradient;
                             }
                         }
                         /* Tally the totals */
                         $climb['total_climbed'] = 0;
                         for ($i = $min + 1; $i <= $max; $i++) {
                             $climb['total_climbed'] += $records[$i]->delta_altitude;
                         }
                         $climb['total_distance'] = round($records[$max]->distance - $records[$min]->distance, 2);
                         $climb['gradient_avg'] = round($climb['total_climbed'] / ($climb['total_distance'] * 1000) * 100, 2);
                         /* Find the category of the climb */
                         $cat = -1;
                         while ($cat + 1 < $num_climbs && $climb['gradient_avg'] >= $climbs[$cat + 1]['min_gradient'] && $climb['total_distance'] * 1000 >= $climbs[$cat + 1]['min_distance'] && $climb['total_climbed'] >= $climbs[$cat + 1]['min_height']) {
                             $cat++;
                         }
                         $climb['cat'] = $cat;
                         if ($cat != -1) {
                             /* Store it into the database */
                             $api->insertClimb($session_timestamp, $climb_num++, $climb['bottom'], $climb['top'], $climb['gradient_avg'], $climb['gradient_max'], $climb['total_distance'], $climb['total_climbed'], $climb['min_altitude'], $climb['max_altitude']);
                             /* Start search for the next climb */
                             $front = $max;
                             $back = $max;
                             $window_distance = 0;
                             $window_altitude = 0;
                         } else {
                             /* It was a false climb, either not steep enough, 
                              * too short, and the window just masked this 
                              * Keep searching for the next climb
                              */
                         }
                         $cat = -1;
                     }
                     /* Move the back of the window up */
                     while ($window_distance > $min_climb['min_distance'] && $back < $num_records) {
                         $window_distance -= $records[$back]->delta_distance * 1000;
                         $window_altitude -= $records[$back]->delta_altitude;
                         $back++;
                     }
                 }
             }
             $timer->setMarker('Climb - End');
             /*
              * Bikes
              * userid
              * name
              * description
              * type, TT or Road
              * weight
              * picture?
              * Assign a bike to an exercise session at creation time?
              */
             unset($records);
             $timer->setMarker('Laps - Start');
             exec('/usr/local/bin/fitdecode -l ' . $upload['tmp_name'], $xml_laps);
             $xml_laps = implode("\n", $xml_laps);
             $laps = parseLaps($xml_laps);
             $timer->setMarker('Laps - End');
             $lap_num = 1;
             foreach ($laps as $lap) {
                 $ftime = strptime($lap->start_time, '%FT%T%z');
                 $start_epoch = mktime($ftime['tm_hour'], $ftime['tm_min'], $ftime['tm_sec'], 1, $ftime['tm_yday'] + 1, $ftime['tm_year'] + 1900);
                 $lap_start = $start_epoch - $session_epoch;
                 $api->insertLap($session_timestamp, $lap_num, $lap_start, $lap->start_position_lat, $lap->start_position_long, $lap->total_timer_time, $lap->total_elapsed_time, $lap->total_calories, $lap->avg_heart_rate, $lap->max_heart_rate, $lap->avg_speed, $lap->max_speed, $lap->total_ascent, $lap->total_descent, $lap->total_distance);
                 $lap_num++;
             }
             //$timer->display();
             $db->commit();
             $plans = Module_Plans_API::getInstance();
             $view->planned = $plans->getClosestPlan($session_timestamp);
             $view->session_timestamp = $session_timestamp;
             $view->UploadStatusMsg = "Is this session the planned exercise session on at ere";
             $view->UploadStatus = "Success";
         } catch (Exception $e) {
             $db->rollback();
             $view->UploadStatusMsg = "Failed to upload";
             $view->UploadStatus = "Error";
             echo $e->getMessage();
         }
         $timer->display();
     }
     $view->addForm($form);
     $view->subTemplate = 'genericForm.tpl';
     echo $view->render();
 }
Exemplo n.º 2
0
function scifinderToRefbase($sourceText, $importRecordsRadio, $importRecordNumbersArray)
{
    global $alnum, $alpha, $cntrl, $dash, $digit, $graph, $lower, $print, $punct, $space, $upper, $word, $patternModifiers;
    // defined in 'transtab_unicode_charset.inc.php' and 'transtab_latin1_charset.inc.php'
    global $errors;
    global $showSource;
    // The SciFinder format uses variable-length field label names, which makes it
    // impossible to match field labels using regular expressions with perl-style
    // look-behinds (such as '(?<=...)'). This poses a problem when specifying an
    // appropriate regex pattern for variable '$dataDelimiter'. Therefore, we'll
    // preprocess the '$sourceText' so that delimiters between field labels and
    // field data can be easily matched.
    $sourceText = preg_replace("/^(FIELD [^:\r\n]+):/m", "\\1__dataDelimiter__", $sourceText);
    // replace the first colon (":"), which separates a field label from its data, with a custom string ("__dataDelimiter__")
    // Define regular expression patterns that will facilitate parsing of SciFinder data:
    // (patterns must be specified as perl-style regular expression, without the leading & trailing slashes, if not stated otherwise)
    // Pattern by which the input text will be split into individual records:
    $recordDelimiter = "\\s*(START_RECORD[\r\n]+|[\r\n]+END_RECORD)\\s*";
    // Pattern by which records will be split into individual fields:
    $fieldDelimiter = "[\r\n]+FIELD *";
    // Pattern by which fields will be split into their field label (tag) and field data:
    $dataDelimiter = " *__dataDelimiter__ *";
    // Pattern by which multiple persons are separated within the author, editor or series editor fields of the source data:
    // (Notes: - name standardization occurs after multiple author fields have been merged by '; '
    //         - the split pattern must be specified as perl-style regular expression (including the leading & trailing
    //           slashes) and may include mode modifiers (such as '/.../i' to perform a case insensitive match))
    $personDelimiter = "/ *; */";
    // Pattern by which a person's family name is separated from the given name (or initials):
    // (the split pattern must be specified as perl-style regular expression (including the leading & trailing
    //  slashes) and may include mode modifiers (such as '/.../i' to perform a case insensitive match))
    $familyNameGivenNameDelimiter = "/ *, */";
    // Specifies whether the person's family name comes first within a person's name
    // ('true' means that the family name is followed by the given name (or initials), 'false' means that the person's family name comes *after* the given name (or initials))
    $familyNameFirst = true;
    // Specifies whether a person's full given name(s) shall be shortened to initial(s):
    // (Notes: - if set to 'true', given names will be abbreviated and initials will get normalized (meaning removal of extra whitespace, adding of dots between initials, etc)
    //         - if set to 'false', given names (and any initials) are taken as is
    //         - in your database, you should stick to either fully written given names OR initials; if you mix these, records won't get sorted correctly on citation output)
    $shortenGivenNames = true;
    // Specifies whether fields whose contents are entirely in upper case shall be transformed to title case ('true') or not ('false'):
    $transformCase = true;
    // Preprocessor actions:
    // Defines search & replace 'actions' that will be applied to each record's raw source data if the pattern in the corresponding 'match' element is matched:
    // (If you don't want to perform any preprocessor actions, specify an empty array, like: '$preprocessorActionsArray = array();'.
    //  Note that, in this case, the search patterns MUST include the leading & trailing slashes -- which is done to allow for mode modifiers such as 'imsxU'.)
    // 								  "/Search Pattern/"  =>  "Replace Pattern"
    $preprocessorActionsArray = array();
    // Postprocessor actions:
    // Defines search & replace 'actions' that will be applied to all those refbase fields that are listed in the corresponding 'fields' element:
    // (If you don't want to perform any search and replace actions, specify an empty array, like: '$postprocessorActionsArray = array();'.
    //  Note that, in this case, the search patterns MUST include the leading & trailing slashes -- which is done to allow for mode modifiers such as 'imsxU'.)
    // 								  "/Search Pattern/"  =>  "Replace Pattern"
    $postprocessorActionsArray = array(array('fields' => array("year"), 'actions' => array("/^.*?(\\d{4}).*/" => "\\1", "/^\\D+\$/" => "")), array('fields' => array("pages"), 'actions' => array("/(\\d+ *pp?)\\./" => "\\1")), array('fields' => array("title", "address"), 'actions' => array("/[,.;:!] *\$/" => "", "/,(?! )/" => ", ")), array('fields' => array("abstract"), 'actions' => array('/\\\\"/' => '"', "/ *\\[on SciFinder \\(R\\)\\]\$/" => "")), array('fields' => array("language"), 'actions' => array("/^[{$lower}{$punct} ]+(?=[{$upper}][{$lower}]+)/{$patternModifiers}" => "", "/language unavailable/" => "", "/[{$punct}] *\$/{$patternModifiers}" => "")), array('fields' => array("notes"), 'actions' => array("/^Can (\\d+)/" => "CAN:\\1", "/^(\\d+)/" => "CAN:\\1")));
    // This array lists patterns which match all SciFinder tags that must occur within a record to be recognized as valid SciFinder record:
    // (Array keys must contain the tag name as it should be displayed to the user; as is the case with search & replace actions,
    //  the search patterns MUST include the leading & trailing slashes.)
    // 				"tag display name"  =>  "tag search pattern"
    $requiredTagsArray = array("Document Type" => "/^FIELD Document Type/m");
    // This array matches SciFinder tags with their corresponding refbase fields:
    // (fields that are unsupported in either SciFinder or refbase are commented out)
    // 													  "SciFinder tag" => "refbase field" // SciFinder tag name (comment)
    $tagsToRefbaseFieldsArray = array("Document Type" => "type", "Author" => "author", "Corporate Source" => "address", "Title" => "title", "Publication Year" => "year", "Publication Date" => "year", "Journal Title" => "publication", "Volume" => "volume", "Issue" => "issue", "Page" => "pages", "Internat.Standard Doc. Number" => array("Book, Section" => "isbn", "Book, Edited" => "isbn", "Book" => "isbn", "Dissertation" => "isbn", "Dissertation/Thesis" => "isbn", "Other" => "issn"), "Language" => "language", "Index Terms" => "keywords", "Abstract" => "abstract", "URL" => "url", "Chemical Abstracts Number(CAN)" => "notes");
    // This array lists all SciFinder tags that may occur multiple times:
    $tagsMultipleArray = array("Publication Year", "Publication Date");
    // This array matches SciFinder reference types with their corresponding refbase types:
    // (SciFinder types that are currently not supported in refbase will be taken as is but will get
    //  prefixed with an "Unsupported: " label; '#fallback#' in comments indicates a type mapping that
    //  is not a perfect match but as close as currently possible)
    // (NOTE: the commented reference types are NOT from SciFinder but are remains from the 'refworksToRefbase()' function!)
    // 																 "SciFinder type"  =>  "refbase type" // name of SciFinder reference type (comment)
    $referenceTypesToRefbaseTypesArray = array("Book(;.*)?" => "Book Whole", "Journal(;.*)?" => "Journal Article", "Report(;.*)?" => "Report", "Preprint" => "Manuscript");
    // Other SciFinder Document Types which I've encountered so far:
    //											"General Review"                       =>  "" // General Review
    //											"Online Computer File"                 =>  "" // Online Computer File
    // -----------------------------------------
    // Split input text into individual records:
    $recordArray = splitSourceText($sourceText, $recordDelimiter, false);
    // split on the "START_RECORD"/"END_RECORD" tags that delimit every SciFinder record
    // Validate all records that shall be imported:
    list($errors, $importRecordNumbersRecognizedFormatArray, $importRecordNumbersNotRecognizedFormatArray) = validateRecords($recordArray, $requiredTagsArray, $importRecordsRadio, $importRecordNumbersArray, $errors);
    // Parse all records that shall be imported:
    list($parsedRecordsArray, $recordsCount) = parseRecords($recordArray, "SciFinder", $importRecordNumbersRecognizedFormatArray, $tagsToRefbaseFieldsArray, $tagsMultipleArray, $referenceTypesToRefbaseTypesArray, $fieldDelimiter, $dataDelimiter, $personDelimiter, $familyNameGivenNameDelimiter, $familyNameFirst, $shortenGivenNames, $transformCase, $postprocessorActionsArray, $preprocessorActionsArray);
    // Build refbase import array:
    $importDataArray = buildImportArray("refbase", "1.0", "http://refbase.net/import/scifinder/", "Matthias Steffens", "*****@*****.**", array('prefix_call_number' => "true"), $parsedRecordsArray);
    // 'records' - array of record(s) (with each record being a sub-array of fields)
    return array($importDataArray, $recordsCount, $importRecordNumbersRecognizedFormatArray, $importRecordNumbersNotRecognizedFormatArray, $errors);
}