// RouteGuideServer is the server API for RouteGuide service. type RouteGuideServer interface { GetFeature(context.Context, *Point) (*Feature, error) ListFeature(*Rectangle, RouteGuide_ListFeatureServer) error RecordRoute(RouteGuide_RecordRouteServer) error RouteChat(RouteGuide_RouteChatServer) error }
// UnimplementedRouteGuideServer can be embedded to have forward compatible implementations. type UnimplementedRouteGuideServer struct { }
type routeGuideServer struct { pb.UnimplementedRouteGuideServer // 模拟地点数据 features []*pb.Feature }
// 根据经纬度获取地点信息 func(s *routeGuideServer)GetFeature(ctx context.Context, point *pb.Point)(*pb.Feature, error) { for _,feature := range s.features { if proto.Equal(feature.Location,point){ return feature, nil } } returnnil, nil }
// check if a point is inside a rectangle. funcinRange(point *pb.Point,rect *pb.Rectangle)bool{ left := math.Min(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude)) right := math.Max(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude)) top := math.Max(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude)) bottom := math.Min(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude))
iffloat64(point.Longitude) >= left && float64(point.Longitude) <= right && float64(point.Latitude) >= bottom && float64(point.Latitude) <= top { returntrue } returnfalse }
// 根据长方形区域获取该地区的所有地点信息 func(s *routeGuideServer)ListFeature(rectangle *pb.Rectangle,stream pb.RouteGuide_ListFeatureServer)error { for _,feature := range s.features{ if inRange(feature.Location,rectangle){ err := stream.Send(feature) if err != nil { panic(err) } } } returnnil }
funccomputeDistance(x *pb.Point, y *pb.Point)int32{ a := (x.Latitude - y.Latitude) * (x.Latitude - y.Latitude) b := (x.Longitude - y.Longitude) * (x.Longitude - y.Longitude) returnint32(math.Sqrt(float64(a + b))) }
// 根据客户端的地点信息输入流(路程信息),返回该段路程的汇总统计 func(s *routeGuideServer)RecordRoute(stream pb.RouteGuide_RecordRouteServer)error { startTime := time.Now() var pointCount,distance int32 var prevPoint *pb.Point for{ point, err := stream.Recv() if err != nil { endTime := time.Now() return stream.SendAndClose(&pb.RouteSummary{ Distance: distance, PointCount: pointCount, ElapsedTime: int32(endTime.Sub(startTime).Seconds()), }) }
if err != nil{ return err }
pointCount++ if prevPoint != nil{ distance += computeDistance(prevPoint,point) } prevPoint = point } }
func(s *routeGuideServer)recommendedOnce(request *pb.RecommendationRequest) *pb.Feature { var nearest,farthest *pb.Feature var nearestDistance,farthestDistance int32
for _,feature := range s.features{ dis := computeDistance(feature.Location,request.Point) if nearest == nil || dis < nearestDistance{ nearestDistance = dis nearest = feature } if farthest == nil || dis > farthestDistance{ farthestDistance = dis farthest = feature } }