Skip to content

Commit

Permalink
- Implemented calculation of CO2 emissions saved from dootrips
Browse files Browse the repository at this point in the history
- Added two new fields in the dootrip object: distance and CO2 savings
- Implemented geolocation cache
  • Loading branch information
jrosgiralt committed Mar 27, 2017
1 parent cda5ef6 commit 34b7429
Show file tree
Hide file tree
Showing 6 changed files with 334 additions and 55 deletions.
81 changes: 52 additions & 29 deletions modules/custom/labdoo_lib/labdoo_lib.module
Expand Up @@ -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, ...)
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 = "
<strong><font color='red'>My contributions</font></strong>
Expand Down
111 changes: 107 additions & 4 deletions modules/custom/lbd_dootrip/lbd_dootrip.module
Expand Up @@ -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 = "";
Expand All @@ -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"));
}


Expand Down
2 changes: 1 addition & 1 deletion modules/custom/lbd_visualize/lbd_visualize.module
Expand Up @@ -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:
Expand Down

0 comments on commit 34b7429

Please sign in to comment.