Files
dev-chiefworks 47f4fad75c Added Other AP
2022-04-26 11:30:34 -04:00

277 lines
11 KiB
PHP
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
class sgbikeApi extends Api
{
public $apiName = 'sgbike';
public function indexAction()
{
$messge = 'Data not found';
return $this->response(
array(
'error' => $message
), 404);
}
/**
* Method GET
* Get single record (by id)
* http://DOMAIN/geocode/1
* @return string
*/
public function viewAction()
{
//id must be the first parameter after /geocode/x
$id = array_shift($this->requestUri);
if($id && (int)$id>0){
$db = new Db();
$address = Geocode::getAddressById($db->getConnect(), (int)$id);
if(is_array($address) && count($address)>0){
return $this->response($address, 200);
}
}
return $this->response(
array(
'error'=> 'Data not found'
), 404);
}
public function createAction()
{
$message = "Failed to run sgbike directions";
$addresses = $this->requestParams["addresses"] ?? array();
$options = $this->requestParams["options"] ?? array();
try {
throw new Exception("We are sorry but sgbikes are not yet launched in your country.  Please check back again soon!");
if ($addresses==NULL || !is_array($addresses) || count($addresses)<1 || !isset($addresses[0]["address"])) {
throw new Exception("Invalid input");
}
$db = new Db();
$result = [];
$input = [];
foreach ($addresses as $item) {
if (isset($item["type"]) && $item["type"]>0 && $item["type"]<3) {
$input[$item["type"]] = $item;
}
}
if (isset($input[1]) && isset($input[2]) &&
isset($input[1]["address"]) && isset($input[2]["address"])) {
list($result, $err) = self::sgbike($db, $input);
if (!is_array($result) || count($result)<1) {
throw new Exception($err!=''? $err : 'No sgbike option available');
}
} else {
throw new Exception("Invalid address");
}
if ((isset($options["travel_time"]) && $options["travel_time"]) ||
(isset($options["quote"]) && $options["quote"]) ||
(isset($options["route_overlay"]) && $options["route_overlay"])) {
$options = self::options($db, $input, $result, $options);
}
return $this->response(
array(
'data'=>$result,
'options'=>$options), 200);
} catch (Exception $e) {
error_log(json_encode($e));
$message = $e->getMessage();
}
return $this->response(
array(
"error" => $message
), 500);
}
public function updateAction()
{
return $this->response(
array(
"error" => "Update error"
), 400);
}
public function deleteAction() {
return $this->response(
array(
"error" => "Delete error"
), 500);
}
public function sgbike($db, $input) {
global $savvyext;
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
$oauth2_url = $savvyext->cfgReadChar('system.oauth2_url');
// Call sgbike service
$gps1 = $input[1]["coordinates"];
$gps2 = $input[2]["coordinates"];
$data = http_build_query(
array(
'gps' => sprintf("%s,%s,%s,%s",$gps1["lat"],$gps1["lng"],$gps2["lat"],$gps2["lng"]),
'from' => $input[1]["address"],
'to' => $input[2]["address"]
)
);
$url = $oauth2_url."sgbike?" . $data;
//error_log($url);
$opts = array(
'http' => array(
'method' => "GET",
'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);
$sgbike = json_decode($body,true);
if (is_array($sgbike) && is_array($sgbike["data"]) && !isset($sgbike["error"])) {
// Cache the result in DB
//$sgbike["data"]["id"] = sgbike::save($db->getConnect(), $sgbike["data"]);
return array($sgbike["data"], NULL);
} else if (is_array($sgbike) && isset($sgbike["error"])) {
$body = $sgbike["error"];
}
return array(NULL, "sgbike service call error: ".$body);
}
public function options($db, $input, $result, $options) {
if (isset($options["travel_time"]) && $options["travel_time"]) {
$travel_time = 0;
foreach ($result as $step) {
$travel_time += $step["duration"];
}
$options["travel_time"] = (int)$travel_time;
}
if (isset($options["quote"]) && $options["quote"] &&
is_array($result) && count($result)>1 &&
isset($result[1]["duration"]) && $result[1]["duration"]>0) {
$sgbike_time = $result[1]["duration"]; // 2nd entry is the sgbike step
list($res,$err) = self::quote($db, $sgbike_time, 'SG');
if ($err!=NULL) {
$options["error"] = $err;
} else {
$options["quote"] = $res;
}
}
if (isset($options["route_overlay"]) && $options["route_overlay"]) {
$options = self::directions($db, $input, $result, $options);
}
return $options;
}
public function quote($db, $seconds, $country='SG',$step_details=[]) {
global $savvyext;
$sgbike_token = $savvyext->cfgReadChar('system.scooter_token');
// Check local DB cache
/* list ($res, $err) = sgbike::checksgbikeQuote($db->getConnect(), $minutes, $country);
if (is_array($res) && isset($res[0]["quote"])) {
return array($res, NULL);
} */
// Call sgbike quote service
$data = http_build_query(
array(
'minutes' => (int)($seconds/60),
'country' => $country
)
);
$url = $savvyext->cfgReadChar('microservices.catalog') . "/api/v1/bikes/price-quote/?" . $data;
//echo $url;exit;
// https://float.catalog.float.sg/api/v1/bikes/price-quote/?minutes=49&country=SG
// curl -X GET "https://float.catalog.float.sg/api/v1/bikes/price-quote/?minutes=60&country=SG" -H "accept: application/json" -H "Authorization: Server-Token MNHEzG4uEDy47NhZqBnBKM9kvKVGXzC8"
$opts = array(
'http' => array(
'method' => "GET",
'header' =>
"Content-Type: application/x-www-form-urlencoded\r\n" .
"Accept: application/json\r\n" .
"Authorization: Server-Token $sgbike_token\r\n",
),
"ssl" => array(
"verify_peer"=>false,
"verify_peer_name"=>false,
)
);
$context = stream_context_create($opts);
$body = file_get_contents($url, false, $context);
$data = json_decode($body,true);
if (is_array($data) && count($data) > 0 && !isset($data["error"])) {
// Cache the result in DB
$extra_fee_default = 5.0; // default extra fee fall-back
$apply_extra_fee = false;
$duration = ceil($duration/60);//
if (is_array($step_details) && $step_details["line"] == null && $step_details["headsign"] != null) {
$apply_extra_fee = true;
if ($vendor == null) {
$vendor = $step_details["headsign"]; /* The provider will be in the "headsign"
and this means we drop off anywhere */
}
}
if (is_array($data) && count($data) > 0 && !isset($data["error"])) {
if ($vendor != null) {
foreach ($data as $d) {
if (isset($d['provider']) && $d['provider'] == $vendor) {
return ($d["quote"]+ ($apply_extra_fee ? ($d["pricing"]["dropoff_anywhere"] != null ? $d["pricing"]["dropoff_anywhere"] : $extra_fee_default) : 0))*100;
}
}
}
$result = 0.0; // If we do not know the vendor - get the most expensive
foreach ($data as $d) {
$value = $d["quote"];
if ($value > $result) {
$result = $value;
$extra_fee = $d["pricing"]["dropoff_anywhere"] != null ? $d["pricing"]["dropoff_anywhere"] : $extra_fee_default;
}
}
$result += ($apply_extra_fee ? $extra_fee : 0);
}
return array($result*100,null);
} else if (is_array($sgbike) && isset($sgbike["error"])) {
$body = $sgbike["error"];
}
return array(NULL, "sgbike quote service call error: ".$body);
}
public function directions($db, $input, $result, $options) {
// Walking with waypoints or 3 routes
$mode='walking';
$waypoints=[
$result[1]["data"]["location_start_lat"], $result[1]["data"]["location_start_lng"],
$result[1]["data"]["location_end_lat"], $result[1]["data"]["location_end_lng"]
];
$fromLat = $input[1]["coordinates"]["lat"];
$fromLng = $input[1]["coordinates"]["lng"];
$toLat = $input[2]["coordinates"]["lat"];
$toLng = $input[2]["coordinates"]["lng"];
list($res, $err) = GeocodeApi::route(
$db, $fromLat, $fromLng, $toLat, $toLng, $mode, $waypoints);
if ($err!=NULL || !is_array($res) || !isset($res["routes"]) || count($res["routes"])<1) {
$options['error'] = $err!=NULL ? $err : 'No available routes';
return $options;
}
$options["route_overlay"] = [];
$travel_time = PHP_INT_MAX;
$travel_distance = PHP_INT_MAX;
foreach ($res["routes"] as $route) {
$r = GeocodeApi::processRoute($route);
if ($travel_time>$r['duration']) {
$travel_time = $r['duration'];
$travel_distance = $r['distance'];
}
$options["route_overlay"][] = $r;
}
// ["route_overlay"]
return $options;
}
}