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