The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#) https://grpc.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
5.9 KiB

<?php
/*
*
* Copyright 2020 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
class RouteGuideService extends \Routeguide\RouteGuideStub
{
public function __construct($dbFilePath)
{
$dbFilePath = $dbFilePath ?? dirname(__FILE__) . '/route_guide_db.json';
$dbData = file_get_contents($dbFilePath);
if (!$dbData) {
throw new InvalidArgumentException(
"Error reading route db file: " . $dbFilePath
);
}
$featureList = json_decode($dbData);
if (!$featureList) {
throw new InvalidArgumentException(
"Error decoding route db file: " . $dbFilePath
);
}
foreach ($featureList as $feature) {
array_push($this->featureList, new Routeguide\Feature([
'name' => $feature->name,
'location' => new Routeguide\Point([
'latitude' => $feature->location->latitude,
'longitude' => $feature->location->longitude,
]),
]));
}
}
private function findFeature(\Routeguide\Point $point)
{
foreach ($this->featureList as $feature) {
$location = $feature->getLocation();
if (
$location->getLatitude() === $point->getLatitude()
&& $location->getLongitude() === $point->getLongitude()
) {
return $feature;
}
}
return null;
}
// The formula is based on http://mathforum.org/library/drmath/view/51879.html
private function calculateDistance(
\Routeguide\Point $start,
\Routeguide\Point $end
) {
$toRadians = function (float $num) {
return $num * 3.1415926 / 180;
};
$coordFactor = 10000000.0;
$R = 6371000; // metres
$lat_1 = $start->getLatitude() / $coordFactor;
$lat_2 = $end->getLatitude() / $coordFactor;
$lon_1 = $start->getLongitude() / $coordFactor;
$lon_2 = $end->getLongitude() / $coordFactor;
$lat_rad_1 = $toRadians($lat_1);
$lat_rad_2 = $toRadians($lat_2);
$delta_lat_rad = $toRadians($lat_2 - $lat_1);
$delta_lon_rad = $toRadians($lon_2 - $lon_1);
$a = pow(sin($delta_lat_rad / 2), 2) +
cos($lat_rad_1) * cos($lat_rad_2) * pow(sin($delta_lon_rad / 2), 2);
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
return $R * $c;
}
public function GetFeature(
\Routeguide\Point $request,
\Grpc\ServerContext $serverContext
): ?\Routeguide\Feature {
$feature = $this->findFeature($request);
$notFoundFeature = new Routeguide\Feature([
'name' => '',
'location' => $request,
]);
return $feature ?? $notFoundFeature;
}
public function ListFeatures(
\Routeguide\Rectangle $request,
\Grpc\ServerCallWriter $writer,
\Grpc\ServerContext $serverContext
): void {
$lo = $request->getLo();
$hi = $request->getHi();
$left = min($lo->getLongitude(), $hi->getLongitude());
$right = max($lo->getLongitude(), $hi->getLongitude());
$top = max($lo->getLatitude(), $hi->getLatitude());
$bottom = min($lo->getLatitude(), $hi->getLatitude());
foreach ($this->featureList as $feature) {
$longitude = $feature->getLocation()->getLongitude();
$latitude = $feature->getLocation()->getLatitude();
if (
$longitude >= $left && $longitude <= $right
&& $latitude >= $bottom && $latitude <= $top
) {
$writer->write($feature);
}
}
$writer->finish();
}
public function RecordRoute(
\Grpc\ServerCallReader $reader,
\Grpc\ServerContext $serverContext
): ?\Routeguide\RouteSummary {
$point_count = 0;
$feature_count = 0;
$distance = 0;
$previous = null;
$start_time = time();
while ($point = $reader->read()) {
$point_count++;
$feature = $this->findFeature($point);
if ($feature) {
$feature_count++;
if ($previous) {
$distance += $this->calculateDistance($previous, $point);
}
$previous = $point;
}
}
$summary = new \Routeguide\RouteSummary();
$summary->setPointCount($point_count);
$summary->setFeatureCount($feature_count);
$summary->setDistance($distance);
$summary->setElapsedTime(time() - $start_time);
return $summary;
}
public function RouteChat(
\Grpc\ServerCallReader $reader,
\Grpc\ServerCallWriter $writer,
\Grpc\ServerContext $serverContext
): void {
while ($note = $reader->read()) {
foreach ($this->received_notes as $n) {
if (
$n->getLocation()->getLatitude() ===
$note->getLocation()->getLatitude()
&& $n->getLocation()->getLongitude() ===
$note->getLocation()->getLongitude()
) {
$writer->write($n);
}
}
array_push($this->received_notes, $note);
}
$writer->finish();
}
private $received_notes = [];
private $featureList = [];
}