// Copyright 2024 Google LLC
//
// 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.

syntax = "proto3";

package google.maps.playablelocations.v3.sample;

import "google/api/field_behavior.proto";
import "google/protobuf/field_mask.proto";
import "google/type/latlng.proto";

option csharp_namespace = "Google.Maps.PlayableLocations.V3.Sample";
option go_package = "cloud.google.com/go/maps/playablelocations/apiv3/sample/samplepb;samplepb";
option java_multiple_files = true;
option java_outer_classname = "ResourcesProto";
option java_package = "com.google.maps.playablelocations.v3.sample";
option objc_class_prefix = "GMPL";

// A geographical point suitable for placing game objects in location-based
// games.
message PlayableLocation {
  // Required. The name of this playable location.
  string name = 1;

  // Required.
  // Each location has one of the following identifiers:
  oneof location_id {
    // A [place ID] (https://developers.google.com/places/place-id)
    string place_id = 2;

    // A [plus code] (http://openlocationcode.com)
    string plus_code = 3;
  }

  // A collection of [Playable Location Types](/maps/tt/games/types) for this
  // playable location. The first type in the collection is the primary type.
  //
  // Type information might not be available for all playable locations.
  repeated string types = 4;

  // Required. The latitude and longitude associated with the center of the
  // playable location.
  //
  // By default, the set of playable locations returned from
  // [SamplePlayableLocations][google.maps.playablelocations.v3.PlayableLocations.SamplePlayableLocations]
  // use center-point coordinates.
  google.type.LatLng center_point = 5;

  // The playable location's coordinates, snapped to the sidewalk of the
  // nearest road, if a nearby road exists.
  google.type.LatLng snapped_point = 6;
}

// A set of options that specifies the separation between playable locations.
message SpacingOptions {
  // Specifies whether the playable location's geographic coordinates (latitude
  // and longitude) correspond to its center-point, or to its location snapped
  // to the sidewalk of the nearest road.
  enum PointType {
    // Unspecified point type. Do not use this value.
    POINT_TYPE_UNSPECIFIED = 0;

    // The geographic coordinates correspond to the center of the location.
    CENTER_POINT = 1;

    // The geographic coordinates correspond to the location snapped to the
    // sidewalk of the nearest road (when a nearby road exists).
    SNAPPED_POINT = 2;
  }

  // Required. The minimum spacing between any two playable locations, measured
  // in meters. The minimum value is 30. The maximum value is 1000.
  //
  // Inputs will be rounded up to the next 10 meter interval.
  //
  // The default value is 200m.
  //
  // Set this field to remove tight clusters of playable locations.
  //
  // Note:
  //
  // The spacing is a greedy algorithm. It optimizes for selecting the highest
  // ranking locations first, not to maximize the number of locations selected.
  // Consider the following scenario:
  //
  //   * Rank: A: 2, B: 1, C: 3.
  //   * Distance: A--200m--B--200m--C
  //
  // If spacing=250, it will pick the highest ranked location [B], not [A, C].
  //
  //
  // Note:
  //
  // Spacing works within the game object type itself, as well as the previous
  // ones.
  // Suppose three game object types, each with the following spacing:
  //
  //   * X: 400m, Y: undefined, Z: 200m.
  //
  // 1. Add locations for X, within 400m of each other.
  // 2. Add locations for Y, without any spacing.
  // 3. Finally, add locations for Z within 200m of each other as well X and Y.
  //
  // The distance diagram between those locations end up as:
  //
  //   * From->To.
  //   * X->X: 400m
  //   * Y->X, Y->Y: unspecified.
  //   * Z->X, Z->Y, Z->Z: 200m.
  double min_spacing_meters = 1 [(google.api.field_behavior) = REQUIRED];

  // Specifies whether the minimum spacing constraint applies to the
  // center-point or to the snapped point of playable locations. The default
  // value is `CENTER_POINT`.
  //
  // If a snapped point is not available for a playable location, its
  // center-point is used instead.
  //
  // Set this to the point type used in your game.
  PointType point_type = 2;
}

// Specifies the filters to use when searching for playable locations.
message Filter {
  // Specifies the maximum number of playable locations to return. This value
  // must not be greater than 1000. The default value is 100.
  //
  // Only the top-ranking playable locations are returned.
  int32 max_location_count = 1;

  // A set of options that control the spacing between playable locations. By
  // default the minimum distance between locations is 200m.
  SpacingOptions spacing = 2;

  // Restricts the set of playable locations to just the
  // [types](/maps/tt/games/types) that you want.
  repeated string included_types = 3;
}

// Encapsulates a filter criterion for searching for a set of playable
// locations.
message Criterion {
  // Required. An arbitrary, developer-defined identifier of the type of game
  // object that the playable location is used for. This field allows you to
  // specify criteria per game object type when searching for playable
  // locations.
  //
  // You should assign a unique `game_object_type` ID across all
  // `request_criteria` to represent a distinct type of game object. For
  // example, 1=monster location, 2=powerup location.
  //
  // The response contains a map<game_object_type, Response>.
  int32 game_object_type = 1 [(google.api.field_behavior) = REQUIRED];

  // Specifies filtering options, and specifies what will be included in the
  // result set.
  Filter filter = 2;

  // Specifies which `PlayableLocation` fields are returned.
  //
  // `name` (which is used for logging impressions), `center_point` and
  // `place_id` (or `plus_code`) are always returned.
  //
  // The following fields are omitted unless you specify them here:
  //
  //   * snapped_point
  //   * types
  //
  // Note: The more fields you include, the more expensive in terms of data and
  // associated latency your query will be.
  google.protobuf.FieldMask fields_to_return = 3;
}

// Specifies the area to search for playable locations.
message AreaFilter {
  // Required. The S2 cell ID of the area you want. This must be between cell
  // level 11 and 14 (inclusive).
  //
  // S2 cells are 64-bit integers that identify areas on the Earth. They are
  // hierarchical, and can therefore be used for spatial indexing.
  //
  // The S2 geometry library is available in a number of languages:
  //
  //   * [C++](https://github.com/google/s2geometry)
  //   * [Java](https://github.com/google/s2-geometry-library-java)
  //   * [Go](https://github.com/golang/geo)
  //   * [Python](https://github.com/google/s2geometry/tree/master/src/python)
  fixed64 s2_cell_id = 1 [(google.api.field_behavior) = REQUIRED];
}

// A list of PlayableLocation objects that satisfies a single Criterion.
message PlayableLocationList {
  // A list of playable locations for this game object type.
  repeated PlayableLocation locations = 1;
}
