diff --git a/CHANGELOG.md b/CHANGELOG.md index 97a33fef90b8b90c97ac3a4c26db5d9a1dcaa14b..bfd2919c3295e49e91dbfce074ff27e024408187 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,12 +8,14 @@ The format is based on [keep a changelog](http://keepachangelog.com) and this pr - Explicitly set cache control header in all API responses. - Add support for CockroachDB 19.1. - Add tournament start active timestamp to the API response. +- Add overridable expiry time when listing leaderboard/tournaments records. ### Changed - Tournament start time can be set to past time. ### Fixed -- Fix delayed first time invocation of tournament and leaderboard callbacks. +- Fix delayed first time invocation of tournament and leaderboard callbacks. +- Expired tournaments will no longer be listed nor any records will be returned. ## [2.5.1] - 2019-05-03 ### Changed diff --git a/api/api.pb.go b/api/api.pb.go index 79eeb51d07cae8f066eb975a0f8cc6b16de01b7d..53190b5a1daffa24c41ed4a1d66062d5ff858ce1 100644 --- a/api/api.pb.go +++ b/api/api.pb.go @@ -2797,10 +2797,12 @@ type ListLeaderboardRecordsAroundOwnerRequest struct { // Max number of records to return. Between 1 and 100. Limit *wrappers.UInt32Value `protobuf:"bytes,2,opt,name=limit,proto3" json:"limit,omitempty"` // The owner to retrieve records around. - OwnerId string `protobuf:"bytes,3,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + OwnerId string `protobuf:"bytes,3,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` + // Expiry in seconds (since epoch) to begin fetching records from. + Expiry *wrappers.Int64Value `protobuf:"bytes,4,opt,name=expiry,proto3" json:"expiry,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ListLeaderboardRecordsAroundOwnerRequest) Reset() { @@ -2851,6 +2853,13 @@ func (m *ListLeaderboardRecordsAroundOwnerRequest) GetOwnerId() string { return "" } +func (m *ListLeaderboardRecordsAroundOwnerRequest) GetExpiry() *wrappers.Int64Value { + if m != nil { + return m.Expiry + } + return nil +} + // List leaderboard records from a given leaderboard. type ListLeaderboardRecordsRequest struct { // The ID of the leaderboard to list for. @@ -2860,10 +2869,12 @@ type ListLeaderboardRecordsRequest struct { // Max number of records to return. Between 1 and 100. Limit *wrappers.Int32Value `protobuf:"bytes,3,opt,name=limit,proto3" json:"limit,omitempty"` // A next or previous page cursor. - Cursor string `protobuf:"bytes,4,opt,name=cursor,proto3" json:"cursor,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Cursor string `protobuf:"bytes,4,opt,name=cursor,proto3" json:"cursor,omitempty"` + // Expiry in seconds (since epoch) to begin fetching records from. Optional. 0 means from current time. + Expiry *wrappers.Int64Value `protobuf:"bytes,5,opt,name=expiry,proto3" json:"expiry,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ListLeaderboardRecordsRequest) Reset() { *m = ListLeaderboardRecordsRequest{} } @@ -2919,6 +2930,13 @@ func (m *ListLeaderboardRecordsRequest) GetCursor() string { return "" } +func (m *ListLeaderboardRecordsRequest) GetExpiry() *wrappers.Int64Value { + if m != nil { + return m.Expiry + } + return nil +} + // List realtime matches. type ListMatchesRequest struct { // Limit the number of returned matches. @@ -3130,10 +3148,12 @@ type ListTournamentRecordsAroundOwnerRequest struct { // Max number of records to return. Between 1 and 100. Limit *wrappers.UInt32Value `protobuf:"bytes,2,opt,name=limit,proto3" json:"limit,omitempty"` // The owner to retrieve records around. - OwnerId string `protobuf:"bytes,3,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + OwnerId string `protobuf:"bytes,3,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` + // Expiry in seconds (since epoch) to begin fetching records from. + Expiry *wrappers.Int64Value `protobuf:"bytes,4,opt,name=expiry,proto3" json:"expiry,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ListTournamentRecordsAroundOwnerRequest) Reset() { @@ -3184,6 +3204,13 @@ func (m *ListTournamentRecordsAroundOwnerRequest) GetOwnerId() string { return "" } +func (m *ListTournamentRecordsAroundOwnerRequest) GetExpiry() *wrappers.Int64Value { + if m != nil { + return m.Expiry + } + return nil +} + // List tournament records from a given tournament. type ListTournamentRecordsRequest struct { // The ID of the tournament to list for. @@ -3193,10 +3220,12 @@ type ListTournamentRecordsRequest struct { // Max number of records to return. Between 1 and 100. Limit *wrappers.Int32Value `protobuf:"bytes,3,opt,name=limit,proto3" json:"limit,omitempty"` // A next or previous page cursor. - Cursor string `protobuf:"bytes,4,opt,name=cursor,proto3" json:"cursor,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Cursor string `protobuf:"bytes,4,opt,name=cursor,proto3" json:"cursor,omitempty"` + // Expiry in seconds (since epoch) to begin fetching records from. + Expiry *wrappers.Int64Value `protobuf:"bytes,5,opt,name=expiry,proto3" json:"expiry,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ListTournamentRecordsRequest) Reset() { *m = ListTournamentRecordsRequest{} } @@ -3252,6 +3281,13 @@ func (m *ListTournamentRecordsRequest) GetCursor() string { return "" } +func (m *ListTournamentRecordsRequest) GetExpiry() *wrappers.Int64Value { + if m != nil { + return m.Expiry + } + return nil +} + // List active/upcoming tournaments based on given filters. type ListTournamentsRequest struct { // The start of the categories to include. Defaults to 0. @@ -5444,215 +5480,217 @@ func init() { func init() { proto.RegisterFile("api/api.proto", fileDescriptor_1b40cafcd4234784) } var fileDescriptor_1b40cafcd4234784 = []byte{ - // 3354 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x1a, 0x4d, 0x8f, 0x1c, 0x47, - 0x35, 0x3d, 0xdf, 0xf3, 0x66, 0x67, 0x77, 0xb6, 0xfc, 0xc1, 0x78, 0xfc, 0xdd, 0x76, 0xb0, 0xa3, - 0xc0, 0x38, 0x59, 0x13, 0x6c, 0x12, 0xe2, 0x78, 0x3f, 0xc6, 0xd6, 0xc4, 0xf6, 0xda, 0xf4, 0xda, - 0x06, 0xc1, 0x61, 0x52, 0xdb, 0x5d, 0x1e, 0x37, 0xdb, 0xd3, 0xdd, 0xe9, 0xee, 0x59, 0xef, 0x46, - 0x70, 0x00, 0x21, 0x91, 0x13, 0x42, 0x9c, 0xb8, 0x00, 0x11, 0x07, 0x94, 0x80, 0xc4, 0x2f, 0xe0, - 0x9e, 0x3b, 0xe2, 0xeb, 0x06, 0x1c, 0x91, 0xf8, 0x07, 0x48, 0x08, 0xd5, 0xab, 0xea, 0xcf, 0x99, - 0xd9, 0x9d, 0xf1, 0xae, 0x13, 0x89, 0xcb, 0xa8, 0xeb, 0xd5, 0x7b, 0x55, 0xaf, 0x5e, 0xbd, 0xef, - 0x1a, 0xa8, 0x53, 0xd7, 0xbc, 0x42, 0x5d, 0xb3, 0xed, 0x7a, 0x4e, 0xe0, 0x10, 0xb0, 0xe9, 0x16, - 0x1d, 0xd0, 0x36, 0x75, 0xcd, 0xd6, 0xd9, 0xbe, 0xe3, 0xf4, 0x2d, 0x76, 0x05, 0x67, 0x36, 0x87, - 0x4f, 0xae, 0x04, 0xe6, 0x80, 0xf9, 0x01, 0x1d, 0xb8, 0x02, 0xb9, 0x75, 0x26, 0x8b, 0xf0, 0xcc, - 0xa3, 0xae, 0xcb, 0x3c, 0x5f, 0xcc, 0xab, 0xff, 0x56, 0xa0, 0xbc, 0xac, 0xeb, 0xce, 0xd0, 0x0e, - 0xc8, 0x45, 0x28, 0x0c, 0x7d, 0xe6, 0x35, 0x95, 0x73, 0xca, 0xe5, 0xda, 0x52, 0xa3, 0x1d, 0xef, - 0xd3, 0x7e, 0xe4, 0x33, 0x4f, 0xc3, 0x59, 0x72, 0x1c, 0x4a, 0xcf, 0xa8, 0x65, 0xb1, 0xa0, 0x99, - 0x3b, 0xa7, 0x5c, 0xae, 0x6a, 0x72, 0x44, 0x8e, 0x42, 0x91, 0x0d, 0xa8, 0x69, 0x35, 0xf3, 0x08, - 0x16, 0x03, 0x72, 0x15, 0xca, 0x06, 0xdb, 0x36, 0x75, 0xe6, 0x37, 0x0b, 0xe7, 0xf2, 0x97, 0x6b, - 0x4b, 0x27, 0x92, 0xcb, 0xca, 0x9d, 0xd7, 0x10, 0x43, 0x0b, 0x31, 0xc9, 0x49, 0xa8, 0xea, 0x43, - 0x3f, 0x70, 0x06, 0x3d, 0xd3, 0x68, 0x16, 0x71, 0xb9, 0x8a, 0x00, 0x74, 0x0d, 0xf2, 0x16, 0xd4, - 0xb6, 0x99, 0x67, 0x3e, 0xd9, 0xed, 0xf1, 0xb3, 0x36, 0x4b, 0xc8, 0x6c, 0xab, 0x2d, 0xce, 0xd9, - 0x0e, 0xcf, 0xd9, 0x7e, 0x18, 0x0a, 0x42, 0x03, 0x81, 0xce, 0x01, 0xea, 0x59, 0xa8, 0xcb, 0x3d, - 0x57, 0x71, 0x3d, 0x32, 0x0f, 0x39, 0xd3, 0xc0, 0x13, 0x57, 0xb5, 0x9c, 0x69, 0x24, 0x10, 0x04, - 0x53, 0x23, 0x08, 0x37, 0x61, 0x4e, 0x22, 0x74, 0xf0, 0x80, 0xd1, 0xb1, 0x95, 0xe4, 0xb1, 0x5b, - 0x50, 0x71, 0xa9, 0xef, 0x3f, 0x73, 0x3c, 0x43, 0x8a, 0x29, 0x1a, 0xab, 0x97, 0x60, 0x41, 0xae, - 0x70, 0x8b, 0xea, 0x6c, 0xd3, 0x71, 0xb6, 0xf8, 0x22, 0x81, 0xb3, 0xc5, 0xec, 0x70, 0x11, 0x1c, - 0xa8, 0x7f, 0x54, 0x60, 0x51, 0x62, 0xde, 0xa6, 0x03, 0xb6, 0xca, 0xec, 0x80, 0x79, 0x5c, 0x38, - 0xae, 0x45, 0x77, 0x99, 0xd7, 0x8b, 0xf8, 0xaa, 0x08, 0x40, 0xd7, 0xe0, 0x93, 0x9b, 0x43, 0xdb, - 0xb0, 0x18, 0x9f, 0x94, 0x1b, 0x0b, 0x40, 0xd7, 0x20, 0xaf, 0xc2, 0x62, 0xa4, 0x1e, 0x3d, 0x9f, - 0xe9, 0x8e, 0x6d, 0xf8, 0x78, 0x5b, 0x79, 0xad, 0x11, 0x4d, 0x6c, 0x08, 0x38, 0x21, 0x50, 0xf0, - 0xa9, 0x15, 0x34, 0x0b, 0xb8, 0x08, 0x7e, 0x93, 0x53, 0x50, 0xf5, 0xcd, 0xbe, 0x4d, 0x83, 0xa1, - 0xc7, 0xe4, 0xbd, 0xc4, 0x00, 0x72, 0x11, 0xe6, 0xdd, 0xe1, 0xa6, 0x65, 0xea, 0xbd, 0x2d, 0xb6, - 0xdb, 0x1b, 0x7a, 0x16, 0xde, 0x4d, 0x55, 0x9b, 0x13, 0xd0, 0x3b, 0x6c, 0xf7, 0x91, 0x67, 0xa9, - 0x2f, 0x47, 0x02, 0xbe, 0x8d, 0x37, 0x36, 0xe1, 0xec, 0x17, 0x23, 0x31, 0x6f, 0x04, 0x8c, 0x0e, - 0x26, 0x60, 0xad, 0xc2, 0xe2, 0xb2, 0x61, 0xdc, 0xf2, 0x4c, 0x66, 0x1b, 0xbe, 0xc6, 0xde, 0x1f, - 0x32, 0x3f, 0x20, 0x0d, 0xc8, 0x9b, 0x86, 0xdf, 0x54, 0xce, 0xe5, 0x2f, 0x57, 0x35, 0xfe, 0xc9, - 0xf9, 0xe6, 0xaa, 0x6b, 0xd3, 0x01, 0xf3, 0x9b, 0x39, 0x84, 0xc7, 0x00, 0xf5, 0x2e, 0x1c, 0x5d, - 0x36, 0x8c, 0xdb, 0x9e, 0x33, 0x74, 0xb9, 0x9a, 0x47, 0xeb, 0x9c, 0x80, 0x4a, 0x9f, 0x03, 0x63, - 0x39, 0x97, 0x71, 0xdc, 0x35, 0xf8, 0x14, 0xa7, 0xef, 0xf1, 0x7d, 0xc4, 0x7a, 0x65, 0x3e, 0xee, - 0x1a, 0xbe, 0xfa, 0x91, 0x02, 0x27, 0x96, 0x87, 0xc1, 0x53, 0x66, 0x07, 0xa6, 0x4e, 0x03, 0x26, - 0xf4, 0x2c, 0x5c, 0xf3, 0x2a, 0x94, 0xa9, 0x38, 0x96, 0xb4, 0xb2, 0x71, 0xe6, 0x20, 0x49, 0x42, - 0x4c, 0xb2, 0x04, 0x25, 0xdd, 0x63, 0x34, 0x60, 0x78, 0xa3, 0xe3, 0x94, 0x7d, 0xc5, 0x71, 0xac, - 0xc7, 0xd4, 0x1a, 0x32, 0x4d, 0x62, 0x72, 0x05, 0x0c, 0x4f, 0x28, 0x0d, 0x32, 0x1a, 0x8f, 0xb0, - 0x28, 0xcd, 0x6f, 0x16, 0x16, 0x43, 0x8b, 0x7d, 0x51, 0x2c, 0xfe, 0x52, 0x81, 0x66, 0x92, 0x45, - 0xb4, 0xb5, 0x90, 0xc3, 0xa5, 0x2c, 0x87, 0xcd, 0x31, 0x1c, 0x0a, 0x8a, 0x17, 0xc6, 0xe0, 0x9f, - 0x14, 0x38, 0x99, 0x64, 0x30, 0x34, 0xe5, 0x90, 0xc7, 0x37, 0xb2, 0x3c, 0x9e, 0x1c, 0xc3, 0x63, - 0x44, 0xf4, 0xa2, 0xd8, 0x24, 0x6d, 0x28, 0xf8, 0xbb, 0xb6, 0x8e, 0x56, 0xbc, 0xf7, 0x6a, 0x88, - 0xa7, 0x7e, 0xac, 0xc0, 0xe9, 0xe4, 0xb1, 0x62, 0xbf, 0x13, 0x1e, 0xec, 0x5a, 0xf6, 0x60, 0xa7, - 0xc7, 0x1c, 0x2c, 0x41, 0xf6, 0x99, 0x69, 0xb1, 0x70, 0x27, 0x33, 0x69, 0xb1, 0x24, 0xf9, 0xcc, - 0xb4, 0x18, 0x5d, 0xd9, 0x4c, 0x5a, 0x2c, 0x28, 0x5e, 0x18, 0x83, 0x1d, 0x38, 0xb2, 0x62, 0x39, - 0xfa, 0xd6, 0x01, 0x3d, 0xe8, 0x87, 0x79, 0x98, 0x5f, 0x7d, 0x4a, 0x6d, 0x9b, 0x59, 0xf7, 0x98, - 0xef, 0xd3, 0x3e, 0x23, 0xa7, 0x01, 0x74, 0x01, 0x89, 0xdd, 0x67, 0x55, 0x42, 0xba, 0x06, 0x9f, - 0x1e, 0x08, 0xcc, 0x38, 0x50, 0x55, 0x25, 0xa4, 0x6b, 0x90, 0x2b, 0x50, 0xd0, 0x1d, 0x43, 0xf0, - 0xcb, 0x4d, 0x27, 0x7b, 0xca, 0xae, 0x1d, 0x5c, 0x5d, 0x92, 0x7a, 0xcb, 0x11, 0x79, 0xdc, 0xf3, - 0x99, 0x6d, 0x88, 0xa0, 0x28, 0x42, 0x56, 0x45, 0x00, 0xba, 0x46, 0x4a, 0x02, 0xc5, 0x8c, 0x81, - 0x34, 0xa1, 0xac, 0x3b, 0x76, 0xc0, 0xec, 0x40, 0x46, 0xab, 0x70, 0xc8, 0xf3, 0x0c, 0x21, 0x41, - 0x91, 0x67, 0x94, 0xf7, 0xcf, 0x33, 0x04, 0x3a, 0x07, 0x70, 0xe2, 0xa1, 0x6b, 0x44, 0xc4, 0x95, - 0xfd, 0x89, 0x05, 0x3a, 0x12, 0xbf, 0x09, 0xc0, 0x33, 0x34, 0xd3, 0x47, 0xb6, 0xaa, 0xfb, 0xde, - 0x74, 0x02, 0x5b, 0xfd, 0x89, 0x02, 0x24, 0x7d, 0x15, 0x77, 0x4d, 0x3f, 0x20, 0x5f, 0x85, 0x8a, - 0x94, 0xae, 0xb8, 0x56, 0xbe, 0x60, 0x42, 0xdb, 0xd2, 0x14, 0x5a, 0x84, 0x4b, 0xce, 0x42, 0xcd, - 0x66, 0x3b, 0x41, 0x4f, 0x1f, 0x7a, 0xbe, 0xe3, 0xc9, 0x8b, 0x02, 0x0e, 0x5a, 0x45, 0x08, 0x47, - 0x70, 0x3d, 0xb6, 0x1d, 0x22, 0x08, 0x05, 0x03, 0x0e, 0x12, 0x08, 0xea, 0xcf, 0x39, 0x43, 0x28, - 0x18, 0x8c, 0xb0, 0xa1, 0x8a, 0x11, 0x28, 0xe0, 0x7d, 0x08, 0xcd, 0xc0, 0x6f, 0x72, 0x0e, 0x6a, - 0x06, 0xf3, 0x75, 0xcf, 0x74, 0x03, 0xd3, 0xb1, 0xe5, 0x66, 0x49, 0x10, 0x8f, 0xbb, 0x16, 0xb5, - 0xfb, 0xbd, 0x80, 0xf6, 0xe5, 0x56, 0x65, 0x3e, 0x7e, 0x48, 0xfb, 0x5c, 0xa3, 0xe8, 0x36, 0x0d, - 0xa8, 0x87, 0x99, 0x87, 0x50, 0x81, 0xaa, 0x80, 0x3c, 0xf2, 0x2c, 0xbe, 0x9f, 0xe3, 0x32, 0x1b, - 0xef, 0xbf, 0xa2, 0xe1, 0xb7, 0x7a, 0x0b, 0x8e, 0xae, 0x31, 0x8b, 0x05, 0xec, 0x80, 0xea, 0x7f, - 0x05, 0x88, 0x58, 0x27, 0x75, 0xc2, 0xc9, 0xe9, 0x83, 0x7a, 0x1b, 0xce, 0x08, 0x82, 0xbb, 0x8c, - 0x1a, 0xcc, 0xdb, 0x74, 0xa8, 0x67, 0x68, 0x4c, 0x77, 0xf8, 0xaf, 0x20, 0x7e, 0x19, 0xe6, 0xad, - 0x78, 0x2e, 0x5e, 0xa2, 0x9e, 0x80, 0x76, 0x0d, 0xb5, 0x0d, 0x2d, 0xb1, 0xd0, 0xba, 0x13, 0x98, - 0x4f, 0xb8, 0x8f, 0x31, 0x1d, 0x7b, 0xf2, 0x39, 0x54, 0x1d, 0x8e, 0x09, 0xfc, 0x8d, 0xc0, 0xf1, - 0x68, 0x9f, 0xdd, 0xdf, 0xfc, 0x2e, 0xd3, 0x83, 0xae, 0x41, 0xce, 0x00, 0xe8, 0x8e, 0x65, 0x31, - 0x1d, 0x25, 0x2f, 0xf6, 0x4a, 0x40, 0xf8, 0x52, 0x5b, 0x6c, 0x57, 0x5e, 0x09, 0xff, 0xe4, 0x86, - 0xb3, 0xcd, 0xd5, 0xce, 0xb1, 0xc3, 0x9b, 0x90, 0x43, 0xb5, 0x07, 0x27, 0xc7, 0x6c, 0x12, 0x71, - 0x75, 0x13, 0xc0, 0x41, 0x48, 0x2f, 0x64, 0xae, 0xb6, 0x74, 0x3e, 0xa9, 0x8c, 0x63, 0x39, 0xd4, - 0xaa, 0x8e, 0xfc, 0xf2, 0xd5, 0xbf, 0x2a, 0x50, 0xec, 0x6c, 0x73, 0x1b, 0x1d, 0xa7, 0x45, 0xcb, - 0x00, 0xae, 0xe7, 0xb8, 0xcc, 0x0b, 0x4c, 0x79, 0x59, 0x99, 0xf5, 0x91, 0xb4, 0xfd, 0x20, 0xc2, - 0xe9, 0xd8, 0x81, 0xb7, 0xab, 0x25, 0x88, 0xc8, 0x75, 0xa8, 0x46, 0xf9, 0xb0, 0xf4, 0x41, 0x7b, - 0xd9, 0x6e, 0x8c, 0xdc, 0x7a, 0x1b, 0x16, 0x32, 0x0b, 0x87, 0xa2, 0x53, 0x62, 0xd1, 0x1d, 0x85, - 0xe2, 0x36, 0x37, 0x5c, 0x29, 0x4e, 0x31, 0x78, 0x33, 0x77, 0x5d, 0x51, 0x3f, 0x51, 0xa0, 0x24, - 0x94, 0x71, 0xca, 0x62, 0xec, 0x75, 0x28, 0xfa, 0x41, 0x1c, 0x0f, 0xf6, 0xf4, 0x94, 0x02, 0x53, - 0xbd, 0x05, 0xc5, 0x0d, 0xfe, 0x41, 0x00, 0x4a, 0xb7, 0xb4, 0x6e, 0x67, 0x7d, 0xad, 0xf1, 0x12, - 0x59, 0x80, 0x5a, 0x77, 0xfd, 0x71, 0xf7, 0x61, 0xa7, 0xb7, 0xd1, 0x59, 0x7f, 0xd8, 0x50, 0xc8, - 0x11, 0x58, 0x90, 0x00, 0xad, 0xb3, 0xda, 0xe9, 0x3e, 0xee, 0xac, 0x35, 0x72, 0xa4, 0x06, 0xe5, - 0x95, 0xbb, 0xf7, 0x57, 0xef, 0x74, 0xd6, 0x1a, 0x79, 0xf5, 0x1a, 0x94, 0xa5, 0xdd, 0x90, 0x2f, - 0x41, 0xf9, 0x89, 0xf8, 0x94, 0xf7, 0x49, 0x92, 0xec, 0x0a, 0x2c, 0x2d, 0x44, 0x51, 0x0d, 0x58, - 0xb8, 0xcd, 0x82, 0x54, 0xaa, 0x3d, 0xa3, 0xc5, 0x91, 0xf3, 0x30, 0xf7, 0x44, 0xe6, 0x4e, 0xa8, - 0x45, 0x79, 0x44, 0xa8, 0x85, 0x30, 0xae, 0x24, 0x1f, 0xe7, 0xa1, 0x88, 0xf6, 0x98, 0xad, 0xe0, - 0x30, 0x34, 0x71, 0x87, 0xe4, 0x78, 0x89, 0xd8, 0x23, 0x21, 0x5d, 0x23, 0xd2, 0xa9, 0xfc, 0x64, - 0xcf, 0x54, 0xd8, 0xdb, 0x33, 0x15, 0xd3, 0x9e, 0xa9, 0xc5, 0x7d, 0x6f, 0x40, 0x0d, 0x1a, 0x50, - 0x19, 0x63, 0xa2, 0x71, 0xc6, 0x6b, 0x95, 0xb3, 0x5e, 0xab, 0x2d, 0xbd, 0x56, 0x65, 0xff, 0xf4, - 0x8d, 0xe3, 0xf1, 0xe5, 0x98, 0xd1, 0x67, 0x3d, 0x91, 0x56, 0xf0, 0xc8, 0x51, 0xd4, 0xaa, 0x1c, - 0xb2, 0x8a, 0xe9, 0xc3, 0x49, 0xa8, 0x0e, 0xe8, 0x8e, 0x9c, 0x05, 0x9c, 0xad, 0x0c, 0xe8, 0x8e, - 0x98, 0xcc, 0xc4, 0xbb, 0xda, 0x41, 0xe2, 0xdd, 0xdc, 0x2c, 0xf1, 0x4e, 0x5d, 0x87, 0x2a, 0xde, - 0x14, 0x46, 0xaa, 0x57, 0xa0, 0x84, 0x6e, 0x32, 0x54, 0xa5, 0xc5, 0xa4, 0x2a, 0x09, 0x07, 0x2b, - 0x11, 0xc8, 0x71, 0x28, 0xa5, 0xe2, 0x92, 0x1c, 0xa9, 0xff, 0x55, 0xa0, 0x1e, 0x95, 0x73, 0xb8, - 0xe8, 0x1a, 0xd4, 0x84, 0x2f, 0xe6, 0x2a, 0x14, 0xae, 0x7c, 0x61, 0x64, 0xe5, 0x10, 0x3f, 0x1e, - 0x69, 0xd0, 0x8f, 0xea, 0xc2, 0xd6, 0x6f, 0x14, 0xc9, 0x28, 0x1f, 0xbe, 0x38, 0x03, 0xbd, 0x19, - 0x1a, 0xe8, 0x3c, 0xc0, 0xc6, 0xa3, 0x07, 0x1d, 0x6d, 0x79, 0xed, 0x5e, 0x77, 0xbd, 0xf1, 0x12, - 0xa9, 0x42, 0x51, 0x7c, 0x2a, 0xdc, 0x76, 0xef, 0x75, 0xee, 0xad, 0x74, 0xb4, 0x46, 0x8e, 0x34, - 0x60, 0xee, 0xdd, 0xfb, 0xdd, 0xf5, 0x9e, 0xd6, 0xf9, 0xc6, 0xa3, 0xce, 0xc6, 0xc3, 0x46, 0x5e, - 0xfd, 0xb1, 0x02, 0xa7, 0xba, 0x03, 0xd7, 0xf1, 0xa2, 0x0a, 0x23, 0x13, 0xe1, 0x9e, 0xb3, 0x3a, - 0x79, 0x0d, 0x8a, 0x1e, 0xf3, 0x65, 0xe7, 0x67, 0x6f, 0x7d, 0x14, 0x88, 0xea, 0x97, 0xa1, 0xf1, - 0xae, 0x63, 0xda, 0xd3, 0x06, 0xc6, 0xaf, 0xc3, 0x31, 0x8e, 0xfe, 0xd0, 0x19, 0xa2, 0xa1, 0xdb, - 0x41, 0x48, 0x73, 0x01, 0xea, 0x41, 0x04, 0x8c, 0x09, 0xe7, 0x62, 0x60, 0xd7, 0x50, 0xef, 0xc1, - 0xb1, 0x3b, 0xa6, 0xbe, 0x75, 0x58, 0x95, 0xfc, 0xbf, 0xf2, 0xb0, 0x38, 0x12, 0xa0, 0xa7, 0x8c, - 0xcc, 0x7c, 0x5d, 0xe7, 0x99, 0xcd, 0x12, 0x2e, 0xa6, 0x8c, 0xe3, 0xae, 0x41, 0xae, 0x67, 0x12, - 0xf2, 0xda, 0xd2, 0xa9, 0x11, 0x41, 0x6e, 0x04, 0x9e, 0x69, 0xf7, 0x85, 0x28, 0xe3, 0x64, 0xf5, - 0x28, 0x14, 0x7d, 0xdd, 0xf1, 0x18, 0x3a, 0xa0, 0xbc, 0x26, 0x06, 0xdc, 0xbf, 0xf8, 0xc3, 0x4d, - 0x31, 0x51, 0xc4, 0x89, 0x68, 0xcc, 0x2d, 0xde, 0x1e, 0x0e, 0x7a, 0x62, 0xb2, 0x24, 0x2c, 0xde, - 0x1e, 0x0e, 0x36, 0x42, 0xc2, 0xc8, 0x31, 0x95, 0x33, 0x8e, 0x29, 0xe3, 0x0d, 0x2a, 0x07, 0xf1, - 0x06, 0xd5, 0x99, 0xb2, 0xdf, 0xb7, 0xa0, 0xc6, 0x76, 0x5c, 0xd3, 0x93, 0xfd, 0x3d, 0xd8, 0x9f, - 0x58, 0xa0, 0x23, 0x31, 0x81, 0x82, 0x47, 0xed, 0x2d, 0xf4, 0x5e, 0x79, 0x0d, 0xbf, 0x89, 0x0a, - 0x75, 0xee, 0xf5, 0x62, 0x39, 0x70, 0xef, 0x54, 0xd7, 0x6a, 0x03, 0xba, 0xb3, 0x2e, 0x45, 0xa1, - 0xfe, 0x45, 0x81, 0x63, 0x23, 0x77, 0x8d, 0xae, 0xe3, 0x1a, 0x94, 0x3d, 0x1c, 0x85, 0x6e, 0x23, - 0x55, 0xef, 0x8e, 0x26, 0x70, 0x21, 0x36, 0x59, 0x81, 0xba, 0xd0, 0x80, 0x90, 0x3c, 0x37, 0x0d, - 0xf9, 0x1c, 0xd2, 0x68, 0x72, 0x8d, 0x4c, 0xfa, 0x9d, 0xdf, 0x2f, 0xfd, 0x2e, 0x8c, 0xa4, 0xdf, - 0x6d, 0xd4, 0xe1, 0xed, 0xa9, 0x53, 0xd3, 0xef, 0xc1, 0x91, 0xbb, 0xa6, 0xbd, 0x75, 0x48, 0xed, - 0x8c, 0x59, 0xdb, 0x0f, 0x7f, 0x50, 0xa0, 0xc5, 0xa5, 0x9e, 0xae, 0x47, 0x22, 0x3b, 0xde, 0xa7, - 0xa8, 0x7c, 0x1d, 0x8a, 0x96, 0x39, 0x30, 0x83, 0xa9, 0x7c, 0x2d, 0x62, 0x92, 0xaf, 0x40, 0xf9, - 0x89, 0xe3, 0x3d, 0xa3, 0x9e, 0x31, 0x31, 0xcf, 0x8b, 0x79, 0x0c, 0x51, 0x13, 0x81, 0xa7, 0x90, - 0x0a, 0x3c, 0x1e, 0x2c, 0x72, 0xee, 0x51, 0xd6, 0xfe, 0x5e, 0x95, 0xce, 0x84, 0xc8, 0x15, 0x9f, - 0x20, 0x3f, 0xed, 0x09, 0xd4, 0x25, 0x38, 0x16, 0xed, 0x39, 0xa5, 0xd3, 0x53, 0x3f, 0x52, 0xe0, - 0x32, 0x27, 0x1a, 0x51, 0x3f, 0x7f, 0xd9, 0x73, 0x86, 0xb6, 0x71, 0x5f, 0xe8, 0xe0, 0x2c, 0xa5, - 0x08, 0x59, 0x4a, 0x0b, 0x7f, 0xd4, 0xa5, 0x3d, 0x1a, 0x95, 0x7e, 0xd2, 0x49, 0xe6, 0x53, 0x4e, - 0x52, 0xfd, 0xbd, 0x02, 0xa7, 0xc7, 0xb3, 0x38, 0x23, 0x5f, 0x27, 0xa1, 0x1a, 0xee, 0x11, 0x7a, - 0xf8, 0x8a, 0xdc, 0xc4, 0x7f, 0x0e, 0x79, 0x4f, 0xbc, 0xfb, 0x7f, 0xe6, 0x80, 0x70, 0x86, 0xef, - 0xd1, 0x40, 0x7f, 0x1a, 0xab, 0x6c, 0xb4, 0x83, 0x32, 0xf5, 0x0e, 0x37, 0xa1, 0x4e, 0x87, 0xc1, - 0x53, 0xc7, 0x33, 0x03, 0x1a, 0x98, 0xdb, 0xd3, 0xf4, 0x7a, 0xd2, 0x04, 0x78, 0x17, 0x74, 0x93, - 0x59, 0x53, 0x85, 0x17, 0x81, 0x8a, 0x1d, 0x02, 0xd3, 0xee, 0xf9, 0xe6, 0x07, 0x4c, 0x9a, 0xeb, - 0x9e, 0xbc, 0x96, 0x07, 0xa6, 0xbd, 0x61, 0x7e, 0xc0, 0x90, 0x8e, 0xee, 0x08, 0xba, 0xe2, 0x34, - 0x74, 0x74, 0x07, 0xe9, 0x96, 0xa0, 0xf8, 0xfe, 0x90, 0x79, 0xbb, 0xf2, 0x01, 0x67, 0x1f, 0x1e, - 0x11, 0x55, 0xdd, 0x81, 0x26, 0x17, 0xf1, 0xd8, 0x62, 0xf7, 0x39, 0x04, 0xfd, 0x0a, 0x34, 0x74, - 0xaa, 0x3f, 0x65, 0x74, 0xd3, 0x62, 0xe9, 0x0e, 0xc7, 0x42, 0x04, 0x97, 0x6e, 0xf4, 0x57, 0x0a, - 0x9c, 0xe0, 0x5b, 0x8f, 0x2f, 0x69, 0xbf, 0x00, 0x65, 0x99, 0x44, 0x48, 0x1d, 0x2c, 0x89, 0x1c, - 0x22, 0x53, 0x56, 0xe7, 0x46, 0xca, 0xea, 0x43, 0xd4, 0xbf, 0x5f, 0x28, 0x70, 0x89, 0x73, 0x98, - 0xcc, 0x9d, 0x26, 0x99, 0xf4, 0x34, 0xd9, 0xd4, 0x61, 0x1b, 0xf4, 0xef, 0x14, 0x38, 0x35, 0x96, - 0xbf, 0x99, 0x98, 0xfa, 0xac, 0xac, 0xf9, 0xef, 0x39, 0x38, 0x9e, 0xe6, 0x36, 0xe2, 0x73, 0x15, - 0xe6, 0x75, 0x1a, 0xb0, 0xbe, 0xe3, 0xed, 0xf6, 0xfc, 0x80, 0x7a, 0xa1, 0xc6, 0xed, 0x2d, 0xa0, - 0x7a, 0x48, 0xb3, 0xc1, 0x49, 0xc8, 0x3b, 0x30, 0x17, 0x2d, 0xc2, 0x6c, 0x63, 0x2a, 0x19, 0xd7, - 0x42, 0x8a, 0x8e, 0x6d, 0x90, 0xb7, 0x00, 0x70, 0x73, 0x91, 0x24, 0xe5, 0xa7, 0x20, 0xaf, 0x22, - 0x3e, 0x66, 0x49, 0xd7, 0xa0, 0xc2, 0x6c, 0x43, 0x90, 0x16, 0xa6, 0x20, 0x2d, 0x33, 0xdb, 0x40, - 0xc2, 0x48, 0xc2, 0xa5, 0xe7, 0x90, 0x70, 0x25, 0x25, 0xe1, 0xd7, 0x44, 0xdc, 0xe2, 0x21, 0x2b, - 0x1d, 0x2f, 0x27, 0x19, 0x93, 0xfa, 0x53, 0x05, 0x8a, 0xe8, 0x5d, 0xb9, 0x9a, 0x0d, 0xf8, 0x47, - 0x22, 0xb4, 0xe1, 0xb8, 0x6b, 0x90, 0x8b, 0xe3, 0x9c, 0x67, 0xe5, 0x30, 0x1c, 0x24, 0x81, 0x42, - 0xe4, 0x1c, 0x8b, 0x1a, 0x7e, 0xab, 0xd7, 0xa1, 0x8a, 0x1c, 0x61, 0xa6, 0xf8, 0x2a, 0x08, 0x2e, - 0xd8, 0xd8, 0xd2, 0x15, 0xf1, 0xb4, 0x10, 0x43, 0xfd, 0x87, 0x02, 0x73, 0x49, 0x3f, 0x36, 0xd2, - 0xa5, 0x68, 0x42, 0xd9, 0x1f, 0xa2, 0x9b, 0x09, 0xeb, 0x07, 0x39, 0x4c, 0xb6, 0xac, 0xf3, 0xe9, - 0x96, 0x35, 0x91, 0x6d, 0x73, 0xc9, 0xe2, 0x68, 0x67, 0xbc, 0x98, 0xe9, 0x8c, 0x67, 0xb2, 0xfc, - 0xd2, 0x4c, 0x59, 0xfe, 0x99, 0x54, 0x9b, 0xba, 0x8c, 0x72, 0x4e, 0xb6, 0xa2, 0xbf, 0x0f, 0x8d, - 0xe4, 0x09, 0x51, 0x46, 0x37, 0xa0, 0x6e, 0x27, 0xbd, 0xb7, 0x94, 0x54, 0xea, 0xe9, 0x23, 0x49, - 0xa4, 0xa5, 0xd1, 0x67, 0x71, 0xd9, 0x0f, 0xa0, 0xf9, 0xc0, 0x73, 0x06, 0x8e, 0x6c, 0xcb, 0x1e, - 0x42, 0x41, 0xf8, 0x1e, 0x1c, 0xd1, 0x18, 0x35, 0x0e, 0xde, 0x3b, 0x4d, 0xa8, 0x78, 0x3e, 0xa5, - 0xe2, 0xdf, 0x81, 0x13, 0x23, 0x3b, 0x44, 0x4c, 0xdf, 0x18, 0xd3, 0x38, 0x3d, 0x9b, 0x14, 0xdc, - 0x18, 0xe6, 0x92, 0x6d, 0xd3, 0x77, 0x21, 0xaf, 0xb9, 0xfa, 0x38, 0x45, 0x73, 0xe9, 0xae, 0xe5, - 0xd0, 0xa8, 0x50, 0x95, 0x43, 0x2e, 0x8a, 0xa7, 0x41, 0xe0, 0xf6, 0x38, 0xf7, 0x52, 0xd3, 0xf8, - 0xf8, 0x0e, 0xdb, 0x55, 0x1f, 0x43, 0x79, 0x83, 0xf9, 0x3e, 0x3f, 0x1e, 0x57, 0x47, 0x54, 0x0a, - 0xb1, 0x68, 0x45, 0x0b, 0x87, 0xf1, 0x9b, 0x7d, 0x2e, 0xf1, 0x66, 0xcf, 0x15, 0x72, 0x68, 0xb8, - 0x3d, 0x31, 0x13, 0x3e, 0x48, 0x19, 0xee, 0x43, 0x7c, 0xd0, 0xff, 0x5b, 0x0e, 0xea, 0xa9, 0x23, - 0x1c, 0xa2, 0x74, 0xe3, 0xbe, 0x6b, 0x21, 0xd1, 0x77, 0x4d, 0x36, 0xb2, 0x8b, 0xa9, 0x46, 0x36, - 0xb9, 0x04, 0x0b, 0x2e, 0xf3, 0x06, 0x26, 0x9e, 0xb3, 0xe7, 0x31, 0x6a, 0xc8, 0x12, 0x7a, 0x3e, - 0x06, 0x73, 0x99, 0x73, 0xad, 0x4c, 0x20, 0x3e, 0xf3, 0xcc, 0x40, 0xbc, 0x17, 0x15, 0xb5, 0xc4, - 0x02, 0xdf, 0xe4, 0xe0, 0xcf, 0xaf, 0xae, 0x56, 0x9f, 0x41, 0x23, 0x25, 0xd9, 0x65, 0x7d, 0xeb, - 0x30, 0xdb, 0xfe, 0x49, 0xb1, 0x17, 0x52, 0x4a, 0xdd, 0x81, 0xc5, 0xec, 0xc6, 0x3e, 0x79, 0x0d, - 0x0a, 0x54, 0xdf, 0x0a, 0xd5, 0xf8, 0x54, 0x52, 0x8d, 0xb3, 0xc8, 0x1a, 0x62, 0xaa, 0x1d, 0x98, - 0x4f, 0xdb, 0x05, 0xb9, 0x0a, 0x65, 0xa1, 0xdd, 0xe1, 0x32, 0x27, 0x26, 0x2e, 0xa3, 0x85, 0x98, - 0xea, 0x7b, 0x19, 0x6e, 0xd0, 0x2d, 0x3d, 0xcf, 0x4a, 0x13, 0xdb, 0x8f, 0x9f, 0x16, 0x00, 0xe2, - 0xbc, 0x61, 0xc4, 0xde, 0xb8, 0x55, 0x98, 0x81, 0x15, 0x75, 0xff, 0x71, 0x90, 0xed, 0x30, 0xe7, - 0x47, 0x3b, 0xcc, 0x2d, 0xa8, 0x84, 0x09, 0x00, 0x0a, 0xb8, 0xae, 0x45, 0x63, 0x5e, 0x18, 0xfb, - 0x8e, 0x17, 0xf4, 0x1c, 0xcf, 0x60, 0x1e, 0xaa, 0x71, 0x5d, 0xab, 0x72, 0xc8, 0x7d, 0x0e, 0x88, - 0x42, 0x57, 0x09, 0x27, 0xf0, 0x5b, 0xc4, 0x50, 0x99, 0xb7, 0x97, 0x11, 0x1e, 0xa5, 0xe6, 0x23, - 0x0d, 0x93, 0xca, 0x48, 0xc3, 0x04, 0xff, 0xa2, 0x45, 0xed, 0x1e, 0xbe, 0xf1, 0xa3, 0x22, 0x56, - 0x38, 0x3b, 0x76, 0x07, 0xff, 0xa2, 0x74, 0x1a, 0x80, 0xe7, 0x17, 0x54, 0xc7, 0x08, 0x0c, 0x82, - 0x1d, 0x66, 0x1b, 0xcb, 0x08, 0xe0, 0xd3, 0xd8, 0xd5, 0x10, 0xbd, 0xc4, 0x9a, 0x98, 0xe6, 0x10, - 0x8d, 0x03, 0x52, 0x6d, 0xa9, 0xb9, 0xbd, 0xdb, 0x52, 0xf5, 0x99, 0xcc, 0xe7, 0x6b, 0xa9, 0x9c, - 0x69, 0x7e, 0xff, 0x77, 0x9d, 0x38, 0x63, 0x7a, 0x23, 0x91, 0x31, 0x2d, 0xec, 0x4b, 0x18, 0xe5, - 0x4b, 0x2d, 0xa8, 0x18, 0x43, 0x0f, 0x63, 0x57, 0xb3, 0x21, 0xee, 0x2c, 0x1c, 0x93, 0xf3, 0x30, - 0x27, 0xb8, 0x91, 0x62, 0x5a, 0x14, 0x42, 0x46, 0x98, 0x10, 0x94, 0xba, 0x09, 0xf3, 0xb1, 0x22, - 0xa1, 0xa2, 0x5e, 0x87, 0x5a, 0x9c, 0x0f, 0x87, 0xca, 0x7a, 0x3c, 0xa9, 0xac, 0x89, 0xfc, 0x3a, - 0x89, 0x3a, 0x51, 0x5b, 0xff, 0xac, 0xc0, 0xd1, 0x6c, 0x4e, 0xfe, 0xff, 0xd0, 0xf8, 0xfa, 0x4f, - 0x0e, 0x8e, 0x3e, 0x42, 0xef, 0x27, 0xbb, 0x53, 0x61, 0x18, 0x4d, 0xb6, 0x5f, 0x95, 0x99, 0xda, - 0xaf, 0xef, 0xc0, 0x9c, 0x61, 0xfa, 0xae, 0x45, 0x77, 0x7b, 0x48, 0x9d, 0x9b, 0x82, 0xba, 0x26, - 0x29, 0xd6, 0x29, 0xfa, 0xef, 0xe4, 0x6b, 0xcf, 0x34, 0xb9, 0x67, 0xe2, 0x2d, 0xe8, 0x5a, 0xe2, - 0x85, 0xa9, 0x30, 0x05, 0x69, 0xf4, 0xfe, 0x74, 0x1d, 0x2a, 0x96, 0x23, 0x12, 0x28, 0x59, 0xa1, - 0xef, 0x73, 0xe0, 0x10, 0x9b, 0x53, 0x72, 0x8d, 0xff, 0xc0, 0xb1, 0xd9, 0x54, 0x65, 0x7a, 0x84, - 0xad, 0x7e, 0x9a, 0x03, 0x22, 0xa4, 0x3f, 0x65, 0xe3, 0x91, 0x07, 0x84, 0xa9, 0x85, 0x2a, 0x9a, - 0x68, 0x37, 0x46, 0x5d, 0xe6, 0xfe, 0xb7, 0x91, 0x70, 0xa8, 0xcf, 0x2d, 0xd0, 0xf4, 0x35, 0x16, - 0x67, 0xbb, 0xc6, 0xf0, 0x49, 0xaf, 0x34, 0xdd, 0x93, 0x9e, 0xfa, 0xb3, 0x02, 0x14, 0xf0, 0xbd, - 0x29, 0x1b, 0x47, 0x92, 0xff, 0x6a, 0xc9, 0x65, 0xfe, 0xd5, 0x72, 0x3e, 0xa3, 0xa9, 0x61, 0x38, - 0x49, 0xe8, 0xe2, 0x3e, 0xff, 0x97, 0xd8, 0xfb, 0x3d, 0x33, 0xd2, 0x27, 0xf9, 0x9e, 0x19, 0x69, - 0x4c, 0x2b, 0xa1, 0x31, 0xf2, 0x49, 0x21, 0x1c, 0xa7, 0xfc, 0x7a, 0x25, 0xe3, 0xd7, 0xcf, 0x42, - 0x2d, 0xf1, 0xa0, 0x8b, 0x01, 0xa5, 0xaa, 0x41, 0xfc, 0x9e, 0xcb, 0xe3, 0x8d, 0x90, 0x14, 0x9f, - 0x06, 0x41, 0x2d, 0x00, 0x5d, 0x83, 0x5c, 0x80, 0x7a, 0x9f, 0x0e, 0x98, 0x8e, 0xd1, 0x88, 0x23, - 0xd4, 0x44, 0xeb, 0x20, 0x06, 0x8a, 0xc4, 0xde, 0x0f, 0x18, 0xc5, 0xff, 0x14, 0xcf, 0xc9, 0x8a, - 0x8a, 0x8f, 0xbb, 0xd8, 0xcf, 0x75, 0x6c, 0xcb, 0xb4, 0x45, 0x40, 0xa9, 0x68, 0x72, 0x94, 0x79, - 0x4e, 0x9d, 0xcf, 0x3e, 0xa7, 0x66, 0x82, 0xd1, 0xc2, 0x41, 0x72, 0xb9, 0xc6, 0x4c, 0xb9, 0xdc, - 0x0f, 0x72, 0x50, 0x8f, 0x2a, 0xe7, 0xf0, 0x85, 0x13, 0xb3, 0xaf, 0xd4, 0xdb, 0xe9, 0x85, 0xec, - 0xa3, 0x64, 0x84, 0x1f, 0x8f, 0x34, 0x18, 0x46, 0x25, 0x78, 0xeb, 0x13, 0x05, 0xaa, 0xd1, 0x0c, - 0xb9, 0x04, 0x45, 0x5c, 0x4e, 0xba, 0xc9, 0x31, 0x2f, 0xb1, 0x62, 0xfe, 0xf3, 0x79, 0xe4, 0xbc, - 0x02, 0x45, 0xac, 0xe9, 0xc8, 0x17, 0xa1, 0x98, 0x7c, 0xd6, 0x1d, 0x7d, 0x89, 0x15, 0xd3, 0xea, - 0x87, 0x39, 0x38, 0x8d, 0x49, 0xf8, 0x01, 0xff, 0x75, 0x43, 0xbe, 0x05, 0x25, 0x11, 0xda, 0xe4, - 0x79, 0x6f, 0x26, 0x77, 0xdc, 0x73, 0x87, 0xd1, 0xb8, 0x87, 0xe8, 0x9a, 0x5c, 0xaf, 0xf5, 0x04, - 0x8e, 0x8f, 0xc7, 0x88, 0x9f, 0xfe, 0x94, 0x49, 0x4f, 0x7f, 0xb9, 0xcc, 0xd3, 0x5f, 0xd2, 0xdc, - 0xf2, 0x69, 0x73, 0x53, 0x7f, 0x94, 0x03, 0x82, 0xeb, 0x1e, 0xb4, 0xd6, 0x8a, 0x4a, 0xaa, 0xfc, - 0x84, 0x92, 0xaa, 0x90, 0x2e, 0x12, 0xd6, 0x46, 0x4b, 0xaa, 0x29, 0x9a, 0xc6, 0xd9, 0x7a, 0xeb, - 0xd6, 0x98, 0x7a, 0x6b, 0x8a, 0x8e, 0x54, 0xb6, 0x18, 0x53, 0x1f, 0x43, 0x6b, 0x54, 0x0a, 0x7e, - 0x9c, 0x28, 0x64, 0x8a, 0x82, 0x33, 0x23, 0xf7, 0x3c, 0xa1, 0xc6, 0xf8, 0x61, 0x0e, 0x4e, 0xe1, - 0x7c, 0x36, 0xb1, 0x9a, 0xa9, 0xd7, 0xf9, 0x38, 0xa3, 0x66, 0x37, 0x46, 0xb6, 0x9f, 0xb0, 0x7c, - 0x3b, 0x0b, 0x4f, 0x2b, 0x19, 0x83, 0x63, 0x63, 0x11, 0x0e, 0x57, 0xc7, 0x56, 0xde, 0x86, 0x13, - 0xba, 0x33, 0x68, 0x3f, 0x65, 0x9e, 0x63, 0xea, 0x16, 0xdd, 0xf4, 0x13, 0xec, 0xaf, 0x54, 0xd7, - 0xf1, 0x7b, 0xd9, 0x35, 0x1f, 0x28, 0xdf, 0xce, 0x53, 0xd7, 0xfc, 0x75, 0xae, 0xb0, 0x7e, 0xe7, - 0xc1, 0xca, 0x6f, 0x73, 0x25, 0x31, 0xb3, 0x59, 0xc2, 0x1b, 0xbc, 0xfa, 0xbf, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xe8, 0x33, 0xa0, 0x9f, 0xfd, 0x32, 0x00, 0x00, + // 3385 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x3a, 0x5d, 0x6f, 0x1b, 0xc7, + 0xb5, 0x59, 0x7e, 0xf3, 0x50, 0x94, 0xa8, 0xf1, 0xc7, 0xa5, 0xe9, 0xef, 0xb5, 0x73, 0xed, 0x20, + 0xf7, 0xca, 0x89, 0x9c, 0xc4, 0xbe, 0xc9, 0x8d, 0x63, 0x7d, 0xd0, 0x06, 0x63, 0x5b, 0x76, 0x57, + 0xb6, 0x5b, 0xb4, 0x0f, 0xcc, 0x68, 0x77, 0x2c, 0x6f, 0xb5, 0xdc, 0x65, 0x76, 0x97, 0xb2, 0x14, + 0xb4, 0x0f, 0x2d, 0x0a, 0x34, 0x4f, 0x45, 0xd1, 0xa7, 0x3e, 0xb5, 0x45, 0x1f, 0x8a, 0xa4, 0xbf, + 0xa1, 0xef, 0x79, 0x0f, 0x9a, 0xb6, 0x6f, 0x6d, 0xd1, 0xa7, 0x02, 0xfd, 0x07, 0x05, 0x8a, 0x62, + 0xce, 0xcc, 0xee, 0xce, 0x2e, 0x49, 0x89, 0xb4, 0xe4, 0x24, 0xe8, 0x0b, 0xb1, 0x73, 0xe6, 0x9c, + 0x99, 0x33, 0x67, 0xce, 0xf7, 0x10, 0xea, 0xb4, 0x6f, 0x5f, 0xa1, 0x7d, 0x7b, 0xa1, 0xef, 0x7b, + 0xa1, 0x47, 0xc0, 0xa5, 0x5b, 0xb4, 0x47, 0x17, 0x68, 0xdf, 0x6e, 0x9d, 0xdd, 0xf4, 0xbc, 0x4d, + 0x87, 0x5d, 0xc1, 0x99, 0x8d, 0xc1, 0x93, 0x2b, 0xa1, 0xdd, 0x63, 0x41, 0x48, 0x7b, 0x7d, 0x81, + 0xdc, 0x3a, 0x93, 0x45, 0x78, 0xe6, 0xd3, 0x7e, 0x9f, 0xf9, 0x81, 0x98, 0xd7, 0xff, 0xa1, 0x41, + 0x79, 0xc9, 0x34, 0xbd, 0x81, 0x1b, 0x92, 0x8b, 0x50, 0x18, 0x04, 0xcc, 0x6f, 0x6a, 0xe7, 0xb4, + 0xcb, 0xb5, 0xc5, 0xc6, 0x42, 0xb2, 0xcf, 0xc2, 0xa3, 0x80, 0xf9, 0x06, 0xce, 0x92, 0xe3, 0x50, + 0x7a, 0x46, 0x1d, 0x87, 0x85, 0xcd, 0xdc, 0x39, 0xed, 0x72, 0xd5, 0x90, 0x23, 0x72, 0x14, 0x8a, + 0xac, 0x47, 0x6d, 0xa7, 0x99, 0x47, 0xb0, 0x18, 0x90, 0xab, 0x50, 0xb6, 0xd8, 0xb6, 0x6d, 0xb2, + 0xa0, 0x59, 0x38, 0x97, 0xbf, 0x5c, 0x5b, 0x3c, 0xa1, 0x2e, 0x2b, 0x77, 0x5e, 0x45, 0x0c, 0x23, + 0xc2, 0x24, 0x27, 0xa1, 0x6a, 0x0e, 0x82, 0xd0, 0xeb, 0x75, 0x6d, 0xab, 0x59, 0xc4, 0xe5, 0x2a, + 0x02, 0xd0, 0xb1, 0xc8, 0x3b, 0x50, 0xdb, 0x66, 0xbe, 0xfd, 0x64, 0xb7, 0xcb, 0xcf, 0xda, 0x2c, + 0x21, 0xb3, 0xad, 0x05, 0x71, 0xce, 0x85, 0xe8, 0x9c, 0x0b, 0x0f, 0x23, 0x41, 0x18, 0x20, 0xd0, + 0x39, 0x40, 0x3f, 0x0b, 0x75, 0xb9, 0xe7, 0x0a, 0xae, 0x47, 0x66, 0x21, 0x67, 0x5b, 0x78, 0xe2, + 0xaa, 0x91, 0xb3, 0x2d, 0x05, 0x41, 0x30, 0x35, 0x84, 0x70, 0x13, 0x66, 0x24, 0x42, 0x1b, 0x0f, + 0x18, 0x1f, 0x5b, 0x53, 0x8f, 0xdd, 0x82, 0x4a, 0x9f, 0x06, 0xc1, 0x33, 0xcf, 0xb7, 0xa4, 0x98, + 0xe2, 0xb1, 0x7e, 0x09, 0xe6, 0xe4, 0x0a, 0xb7, 0xa8, 0xc9, 0x36, 0x3c, 0x6f, 0x8b, 0x2f, 0x12, + 0x7a, 0x5b, 0xcc, 0x8d, 0x16, 0xc1, 0x81, 0xfe, 0xb9, 0x06, 0xf3, 0x12, 0xf3, 0x36, 0xed, 0xb1, + 0x15, 0xe6, 0x86, 0xcc, 0xe7, 0xc2, 0xe9, 0x3b, 0x74, 0x97, 0xf9, 0xdd, 0x98, 0xaf, 0x8a, 0x00, + 0x74, 0x2c, 0x3e, 0xb9, 0x31, 0x70, 0x2d, 0x87, 0xf1, 0x49, 0xb9, 0xb1, 0x00, 0x74, 0x2c, 0xf2, + 0x2a, 0xcc, 0xc7, 0xea, 0xd1, 0x0d, 0x98, 0xe9, 0xb9, 0x56, 0x80, 0xb7, 0x95, 0x37, 0x1a, 0xf1, + 0xc4, 0xba, 0x80, 0x13, 0x02, 0x85, 0x80, 0x3a, 0x61, 0xb3, 0x80, 0x8b, 0xe0, 0x37, 0x39, 0x05, + 0xd5, 0xc0, 0xde, 0x74, 0x69, 0x38, 0xf0, 0x99, 0xbc, 0x97, 0x04, 0x40, 0x2e, 0xc2, 0x6c, 0x7f, + 0xb0, 0xe1, 0xd8, 0x66, 0x77, 0x8b, 0xed, 0x76, 0x07, 0xbe, 0x83, 0x77, 0x53, 0x35, 0x66, 0x04, + 0xf4, 0x0e, 0xdb, 0x7d, 0xe4, 0x3b, 0xfa, 0xcb, 0xb1, 0x80, 0x6f, 0xe3, 0x8d, 0x8d, 0x39, 0xfb, + 0xc5, 0x58, 0xcc, 0xeb, 0x21, 0xa3, 0xbd, 0x31, 0x58, 0x2b, 0x30, 0xbf, 0x64, 0x59, 0xb7, 0x7c, + 0x9b, 0xb9, 0x56, 0x60, 0xb0, 0x0f, 0x07, 0x2c, 0x08, 0x49, 0x03, 0xf2, 0xb6, 0x15, 0x34, 0xb5, + 0x73, 0xf9, 0xcb, 0x55, 0x83, 0x7f, 0x72, 0xbe, 0xb9, 0xea, 0xba, 0xb4, 0xc7, 0x82, 0x66, 0x0e, + 0xe1, 0x09, 0x40, 0xbf, 0x0b, 0x47, 0x97, 0x2c, 0xeb, 0xb6, 0xef, 0x0d, 0xfa, 0x5c, 0xcd, 0xe3, + 0x75, 0x4e, 0x40, 0x65, 0x93, 0x03, 0x13, 0x39, 0x97, 0x71, 0xdc, 0xb1, 0xf8, 0x14, 0xa7, 0xef, + 0xf2, 0x7d, 0xc4, 0x7a, 0x65, 0x3e, 0xee, 0x58, 0x81, 0xfe, 0x2b, 0x0d, 0x4e, 0x2c, 0x0d, 0xc2, + 0xa7, 0xcc, 0x0d, 0x6d, 0x93, 0x86, 0x4c, 0xe8, 0x59, 0xb4, 0xe6, 0x55, 0x28, 0x53, 0x71, 0x2c, + 0x69, 0x65, 0xa3, 0xcc, 0x41, 0x92, 0x44, 0x98, 0x64, 0x11, 0x4a, 0xa6, 0xcf, 0x68, 0xc8, 0xf0, + 0x46, 0x47, 0x29, 0xfb, 0xb2, 0xe7, 0x39, 0x8f, 0xa9, 0x33, 0x60, 0x86, 0xc4, 0xe4, 0x0a, 0x18, + 0x9d, 0x50, 0x1a, 0x64, 0x3c, 0x1e, 0x62, 0x51, 0x9a, 0xdf, 0x34, 0x2c, 0x46, 0x16, 0xfb, 0xa2, + 0x58, 0xfc, 0x85, 0x06, 0x4d, 0x95, 0x45, 0xb4, 0xb5, 0x88, 0xc3, 0xc5, 0x2c, 0x87, 0xcd, 0x11, + 0x1c, 0x0a, 0x8a, 0x17, 0xc6, 0xe0, 0xef, 0x35, 0x38, 0xa9, 0x32, 0x18, 0x99, 0x72, 0xc4, 0xe3, + 0x9b, 0x59, 0x1e, 0x4f, 0x8e, 0xe0, 0x31, 0x26, 0x7a, 0x51, 0x6c, 0x92, 0x05, 0x28, 0x04, 0xbb, + 0xae, 0x89, 0x56, 0xbc, 0xf7, 0x6a, 0x88, 0xa7, 0x7f, 0xa2, 0xc1, 0x69, 0xf5, 0x58, 0x89, 0xdf, + 0x89, 0x0e, 0x76, 0x2d, 0x7b, 0xb0, 0xd3, 0x23, 0x0e, 0xa6, 0x90, 0x7d, 0x69, 0x5a, 0x2c, 0xdc, + 0xc9, 0x54, 0x5a, 0x2c, 0x49, 0xbe, 0x34, 0x2d, 0x46, 0x57, 0x36, 0x95, 0x16, 0x0b, 0x8a, 0x17, + 0xc6, 0x60, 0x1b, 0x8e, 0x2c, 0x3b, 0x9e, 0xb9, 0x75, 0x40, 0x0f, 0xfa, 0x71, 0x1e, 0x66, 0x57, + 0x9e, 0x52, 0xd7, 0x65, 0xce, 0x3d, 0x16, 0x04, 0x74, 0x93, 0x91, 0xd3, 0x00, 0xa6, 0x80, 0x24, + 0xee, 0xb3, 0x2a, 0x21, 0x1d, 0x8b, 0x4f, 0xf7, 0x04, 0x66, 0x12, 0xa8, 0xaa, 0x12, 0xd2, 0xb1, + 0xc8, 0x15, 0x28, 0x98, 0x9e, 0x25, 0xf8, 0xe5, 0xa6, 0x93, 0x3d, 0x65, 0xc7, 0x0d, 0xaf, 0x2e, + 0x4a, 0xbd, 0xe5, 0x88, 0x3c, 0xee, 0x05, 0xcc, 0xb5, 0x44, 0x50, 0x14, 0x21, 0xab, 0x22, 0x00, + 0x1d, 0x2b, 0x25, 0x81, 0x62, 0xc6, 0x40, 0x9a, 0x50, 0x36, 0x3d, 0x37, 0x64, 0x6e, 0x28, 0xa3, + 0x55, 0x34, 0xe4, 0x79, 0x86, 0x90, 0xa0, 0xc8, 0x33, 0xca, 0xfb, 0xe7, 0x19, 0x02, 0x9d, 0x03, + 0x38, 0xf1, 0xa0, 0x6f, 0xc5, 0xc4, 0x95, 0xfd, 0x89, 0x05, 0x3a, 0x12, 0xbf, 0x0d, 0xc0, 0x33, + 0x34, 0x3b, 0x40, 0xb6, 0xaa, 0xfb, 0xde, 0xb4, 0x82, 0xad, 0xff, 0x44, 0x03, 0x92, 0xbe, 0x8a, + 0xbb, 0x76, 0x10, 0x92, 0xb7, 0xa0, 0x22, 0xa5, 0x2b, 0xae, 0x95, 0x2f, 0xa8, 0x68, 0x5b, 0x9a, + 0xc2, 0x88, 0x71, 0xc9, 0x59, 0xa8, 0xb9, 0x6c, 0x27, 0xec, 0x9a, 0x03, 0x3f, 0xf0, 0x7c, 0x79, + 0x51, 0xc0, 0x41, 0x2b, 0x08, 0xe1, 0x08, 0x7d, 0x9f, 0x6d, 0x47, 0x08, 0x42, 0xc1, 0x80, 0x83, + 0x04, 0x82, 0xfe, 0x73, 0xce, 0x10, 0x0a, 0x06, 0x23, 0x6c, 0xa4, 0x62, 0x04, 0x0a, 0x78, 0x1f, + 0x42, 0x33, 0xf0, 0x9b, 0x9c, 0x83, 0x9a, 0xc5, 0x02, 0xd3, 0xb7, 0xfb, 0xa1, 0xed, 0xb9, 0x72, + 0x33, 0x15, 0xc4, 0xe3, 0xae, 0x43, 0xdd, 0xcd, 0x6e, 0x48, 0x37, 0xe5, 0x56, 0x65, 0x3e, 0x7e, + 0x48, 0x37, 0xb9, 0x46, 0xd1, 0x6d, 0x1a, 0x52, 0x1f, 0x33, 0x0f, 0xa1, 0x02, 0x55, 0x01, 0x79, + 0xe4, 0x3b, 0x7c, 0x3f, 0xaf, 0xcf, 0x5c, 0xbc, 0xff, 0x8a, 0x81, 0xdf, 0xfa, 0x2d, 0x38, 0xba, + 0xca, 0x1c, 0x16, 0xb2, 0x03, 0xaa, 0xff, 0x15, 0x20, 0x62, 0x9d, 0xd4, 0x09, 0xc7, 0xa7, 0x0f, + 0xfa, 0x6d, 0x38, 0x23, 0x08, 0xee, 0x32, 0x6a, 0x31, 0x7f, 0xc3, 0xa3, 0xbe, 0x65, 0x30, 0xd3, + 0xe3, 0xbf, 0x82, 0xf8, 0x65, 0x98, 0x75, 0x92, 0xb9, 0x64, 0x89, 0xba, 0x02, 0xed, 0x58, 0xfa, + 0x02, 0xb4, 0xc4, 0x42, 0x6b, 0x5e, 0x68, 0x3f, 0xe1, 0x3e, 0xc6, 0xf6, 0xdc, 0xf1, 0xe7, 0xd0, + 0x4d, 0x38, 0x26, 0xf0, 0xd7, 0x43, 0xcf, 0xa7, 0x9b, 0xec, 0xfe, 0xc6, 0x77, 0x99, 0x19, 0x76, + 0x2c, 0x72, 0x06, 0xc0, 0xf4, 0x1c, 0x87, 0x99, 0x28, 0x79, 0xb1, 0x97, 0x02, 0xe1, 0x4b, 0x6d, + 0xb1, 0x5d, 0x79, 0x25, 0xfc, 0x93, 0x1b, 0xce, 0x36, 0x57, 0x3b, 0xcf, 0x8d, 0x6e, 0x42, 0x0e, + 0xf5, 0x2e, 0x9c, 0x1c, 0xb1, 0x49, 0xcc, 0xd5, 0x4d, 0x00, 0x0f, 0x21, 0xdd, 0x88, 0xb9, 0xda, + 0xe2, 0x79, 0x55, 0x19, 0x47, 0x72, 0x68, 0x54, 0x3d, 0xf9, 0x15, 0xe8, 0x7f, 0xd4, 0xa0, 0xd8, + 0xde, 0xe6, 0x36, 0x3a, 0x4a, 0x8b, 0x96, 0x00, 0xfa, 0xbe, 0xd7, 0x67, 0x7e, 0x68, 0xcb, 0xcb, + 0xca, 0xac, 0x8f, 0xa4, 0x0b, 0x0f, 0x62, 0x9c, 0xb6, 0x1b, 0xfa, 0xbb, 0x86, 0x42, 0x44, 0xae, + 0x43, 0x35, 0xce, 0x87, 0xa5, 0x0f, 0xda, 0xcb, 0x76, 0x13, 0xe4, 0xd6, 0xbb, 0x30, 0x97, 0x59, + 0x38, 0x12, 0x9d, 0x96, 0x88, 0xee, 0x28, 0x14, 0xb7, 0xb9, 0xe1, 0x4a, 0x71, 0x8a, 0xc1, 0xdb, + 0xb9, 0xeb, 0x9a, 0xfe, 0xa9, 0x06, 0x25, 0xa1, 0x8c, 0x13, 0x16, 0x63, 0xaf, 0x43, 0x31, 0x08, + 0x93, 0x78, 0xb0, 0xa7, 0xa7, 0x14, 0x98, 0xfa, 0x2d, 0x28, 0xae, 0xf3, 0x0f, 0x02, 0x50, 0xba, + 0x65, 0x74, 0xda, 0x6b, 0xab, 0x8d, 0x97, 0xc8, 0x1c, 0xd4, 0x3a, 0x6b, 0x8f, 0x3b, 0x0f, 0xdb, + 0xdd, 0xf5, 0xf6, 0xda, 0xc3, 0x86, 0x46, 0x8e, 0xc0, 0x9c, 0x04, 0x18, 0xed, 0x95, 0x76, 0xe7, + 0x71, 0x7b, 0xb5, 0x91, 0x23, 0x35, 0x28, 0x2f, 0xdf, 0xbd, 0xbf, 0x72, 0xa7, 0xbd, 0xda, 0xc8, + 0xeb, 0xd7, 0xa0, 0x2c, 0xed, 0x86, 0xfc, 0x0f, 0x94, 0x9f, 0x88, 0x4f, 0x79, 0x9f, 0x44, 0x65, + 0x57, 0x60, 0x19, 0x11, 0x8a, 0x6e, 0xc1, 0xdc, 0x6d, 0x16, 0xa6, 0x52, 0xed, 0x29, 0x2d, 0x8e, + 0x9c, 0x87, 0x99, 0x27, 0x32, 0x77, 0x42, 0x2d, 0xca, 0x23, 0x42, 0x2d, 0x82, 0x71, 0x25, 0xf9, + 0x24, 0x0f, 0x45, 0xb4, 0xc7, 0x6c, 0x05, 0x87, 0xa1, 0x89, 0x3b, 0x24, 0xcf, 0x57, 0x62, 0x8f, + 0x84, 0x74, 0xac, 0x58, 0xa7, 0xf2, 0xe3, 0x3d, 0x53, 0x61, 0x6f, 0xcf, 0x54, 0x4c, 0x7b, 0xa6, + 0x16, 0xf7, 0xbd, 0x21, 0xb5, 0x68, 0x48, 0x65, 0x8c, 0x89, 0xc7, 0x19, 0xaf, 0x55, 0xce, 0x7a, + 0xad, 0x05, 0xe9, 0xb5, 0x2a, 0xfb, 0xa7, 0x6f, 0x1c, 0x8f, 0x2f, 0xc7, 0xac, 0x4d, 0xd6, 0x15, + 0x69, 0x05, 0x8f, 0x1c, 0x45, 0xa3, 0xca, 0x21, 0x2b, 0x98, 0x3e, 0x9c, 0x84, 0x6a, 0x8f, 0xee, + 0xc8, 0x59, 0xc0, 0xd9, 0x4a, 0x8f, 0xee, 0x88, 0xc9, 0x4c, 0xbc, 0xab, 0x1d, 0x24, 0xde, 0xcd, + 0x4c, 0x13, 0xef, 0xf4, 0x35, 0xa8, 0xe2, 0x4d, 0x61, 0xa4, 0x7a, 0x05, 0x4a, 0xe8, 0x26, 0x23, + 0x55, 0x9a, 0x57, 0x55, 0x49, 0x38, 0x58, 0x89, 0x40, 0x8e, 0x43, 0x29, 0x15, 0x97, 0xe4, 0x48, + 0xff, 0x97, 0x06, 0xf5, 0xb8, 0x9c, 0xc3, 0x45, 0x57, 0xa1, 0x26, 0x7c, 0x31, 0x57, 0xa1, 0x68, + 0xe5, 0x0b, 0x43, 0x2b, 0x47, 0xf8, 0xc9, 0xc8, 0x80, 0xcd, 0xb8, 0x2e, 0x6c, 0xfd, 0x46, 0x93, + 0x8c, 0xf2, 0xe1, 0x8b, 0x33, 0xd0, 0x9b, 0x91, 0x81, 0xce, 0x02, 0xac, 0x3f, 0x7a, 0xd0, 0x36, + 0x96, 0x56, 0xef, 0x75, 0xd6, 0x1a, 0x2f, 0x91, 0x2a, 0x14, 0xc5, 0xa7, 0xc6, 0x6d, 0xf7, 0x5e, + 0xfb, 0xde, 0x72, 0xdb, 0x68, 0xe4, 0x48, 0x03, 0x66, 0xde, 0xbf, 0xdf, 0x59, 0xeb, 0x1a, 0xed, + 0x6f, 0x3c, 0x6a, 0xaf, 0x3f, 0x6c, 0xe4, 0xf5, 0x1f, 0x6b, 0x70, 0xaa, 0xd3, 0xeb, 0x7b, 0x7e, + 0x5c, 0x61, 0x64, 0x22, 0xdc, 0x73, 0x56, 0x27, 0xaf, 0x41, 0xd1, 0x67, 0x81, 0xec, 0xfc, 0xec, + 0xad, 0x8f, 0x02, 0x51, 0xff, 0x5f, 0x68, 0xbc, 0xef, 0xd9, 0xee, 0xa4, 0x81, 0xf1, 0xff, 0xe1, + 0x18, 0x47, 0x7f, 0xe8, 0x0d, 0xd0, 0xd0, 0xdd, 0x30, 0xa2, 0xb9, 0x00, 0xf5, 0x30, 0x06, 0x26, + 0x84, 0x33, 0x09, 0xb0, 0x63, 0xe9, 0xf7, 0xe0, 0xd8, 0x1d, 0xdb, 0xdc, 0x3a, 0xac, 0x4a, 0xfe, + 0xef, 0x79, 0x98, 0x1f, 0x0a, 0xd0, 0x13, 0x46, 0x66, 0xbe, 0xae, 0xf7, 0xcc, 0x65, 0x8a, 0x8b, + 0x29, 0xe3, 0xb8, 0x63, 0x91, 0xeb, 0x99, 0x84, 0xbc, 0xb6, 0x78, 0x6a, 0x48, 0x90, 0xeb, 0xa1, + 0x6f, 0xbb, 0x9b, 0x42, 0x94, 0x49, 0xb2, 0x7a, 0x14, 0x8a, 0x81, 0xe9, 0xf9, 0x0c, 0x1d, 0x50, + 0xde, 0x10, 0x03, 0xee, 0x5f, 0x82, 0xc1, 0x86, 0x98, 0x28, 0xe2, 0x44, 0x3c, 0xe6, 0x16, 0xef, + 0x0e, 0x7a, 0x5d, 0x31, 0x59, 0x12, 0x16, 0xef, 0x0e, 0x7a, 0xeb, 0x11, 0x61, 0xec, 0x98, 0xca, + 0x19, 0xc7, 0x94, 0xf1, 0x06, 0x95, 0x83, 0x78, 0x83, 0xea, 0x54, 0xd9, 0xef, 0x3b, 0x50, 0x63, + 0x3b, 0x7d, 0xdb, 0x97, 0xfd, 0x3d, 0xd8, 0x9f, 0x58, 0xa0, 0x23, 0x31, 0x81, 0x82, 0x4f, 0xdd, + 0x2d, 0xf4, 0x5e, 0x79, 0x03, 0xbf, 0x89, 0x0e, 0x75, 0xee, 0xf5, 0x12, 0x39, 0x70, 0xef, 0x54, + 0x37, 0x6a, 0x3d, 0xba, 0xb3, 0x26, 0x45, 0xa1, 0xff, 0x41, 0x83, 0x63, 0x43, 0x77, 0x8d, 0xae, + 0xe3, 0x1a, 0x94, 0x7d, 0x1c, 0x45, 0x6e, 0x23, 0x55, 0xef, 0x0e, 0x27, 0x70, 0x11, 0x36, 0x59, + 0x86, 0xba, 0xd0, 0x80, 0x88, 0x3c, 0x37, 0x09, 0xf9, 0x0c, 0xd2, 0x18, 0x72, 0x8d, 0x4c, 0xfa, + 0x9d, 0xdf, 0x2f, 0xfd, 0x2e, 0x0c, 0xa5, 0xdf, 0x0b, 0xa8, 0xc3, 0xdb, 0x13, 0xa7, 0xa6, 0xdf, + 0x83, 0x23, 0x77, 0x6d, 0x77, 0xeb, 0x90, 0xda, 0x19, 0xd3, 0xb6, 0x1f, 0x7e, 0xa7, 0x41, 0x8b, + 0x4b, 0x3d, 0x5d, 0x8f, 0xc4, 0x76, 0xbc, 0x4f, 0x51, 0xf9, 0x3a, 0x14, 0x1d, 0xbb, 0x67, 0x87, + 0x13, 0xf9, 0x5a, 0xc4, 0x24, 0x6f, 0x40, 0xf9, 0x89, 0xe7, 0x3f, 0xa3, 0xbe, 0x35, 0x36, 0xcf, + 0x4b, 0x78, 0x8c, 0x50, 0x95, 0xc0, 0x53, 0x48, 0x05, 0x1e, 0x1f, 0xe6, 0x39, 0xf7, 0x28, 0xeb, + 0x60, 0xaf, 0x4a, 0x67, 0x4c, 0xe4, 0x4a, 0x4e, 0x90, 0x9f, 0xf4, 0x04, 0xfa, 0x22, 0x1c, 0x8b, + 0xf7, 0x9c, 0xd0, 0xe9, 0xe9, 0x5f, 0x68, 0x70, 0x99, 0x13, 0x0d, 0xa9, 0x5f, 0xb0, 0xe4, 0x7b, + 0x03, 0xd7, 0xba, 0x2f, 0x74, 0x70, 0x9a, 0x52, 0x84, 0x2c, 0xa6, 0x85, 0x3f, 0xec, 0xd2, 0x1e, + 0x0d, 0x4b, 0x5f, 0x75, 0x92, 0xf9, 0xb4, 0x93, 0xbc, 0x0a, 0x25, 0x61, 0xd6, 0x52, 0x77, 0x46, + 0x8a, 0xe2, 0xad, 0x37, 0x64, 0xab, 0x43, 0xa0, 0xea, 0x7f, 0xd3, 0xe0, 0xf4, 0xe8, 0x73, 0x4d, + 0x79, 0x98, 0x93, 0x50, 0x8d, 0x18, 0x8b, 0xc2, 0x42, 0x45, 0x72, 0x16, 0x3c, 0xc7, 0x25, 0x8d, + 0x53, 0x18, 0xe5, 0x94, 0xc5, 0xc9, 0x4f, 0xf9, 0xd7, 0x1c, 0x10, 0x7e, 0xca, 0x7b, 0x34, 0x34, + 0x9f, 0x26, 0xc6, 0x11, 0xb3, 0xa5, 0x4d, 0xcc, 0xd6, 0x4d, 0xa8, 0xd3, 0x41, 0xf8, 0xd4, 0xf3, + 0xed, 0x90, 0x86, 0xf6, 0xf6, 0x24, 0x5d, 0xa5, 0x34, 0x01, 0xde, 0x3a, 0xdd, 0x60, 0xce, 0x44, + 0x81, 0x4c, 0xa0, 0x62, 0x2f, 0xc2, 0x76, 0xbb, 0x81, 0xfd, 0x11, 0xdb, 0xeb, 0x72, 0x23, 0x5e, + 0xcb, 0x3d, 0xdb, 0x5d, 0xb7, 0x3f, 0x62, 0x48, 0x47, 0x77, 0x04, 0x5d, 0x71, 0x12, 0x3a, 0xba, + 0x83, 0x74, 0x8b, 0x50, 0xfc, 0x70, 0xc0, 0xfc, 0x5d, 0xf9, 0x54, 0xb4, 0x0f, 0x8f, 0x88, 0xaa, + 0xef, 0x40, 0x93, 0x8b, 0x78, 0x64, 0x59, 0xfd, 0x1c, 0x82, 0x7e, 0x05, 0x1a, 0x26, 0x35, 0x9f, + 0x32, 0xba, 0xe1, 0xb0, 0x74, 0x2f, 0x65, 0x2e, 0x86, 0x4b, 0x87, 0xfd, 0x4b, 0x0d, 0x4e, 0xf0, + 0xad, 0x47, 0x17, 0xcf, 0xff, 0x05, 0x65, 0x99, 0xae, 0x48, 0xc5, 0x2d, 0x89, 0x6c, 0x25, 0x53, + 0xc0, 0xe7, 0x86, 0x0a, 0xf8, 0xc3, 0x53, 0x5a, 0xfd, 0x73, 0x0d, 0x2e, 0x71, 0x0e, 0xd5, 0x2c, + 0x6d, 0x9c, 0xf3, 0x98, 0x24, 0x6f, 0xfb, 0x5a, 0xb8, 0x8e, 0xbf, 0x68, 0x70, 0x6a, 0xe4, 0xa1, + 0xa6, 0x3a, 0xc9, 0xd7, 0xda, 0x6f, 0xfc, 0x39, 0x07, 0xc7, 0xd3, 0x47, 0x8c, 0x0f, 0xb7, 0x02, + 0xb3, 0x26, 0x0d, 0xd9, 0xa6, 0xe7, 0xef, 0x76, 0x83, 0x90, 0xfa, 0x91, 0x6e, 0xef, 0x7d, 0x15, + 0xf5, 0x88, 0x66, 0x9d, 0x93, 0x90, 0xf7, 0x60, 0x26, 0x5e, 0x84, 0xb9, 0xd6, 0x44, 0xb7, 0x59, + 0x8b, 0x28, 0xda, 0xae, 0x45, 0xde, 0x01, 0xc0, 0xcd, 0x45, 0xe2, 0x97, 0x9f, 0x80, 0xbc, 0x8a, + 0xf8, 0x98, 0xf9, 0x5d, 0x83, 0x0a, 0x73, 0x2d, 0x41, 0x5a, 0x98, 0x80, 0xb4, 0xcc, 0x5c, 0x0b, + 0x09, 0xe3, 0x6b, 0x29, 0x3d, 0xc7, 0xb5, 0x54, 0x52, 0x96, 0xf1, 0x9a, 0x88, 0xc5, 0x3c, 0x0c, + 0xa7, 0x73, 0x80, 0x71, 0x66, 0xab, 0xff, 0x54, 0x83, 0x22, 0xfa, 0x71, 0xae, 0xd0, 0x3d, 0xfe, + 0xa1, 0x84, 0x6b, 0x1c, 0x77, 0x2c, 0x72, 0x71, 0x94, 0x9b, 0xae, 0x1c, 0x86, 0x2b, 0x26, 0x50, + 0x88, 0xdd, 0x70, 0xd1, 0xc0, 0x6f, 0xfd, 0x3a, 0x54, 0x91, 0x23, 0xcc, 0x7e, 0x5f, 0x05, 0xc1, + 0x05, 0x1b, 0x59, 0x8e, 0x23, 0x9e, 0x11, 0x61, 0x70, 0x1b, 0x9a, 0x51, 0x3d, 0xe6, 0x50, 0xe7, + 0xa5, 0x09, 0xe5, 0x60, 0x80, 0x0e, 0x2d, 0xaa, 0x89, 0xe4, 0x50, 0x6d, 0xc3, 0xe7, 0xd3, 0x6d, + 0x78, 0x22, 0x9f, 0x02, 0x24, 0x8b, 0xc3, 0xdd, 0xfe, 0x62, 0xa6, 0xdb, 0x9f, 0xa9, 0x5c, 0x4a, + 0x53, 0x55, 0x2e, 0x67, 0x52, 0xad, 0xf7, 0x32, 0xca, 0x59, 0x6d, 0xaf, 0x7f, 0x1f, 0x1a, 0xea, + 0x09, 0x51, 0x46, 0x37, 0xa0, 0xee, 0xaa, 0x71, 0x42, 0x4a, 0x2a, 0xf5, 0x9c, 0xa3, 0x12, 0x19, + 0x69, 0xf4, 0x69, 0x82, 0xc3, 0x03, 0x68, 0x3e, 0xf0, 0xbd, 0x9e, 0x27, 0x5b, 0xcd, 0x87, 0x50, + 0xe4, 0x7e, 0x00, 0x47, 0x0c, 0x46, 0xad, 0x83, 0xf7, 0x83, 0x15, 0x15, 0xcf, 0xa7, 0x54, 0xfc, + 0x3b, 0x70, 0x62, 0x68, 0x87, 0x98, 0xe9, 0x1b, 0x23, 0x9a, 0xc1, 0x67, 0x55, 0xc1, 0x8d, 0x60, + 0x4e, 0x6d, 0x05, 0xbf, 0x0f, 0x79, 0xa3, 0x6f, 0x8e, 0x52, 0xb4, 0x3e, 0xdd, 0x75, 0x3c, 0x1a, + 0x17, 0xdf, 0x72, 0xc8, 0x45, 0xf1, 0x34, 0x0c, 0xfb, 0x5d, 0xce, 0xbd, 0xd4, 0x34, 0x3e, 0xbe, + 0xc3, 0x76, 0xf5, 0xc7, 0x50, 0x5e, 0x67, 0x41, 0xc0, 0x8f, 0xc7, 0xd5, 0x11, 0x95, 0x42, 0x2c, + 0x5a, 0x31, 0xa2, 0x61, 0xf2, 0x3f, 0x84, 0x9c, 0xf2, 0x3f, 0x04, 0xae, 0x90, 0x03, 0xab, 0xdf, + 0x15, 0x33, 0xd1, 0x23, 0x9b, 0xd5, 0x7f, 0x88, 0x7f, 0x52, 0xf8, 0x53, 0x0e, 0xea, 0xa9, 0x23, + 0x1c, 0xa2, 0x74, 0x93, 0x5e, 0x72, 0x41, 0xe9, 0x25, 0xab, 0xcd, 0xf9, 0x62, 0xaa, 0x39, 0x4f, + 0x2e, 0xc1, 0x5c, 0x9f, 0xf9, 0x3d, 0x1b, 0xcf, 0xd9, 0xf5, 0x19, 0xb5, 0x64, 0x5b, 0x60, 0x36, + 0x01, 0x73, 0x99, 0x73, 0xad, 0x54, 0x10, 0x9f, 0xf9, 0x76, 0x28, 0xde, 0xc0, 0x8a, 0x86, 0xb2, + 0xc0, 0x37, 0x39, 0xf8, 0xab, 0xeb, 0x15, 0xe8, 0xcf, 0xa0, 0x91, 0x92, 0xec, 0x92, 0xb9, 0x75, + 0x98, 0x4f, 0x19, 0xaa, 0xd8, 0x0b, 0x29, 0xa5, 0x6e, 0xc3, 0x7c, 0x76, 0xe3, 0x80, 0xbc, 0x06, + 0x05, 0x6a, 0x6e, 0x45, 0x6a, 0x7c, 0x4a, 0x55, 0xe3, 0x2c, 0xb2, 0x81, 0x98, 0x7a, 0x1b, 0x66, + 0xd3, 0x76, 0x41, 0xae, 0x42, 0x59, 0x68, 0x77, 0xb4, 0xcc, 0x89, 0xb1, 0xcb, 0x18, 0x11, 0xa6, + 0xfe, 0x41, 0x86, 0x1b, 0x74, 0x4b, 0xcf, 0xb3, 0xd2, 0xd8, 0x96, 0xea, 0x67, 0x05, 0x80, 0x24, + 0x6f, 0x18, 0xb2, 0x37, 0x6e, 0x15, 0x76, 0xe8, 0xc4, 0x2f, 0x1a, 0x38, 0xc8, 0x76, 0xcd, 0xf3, + 0xc3, 0x5d, 0xf3, 0x16, 0x54, 0xa2, 0x04, 0x00, 0x05, 0x5c, 0x37, 0xe2, 0x31, 0x2f, 0xf6, 0x03, + 0xcf, 0x0f, 0xbb, 0x9e, 0x6f, 0x31, 0x1f, 0xd5, 0xb8, 0x6e, 0x54, 0x39, 0xe4, 0x3e, 0x07, 0xc4, + 0xa1, 0xab, 0x84, 0x13, 0xf8, 0x2d, 0x62, 0xa8, 0xac, 0x10, 0xca, 0x08, 0x8f, 0x8b, 0x80, 0xa1, + 0x26, 0x50, 0x65, 0xa8, 0x09, 0x84, 0x7f, 0x3b, 0xa3, 0x6e, 0x17, 0xff, 0xb7, 0x80, 0x8a, 0x58, + 0xe1, 0xec, 0xb8, 0x6d, 0xfc, 0xdb, 0xd5, 0x69, 0x00, 0x9e, 0x5f, 0x50, 0x13, 0x23, 0x30, 0x08, + 0x76, 0x98, 0x6b, 0x2d, 0x21, 0x80, 0x4f, 0x63, 0xa7, 0x46, 0xf4, 0x47, 0x6b, 0x62, 0x9a, 0x43, + 0x0c, 0x0e, 0x48, 0xb5, 0xda, 0x66, 0xf6, 0x6e, 0xb5, 0xd5, 0xa7, 0x32, 0x9f, 0xff, 0x4b, 0xe5, + 0x4c, 0xb3, 0xfb, 0xbf, 0x55, 0x25, 0x19, 0xd3, 0x9b, 0x4a, 0xc6, 0x34, 0xb7, 0x2f, 0x61, 0x9c, + 0x2f, 0xb5, 0xa0, 0x62, 0x0d, 0x7c, 0x8c, 0x5d, 0xcd, 0x86, 0xb8, 0xb3, 0x68, 0x4c, 0xce, 0xc3, + 0x8c, 0xe0, 0x46, 0x8a, 0x69, 0x5e, 0x08, 0x19, 0x61, 0x42, 0x50, 0xfa, 0x06, 0xcc, 0x26, 0x8a, + 0x84, 0x8a, 0x7a, 0x1d, 0x6a, 0x49, 0x12, 0x1d, 0x29, 0xeb, 0x71, 0x55, 0x59, 0x95, 0xa4, 0x5c, + 0x45, 0x1d, 0xab, 0xad, 0x5f, 0x68, 0x70, 0x34, 0x9b, 0xc8, 0xff, 0x27, 0x34, 0xf3, 0xfe, 0x99, + 0x83, 0xa3, 0x8f, 0xd0, 0xfb, 0xc9, 0x8e, 0x5b, 0x14, 0x46, 0xd5, 0x96, 0xb2, 0x36, 0x55, 0x4b, + 0xf9, 0x3d, 0x98, 0xb1, 0xec, 0xa0, 0xef, 0xd0, 0xdd, 0x2e, 0x52, 0xe7, 0x26, 0xa0, 0xae, 0x49, + 0x8a, 0x35, 0x8a, 0xfe, 0x5b, 0x7d, 0xc1, 0x9a, 0x24, 0xf7, 0x54, 0xde, 0xb7, 0xae, 0x29, 0xaf, + 0x66, 0x85, 0x09, 0x48, 0xe3, 0x37, 0xb5, 0xeb, 0x50, 0x71, 0x3c, 0x91, 0x40, 0xc9, 0x12, 0x68, + 0x9f, 0x03, 0x47, 0xd8, 0x9c, 0x92, 0x6b, 0xfc, 0x47, 0x9e, 0xcb, 0x26, 0x6a, 0x08, 0xc4, 0xd8, + 0xfa, 0x67, 0x39, 0x20, 0x42, 0xfa, 0x13, 0x36, 0x53, 0x79, 0x40, 0x98, 0x58, 0xa8, 0xa2, 0x31, + 0x78, 0x63, 0xd8, 0x65, 0xee, 0x7f, 0x1b, 0x8a, 0x43, 0x7d, 0x6e, 0x81, 0xa6, 0xaf, 0xb1, 0x38, + 0xdd, 0x35, 0x46, 0xcf, 0x94, 0xa5, 0xc9, 0x9e, 0x29, 0xf5, 0x9f, 0x15, 0xa0, 0x80, 0x6f, 0x68, + 0xd9, 0x38, 0xa2, 0xfe, 0x53, 0x27, 0x97, 0xf9, 0xa7, 0xce, 0xf9, 0x8c, 0xa6, 0x46, 0xe1, 0x44, + 0xd1, 0xc5, 0x7d, 0xfe, 0x03, 0xb2, 0xf7, 0x1b, 0x6d, 0xac, 0x4f, 0xf2, 0x8d, 0x36, 0xd6, 0x98, + 0x96, 0xa2, 0x31, 0xf2, 0x99, 0x24, 0x1a, 0xa7, 0xfc, 0x7a, 0x25, 0xe3, 0xd7, 0xcf, 0x42, 0x4d, + 0x79, 0xa4, 0xc6, 0x80, 0x52, 0x35, 0x20, 0x79, 0xa3, 0xe6, 0xf1, 0x46, 0x48, 0x8a, 0x4f, 0x83, + 0xa0, 0x16, 0x80, 0x8e, 0x45, 0x2e, 0x40, 0x7d, 0x93, 0xf6, 0x98, 0x89, 0xd1, 0x88, 0x23, 0xd4, + 0x44, 0xbf, 0x21, 0x01, 0x8a, 0xc4, 0x3e, 0x08, 0x19, 0xc5, 0xff, 0x49, 0xcf, 0xc8, 0x8a, 0x8a, + 0x8f, 0x3b, 0xd8, 0xa3, 0xf6, 0x5c, 0xc7, 0x76, 0x45, 0x40, 0xa9, 0x18, 0x72, 0x94, 0x79, 0x22, + 0x9e, 0xcd, 0x3e, 0x11, 0x67, 0x82, 0xd1, 0xdc, 0x41, 0x72, 0xb9, 0xc6, 0x54, 0xb9, 0xdc, 0x0f, + 0x72, 0x50, 0x8f, 0x2b, 0xe7, 0xe8, 0xd5, 0x16, 0xb3, 0xaf, 0xd4, 0x7b, 0xf0, 0x85, 0xec, 0x43, + 0x6b, 0x8c, 0x9f, 0x8c, 0x0c, 0x18, 0xc4, 0x25, 0x78, 0xeb, 0x53, 0x0d, 0xaa, 0xf1, 0x0c, 0xb9, + 0x04, 0x45, 0x5c, 0x4e, 0xba, 0xc9, 0x11, 0xaf, 0xcb, 0x62, 0xfe, 0xab, 0x79, 0xb8, 0xbd, 0x02, + 0x45, 0xac, 0xe9, 0xc8, 0x7f, 0x43, 0x51, 0x7d, 0xaa, 0x1e, 0x7e, 0x5d, 0x16, 0xd3, 0xfa, 0xc7, + 0x39, 0x38, 0x8d, 0x49, 0xf8, 0x01, 0xff, 0x49, 0x44, 0xbe, 0x05, 0x25, 0x11, 0xda, 0xe4, 0x79, + 0x6f, 0xaa, 0x3b, 0xee, 0xb9, 0xc3, 0x70, 0xdc, 0x43, 0x74, 0x43, 0xae, 0xd7, 0x7a, 0x02, 0xc7, + 0x47, 0x63, 0x24, 0xcf, 0x99, 0xda, 0xb8, 0xe7, 0xcc, 0x5c, 0xe6, 0x39, 0x53, 0x35, 0xb7, 0x7c, + 0xda, 0xdc, 0xf4, 0x1f, 0xe5, 0x80, 0xe0, 0xba, 0x07, 0xad, 0xb5, 0xe2, 0x92, 0x2a, 0x3f, 0xa6, + 0xa4, 0x2a, 0xa4, 0x8b, 0x84, 0xd5, 0xe1, 0x92, 0x6a, 0x82, 0xf6, 0x74, 0xb6, 0xde, 0xba, 0x35, + 0xa2, 0xde, 0x9a, 0xa0, 0x23, 0x95, 0x2d, 0xc6, 0xf4, 0xc7, 0xd0, 0x1a, 0x96, 0x42, 0x90, 0x24, + 0x0a, 0x99, 0xa2, 0xe0, 0xcc, 0xd0, 0x3d, 0x8f, 0xa9, 0x31, 0x7e, 0x98, 0x83, 0x53, 0x38, 0x9f, + 0x4d, 0xac, 0xa6, 0x6a, 0x90, 0x3e, 0xce, 0xa8, 0xd9, 0x8d, 0xa1, 0xed, 0xc7, 0x2c, 0xbf, 0x90, + 0x85, 0xa7, 0x95, 0x8c, 0xc1, 0xb1, 0x91, 0x08, 0x87, 0xab, 0x63, 0xcb, 0xef, 0xc2, 0x09, 0xd3, + 0xeb, 0x2d, 0x3c, 0x65, 0xbe, 0x67, 0x9b, 0x0e, 0xdd, 0x08, 0x14, 0xf6, 0x97, 0xab, 0x6b, 0xf8, + 0xbd, 0xd4, 0xb7, 0x1f, 0x68, 0xdf, 0xce, 0xd3, 0xbe, 0xfd, 0xeb, 0x5c, 0x61, 0xed, 0xce, 0x83, + 0xe5, 0xdf, 0xe6, 0x4a, 0x62, 0x66, 0xa3, 0x84, 0x37, 0x78, 0xf5, 0xdf, 0x01, 0x00, 0x00, 0xff, + 0xff, 0x82, 0x72, 0x56, 0x06, 0xd1, 0x33, 0x00, 0x00, } diff --git a/api/api.proto b/api/api.proto index 7aae43e76e05c379a86f99862d58ffe3f394451d..4e0bc5924b45fd3c6d195dc501cd68c65a3c1427 100644 --- a/api/api.proto +++ b/api/api.proto @@ -514,6 +514,8 @@ message ListLeaderboardRecordsAroundOwnerRequest { google.protobuf.UInt32Value limit = 2; // The owner to retrieve records around. string owner_id = 3; + // Expiry in seconds (since epoch) to begin fetching records from. + google.protobuf.Int64Value expiry = 4; } // List leaderboard records from a given leaderboard. @@ -526,6 +528,8 @@ message ListLeaderboardRecordsRequest { google.protobuf.Int32Value limit = 3; // A next or previous page cursor. string cursor = 4; + // Expiry in seconds (since epoch) to begin fetching records from. Optional. 0 means from current time. + google.protobuf.Int64Value expiry = 5; } // List realtime matches. @@ -572,6 +576,8 @@ message ListTournamentRecordsAroundOwnerRequest { google.protobuf.UInt32Value limit = 2; // The owner to retrieve records around. string owner_id = 3; + // Expiry in seconds (since epoch) to begin fetching records from. + google.protobuf.Int64Value expiry = 4; } // List tournament records from a given tournament. @@ -584,6 +590,8 @@ message ListTournamentRecordsRequest { google.protobuf.Int32Value limit = 3; // A next or previous page cursor. string cursor = 4; + // Expiry in seconds (since epoch) to begin fetching records from. + google.protobuf.Int64Value expiry = 5; } // List active/upcoming tournaments based on given filters. diff --git a/apigrpc/apigrpc.swagger.json b/apigrpc/apigrpc.swagger.json index 6ea986bdab14bcc084e15df2ad7c562286a1d492..74122dcca746409ec9c4dc38bc1a2171674d7b71 100644 --- a/apigrpc/apigrpc.swagger.json +++ b/apigrpc/apigrpc.swagger.json @@ -1379,6 +1379,14 @@ "in": "query", "required": false, "type": "string" + }, + { + "name": "expiry", + "description": "Expiry in seconds (since epoch) to begin fetching records from. Optional. 0 means from current time.", + "in": "query", + "required": false, + "type": "string", + "format": "int64" } ], "tags": [ @@ -1477,6 +1485,14 @@ "required": false, "type": "integer", "format": "int64" + }, + { + "name": "expiry", + "description": "Expiry in seconds (since epoch) to begin fetching records from.", + "in": "query", + "required": false, + "type": "string", + "format": "int64" } ], "tags": [ @@ -1815,6 +1831,14 @@ "in": "query", "required": false, "type": "string" + }, + { + "name": "expiry", + "description": "Expiry in seconds (since epoch) to begin fetching records from.", + "in": "query", + "required": false, + "type": "string", + "format": "int64" } ], "tags": [ @@ -2080,6 +2104,14 @@ "required": false, "type": "integer", "format": "int64" + }, + { + "name": "expiry", + "description": "Expiry in seconds (since epoch) to begin fetching records from.", + "in": "query", + "required": false, + "type": "string", + "format": "int64" } ], "tags": [ diff --git a/runtime/runtime.go b/runtime/runtime.go index 56ceb53c8dea35f7cfeb4fce64611210b07fd3eb..9a2d33aff320910442b5db2877d608012213f40b 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -818,7 +818,7 @@ type NakamaModule interface { TournamentJoin(ctx context.Context, id, ownerID, username string) error TournamentList(ctx context.Context, categoryStart, categoryEnd, startTime, endTime, limit int, cursor string) (*api.TournamentList, error) TournamentRecordWrite(ctx context.Context, id, ownerID, username string, score, subscore int64, metadata map[string]interface{}) (*api.LeaderboardRecord, error) - TournamentRecordsHaystack(ctx context.Context, id, ownerID string, limit int) ([]*api.LeaderboardRecord, error) + TournamentRecordsHaystack(ctx context.Context, id, ownerID string, limit int, expiry int64) ([]*api.LeaderboardRecord, error) GroupsGetId(ctx context.Context, groupIDs []string) ([]*api.Group, error) GroupCreate(ctx context.Context, userID, name, creatorID, langTag, description, avatarUrl string, open bool, metadata map[string]interface{}, maxCount int) (*api.Group, error) diff --git a/server/api_leaderboard.go b/server/api_leaderboard.go index 8bb33b312c520e264cbd3c172ce23891b53192db..0543f562fb11c20128ab7f23c86d1015e5529680 100644 --- a/server/api_leaderboard.go +++ b/server/api_leaderboard.go @@ -16,6 +16,7 @@ package server import ( "encoding/json" + "github.com/gofrs/uuid" "github.com/golang/protobuf/ptypes/empty" "github.com/golang/protobuf/ptypes/wrappers" @@ -124,7 +125,12 @@ func (s *ApiServer) ListLeaderboardRecords(ctx context.Context, in *api.ListLead } } - records, err := LeaderboardRecordsList(ctx, s.logger, s.db, s.leaderboardCache, s.leaderboardRankCache, in.LeaderboardId, limit, in.Cursor, in.OwnerIds, 0) + overrideExpiry := int64(0) + if in.Expiry != nil { + overrideExpiry = in.Expiry.Value + } + + records, err := LeaderboardRecordsList(ctx, s.logger, s.db, s.leaderboardCache, s.leaderboardRankCache, in.LeaderboardId, limit, in.Cursor, in.OwnerIds, overrideExpiry) if err == ErrLeaderboardNotFound { return nil, status.Error(codes.NotFound, "Leaderboard not found.") } else if err == ErrLeaderboardInvalidCursor { @@ -251,7 +257,12 @@ func (s *ApiServer) ListLeaderboardRecordsAroundOwner(ctx context.Context, in *a return nil, status.Error(codes.InvalidArgument, "Invalid owner ID provided.") } - records, err := LeaderboardRecordsHaystack(ctx, s.logger, s.db, s.leaderboardCache, s.leaderboardRankCache, in.GetLeaderboardId(), ownerId, limit) + overrideExpiry := int64(0) + if in.Expiry != nil { + overrideExpiry = in.Expiry.Value + } + + records, err := LeaderboardRecordsHaystack(ctx, s.logger, s.db, s.leaderboardCache, s.leaderboardRankCache, in.GetLeaderboardId(), ownerId, limit, overrideExpiry) if err == ErrLeaderboardNotFound { return nil, status.Error(codes.NotFound, "Leaderboard not found.") } else if err != nil { diff --git a/server/api_tournament.go b/server/api_tournament.go index 5a37ba05590fc576fa5e33f0bcb9035b0d07b4d6..97921b3d32b448ebbde10c3beda516a390796465 100644 --- a/server/api_tournament.go +++ b/server/api_tournament.go @@ -118,8 +118,13 @@ func (s *ApiServer) ListTournamentRecords(ctx context.Context, in *api.ListTourn return nil, status.Error(codes.NotFound, "Tournament not found.") } - if tournament.EndTime > 0 && tournament.EndTime <= time.Now().UTC().Unix() { - return nil, status.Error(codes.NotFound, "Tournament not found or has ended.") + overrideExpiry := int64(0) + if in.Expiry != nil { + overrideExpiry = in.Expiry.Value + } else { + if tournament.EndTime > 0 && tournament.EndTime <= time.Now().UTC().Unix() { + return nil, status.Error(codes.NotFound, "Tournament not found or has ended.") + } } var limit *wrappers.Int32Value @@ -140,7 +145,7 @@ func (s *ApiServer) ListTournamentRecords(ctx context.Context, in *api.ListTourn } } - records, err := LeaderboardRecordsList(ctx, s.logger, s.db, s.leaderboardCache, s.leaderboardRankCache, in.GetTournamentId(), limit, in.GetCursor(), in.GetOwnerIds(), 0) + records, err := LeaderboardRecordsList(ctx, s.logger, s.db, s.leaderboardCache, s.leaderboardRankCache, in.GetTournamentId(), limit, in.GetCursor(), in.GetOwnerIds(), overrideExpiry) if err == ErrLeaderboardNotFound { return nil, status.Error(codes.NotFound, "Tournament not found.") } else if err == ErrLeaderboardInvalidCursor { @@ -386,7 +391,12 @@ func (s *ApiServer) ListTournamentRecordsAroundOwner(ctx context.Context, in *ap return nil, status.Error(codes.InvalidArgument, "Invalid owner ID provided.") } - records, err := TournamentRecordsHaystack(ctx, s.logger, s.db, s.leaderboardCache, s.leaderboardRankCache, in.GetTournamentId(), ownerId, limit) + overrideExpiry := int64(0) + if in.Expiry != nil { + overrideExpiry = in.Expiry.Value + } + + records, err := TournamentRecordsHaystack(ctx, s.logger, s.db, s.leaderboardCache, s.leaderboardRankCache, in.GetTournamentId(), ownerId, limit, overrideExpiry) if err == ErrLeaderboardNotFound { return nil, status.Error(codes.NotFound, "Tournament not found.") } else if err != nil { diff --git a/server/core_leaderboard.go b/server/core_leaderboard.go index 0fa0fbee4fdfe66dfa5e48d41b312ca231e4a1fd..f88a34e09072021fb6524d8b7a2478b456d1b7a4 100644 --- a/server/core_leaderboard.go +++ b/server/core_leaderboard.go @@ -62,8 +62,15 @@ func LeaderboardRecordsList(ctx context.Context, logger *zap.Logger, db *sql.DB, now := time.Now().UTC() if leaderboard.IsTournament() { _, _, expiryTime = calculateTournamentDeadlines(leaderboard.StartTime, leaderboard.EndTime, int64(leaderboard.Duration), leaderboard.ResetSchedule, now) + if expiryTime != 0 && expiryTime <= now.Unix() { + // if the expiry time is in the past, we wont have any records to return + return &api.LeaderboardRecordList{}, nil + } } else if leaderboard.ResetSchedule != nil { expiryTime = leaderboard.ResetSchedule.Next(now).UTC().Unix() + if leaderboard.EndTime > 0 && expiryTime > leaderboard.EndTime { + expiryTime = leaderboard.EndTime + } } } @@ -471,14 +478,14 @@ func LeaderboardRecordsDeleteAll(ctx context.Context, logger *zap.Logger, tx *sq return nil } -func LeaderboardRecordsHaystack(ctx context.Context, logger *zap.Logger, db *sql.DB, leaderboardCache LeaderboardCache, rankCache LeaderboardRankCache, leaderboardId string, ownerId uuid.UUID, limit int) ([]*api.LeaderboardRecord, error) { +func LeaderboardRecordsHaystack(ctx context.Context, logger *zap.Logger, db *sql.DB, leaderboardCache LeaderboardCache, rankCache LeaderboardRankCache, leaderboardId string, ownerId uuid.UUID, limit int, expiry int64) ([]*api.LeaderboardRecord, error) { leaderboard := leaderboardCache.Get(leaderboardId) if leaderboard == nil { return nil, ErrLeaderboardNotFound } sortOrder := leaderboard.SortOrder - expiryTime := time.Unix(0, 0).UTC() + expiryTime := time.Unix(expiry, 0).UTC() if leaderboard.ResetSchedule != nil { expiryTime = leaderboard.ResetSchedule.Next(time.Now().UTC()).UTC() } diff --git a/server/core_tournament.go b/server/core_tournament.go index 9ba51449954ebf687d0d22631afcd3d19abaf079..f164ea4dc1a749080231b9ff877ab9ddbb713125 100644 --- a/server/core_tournament.go +++ b/server/core_tournament.go @@ -69,13 +69,16 @@ func TournamentDelete(ctx context.Context, logger *zap.Logger, cache Leaderboard // If it does not exist treat it as success. return nil } - // Allow deletion of non-tournament leaderboards here. var expiryUnix int64 if leaderboard.ResetSchedule != nil { expiryUnix = leaderboard.ResetSchedule.Next(time.Now().UTC()).UTC().Unix() } + if leaderboard.EndTime > 0 && expiryUnix > leaderboard.EndTime { + expiryUnix = leaderboard.EndTime + } + if err := cache.Delete(ctx, leaderboardId); err != nil { return err } @@ -104,6 +107,9 @@ func TournamentAddAttempt(ctx context.Context, logger *zap.Logger, db *sql.DB, c expiryTime := int64(0) if leaderboard.ResetSchedule != nil { expiryTime = leaderboard.ResetSchedule.Next(time.Now().UTC()).UTC().Unix() + if leaderboard.EndTime > 0 && expiryTime > leaderboard.EndTime { + expiryTime = leaderboard.EndTime + } } query := `UPDATE leaderboard_record SET max_num_score = (max_num_score + $1) WHERE leaderboard_id = $2 AND owner_id = $3 AND expiry_time = $4` @@ -198,19 +204,8 @@ func TournamentList(ctx context.Context, logger *zap.Logger, db *sql.DB, categor SELECT id, sort_order, reset_schedule, metadata, create_time, category, description, duration, end_time, max_size, max_num_score, title, size, start_time FROM leaderboard -WHERE duration > 0 AND start_time >= $1 AND end_time <= $2 AND category >= $3 AND category <= $4` - +WHERE duration > 0 AND category >= $1 AND category <= $2 AND start_time >= $3` params := make([]interface{}, 0, 6) - if startTime >= 0 { - params = append(params, time.Unix(int64(startTime), 0).UTC()) - } else { - params = append(params, time.Unix(0, 0).UTC()) - } - if endTime >= 0 { - params = append(params, time.Unix(int64(endTime), 0).UTC()) - } else { - params = append(params, time.Unix(0, 0).UTC()) - } if categoryStart >= 0 && categoryStart <= 127 { params = append(params, categoryStart) } else { @@ -222,7 +217,26 @@ WHERE duration > 0 AND start_time >= $1 AND end_time <= $2 AND category >= $3 AN params = append(params, 127) } - // To ensure that there are more records, so the cursor is returned/ + if startTime >= 0 { + params = append(params, time.Unix(int64(startTime), 0).UTC()) + } else { + params = append(params, time.Unix(0, 0).UTC()) + } + + if endTime == 0 { + query += " AND end_time = $4" + params = append(params, time.Unix(0, 0).UTC()) + } else if int64(endTime) < now.Unix() { + // if end time is set explicitly in the past + query += " AND end_time <= $4" + params = append(params, time.Unix(int64(endTime), 0).UTC()) + } else { + // if end time is in the future, return both tournaments that end in the future as well as the ones that never end. + query += " AND (end_time <= $4 OR end_time = '1970-01-01 00:00:00 UTC')" + params = append(params, time.Unix(int64(endTime), 0).UTC()) + } + + // To ensure that there are more records, so the cursor is returned params = append(params, limit+1) if cursor != nil { @@ -449,7 +463,7 @@ func TournamentRecordWrite(ctx context.Context, logger *zap.Logger, db *sql.DB, return record, nil } -func TournamentRecordsHaystack(ctx context.Context, logger *zap.Logger, db *sql.DB, leaderboardCache LeaderboardCache, rankCache LeaderboardRankCache, leaderboardId string, ownerId uuid.UUID, limit int) ([]*api.LeaderboardRecord, error) { +func TournamentRecordsHaystack(ctx context.Context, logger *zap.Logger, db *sql.DB, leaderboardCache LeaderboardCache, rankCache LeaderboardRankCache, leaderboardId string, ownerId uuid.UUID, limit int, expiryOverride int64) ([]*api.LeaderboardRecord, error) { leaderboard := leaderboardCache.Get(leaderboardId) if leaderboard == nil { return nil, ErrLeaderboardNotFound @@ -457,9 +471,17 @@ func TournamentRecordsHaystack(ctx context.Context, logger *zap.Logger, db *sql. sortOrder := leaderboard.SortOrder - _, _, expiry := calculateTournamentDeadlines(leaderboard.StartTime, leaderboard.EndTime, int64(leaderboard.Duration), leaderboard.ResetSchedule, time.Now().UTC()) - expiryTime := time.Unix(expiry, 0).UTC() + expiry := expiryOverride + if expiry == 0 { + now := time.Now().UTC() + _, _, expiry = calculateTournamentDeadlines(leaderboard.StartTime, leaderboard.EndTime, int64(leaderboard.Duration), leaderboard.ResetSchedule, now) + if expiry != 0 && expiry <= now.Unix() { + // if the expiry time is in the past, we wont have any records to return + return make([]*api.LeaderboardRecord, 0), nil + } + } + expiryTime := time.Unix(expiry, 0).UTC() return getLeaderboardRecordsHaystack(ctx, logger, db, rankCache, ownerId, limit, leaderboard.Id, sortOrder, expiryTime) } @@ -488,6 +510,10 @@ func calculateTournamentDeadlines(startTime, endTime, duration int64, resetSched startActiveUnix = startTime } + if endTime > 0 && expiryUnix > endTime { + expiryUnix = endTime + } + return startActiveUnix, endActiveUnix, expiryUnix } else { endActiveUnix := int64(0) diff --git a/server/leaderboard_rank_cache.go b/server/leaderboard_rank_cache.go index d15d4094f40effc5c106eea7327ef4d4a4294a18..8c25aefe7ae034e2ca8ec121e83e2f4538cf2a7c 100644 --- a/server/leaderboard_rank_cache.go +++ b/server/leaderboard_rank_cache.go @@ -122,6 +122,9 @@ func NewLocalLeaderboardRankCache(startupLogger *zap.Logger, db *sql.DB, config var expiryUnix int64 if leaderboard.ResetSchedule != nil { expiryUnix = leaderboard.ResetSchedule.Next(nowTime).UTC().Unix() + if leaderboard.EndTime > 0 && expiryUnix > leaderboard.EndTime { + expiryUnix = leaderboard.EndTime + } } else { expiryUnix = leaderboard.EndTime } diff --git a/server/runtime_go_nakama.go b/server/runtime_go_nakama.go index 71315241c3e452b12c6027cb1b4e0f6cd6e172be..d064f5dee636ec36d8d414315f61f87aa07755a0 100644 --- a/server/runtime_go_nakama.go +++ b/server/runtime_go_nakama.go @@ -1470,7 +1470,7 @@ func (n *RuntimeGoNakamaModule) TournamentRecordWrite(ctx context.Context, id, o return TournamentRecordWrite(ctx, n.logger, n.db, n.leaderboardCache, n.leaderboardRankCache, id, owner, username, score, subscore, metadataStr) } -func (n *RuntimeGoNakamaModule) TournamentRecordsHaystack(ctx context.Context, id, ownerID string, limit int) ([]*api.LeaderboardRecord, error) { +func (n *RuntimeGoNakamaModule) TournamentRecordsHaystack(ctx context.Context, id, ownerID string, limit int, expiry int64) ([]*api.LeaderboardRecord, error) { if id == "" { return nil, errors.New("expects a tournament ID string") } @@ -1484,7 +1484,11 @@ func (n *RuntimeGoNakamaModule) TournamentRecordsHaystack(ctx context.Context, i return nil, errors.New("limit must be 1-100") } - return TournamentRecordsHaystack(ctx, n.logger, n.db, n.leaderboardCache, n.leaderboardRankCache, id, owner, limit) + if expiry < 0 { + return nil, errors.New("expiry should be time since epoch in seconds and has to be a positive integer") + } + + return TournamentRecordsHaystack(ctx, n.logger, n.db, n.leaderboardCache, n.leaderboardRankCache, id, owner, limit, expiry) } func (n *RuntimeGoNakamaModule) GroupsGetId(ctx context.Context, groupIDs []string) ([]*api.Group, error) { diff --git a/server/runtime_lua_nakama.go b/server/runtime_lua_nakama.go index 175cffb1aa9e8e1bedd3c2be665ac7d667620c73..85c4d6730e320dc316844ae55f9ab71f1c5ee295 100644 --- a/server/runtime_lua_nakama.go +++ b/server/runtime_lua_nakama.go @@ -4140,6 +4140,8 @@ func (n *RuntimeLuaNakamaModule) leaderboardDelete(l *lua.LState) int { if err := n.leaderboardCache.Delete(l.Context(), id); err != nil { l.RaiseError("error deleting leaderboard: %v", err.Error()) } + + n.leaderboardScheduler.Update() return 0 } @@ -4743,7 +4745,13 @@ func (n *RuntimeLuaNakamaModule) tournamentRecordsHaystack(l *lua.LState) int { return 0 } - records, err := TournamentRecordsHaystack(l.Context(), n.logger, n.db, n.leaderboardCache, n.rankCache, id, userID, limit) + expiry := l.OptInt(4, 0) + if expiry < 0 { + l.ArgError(4, "expiry should be time since epoch in seconds and has to be a positive integer") + return 0 + } + + records, err := TournamentRecordsHaystack(l.Context(), n.logger, n.db, n.leaderboardCache, n.rankCache, id, userID, limit, int64(expiry)) if err != nil { l.RaiseError("error listing tournament records haystack: %v", err.Error()) return 0