diff --git a/modules/custom/labdoo_lib/labdoo_lib.module b/modules/custom/labdoo_lib/labdoo_lib.module index cb2545f..02fb1ed 100644 --- a/modules/custom/labdoo_lib/labdoo_lib.module +++ b/modules/custom/labdoo_lib/labdoo_lib.module @@ -159,6 +159,16 @@ function _update_hub($node) { * by querying an Internet service. Therefore, requires connectivity to the Internet. * To avoid all same [country, city] queries be mapped onto the same point, a small * random value is added to both latitude and longitude. + * Cache implementation: + * + * Implementation note: + * In order to avoid consuming to much network bandwidth and exhausting the Google API + * quota, this function uses a cache. The cache stores geolocation query results. + * + * To see the current status of the cache, run the following db command: + * mysql> SELECT cid FROM cache WHERE cid LIKE '%labdoo_lookup_coordinates%'; + * To clean the cash, run the following drush command: + * # drush php-eval "cache_clear_all('labdoo_lookup_coordinates', 'cache', TRUE);" * * @param string $country * Country code (e.g. us, de, ...) @@ -183,27 +193,34 @@ function _update_hub($node) { * */ function labdoo_lookup_coordinates($country, $city, &$lat, &$lon, $silent=True, $street="", $state="", $zip="", $accuracy=100) { - # There are various online services to pull the GPS - # coordinates of a location. Use one of them. + // Try to use the cached value if available $locationString = $street . "+" . $city . "+" . $zip . "+" . $country; - $query = str_replace(' ', '+', 'https://maps.googleapis.com/maps/api/geocode/json?address='.$locationString.'&key=AIzaSyA5kbnku56o714TnQC0cDz7LDHSO31_0iw'); - $mapQuery = drupal_http_request($query); - if(!property_exists($mapQuery, 'data')) { - if($silent == False) - drupal_set_message(t('Could not resolve coordinates from the given city and country names.'), 'warning', FALSE); - return -1; + if($cacheResult = cache_get('labdoo_lookup_coordinates'.$locationString)) { + $coordinates = $cacheResult->data; } - $mapQueryDecoded = drupal_json_decode($mapQuery->data); - if(!isset($mapQueryDecoded['results'][0])) { -// if($mapQueryDecoded['status'] == "OVER_QUERY_LIMIT") -// drupal_set_message(t('We have exceeded the daily request quota for computing the map. -// Please email Labdoo at contact@labdoo.org and send us the URL of i -// this page so we can take a look, thanks. The Labdoo Team'), $repeat=FALSE); - if($silent == False) - drupal_set_message(t('Could not resolve coordinates from the given city and country names.'), 'warning', FALSE); - return -1; + else { + $query = str_replace(' ', '+', 'https://maps.googleapis.com/maps/api/geocode/json?address='.$locationString.'&key=AIzaSyA5kbnku56o714TnQC0cDz7LDHSO31_0iw'); + $mapQuery = drupal_http_request($query); + if(!property_exists($mapQuery, 'data')) { + if($silent == False) + drupal_set_message(t('Could not resolve coordinates from the given city and country names.'), 'warning', FALSE); + return -1; + } + $mapQueryDecoded = drupal_json_decode($mapQuery->data); + if(!isset($mapQueryDecoded['results'][0])) { + if($mapQueryDecoded['status'] == "OVER_QUERY_LIMIT") + drupal_set_message(t('We have exceeded the daily request quota for computing the map. + Please email Labdoo at contact@labdoo.org and send us the URL of i + this page so we can take a look, thanks. The Labdoo Team'), $repeat=FALSE); + if($silent == False) + drupal_set_message(t('Could not resolve coordinates from the given city and country names.'), 'warning', FALSE); + return -1; + } + $coordinates = $mapQueryDecoded['results'][0]['geometry']['location']; + // Cache the value so we don't have to query the Google API again + cache_set('labdoo_lookup_coordinates'.$locationString, $coordinates, 'cache'); } - $coordinates = $mapQueryDecoded['results'][0]['geometry']['location']; + $lat = strval(floatval($coordinates['lat'])+rand(-1 * $accuracy, 1 * $accuracy)/100000); $lon = strval(floatval($coordinates['lng'])+rand(-1 * $accuracy, 1 * $accuracy)/100000); return 0; @@ -1951,6 +1968,10 @@ function labdoo_lib_compute_dootrip_edoovillages($nodeLoaded) { $edoovillagesCode = ""; $edoovillagesList = array(); foreach($edoovillageIds as $edoovillageId) { + if($edoovillageId == 0) + // A dootronic is assigned to this dootrip but has no + // edoovillage assigned, skip it. + continue; if(in_array($edoovillageId, $edoovillagesList)) continue; $edoovillagesList[] = $edoovillageId; @@ -3217,6 +3238,8 @@ function _labdoo_lib_user_num_dootrips($userId) { $query = $query . ") AS t GROUP BY entity_id HAVING count(*) >= " . $numberOfQueries; $result = db_query($query, $placeHolders); +// foreach($result as $item) +// labdoo_lib_print_array($item->entity_id); $num = $result->rowCount(); return($num); @@ -3341,17 +3364,17 @@ function _labdoo_lib_user_metrics($account = NULL) { // Compute carbon footprint (constants are taken from the Labdoo carbon footprint calculator) $footprintCarbon = $numDoojects * 18.59; - $footprintTrees = $numDoojects * 2; - $footprintGas = $numDoojects * 26.5; - $footprintPlastic = $numDoojects * 59; - $footprintWater = $numDoojects * 1500; - $footprintAluminum = $numDoojects * 270; - $footprintGold = $numDoojects * 0.22; - $footprintSilver = $numDoojects * 0.44; - $footprintPalladium = $numDoojects * 0.08; - $footprintCopper = $numDoojects * 0.3; - $footprintCobalt = $numDoojects * 0.065; - $footprintChemical = $numDoojects * 22; + $footprintTrees = $footprintCarbon / 18.59 * 2; + $footprintGas = $footprintCarbon / 18.59 * 26.5; + $footprintPlastic = $footprintCarbon / 18.59 * 59; + $footprintWater = $footprintCarbon / 18.59 * 1500; + $footprintAluminum = $footprintCarbon / 18.59 * 270; + $footprintGold = $footprintCarbon / 18.59 * 0.22; + $footprintSilver = $footprintCarbon / 18.59 * 0.44; + $footprintPalladium = $footprintCarbon / 18.59 * 0.08; + $footprintCopper = $footprintCarbon / 18.59 * 0.3; + $footprintCobalt = $footprintCarbon / 18.59 * 0.065; + $footprintChemical = $footprintCarbon / 18.59 * 22; $code = " My contributions diff --git a/modules/custom/lbd_dootrip/lbd_dootrip.module b/modules/custom/lbd_dootrip/lbd_dootrip.module index 91d09b5..4de668c 100644 --- a/modules/custom/lbd_dootrip/lbd_dootrip.module +++ b/modules/custom/lbd_dootrip/lbd_dootrip.module @@ -141,14 +141,14 @@ function lbd_dootrip_node_insert($node) { /** - * _calculate_dootrip_weight + * labdoo_calculate_dootrip_weight * * @param node $node * A dootrip node * @return A message indicating the weight of all the doojects associated with the dootrip * */ -function _calculate_dootrip_weight($node) { +function labdoo_calculate_dootrip_weight($node) { $weight = 0; $suffix = ""; $prefix = ""; @@ -174,10 +174,113 @@ function _calculate_dootrip_weight($node) { } if($weight == 0) - return t("Please update the weight of each individual dooject"); + return t("Please update the weight of each individual dootronic"); else return t($suffix . $weight . " Kgms" . $prefix); - return $weight; +} + + +/** + * Calculates the great-circle distance between two points, with + * the Vincenty formula. + * @param float $latitudeFrom Latitude of start point in [deg decimal] + * @param float $longitudeFrom Longitude of start point in [deg decimal] + * @param float $latitudeTo Latitude of target point in [deg decimal] + * @param float $longitudeTo Longitude of target point in [deg decimal] + * @param float $earthRadius Mean earth radius in [m] + * @return float Distance between points in [m] (same as earthRadius) + */ +function _vincentyGreatCircleDistance($latitudeFrom, + $longitudeFrom, + $latitudeTo, + $longitudeTo, + $earthRadius = 6371000) { + // convert from degrees to radians + $latFrom = deg2rad($latitudeFrom); + $lonFrom = deg2rad($longitudeFrom); + $latTo = deg2rad($latitudeTo); + $lonTo = deg2rad($longitudeTo); + + $lonDelta = $lonTo - $lonFrom; + $a = pow(cos($latTo) * sin($lonDelta), 2) + + pow(cos($latFrom) * sin($latTo) - sin($latFrom) * cos($latTo) * cos($lonDelta), 2); + $b = sin($latFrom) * sin($latTo) + cos($latFrom) * cos($latTo) * cos($lonDelta); + + $angle = atan2(sqrt($a), $b); + return $angle * $earthRadius; +} + + +/** + * _calculate_dootrip_distance + * + * @param node $node + * A dootrip node + * @return The traveling distance of the dootrip in Kms + * + */ +function _calculate_dootrip_distance($node) { + $srcLat = ""; + $srcLon = ""; + $dstLat = ""; + $dstLon = ""; + + $srcCity = labdoo_lib_get_field($node, 'field_origin_of_the_trip', 'node', 'city'); + $srcCity = preg_replace('/\s+/', '%20', $srcCity); + $srcCountry = labdoo_lib_get_field($node, 'field_origin_of_the_trip', 'node', 'country'); + $srcCountryLong = labdoo_country_code2name($srcCountry); + + $dstCity = labdoo_lib_get_field($node, 'field_destination_of_the_trip', 'node', 'city'); + $dstCity = preg_replace('/\s+/', '%20', $dstCity); + $dstCountry = labdoo_lib_get_field($node, 'field_destination_of_the_trip', 'node', 'country'); + $dstCountryLong = labdoo_country_code2name($dstCountry); + + if(labdoo_lookup_coordinates($srcCountry, $srcCity, $srcLat, $srcLon) < 0) + return t("[Not available this time, try again later]"); + if(labdoo_lookup_coordinates($dstCountry, $dstCity, $dstLat, $dstLon) < 0) + return t("[Not available this time, try again later]"); + + $distKms = round(_vincentyGreatCircleDistance($srcLat, $srcLon, $dstLat, $dstLon)/1000); + return $distKms; +} + + +/** + * labdoo_calculate_dootrip_distance + * + * @param node $node + * A dootrip node + * @return A message indicating the traveling distance of the dootrip + * + */ +function labdoo_calculate_dootrip_distance($node) { + return(strval(_calculate_dootrip_distance($node)) . " Kms"); +} + + +/** + * labdoo_calculate_dootrip_co2_savings + * + * @param node $node + * A dootrip node + * @return A message indicating the amount of CO2 emissions saved thanks to the dootrip + * + */ +function labdoo_calculate_dootrip_co2_savings($node) { + $dootronicWeightKgms = 2.5; // The dootronic weight field is not mandatory, so assume here a reasonable value + $CO2gramsPerKgmPerKm = 0.5; // See http://timeforchange.org/co2-emissions-shipping-goods + $numDootronics = 1; // If no dootronics assigned, use the smallest number + + $dootronics = field_get_items('node', $node, 'field_laptops'); + if(!empty($dootronics)) + $numDootronics = count($dootronics); + + $co2SavingsKgms = round($CO2gramsPerKgmPerKm * + $numDootronics * + $dootronicWeightKgms * + _calculate_dootrip_distance($node) / 1000, 1); + + return(strval($co2SavingsKgms) . t(" Kgms of CO2 emissions saved")); } diff --git a/modules/custom/lbd_visualize/lbd_visualize.module b/modules/custom/lbd_visualize/lbd_visualize.module index 92cb2f2..4b3f45a 100644 --- a/modules/custom/lbd_visualize/lbd_visualize.module +++ b/modules/custom/lbd_visualize/lbd_visualize.module @@ -54,7 +54,7 @@ function sanitizeStringForVisualization($unsanitizedText) { * * In order to scale up the computation of the dashboard (as the number of objects increase), * the code incorporates a cache. The cache stores results for both geolocation maps and - * tables and is indexed accross all possible dimensions of the dashboards: users, doojects, + * tables and is indexed across all possible dimensions of the dashboards: users, doojects, * dootrips, hubs, edoovillages. * * To see the current status of the cache, run the following db command: diff --git a/modules/features/labdoo_objects/labdoo_objects.features.field.inc b/modules/features/labdoo_objects/labdoo_objects.features.field.inc index 263f926..ea5d3b3 100644 --- a/modules/features/labdoo_objects/labdoo_objects.features.field.inc +++ b/modules/features/labdoo_objects/labdoo_objects.features.field.inc @@ -123,10 +123,9 @@ function labdoo_objects_field_default_fields() { 'display' => array( 'default' => array( 'label' => 'above', - 'module' => 'list', 'settings' => array(), - 'type' => 'list_default', - 'weight' => '17', + 'type' => 'hidden', + 'weight' => '21', ), 'node_gallery_node_thumbnail' => array( 'label' => 'above', @@ -155,7 +154,7 @@ function labdoo_objects_field_default_fields() { 'display_label' => 1, ), 'type' => 'options_onoff', - 'weight' => '21', + 'weight' => '23', ), ), ); @@ -252,6 +251,81 @@ function labdoo_objects_field_default_fields() { ), ); + // Exported field: 'node-dootrip-field_co2_savings_dootrip'. + $fields['node-dootrip-field_co2_savings_dootrip'] = array( + 'field_config' => array( + 'active' => '1', + 'cardinality' => '1', + 'deleted' => '0', + 'entity_types' => array(), + 'field_name' => 'field_co2_savings_dootrip', + 'foreign keys' => array(), + 'indexes' => array(), + 'locked' => '0', + 'module' => 'computed_field', + 'settings' => array( + 'code' => 'drupal_page_is_cacheable(FALSE); +$entity_field[0][\'value\'] = labdoo_calculate_dootrip_co2_savings($entity);', + 'database' => array( + 'data_default' => '', + 'data_index' => 0, + 'data_length' => '32', + 'data_not_NULL' => 0, + 'data_precision' => '10', + 'data_scale' => '2', + 'data_size' => 'normal', + 'data_type' => 'int', + ), + 'display_format' => 'drupal_page_is_cacheable(FALSE); +$display_output = $entity_field_item[\'value\'];', + 'recalculate' => 0, + 'store' => 0, + ), + 'translatable' => '0', + 'type' => 'computed', + ), + 'field_instance' => array( + 'bundle' => 'dootrip', + 'deleted' => '0', + 'description' => '', + 'display' => array( + 'default' => array( + 'label' => 'inline', + 'module' => 'computed_field', + 'settings' => array(), + 'type' => 'computed_field_plain', + 'weight' => '14', + ), + 'node_gallery_node_thumbnail' => array( + 'label' => 'above', + 'settings' => array(), + 'type' => 'hidden', + 'weight' => 0, + ), + 'teaser' => array( + 'label' => 'above', + 'settings' => array(), + 'type' => 'hidden', + 'weight' => 0, + ), + ), + 'entity_type' => 'node', + 'field_name' => 'field_co2_savings_dootrip', + 'label' => 'CO2 emissions savings', + 'required' => 0, + 'settings' => array( + 'user_register_form' => FALSE, + ), + 'widget' => array( + 'active' => 0, + 'module' => 'computed_field', + 'settings' => array(), + 'type' => 'computed', + 'weight' => '16', + ), + ), + ); + // Exported field: 'node-dootrip-field_comments'. $fields['node-dootrip-field_comments'] = array( 'field_config' => array( @@ -290,7 +364,7 @@ function labdoo_objects_field_default_fields() { 'module' => 'text', 'settings' => array(), 'type' => 'text_default', - 'weight' => '15', + 'weight' => '17', ), 'node_gallery_node_thumbnail' => array( 'label' => 'above', @@ -320,7 +394,7 @@ function labdoo_objects_field_default_fields() { 'rows' => '3', ), 'type' => 'text_textarea', - 'weight' => '17', + 'weight' => '19', ), ), ); @@ -659,6 +733,81 @@ function labdoo_objects_field_default_fields() { ), ); + // Exported field: 'node-dootrip-field_distance_dootrip'. + $fields['node-dootrip-field_distance_dootrip'] = array( + 'field_config' => array( + 'active' => '1', + 'cardinality' => '1', + 'deleted' => '0', + 'entity_types' => array(), + 'field_name' => 'field_distance_dootrip', + 'foreign keys' => array(), + 'indexes' => array(), + 'locked' => '0', + 'module' => 'computed_field', + 'settings' => array( + 'code' => 'drupal_page_is_cacheable(FALSE); +$entity_field[0][\'value\'] = labdoo_calculate_dootrip_distance($entity);', + 'database' => array( + 'data_default' => '', + 'data_index' => 0, + 'data_length' => '32', + 'data_not_NULL' => 0, + 'data_precision' => '10', + 'data_scale' => '2', + 'data_size' => 'normal', + 'data_type' => 'int', + ), + 'display_format' => 'drupal_page_is_cacheable(FALSE); +$display_output = $entity_field_item[\'value\'];', + 'recalculate' => 0, + 'store' => 0, + ), + 'translatable' => '0', + 'type' => 'computed', + ), + 'field_instance' => array( + 'bundle' => 'dootrip', + 'deleted' => '0', + 'description' => '', + 'display' => array( + 'default' => array( + 'label' => 'inline', + 'module' => 'computed_field', + 'settings' => array(), + 'type' => 'computed_field_plain', + 'weight' => '13', + ), + 'node_gallery_node_thumbnail' => array( + 'label' => 'above', + 'settings' => array(), + 'type' => 'hidden', + 'weight' => 0, + ), + 'teaser' => array( + 'label' => 'above', + 'settings' => array(), + 'type' => 'hidden', + 'weight' => 0, + ), + ), + 'entity_type' => 'node', + 'field_name' => 'field_distance_dootrip', + 'label' => 'Travel distance', + 'required' => 0, + 'settings' => array( + 'user_register_form' => FALSE, + ), + 'widget' => array( + 'active' => 0, + 'module' => 'computed_field', + 'settings' => array(), + 'type' => 'computed', + 'weight' => '15', + ), + ), + ); + // Exported field: 'node-dootrip-field_dootrip_additional_editors'. $fields['node-dootrip-field_dootrip_additional_editors'] = array( 'field_config' => array( @@ -711,7 +860,7 @@ function labdoo_objects_field_default_fields() { 'label' => 'hidden', 'settings' => array(), 'type' => 'hidden', - 'weight' => '18', + 'weight' => '19', ), 'node_gallery_node_thumbnail' => array( 'label' => 'above', @@ -798,7 +947,7 @@ function labdoo_objects_field_default_fields() { 'size' => '60', ), 'type' => 'entityreference_autocomplete', - 'weight' => '19', + 'weight' => '21', ), ), ); @@ -829,7 +978,7 @@ function labdoo_objects_field_default_fields() { 'label' => 'hidden', 'settings' => array(), 'type' => 'hidden', - 'weight' => '19', + 'weight' => '20', ), 'node_gallery_node_thumbnail' => array( 'label' => 'above', @@ -968,7 +1117,7 @@ function labdoo_objects_field_default_fields() { 'label' => 'above', 'settings' => array(), 'type' => 'hidden', - 'weight' => '20', + 'weight' => '22', ), 'node_gallery_node_thumbnail' => array( 'label' => 'above', @@ -998,7 +1147,7 @@ function labdoo_objects_field_default_fields() { 'rows' => '5', ), 'type' => 'text_textarea', - 'weight' => '22', + 'weight' => '24', ), ), ); @@ -1017,7 +1166,7 @@ function labdoo_objects_field_default_fields() { 'module' => 'computed_field', 'settings' => array( 'code' => 'drupal_page_is_cacheable(FALSE); -$entity_field[0][\'value\'] = _calculate_dootrip_weight($entity);', +$entity_field[0][\'value\'] = labdoo_calculate_dootrip_weight($entity);', 'database' => array( 'data_default' => '', 'data_index' => 0, @@ -1030,7 +1179,7 @@ $entity_field[0][\'value\'] = _calculate_dootrip_weight($entity);', ), 'display_format' => 'drupal_page_is_cacheable(FALSE); $display_output = $entity_field_item[\'value\'];', - 'recalculate' => FALSE, + 'recalculate' => 0, 'store' => 0, ), 'translatable' => '0', @@ -1266,7 +1415,7 @@ $display_output = $entity_field_item[\'value\'];', 'module' => 'computed_field', 'settings' => array(), 'type' => 'computed_field_unsanitized', - 'weight' => '14', + 'weight' => '16', ), 'node_gallery_node_thumbnail' => array( 'label' => 'above', @@ -1293,7 +1442,7 @@ $display_output = $entity_field_item[\'value\'];', 'module' => 'computed_field', 'settings' => array(), 'type' => 'computed', - 'weight' => '20', + 'weight' => '22', ), ), ); @@ -1904,7 +2053,7 @@ $display_output = $entity_field_item[\'value\'];', 'link' => 1, ), 'type' => 'entityreference_label', - 'weight' => '13', + 'weight' => '15', ), 'node_gallery_node_thumbnail' => array( 'label' => 'above', @@ -1940,7 +2089,7 @@ $display_output = $entity_field_item[\'value\'];', 'size' => '120', ), 'type' => 'entityreference_autocomplete', - 'weight' => '15', + 'weight' => '17', ), ), ); @@ -2010,7 +2159,7 @@ $display_output = $entity_field_item[\'value\'];', 'module' => 'options', 'settings' => array(), 'type' => 'options_select', - 'weight' => '16', + 'weight' => '18', ), ), ); @@ -6671,6 +6820,7 @@ See wiki page on dootrips notifications for more details.'); t('Comments'); @@ -6736,6 +6886,7 @@ See