829 lines
36 KiB
PHP
829 lines
36 KiB
PHP
<?php
|
|
|
|
class MultiModalApi extends Api
|
|
{
|
|
public $apiName = 'multimodal';
|
|
const CACHE_TIMEOUT = 1800; // 30 minutes
|
|
|
|
public function indexAction() {
|
|
syslog(LOG_WARNING,'MultiModalApi::indexAction()');
|
|
// 16279
|
|
$message = "Unexpected error";
|
|
$leg_id = $this->requestParams["leg_id"] ?? 0;
|
|
$country = $this->requestParams["country"] ?? 'SG';
|
|
$member_id = $this->requestParams["member_id"] ?? 0;
|
|
$advice_id = 0;
|
|
try {
|
|
if ($leg_id<1) {
|
|
throw new Exception('Invalid trip leg ID');
|
|
}
|
|
$db = new Db();
|
|
list ($leg, $err) = MultiModal::getLegById($db->getConnect(), (int)$leg_id);
|
|
if (!$leg || !isset($leg['id']) || $leg['id']<1) {
|
|
throw new Exception($err!=""?$err:'No trip leg found');
|
|
}
|
|
syslog(LOG_WARNING,'111111111');
|
|
list ($advice, $err) = MultiModal::getLegAdviceGoogleById($db->getConnect(), (int)$leg['parsedemail_item_advice_google_id']);
|
|
if ($advice && $advice['id']>0) {
|
|
$advice_id = $advice['id'];
|
|
} else {
|
|
throw new Exception($err!=""?$err:'No google advice found');
|
|
}
|
|
// DEBUG
|
|
$country = Geocode::mockGPSCountry($db->getConnect(), $member_id, $country, 'default');
|
|
|
|
list ($legs, $err) = MultiModal::getAdviceLegs($db->getConnect(), $advice_id);
|
|
return MultiModalApi::processLegs($db, $legs, $advice_id, $country);
|
|
} catch (Exception $e) {
|
|
syslog(LOG_WARNING,json_encode($e));
|
|
$message = $e->getMessage();
|
|
}
|
|
return $this->response(
|
|
array(
|
|
'error' => $message
|
|
), 500);
|
|
}
|
|
|
|
protected function processSteps($db, $leg, $ok) {
|
|
list ($steps, $err) = MultiModal::getLegSteps($db->getConnect(), (int)$leg['id']);
|
|
if ($steps || count($steps)>0) {
|
|
$total = 0;
|
|
$overview = [];
|
|
foreach ($steps as $key=>$step) {
|
|
$leg['step_fares'][$step['sid']] = NULL;
|
|
// We support BUS, SUBWAY, TAXI only (and Singapore...)
|
|
if ($step['travel_mode']=='TAXI' || $step['travel_mode']=='SCOOTER' ||
|
|
($step['travel_mode']=='TRANSIT' && isset($step['vehicle']) &&
|
|
($step['vehicle']='BUS' || $step['vehicle']=='SUBWAY'))) {
|
|
if (isset($step['fare_raw']) && $step['fare_raw']!="") {
|
|
// OK
|
|
$total += (int)$step['fare_raw'];
|
|
$leg['step_fares'][$step['sid']] = (int)$step['fare_raw'];
|
|
} else {
|
|
// Not OK
|
|
$ok = false;
|
|
error_log('No quote for step_id='.$step['sid'].' traveling by '.(isset($step['vehicle'])?$step['vehicle']:"NO VEHICLE"));
|
|
}
|
|
} else {
|
|
error_log('Unsupported travel mode: '.$step['travel_mode']."/".(isset($step['vehicle'])?$step['vehicle']:"NO VEHICLE"));
|
|
}
|
|
if (array_key_exists("polyline",$step)) {
|
|
$overview[] = $step["polyline"];
|
|
}
|
|
if (!array_key_exists('duration',$step) || $step['duration']<60) {
|
|
$step['duration'] = 60;
|
|
}
|
|
$steps[$key] = $step;
|
|
}
|
|
if ($leg['fare_raw']!=$total && $total>0) {
|
|
error_log('Leg #'.$leg['id'].' total ('.$leg['fare_raw'].') != calculated ('.$total.')');
|
|
$leg['fare_raw'] = $total;
|
|
}
|
|
if (count($overview)>0) {
|
|
require_once('../common/Polyline.php');
|
|
$leg["polyline"] = MultiModal::processPolyline($overview);
|
|
}
|
|
} else {
|
|
error_log('No steps found for leg #'.$leg['id']);
|
|
}
|
|
return [$leg, $ok, $steps];
|
|
}
|
|
|
|
/**
|
|
* Method GET
|
|
* Get single record (by id)
|
|
* http://DOMAIN/multimodal/1
|
|
* @return string
|
|
*/
|
|
public function viewAction() {
|
|
//id must be the first parameter after /multimodal/x
|
|
$id = array_shift($this->requestUri);
|
|
|
|
if($id && (int)$id>0){
|
|
$db = new Db();
|
|
$tripOptions = Trips::getOptionsById($db->getConnect(), (int)$id);
|
|
if(is_array($tripOptions) && count($tripOptions)>0) {
|
|
/*$tripOptions = ActivityApi::processQuotesTripMultimodalOptions(
|
|
$db, $member_id, $country, $tripOptions);*/
|
|
return $this->response(
|
|
array(
|
|
'id' => $id,
|
|
'count' => count($tripOptions),
|
|
'options' => $tripOptions
|
|
), 200);
|
|
}
|
|
}
|
|
return $this->response(
|
|
array(
|
|
'error'=> 'Data not found'
|
|
), 404);
|
|
}
|
|
|
|
public function createAction() {
|
|
syslog(LOG_WARNING,'MultiModalApi::createAction()');
|
|
$message = "Failed to run multi-modal router";
|
|
$origin = $this->requestParams["origin"] ?? 0;
|
|
$destination = $this->requestParams["destination"] ?? 0;
|
|
$country = $this->requestParams["country"] ?? 'SG';
|
|
$no_cache = $this->requestParams["no_cache"] ?? false;
|
|
$member_id = $this->requestParams["member_id"] ?? 0;
|
|
$cache_timeout = $this->requestParams["cache_timeout"] ?? MultiModalApi::CACHE_TIMEOUT;
|
|
$distance = $this->requestParams["distance"] ?? 0;
|
|
$duration = $this->requestParams["duration"] ?? 0;
|
|
|
|
try {
|
|
$db = new Db();
|
|
|
|
// DEBUG
|
|
$country = Geocode::mockGPSCountry($db->getConnect(), $member_id, $country, 'default');
|
|
|
|
// Check country
|
|
if ($country!='SG' && $country!='US') {
|
|
throw new RuntimeException('Trips has not yet launched in your country. You can still track your travel activity and access exclusive deals. Start exploring!',500);
|
|
}
|
|
// Check input
|
|
$addrOrigin = Address::getAddressById($db->getConnect(), (int)$origin);
|
|
$addrDestination = Address::getAddressById($db->getConnect(), (int)$destination);
|
|
if ($addrOrigin==NULL || $addrDestination==NULL) {
|
|
throw new Exception('Invalid origin and/or destination address');
|
|
}
|
|
|
|
$checkOptions = [
|
|
[
|
|
"type"=>1,
|
|
"geocode" => [
|
|
"lat" => $addrOrigin["latitude"],
|
|
"lng" => $addrOrigin["longitude"]
|
|
]
|
|
]
|
|
];
|
|
syslog(LOG_WARNING,'MultiModalApi: '.json_encode($checkOptions));
|
|
$withinTheServiceArea = GeocodeApi::checkWithinTheServiceArea($country, $checkOptions, false);
|
|
if ($withinTheServiceArea) {
|
|
syslog(LOG_WARNING,'MultiModalApi: WITHIN SERVICE AREA!');
|
|
$trip = MultiModalApi::multimodal(
|
|
$db, $addrOrigin, $addrDestination, $country, $no_cache, $member_id, $cache_timeout, $distance, $duration
|
|
);
|
|
} else {
|
|
// Trip format
|
|
syslog(LOG_WARNING,'MultiModalApi: IS NOT WITHIN SERVICE AREA!');
|
|
$trip = ActivityApi::createTrip($db, $country, $duration, $distance, $addrOrigin["id"], $addrDestination["id"]);
|
|
}
|
|
|
|
/******* Start GOJEK ******/
|
|
//$trip = MultiModalApi::processGojekOption($db, $member_id, $country, $trip);
|
|
/******* End GOJEK ******/
|
|
if ($country=='US') {
|
|
$trip = MultiModalApi::processRidesharesOption($db, $member_id, $country, $trip);
|
|
}
|
|
|
|
if ($trip && count($trip)) {
|
|
$trip = MultiModalFilter::sortTrip($trip);
|
|
return $this->response($trip, 200);
|
|
} else {
|
|
$message = "Failed to process multimodal trip";
|
|
}
|
|
} catch (Exception $e) {
|
|
error_log(json_encode($e));
|
|
$message = $e->getMessage();
|
|
}
|
|
return $this->response(
|
|
array(
|
|
"error" => $message
|
|
), 500);
|
|
}
|
|
|
|
public static function processGojekOption($db, $member_id, $country, $trip) {
|
|
$trips = ActivityApi::processGojekOption($db, $member_id, $country, [
|
|
[
|
|
'trip' => $trip
|
|
]
|
|
]);
|
|
$n = count($trips) - 1;
|
|
if ($n>0 && array_key_exists('rideshare',$trips[$n]) && is_array($trips[$n]['rideshare']) && count($trips[$n]['rideshare'])>10) {
|
|
$gojek = $trips[$n]['rideshare'];
|
|
$options = $gojek['options'];
|
|
$leg = $options['legs'][0];
|
|
$leg_fare = $options['leg_fare'][$leg['id']];
|
|
$leg_steps = $options['leg_steps'][$leg['id']];
|
|
$trip['options']['legs'][] = $leg; // Append GOJEK
|
|
$trip['options']['leg_fare'][$leg['id']] = $leg_fare;
|
|
$trip['options']['leg_steps'][$leg['id']] = $leg_steps;
|
|
$trip['options']['routes'] = count($trip['options']['legs']);
|
|
}
|
|
return $trip;
|
|
}
|
|
|
|
public static function processRidesharesOption($db, $member_id, $country, $trip) {
|
|
syslog(LOG_WARNING,"MultiModalApi::processRidesharesOption(\$db, $member_id, $country, \$trip)");
|
|
$trips = ActivityApi::processRidesharesOption($db, $member_id, $country, [
|
|
[
|
|
'trip' => $trip
|
|
]
|
|
]);
|
|
foreach ($trips as $item) {
|
|
if (is_array($item) && array_key_exists('rideshare',$item) && is_array($item['rideshare']) && count($item['rideshare'])>10) {
|
|
$rideshare = $item['rideshare'];
|
|
$options = $rideshare['options'];
|
|
$leg = $options['legs'][0];
|
|
$leg_fare = $options['leg_fare'][$leg['id']];
|
|
$leg_steps = $options['leg_steps'][$leg['id']];
|
|
$trip['options']['legs'][] = $leg; // Append Rideshare
|
|
$trip['options']['leg_fare'][$leg['id']] = $leg_fare;
|
|
$trip['options']['leg_steps'][$leg['id']] = $leg_steps;
|
|
$trip['options']['routes'] = count($trip['options']['legs']);
|
|
} else {
|
|
syslog(LOG_WARNING,"Invalid rideshare entry!");
|
|
}
|
|
}
|
|
/*
|
|
$n = count($trips) - 1;
|
|
if ($n>0 && array_key_exists('rideshare',$trips[$n]) && is_array($trips[$n]['rideshare']) && count($trips[$n]['rideshare'])>10) {
|
|
$rideshare = $trips[$n]['rideshare'];
|
|
$options = $rideshare['options'];
|
|
$leg = $options['legs'][0];
|
|
$leg_fare = $options['leg_fare'][$leg['id']];
|
|
$leg_steps = $options['leg_steps'][$leg['id']];
|
|
$trip['options']['legs'][] = $leg; // Append Rideshare
|
|
$trip['options']['leg_fare'][$leg['id']] = $leg_fare;
|
|
$trip['options']['leg_steps'][$leg['id']] = $leg_steps;
|
|
$trip['options']['routes'] = count($trip['options']['legs']);
|
|
}*/
|
|
return $trip;
|
|
}
|
|
|
|
public function multimodal($db, $addrOrigin, $addrDestination, $country, $no_cache, $member_id, $cache_timeout, $distance, $duration) {
|
|
error_log('MultiModalApi::multimodal()');
|
|
$trip = NULL;
|
|
try {
|
|
// id,address,latitude,longitude,timezone,geocoding_date,postal
|
|
// 3,'97 Meyer Road, Singapore', 1.2833754, 103.8607264, 1, 2019-05-18, 018956
|
|
if (!$no_cache) { // we can force to skip the cache...
|
|
$trip = Trips::getByCoordinates(
|
|
$db->getConnect(),
|
|
['lat' => $addrOrigin['latitude'], 'lng' => $addrOrigin['longitude']],
|
|
['lat' => $addrDestination['latitude'], 'lng' => $addrDestination['longitude']],
|
|
1
|
|
);
|
|
if ($trip && $trip["id"]>0 && MultiModalApi::checkCache($db, $trip, $cache_timeout)) {
|
|
// Trip options
|
|
$trip["member_id"] = $member_id; // Pass along
|
|
$tripOptions = Trips::getOptionsById($db->getConnect(), $trip["id"]);
|
|
if(is_array($tripOptions) && count($tripOptions)>0) {
|
|
|
|
ActivityApi::debugTrips([['multimodal'=>['options'=>$tripOptions]]],'11111');
|
|
|
|
$tripOptions = ActivityApi::processQuotesTripMultimodalOptions($db, $member_id, $country, $tripOptions);
|
|
$trip = array_merge($trip, array(
|
|
'count' => count($tripOptions),
|
|
'options' => $tripOptions,
|
|
'from_cache' => true
|
|
));
|
|
|
|
ActivityApi::debugTrips([['multimodal'=>$trip]],'11112');
|
|
|
|
$trip['country'] = $country;
|
|
$trip = MultiModalApi::processTrip($db, $trip, $country);
|
|
|
|
ActivityApi::debugTrips([['multimodal'=>$trip]],'11113');
|
|
|
|
|
|
throw new Exception('OK');
|
|
} else {
|
|
// Will need new trip options!
|
|
error_log('Trip parsedemail_item.id='.$trip["id"].' does not have options!');
|
|
}
|
|
} else if ($trip && $trip["id"]>0) {
|
|
$trip = NULL; // cache miss - we will need a new trip!
|
|
} // else trip was not found
|
|
}
|
|
// Create a new trip entry
|
|
if ($trip==NULL || !isset($trip["id"])) {
|
|
$data = [
|
|
'travel_date' => MultiModal::getDate($country),
|
|
'duration' => (int)$duration,
|
|
'cost_raw' => NULL,
|
|
'trackedemail_item_id' => NULL,
|
|
'cost' => NULL,
|
|
'distance' => $distance,
|
|
'transport_provider_id' => NULL,
|
|
'scheduled' => NULL,
|
|
'travel_date_end' => MultiModal::getDate($country),
|
|
'dup_id' => NULL,
|
|
'location_start_id' => $addrOrigin['id'],
|
|
'location_end_id' => $addrDestination['id'],
|
|
'private' => 't' /* this is a private entry without the source e-mail */
|
|
];
|
|
list($id, $err) = Trips::create($db->getConnect(), $data);
|
|
if ($id && $id>0) {
|
|
$trip = Trips::getById($db->getConnect(), $id);
|
|
}
|
|
if ($trip==NULL || !isset($trip["id"])) {
|
|
throw new Exception('Failed to create new trip record'.($err?": ${err}":""));
|
|
}
|
|
}
|
|
// New directions
|
|
$tripService = MultiModalApi::tripService($trip["id"], $country);
|
|
//error_log(json_encode($tripService));
|
|
if (is_array($tripService) && isset($tripService["travel_date"])) {
|
|
$tripService["member_id"] = $member_id; // Pass along
|
|
$tripService["country"] = $country;
|
|
|
|
$tripService = MultiModalFilter::byDuration($tripService);
|
|
|
|
ActivityApi::debugTrips([['multimodal'=>$tripService]],'11114');
|
|
|
|
$tripService = MultiModalApi::processTrip($db, $tripService, $country);
|
|
|
|
ActivityApi::debugTrips([['multimodal'=>$tripService]],'11115');
|
|
|
|
$tripOptions = $tripService["options"];
|
|
|
|
ActivityApi::debugTrips([['multimodal'=>$tripService]],'111');
|
|
|
|
$tripOptions = ActivityApi::processQuotesTripMultimodalOptions(
|
|
$db, $member_id, $country, $tripOptions);
|
|
$tripService["options"] = $tripOptions;
|
|
$trip = $tripService;
|
|
|
|
ActivityApi::debugTrips([['multimodal'=>$trip]],'112');
|
|
|
|
$trip = MultiModalFilter::byCost($trip);
|
|
}
|
|
} catch (Exception $e) {
|
|
error_log($e->getMessage());
|
|
}
|
|
return $trip;
|
|
}
|
|
|
|
protected function checkCache($db, $trip, $cache_timeout) {
|
|
error_log('MultiModalApi::checkCache()');
|
|
$advice = NULL;
|
|
if (!is_array($trip) || $trip['id']<1) {
|
|
error_log('No trip data to analyse => no cache!');
|
|
return false;
|
|
}
|
|
list ($res, $err) = MultiModal::getLastGoogleAdviceByTrip($db->getConnect(),$trip['id']);
|
|
error_log(json_encode($res));
|
|
if ($res && $res['id']>0) {
|
|
$advice = $res;
|
|
} else {
|
|
error_log('No parsedemail_item_advice_google record => no cache!');
|
|
return false;
|
|
}
|
|
if ($advice['elapsed'] > $cache_timeout) {
|
|
error_log('Cache expired! We will need a new advice!');
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
protected function checkTaxiQuote($db, $trip, $country) {
|
|
syslog(LOG_WARNING,"MultiModalApi::checkTaxiQuote(\$db, \$trip, $country)");
|
|
try {
|
|
// Do we have trip options?
|
|
if (!isset($trip['options']) || !is_array($trip['options']) || !isset($trip['options']['legs'])) {
|
|
error_log('Trip parsedemail_item.id='.$trip['id'].' has no options!');
|
|
return $trip;
|
|
}
|
|
// Do we have a member_id?
|
|
$member_id = 0;
|
|
if (isset($trip["member_id"])) {
|
|
$member_id = $trip["member_id"];
|
|
}
|
|
// Do we have transport providers?
|
|
$transport_providers = [];
|
|
list ($result, $error) = Geocode::getTransportProvidersByCountry(
|
|
$db->getConnect(), $trip["country"]);
|
|
if ($result==NULL || count($result)<1) {
|
|
syslog(LOG_WARNING,"Failed to get transport providers: ".$error);
|
|
return $trip;
|
|
}
|
|
foreach ($result as $f) {
|
|
if ($trip["country"]!='SG' || $f["transport_provider_id"]==4) { // ComfortDelGro
|
|
$transport_providers[] = $f["transport_provider_id"];
|
|
}
|
|
}
|
|
// Check leg steps for the taxi
|
|
$n = count($trip['options']['legs']);
|
|
for ($i=0; $i<$n; $i++) {
|
|
$leg = $trip['options']['legs'][$i];
|
|
$leg_id = $leg['id'];
|
|
$leg_steps = $trip['options']['leg_steps'][$leg_id];
|
|
$leg_fare = $trip['options']['leg_fare'][$leg_id];
|
|
$m = count($leg_steps);
|
|
$total = 0;
|
|
for ($j=0; $j<$m; $j++) {
|
|
$step = $leg_steps[$j];
|
|
if ($step['travel_mode']=="TAXI") {
|
|
// Reverse geocode
|
|
list($origin, $err1) = GeocodeApi::reverseGeocode($db, $step["location_start_lat"], $step["location_start_lng"]);
|
|
list($destination, $err2) = GeocodeApi::reverseGeocode($db, $step["location_end_lat"], $step["location_end_lng"]);
|
|
if ($origin=='' || $destination=='') {
|
|
syslog(LOG_WARNING,'MultiModalApi::checkTaxiQuote() Reverse geocoding failed! From "'.$origin.'"('.$step["location_start_lat"].','.$step["location_start_lng"].') to "'.$destination.'"('.$step["location_end_lat"].','.$step["location_end_lng"].')');
|
|
continue;
|
|
}
|
|
syslog(LOG_WARNING,"origin='${origin}'");
|
|
syslog(LOG_WARNING,"destination='${destination}");
|
|
list($message,$code,$action,$data) = QuoteGroupApi::createReal(
|
|
$db, $origin, $destination, $member_id, $transport_providers, $country
|
|
);
|
|
if (is_array($data) && isset($data["id"]) && $data["id"]>0) {
|
|
syslog(LOG_WARNING,"QuoteGroup ID: ".$data["id"]);
|
|
$quoteGroupId = $data["id"];
|
|
// Check quote
|
|
$step["quote_group_id"] = $quoteGroupId;
|
|
sleep(3);
|
|
list($message,$code,$action,$data) = QuoteGroupApi::viewReal($db, $quoteGroupId);
|
|
if ($code==200 && isset($data["cost"]) && $data["cost"]>0) {
|
|
// TODO: double-check!
|
|
$step["fare_quote"] = ((int)(100*$data["cost"]));
|
|
if (!array_key_exists('fare_raw',$step) || $step['fare_raw']<$step["fare_quote"]) {
|
|
$step['fare_raw'] = $step["fare_quote"];
|
|
}
|
|
if ($leg_fare==NULL) $leg_fare = $step["fare_quote"];
|
|
else $leg_fare += $step["fare_quote"];
|
|
} else {
|
|
syslog(LOG_WARNING,"ERROR: ".$message);
|
|
}
|
|
} else {
|
|
syslog(LOG_WARNING,"ERROR: ".$message);
|
|
}
|
|
}
|
|
if (array_key_exists('fare_raw',$step) && $step['fare_raw']>0) {
|
|
$total += $step['fare_raw'];
|
|
}
|
|
if (!array_key_exists('duration',$step) || $step['duration']<60) {
|
|
$step['duration'] = 60;
|
|
}
|
|
$leg_steps[$j] = $step;
|
|
}
|
|
if (!array_key_exists('fare_raw',$leg) || $leg['fare_raw']<$leg_fare || $leg['fare_raw']<$total) {
|
|
$leg['fare_raw'] = $leg_fare>$total ? $leg_fare : $total;
|
|
}
|
|
$trip['options']['leg_fare'][$leg_id] = $leg_fare>$total ? $leg_fare : $total;
|
|
$trip['options']['leg_steps'][$leg_id] = $leg_steps;
|
|
$trip['options']['legs'][$i] = $leg;
|
|
}
|
|
//*/
|
|
} catch (Exception $e) {
|
|
syslog(LOG_WARNING,'MultiModalApi::checkTaxiQuote() EXCEPTION: '.$e->getMessage());
|
|
}
|
|
return $trip;
|
|
}
|
|
|
|
protected function processTrip($db, $trip, $country) {
|
|
syslog(LOG_WARNING,'MultiModalApi::processTrip()');
|
|
require_once('../common/Polyline.php');
|
|
//error_log(json_encode($trip));
|
|
|
|
ActivityApi::debugTrips([['multimodal'=>$trip]],'1111');
|
|
|
|
if (array_key_exists('options',$trip) && is_array($trip['options']) && isset($trip['options']['legs'])) {
|
|
if ($trip['options']['gid']<1) {
|
|
// Save options...
|
|
list($res, $err) = MultiModal::create($db->getConnect(), $trip);
|
|
error_log($err);
|
|
if ($res && $res['id']>0) {
|
|
$trip = $res;
|
|
// TODO: fix!
|
|
//unset($trip['error']);
|
|
} else {
|
|
$message = $err!='' ? $err : 'Failed to save multi-modal option';
|
|
error_log($message);
|
|
$trip['error'] = $message;
|
|
$trip['options']['routes'] = count($trip['options']['legs']);
|
|
$trip = MultiModalApi::checkTaxiQuote($db, $trip, $country);
|
|
return $trip;
|
|
}
|
|
} else {
|
|
error_log('DB record for options already exists');
|
|
}
|
|
// Schedule quote
|
|
$trip = MultiModalApi::checkTaxiQuote($db, $trip, $country);
|
|
$n = count($trip['options']['legs']);
|
|
for ($i=0; $i<$n; $i++) {
|
|
$leg = $trip['options']['legs'][$i];
|
|
$leg_id = $leg['id'];
|
|
$leg_steps = $trip['options']['leg_steps'][$leg_id];
|
|
$leg_fare = $trip['options']['leg_fare'][$leg_id];
|
|
// We must schedule leg fare quote...
|
|
$m = count($leg_steps);
|
|
$overview = [];
|
|
for ($j=0; $j<$m; $j++) {
|
|
$step = $leg_steps[$j];
|
|
//"travel_mode": "TRANSIT"
|
|
//"vehicle": "BUS",
|
|
//"line": "", <------------- WTF?
|
|
if ($step['travel_mode']=="SCOOTER") {
|
|
$polyline = [];
|
|
// Get directions
|
|
$input = [
|
|
1 => [
|
|
"coordinates" => [
|
|
"lat" => $trip["location_start_lat"],
|
|
"lng" => $trip["location_start_lng"]
|
|
]
|
|
],
|
|
2 => [
|
|
"coordinates" => [
|
|
"lat" => $trip["location_end_lat"],
|
|
"lng" => $trip["location_end_lng"]
|
|
]
|
|
]
|
|
];
|
|
$result = [
|
|
1 => [
|
|
"data" => [
|
|
"location_start_lat" => $step["location_start_lat"],
|
|
"location_start_lng" => $step["location_start_lng"],
|
|
"location_end_lat" => $step["location_end_lat"],
|
|
"location_end_lng" => $step["location_end_lng"]
|
|
]
|
|
]
|
|
];
|
|
$options = ScooterApi::directions($db, $input, $result, []);
|
|
$step["route_overlay"] = isset($options["route_overlay"]) ? $options["route_overlay"][0] : [];
|
|
$step["polyline"] = $options["route_overlay"][0]["polyline"];
|
|
$polyline = $step["polyline"]; // TODO: merge with walking...
|
|
// Get quote
|
|
$scooter_time = $step['duration'];
|
|
$country = 'SG'; // Singapore only!
|
|
list($res,$err) = ScooterApi::quote($db, $scooter_time, $country);
|
|
if ($res && count($res)>0) {
|
|
$fare_raw = PHP_INT_MAX;
|
|
foreach ($res as $quote) {
|
|
if ($quote['pricing']['dropoff_anywhere']!=null) {
|
|
$fare_raw = $quote['quote'] + $quote['pricing']['dropoff_anywhere'];
|
|
break; // with this option we have Neuron only and that be it
|
|
}
|
|
if ($fare_raw > $quote['quote']) {
|
|
$fare_raw = $quote['quote'];
|
|
}
|
|
}
|
|
if ($fare_raw == PHP_INT_MAX) {
|
|
$fare_raw = NULL; // we did not get any quote?
|
|
} else {
|
|
$fare_raw = (int)($fare_raw);
|
|
}
|
|
$trip['options']['leg_fare'][$leg_id] = $fare_raw;
|
|
$leg['fare_raw'] = $fare_raw;
|
|
$step['fare_raw'] = $fare_raw;
|
|
}
|
|
$leg['polyline'] = $polyline;
|
|
$step['polyline'] = $polyline;
|
|
}
|
|
//error_log(json_encode($step));
|
|
$leg_steps[$j] = $step;
|
|
|
|
// TODO: FIX!!!
|
|
|
|
if (array_key_exists("polyline",$step)) {
|
|
$overview[] = $step["polyline"];
|
|
}
|
|
|
|
}
|
|
if (count($overview)>0) {
|
|
$leg["polyline"] = MultiModal::processPolyline($overview);
|
|
}
|
|
//syslog(LOG_WARNING,'$leg["polyline"] = '.$leg["polyline"]);
|
|
$trip['options']['leg_steps'][$leg_id] = $leg_steps;
|
|
$trip['options']['legs'][$i] = $leg;
|
|
}
|
|
$trip['options']['routes'] = count($trip['options']['legs']);
|
|
} else {
|
|
syslog(LOG_WARNING,'Trip parsedemail_item.id='.$trip['id'].' has no options!');
|
|
}
|
|
return $trip;
|
|
}
|
|
|
|
public function updateAction() {
|
|
return $this->response(
|
|
array(
|
|
"error" => "Update error"
|
|
), 400);
|
|
}
|
|
|
|
public function deleteAction() {
|
|
$res = 0;
|
|
$message = "Delete error";
|
|
$id = (int)array_shift($this->requestUri);
|
|
if ($id>0) {
|
|
$db = new Db();
|
|
$res = MultiModal::delete($db->getConnect(), $id);
|
|
if ($res>0) {
|
|
return $this->response(array(
|
|
'id' => $id,
|
|
'result' => $res
|
|
), 200);
|
|
} else {
|
|
$message = "Delete failed";
|
|
}
|
|
} else {
|
|
$message = "Invalid error";
|
|
}
|
|
return $this->response(
|
|
array(
|
|
"error" => $message,
|
|
"result" => $res
|
|
), 500);
|
|
}
|
|
|
|
public function tripService($id, $country) {
|
|
global $savvyext;
|
|
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
|
$oauth2_url = $savvyext->cfgReadChar('system.oauth2_url');
|
|
error_log("MultiModalApi::tripService($id)");
|
|
if ($country!='SG' && $country!='US') {
|
|
throw new Exception('Unsupported country: '.$country);
|
|
}
|
|
// curl -d 'id=8907' -X POST {$oauth2_url}trips/
|
|
$postdata = http_build_query(
|
|
array(
|
|
'id'=> $id,
|
|
'country' => $country
|
|
)
|
|
);
|
|
$url = $oauth2_url."trips";
|
|
$opts = array(
|
|
'http' => array(
|
|
'method' => "POST",
|
|
'timeout' => 60, /* 1 minute */
|
|
'header' =>
|
|
"Content-Type: application/x-www-form-urlencoded\r\n" .
|
|
"Accept: application/json\r\n" .
|
|
"Authorization: Server-Token ${httpAuthToken}\r\n",
|
|
'content' => $postdata
|
|
),
|
|
"ssl" => array(
|
|
"verify_peer"=>false,
|
|
"verify_peer_name"=>false,
|
|
)
|
|
);
|
|
$context = stream_context_create($opts);
|
|
error_log("started trips service call");
|
|
$t = time();
|
|
$body = file_get_contents($url, false, $context);
|
|
error_log("complete trips service call: ".(time()-$t)." seconds");
|
|
file_put_contents('/home/savvy/FloatWeb/adminsavvy/DEBUG/trips'.time().'.json',$body);
|
|
$trip = json_decode($body,true);
|
|
return $trip;
|
|
}
|
|
|
|
public function mytansportsgService($id) {
|
|
global $savvyext;
|
|
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
|
$oauth2_url = $savvyext->cfgReadChar('system.oauth2_url');
|
|
error_log("public function mytransportsgService($id)");
|
|
// curl -d 'id=8907' -X POST $oauth2_url.'mytransportsg'/
|
|
$postdata = http_build_query(
|
|
array(
|
|
'advice_id'=> $id
|
|
)
|
|
);
|
|
$url = $oauth2_url."mytransportsg";
|
|
$opts = array(
|
|
'http' => array(
|
|
'method' => "POST",
|
|
'timeout' => 60, /* 1 minute */
|
|
'header' =>
|
|
"Content-Type: application/x-www-form-urlencoded\r\n" .
|
|
"Accept: application/json\r\n" .
|
|
"Authorization: Server-Token ${httpAuthToken}\r\n",
|
|
'content' => $postdata
|
|
),
|
|
"ssl" => array(
|
|
"verify_peer"=>false,
|
|
"verify_peer_name"=>false,
|
|
)
|
|
);
|
|
$context = stream_context_create($opts);
|
|
$body = file_get_contents($url, false, $context);
|
|
$advice = json_decode($body,true);
|
|
return $advice;
|
|
}
|
|
|
|
public function mytansportsgServiceLeg($id) {
|
|
global $savvyext;
|
|
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
|
$oauth2_url = $savvyext->cfgReadChar('system.oauth2_url');
|
|
error_log("public function mytransportsgServiceLeg($id)");
|
|
$url = $oauth2_url."mytransportsg/" . $id;
|
|
$opts = array(
|
|
'http' => array(
|
|
'method' => "GET",
|
|
'timeout' => 60, /* 1 minute */
|
|
'header' =>
|
|
"Content-Type: application/x-www-form-urlencoded\r\n" .
|
|
"Accept: application/json\r\n" .
|
|
"Authorization: Server-Token ${httpAuthToken}\r\n",
|
|
),
|
|
"ssl" => array(
|
|
"verify_peer"=>false,
|
|
"verify_peer_name"=>false,
|
|
)
|
|
);
|
|
$context = stream_context_create($opts);
|
|
$body = file_get_contents($url, false, $context);
|
|
$advice = json_decode($body,true);
|
|
return $advice;
|
|
}
|
|
|
|
public function bartService($db, $legs, $id) {
|
|
$quotes = []; // We do not call the service as the data is presented after the initial call
|
|
foreach ($legs as $leg_id=>$leg) {
|
|
$total = 0;
|
|
list ($res, $err) = MultiModal::getLegStepQuotes($db->getConnect(), $leg_id);
|
|
if ($res && count($res)>0) {
|
|
foreach ($res as $quote) {
|
|
$total += ((int)$f["fare_raw"]);
|
|
}
|
|
}
|
|
$quotes[$leg_id] = [
|
|
"total" => $total,
|
|
];
|
|
}
|
|
$result = [
|
|
"code" => 0,
|
|
"data" => $quotes
|
|
];
|
|
return $result;
|
|
}
|
|
|
|
protected function processLegs($db, $legs, $advice_id, $country) {
|
|
syslog(LOG_WARNING,"MultiModalApi::processLegs(\$db, \$legs, $advice_id, $country)");
|
|
$ok = true; // All the steps on all the legs have the quotes?
|
|
$leg_steps = [];
|
|
foreach ($legs as $leg_id=>$leg) {
|
|
list ($leg, $ok, $steps) = MultiModalApi::processSteps($db, $leg, $ok);
|
|
$legs[$leg_id] = $leg;
|
|
$leg_steps[$leg_id] = $leg_steps;
|
|
}
|
|
if ($ok) {
|
|
return $this->response($legs, 200);
|
|
}
|
|
// Get quote
|
|
$options = [
|
|
"legs" => $legs,
|
|
"leg_steps" => $leg_steps
|
|
];
|
|
$options = ActivityApi::processQuotesTripMultimodalOptions(
|
|
$db, 0, $country, $options); /* NOTE: $member_id = 0; */
|
|
$legs = $options["legs"];
|
|
/*
|
|
if (is_array($result) && isset($result["code"]) && $result["code"]==0 && isset($result["data"])) {
|
|
$data = $result["data"];
|
|
error_log(json_encode($data));
|
|
foreach ($data as $leg_id=>$quote) {
|
|
$leg = $legs[$leg_id];
|
|
if (isset($quote['total']) && $quote['total']>0) {
|
|
$leg['fare_raw'] = $quote['total'];
|
|
}
|
|
$ok = true;
|
|
list ($leg, $ok, $steps) = MultiModalApi::processSteps($db, $leg, $ok);
|
|
if ($ok) {
|
|
$legs[$leg_id] = $leg;
|
|
} else {
|
|
error_log('Failed to process steps for leg #'.$leg_id);
|
|
}
|
|
}
|
|
return $this->response($legs, 200);
|
|
}
|
|
*/
|
|
return $this->response($legs, 200);
|
|
/*
|
|
return $this->response(
|
|
array(
|
|
'error' => isset($result["error"])?$result["error"]:"MyTrasnport.sg service call failed"
|
|
), 500);*/
|
|
}
|
|
|
|
public static function getPolyline($id) {
|
|
global $savvyext;
|
|
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
|
$oauth2_url = $savvyext->cfgReadChar('system.oauth2_url');
|
|
$url = $oauth2_url."polyline/" . $id;
|
|
$opts = array(
|
|
'http' => array(
|
|
'method' => "GET",
|
|
'timeout' => 60, /* 1 minute */
|
|
'header' =>
|
|
"Content-Type: application/x-www-form-urlencoded\r\n" .
|
|
"Accept: application/json\r\n" .
|
|
"Authorization: Server-Token ${httpAuthToken}\r\n",
|
|
),
|
|
"ssl" => array(
|
|
"verify_peer"=>false,
|
|
"verify_peer_name"=>false,
|
|
)
|
|
);
|
|
$context = stream_context_create($opts);
|
|
$body = file_get_contents($url, false, $context);
|
|
$geocoded = json_decode($body,true);
|
|
|
|
//var_dump($http_response_header);
|
|
//var_dump($body);
|
|
return $geocoded;
|
|
}
|
|
}
|