xref: /aosp_15_r20/external/grpc-grpc/examples/php/route_guide/RouteGuideService.php (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1<?php
2/*
3 *
4 * Copyright 2020 gRPC authors.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20
21class RouteGuideService extends \Routeguide\RouteGuideStub
22{
23    public function __construct($dbFilePath)
24    {
25        $dbFilePath = $dbFilePath ?? dirname(__FILE__) . '/route_guide_db.json';
26        $dbData = file_get_contents($dbFilePath);
27        if (!$dbData) {
28            throw new InvalidArgumentException(
29                "Error reading route db file: " . $dbFilePath
30            );
31        }
32        $featureList = json_decode($dbData);
33        if (!$featureList) {
34            throw new InvalidArgumentException(
35                "Error decoding route db file: " . $dbFilePath
36            );
37        }
38        foreach ($featureList as $feature) {
39            array_push($this->featureList, new Routeguide\Feature([
40                'name' => $feature->name,
41                'location' => new Routeguide\Point([
42                    'latitude' => $feature->location->latitude,
43                    'longitude' => $feature->location->longitude,
44                ]),
45            ]));
46        }
47    }
48
49    private function findFeature(\Routeguide\Point $point)
50    {
51        foreach ($this->featureList as $feature) {
52            $location = $feature->getLocation();
53            if (
54                $location->getLatitude() === $point->getLatitude()
55                && $location->getLongitude() === $point->getLongitude()
56            ) {
57                return $feature;
58            }
59        }
60        return null;
61    }
62
63    // The formula is based on http://mathforum.org/library/drmath/view/51879.html
64    private function calculateDistance(
65        \Routeguide\Point $start,
66        \Routeguide\Point $end
67    ) {
68        $toRadians = function (float $num) {
69            return $num * 3.1415926 / 180;
70        };
71        $coordFactor = 10000000.0;
72        $R = 6371000; // metres
73
74        $lat_1 = $start->getLatitude() / $coordFactor;
75        $lat_2 = $end->getLatitude() / $coordFactor;
76        $lon_1 = $start->getLongitude() / $coordFactor;
77        $lon_2 = $end->getLongitude() / $coordFactor;
78        $lat_rad_1 = $toRadians($lat_1);
79        $lat_rad_2 = $toRadians($lat_2);
80        $delta_lat_rad = $toRadians($lat_2 - $lat_1);
81        $delta_lon_rad = $toRadians($lon_2 - $lon_1);
82
83        $a = pow(sin($delta_lat_rad / 2), 2) +
84            cos($lat_rad_1) * cos($lat_rad_2) * pow(sin($delta_lon_rad / 2), 2);
85        $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
86
87        return $R * $c;
88    }
89
90    public function GetFeature(
91        \Routeguide\Point $request,
92        \Grpc\ServerContext $serverContext
93    ): ?\Routeguide\Feature {
94        $feature = $this->findFeature($request);
95        $notFoundFeature = new Routeguide\Feature([
96            'name' => '',
97            'location' => $request,
98        ]);
99        return $feature ?? $notFoundFeature;
100    }
101
102    public function ListFeatures(
103        \Routeguide\Rectangle $request,
104        \Grpc\ServerCallWriter $writer,
105        \Grpc\ServerContext $serverContext
106    ): void {
107        $lo = $request->getLo();
108        $hi = $request->getHi();
109        $left = min($lo->getLongitude(), $hi->getLongitude());
110        $right = max($lo->getLongitude(), $hi->getLongitude());
111        $top = max($lo->getLatitude(), $hi->getLatitude());
112        $bottom = min($lo->getLatitude(), $hi->getLatitude());
113
114        foreach ($this->featureList as $feature) {
115            $longitude = $feature->getLocation()->getLongitude();
116            $latitude = $feature->getLocation()->getLatitude();
117            if (
118                $longitude >= $left && $longitude <= $right
119                && $latitude >= $bottom && $latitude <= $top
120            ) {
121                $writer->write($feature);
122            }
123        }
124
125        $writer->finish();
126    }
127
128    public function RecordRoute(
129        \Grpc\ServerCallReader $reader,
130        \Grpc\ServerContext $serverContext
131    ): ?\Routeguide\RouteSummary {
132        $point_count = 0;
133        $feature_count = 0;
134        $distance = 0;
135        $previous = null;
136
137        $start_time = time();
138        while ($point = $reader->read()) {
139            $point_count++;
140            $feature = $this->findFeature($point);
141            if ($feature) {
142                $feature_count++;
143                if ($previous) {
144                    $distance += $this->calculateDistance($previous, $point);
145                }
146                $previous = $point;
147            }
148        }
149
150        $summary = new \Routeguide\RouteSummary();
151        $summary->setPointCount($point_count);
152        $summary->setFeatureCount($feature_count);
153        $summary->setDistance($distance);
154        $summary->setElapsedTime(time() - $start_time);
155
156        return $summary;
157    }
158
159    public function RouteChat(
160        \Grpc\ServerCallReader $reader,
161        \Grpc\ServerCallWriter $writer,
162        \Grpc\ServerContext $serverContext
163    ): void {
164        while ($note = $reader->read()) {
165            foreach ($this->received_notes as $n) {
166                if (
167                    $n->getLocation()->getLatitude() ===
168                    $note->getLocation()->getLatitude()
169                    && $n->getLocation()->getLongitude() ===
170                    $note->getLocation()->getLongitude()
171                ) {
172                    $writer->write($n);
173                }
174            }
175            array_push($this->received_notes, $note);
176        }
177        $writer->finish();
178    }
179
180    private $received_notes = [];
181    private $featureList = [];
182}
183