123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- // Copyright 2015 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.
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using Grpc.Core;
- using Grpc.Core.Utils;
- namespace Routeguide
- {
- /// <summary>
- /// Example implementation of RouteGuide server.
- /// </summary>
- public class RouteGuideImpl : RouteGuide.RouteGuideBase
- {
- readonly List<Feature> features;
- readonly object myLock = new object();
- readonly Dictionary<Point, List<RouteNote>> routeNotes = new Dictionary<Point, List<RouteNote>>();
- public RouteGuideImpl(List<Feature> features)
- {
- this.features = features;
- }
- /// <summary>
- /// Gets the feature at the requested point. If no feature at that location
- /// exists, an unnammed feature is returned at the provided location.
- /// </summary>
- public override Task<Feature> GetFeature(Point request, ServerCallContext context)
- {
- return Task.FromResult(CheckFeature(request));
- }
- /// <summary>
- /// Gets all features contained within the given bounding rectangle.
- /// </summary>
- public override async Task ListFeatures(Rectangle request, IServerStreamWriter<Feature> responseStream, ServerCallContext context)
- {
- var responses = features.FindAll( (feature) => feature.Exists() && request.Contains(feature.Location) );
- foreach (var response in responses)
- {
- await responseStream.WriteAsync(response);
- }
- }
- /// <summary>
- /// Gets a stream of points, and responds with statistics about the "trip": number of points,
- /// number of known features visited, total distance traveled, and total time spent.
- /// </summary>
- public override async Task<RouteSummary> RecordRoute(IAsyncStreamReader<Point> requestStream, ServerCallContext context)
- {
- int pointCount = 0;
- int featureCount = 0;
- int distance = 0;
- Point previous = null;
- var stopwatch = new Stopwatch();
- stopwatch.Start();
- while (await requestStream.MoveNext())
- {
- var point = requestStream.Current;
- pointCount++;
- if (CheckFeature(point).Exists())
- {
- featureCount++;
- }
- if (previous != null)
- {
- distance += (int) previous.GetDistance(point);
- }
- previous = point;
- }
- stopwatch.Stop();
-
- return new RouteSummary
- {
- PointCount = pointCount,
- FeatureCount = featureCount,
- Distance = distance,
- ElapsedTime = (int)(stopwatch.ElapsedMilliseconds / 1000)
- };
- }
- /// <summary>
- /// Receives a stream of message/location pairs, and responds with a stream of all previous
- /// messages at each of those locations.
- /// </summary>
- public override async Task RouteChat(IAsyncStreamReader<RouteNote> requestStream, IServerStreamWriter<RouteNote> responseStream, ServerCallContext context)
- {
- while (await requestStream.MoveNext())
- {
- var note = requestStream.Current;
- List<RouteNote> prevNotes = AddNoteForLocation(note.Location, note);
- foreach (var prevNote in prevNotes)
- {
- await responseStream.WriteAsync(prevNote);
- }
- }
- }
- /// <summary>
- /// Adds a note for location and returns a list of pre-existing notes for that location (not containing the newly added note).
- /// </summary>
- private List<RouteNote> AddNoteForLocation(Point location, RouteNote note)
- {
- lock (myLock)
- {
- List<RouteNote> notes;
- if (!routeNotes.TryGetValue(location, out notes)) {
- notes = new List<RouteNote>();
- routeNotes.Add(location, notes);
- }
- var preexistingNotes = new List<RouteNote>(notes);
- notes.Add(note);
- return preexistingNotes;
- }
- }
- /// <summary>
- /// Gets the feature at the given point.
- /// </summary>
- /// <param name="location">the location to check</param>
- /// <returns>The feature object at the point Note that an empty name indicates no feature.</returns>
- private Feature CheckFeature(Point location)
- {
- var result = features.FirstOrDefault((feature) => feature.Location.Equals(location));
- if (result == null)
- {
- // No feature was found, return an unnamed feature.
- return new Feature { Name = "", Location = location };
- }
- return result;
- }
- }
- }
|