RouteGuideImpl.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Copyright 2015 gRPC authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. using System;
  15. using System.Collections.Concurrent;
  16. using System.Collections.Generic;
  17. using System.Diagnostics;
  18. using System.Linq;
  19. using System.Text;
  20. using System.Threading.Tasks;
  21. using Grpc.Core;
  22. using Grpc.Core.Utils;
  23. namespace Routeguide
  24. {
  25. /// <summary>
  26. /// Example implementation of RouteGuide server.
  27. /// </summary>
  28. public class RouteGuideImpl : RouteGuide.RouteGuideBase
  29. {
  30. readonly List<Feature> features;
  31. readonly object myLock = new object();
  32. readonly Dictionary<Point, List<RouteNote>> routeNotes = new Dictionary<Point, List<RouteNote>>();
  33. public RouteGuideImpl(List<Feature> features)
  34. {
  35. this.features = features;
  36. }
  37. /// <summary>
  38. /// Gets the feature at the requested point. If no feature at that location
  39. /// exists, an unnammed feature is returned at the provided location.
  40. /// </summary>
  41. public override Task<Feature> GetFeature(Point request, ServerCallContext context)
  42. {
  43. return Task.FromResult(CheckFeature(request));
  44. }
  45. /// <summary>
  46. /// Gets all features contained within the given bounding rectangle.
  47. /// </summary>
  48. public override async Task ListFeatures(Rectangle request, IServerStreamWriter<Feature> responseStream, ServerCallContext context)
  49. {
  50. var responses = features.FindAll( (feature) => feature.Exists() && request.Contains(feature.Location) );
  51. foreach (var response in responses)
  52. {
  53. await responseStream.WriteAsync(response);
  54. }
  55. }
  56. /// <summary>
  57. /// Gets a stream of points, and responds with statistics about the "trip": number of points,
  58. /// number of known features visited, total distance traveled, and total time spent.
  59. /// </summary>
  60. public override async Task<RouteSummary> RecordRoute(IAsyncStreamReader<Point> requestStream, ServerCallContext context)
  61. {
  62. int pointCount = 0;
  63. int featureCount = 0;
  64. int distance = 0;
  65. Point previous = null;
  66. var stopwatch = new Stopwatch();
  67. stopwatch.Start();
  68. while (await requestStream.MoveNext())
  69. {
  70. var point = requestStream.Current;
  71. pointCount++;
  72. if (CheckFeature(point).Exists())
  73. {
  74. featureCount++;
  75. }
  76. if (previous != null)
  77. {
  78. distance += (int) previous.GetDistance(point);
  79. }
  80. previous = point;
  81. }
  82. stopwatch.Stop();
  83. return new RouteSummary
  84. {
  85. PointCount = pointCount,
  86. FeatureCount = featureCount,
  87. Distance = distance,
  88. ElapsedTime = (int)(stopwatch.ElapsedMilliseconds / 1000)
  89. };
  90. }
  91. /// <summary>
  92. /// Receives a stream of message/location pairs, and responds with a stream of all previous
  93. /// messages at each of those locations.
  94. /// </summary>
  95. public override async Task RouteChat(IAsyncStreamReader<RouteNote> requestStream, IServerStreamWriter<RouteNote> responseStream, ServerCallContext context)
  96. {
  97. while (await requestStream.MoveNext())
  98. {
  99. var note = requestStream.Current;
  100. List<RouteNote> prevNotes = AddNoteForLocation(note.Location, note);
  101. foreach (var prevNote in prevNotes)
  102. {
  103. await responseStream.WriteAsync(prevNote);
  104. }
  105. }
  106. }
  107. /// <summary>
  108. /// Adds a note for location and returns a list of pre-existing notes for that location (not containing the newly added note).
  109. /// </summary>
  110. private List<RouteNote> AddNoteForLocation(Point location, RouteNote note)
  111. {
  112. lock (myLock)
  113. {
  114. List<RouteNote> notes;
  115. if (!routeNotes.TryGetValue(location, out notes)) {
  116. notes = new List<RouteNote>();
  117. routeNotes.Add(location, notes);
  118. }
  119. var preexistingNotes = new List<RouteNote>(notes);
  120. notes.Add(note);
  121. return preexistingNotes;
  122. }
  123. }
  124. /// <summary>
  125. /// Gets the feature at the given point.
  126. /// </summary>
  127. /// <param name="location">the location to check</param>
  128. /// <returns>The feature object at the point Note that an empty name indicates no feature.</returns>
  129. private Feature CheckFeature(Point location)
  130. {
  131. var result = features.FirstOrDefault((feature) => feature.Location.Equals(location));
  132. if (result == null)
  133. {
  134. // No feature was found, return an unnamed feature.
  135. return new Feature { Name = "", Location = location };
  136. }
  137. return result;
  138. }
  139. }
  140. }