Compare commits
	
		
			227 Commits
		
	
	
		
			08183ed952
			...
			kat/remove
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4609af726b | |||
| c5919c90d0 | |||
| 605adc3293 | |||
| b40554d38d | |||
| 194d7c66a0 | |||
| 3adc301935 | |||
| 9232c673e8 | |||
| c2cb411469 | |||
| 44ddc732a1 | |||
| d6ef3e0487 | |||
| 8c191bdb90 | |||
| 8246699915 | |||
| de9d47c289 | |||
| 39b1808cab | |||
| a78f9e7b9d | |||
| f573026853 | |||
| f98c98ecdd | |||
| 3f6314aab7 | |||
| 3051c155e2 | |||
| e686be5acd | |||
| d49f9b213a | |||
| 8f346d7832 | |||
| 163c6a4e0c | |||
| b9036001aa | |||
| b16b36588f | |||
| efaaeeaad1 | |||
| 5d93f7166e | |||
| 72ac956758 | |||
| 5cb7df174b | |||
| d15dae23c1 | |||
| c98a65bb6f | |||
| e701c79469 | |||
| 18cd3efe80 | |||
| d71974d385 | |||
| 0defdf0892 | |||
| 8d1f79b8a8 | |||
| 9dc426ea0f | |||
| 19a63b9d19 | |||
| ae97f956b3 | |||
| d619751144 | |||
| e431a1751f | |||
| 209f0aa019 | |||
| 70015a942c | |||
| 91cfcb28e7 | |||
| b2a09c1b8c | |||
| 59aaf47cbe | |||
| c426e753cd | |||
| c8cf97421b | |||
| 9718137ad3 | |||
| af1fb3fee7 | |||
| 025baf257a | |||
| 8239ab6e1b | |||
| 1f018f954e | |||
| fd78ddf641 | |||
| 7662f1f050 | |||
| 890bea2571 | |||
| f57f6dc32d | |||
| 14863e3357 | |||
|  | 58f01c567c | ||
| 937368c753 | |||
| d8c11875d4 | |||
| bacd9e77f0 | |||
| 69d755ba32 | |||
| 31fb95e3b0 | |||
| 7d0f9870dd | |||
| 4a493b4e8d | |||
| 341dc819a0 | |||
| b58aecf7a5 | |||
| 301c017d5e | |||
| 1a4b676635 | |||
| ce54bef0b4 | |||
| 2699d29d7b | |||
| 63a07d58ca | |||
| 59fe332fe0 | |||
| 33723f4ea2 | |||
| c0ee55069e | |||
| 492ae4a225 | |||
| dcdb324391 | |||
| 90685cfdbf | |||
| ab61894373 | |||
| 662e0ade64 | |||
| 75aa847ae1 | |||
| c013228f79 | |||
| 740daf95ae | |||
| 768d29f93e | |||
| 837e084a5a | |||
| caea1b9572 | |||
| 0a255f161a | |||
| 85a2da4b5c | |||
| 647ef3049b | |||
| 7b48a5b6e2 | |||
| ec2e3da513 | |||
| 72729e410b | |||
| 5a9205a9b8 | |||
| a33601158f | |||
| 3c6b37b567 | |||
| 9b18ada78d | |||
| d57bb607e4 | |||
| 1f88ee4a0c | |||
| a32317e72f | |||
| b60cbe3854 | |||
| e0b150aa2a | |||
| 2bdfcb994e | |||
| d5c6014548 | |||
| de6fcacfd0 | |||
|  | 993f62b6cf | ||
| aabd74d7d7 | |||
| 15b307a88f | |||
| 72b338bfc2 | |||
| 267486774c | |||
| b94a568ef1 | |||
| b773ccfc8f | |||
| fd5c28e073 | |||
| 4c232829b6 | |||
| ddf1036009 | |||
| 9b3e5c23a0 | |||
| a7eae9d46b | |||
| 8c3e9d6273 | |||
| f306cc6c16 | |||
| 643cdb29e3 | |||
| 89287a0100 | |||
| f9b02f65e0 | |||
| 41169e2848 | |||
| ba36bc709c | |||
| 4005416233 | |||
| db4a6315cd | |||
| af38fdea64 | |||
| 172df69340 | |||
| a030a0ef16 | |||
| 7a6cc2739f | |||
| 41c9701e18 | |||
| 16e79ed608 | |||
| f401e1879b | |||
| 72b451d322 | |||
| 5350c46e0a | |||
| 1f5c5774e1 | |||
| 3b29502e7e | |||
| abc7e9fd05 | |||
| dd5ce77102 | |||
| dabaa3d1e1 | |||
| a6604a3a6d | |||
| 09a3e0e294 | |||
| f20ca53a2a | |||
| a2b912500c | |||
| 7de3d196ba | |||
| 6d5669aaf8 | |||
| 2c583509a2 | |||
| 3480637600 | |||
| f4665f51b1 | |||
| 810212dc12 | |||
| c3210df517 | |||
| 9f5c354433 | |||
| 23d9fef2b1 | |||
| df3087de7d | |||
| 5dd8318dab | |||
| 56c8bcce20 | |||
| 1c4961db5b | |||
| 5e0d01ea5b | |||
| e8938621fc | |||
| 8c8dcdd8e1 | |||
| 5085c9af90 | |||
| 85bc743c8e | |||
| b8efa644e3 | |||
| c18628a4ca | |||
| 535e24c9c2 | |||
| 04308b1003 | |||
| 43c626141e | |||
| c49266e4c1 | |||
| 6677b9232f | |||
| 76e792be88 | |||
| 5eac3d9d40 | |||
| 64593f09b7 | |||
| e20b68799f | |||
| 378878967a | |||
| 251ebe7056 | |||
| 615e4d5467 | |||
| a4f602d651 | |||
| c48512fc45 | |||
| d75822c465 | |||
| 4feeba5150 | |||
| e1237363f0 | |||
| b1550b31c5 | |||
| 81b9fd9f12 | |||
| d3559ede21 | |||
| ef6ccca3f9 | |||
| f781e9648f | |||
| 18d2eea029 | |||
| a95bdab8bf | |||
| eaeb1ed0ea | |||
| f9d6377fe4 | |||
| 30cf72de78 | |||
| fd49dec34c | |||
| cdd1cdd526 | |||
| bce363e8ff | |||
| 80f609b8a2 | |||
| 6205e9a353 | |||
| 12f7e1f115 | |||
| 296ad969f4 | |||
| d25c08447e | |||
| 7502a75753 | |||
| 1a14db1a17 | |||
| 67d8bcac21 | |||
| 4ca27317b4 | |||
| dc214e878f | |||
| d669dba320 | |||
| 235f4a58e9 | |||
| 03c1d08d8c | |||
| cc36a8b51d | |||
| d743ad83e3 | |||
| 194c258dcd | |||
| e0e1ae1108 | |||
| ee73443374 | |||
| 88801f9186 | |||
| 524d469a0d | |||
| c7b225ff00 | |||
| ba84f6d9c0 | |||
| 6a72f9f43f | |||
| efc0b2d858 | |||
| f140807886 | |||
| 37a13f1418 | |||
| 1cc0660a93 | |||
| 14da2ae388 | |||
| 9ee4d43c89 | |||
| fcac551806 | |||
| 044d8fa46d | |||
| 33f5404820 | |||
| 04a30e67d3 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -3,3 +3,4 @@ dist | |||||||
| .direnv | .direnv | ||||||
| /after.txt | /after.txt | ||||||
| /before.txt | /before.txt | ||||||
|  | **/__pycache__/** | ||||||
|   | |||||||
| @@ -1,5 +1,7 @@ | |||||||
| overwrite: true | overwrite: true | ||||||
| schema: "src/schema.gql" | schema: | ||||||
|  |   - "src/schema.gql" | ||||||
|  |   - "src/client-schema.gql" | ||||||
| documents: "src/**/*.gql" | documents: "src/**/*.gql" | ||||||
| generates: | generates: | ||||||
|   src/index.tsx: |   src/index.tsx: | ||||||
|   | |||||||
| @@ -13,19 +13,37 @@ _sym_db = _symbol_database.Default() | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\nshot.proto\x12\x0fserialized_shot\",\n\x05Point\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\x12\r\n\x05\x63ount\x18\x03 \x01(\x05\"i\n\x04Path\x12\x13\n\x0bstart_frame\x18\x01 \x01(\x05\x12\x11\n\tend_frame\x18\x02 \x01(\x05\x12\x11\n\tis_static\x18\x03 \x01(\x08\x12&\n\x06points\x18\x04 \x03(\x0b\x32\x16.serialized_shot.Point\"J\n\tBallPaths\x12\x17\n\x0f\x62\x61ll_identifier\x18\x01 \x01(\x05\x12$\n\x05paths\x18\x02 \x03(\x0b\x32\x15.serialized_shot.Path\"^\n\x04Shot\x12\x13\n\x0bstart_frame\x18\x01 \x01(\x05\x12\x11\n\tend_frame\x18\x02 \x01(\x05\x12.\n\nball_paths\x18\x03 \x03(\x0b\x32\x1a.serialized_shot.BallPathsb\x06proto3') | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\nshot.proto\x12\x0fserialized_shot\"?\n\x03\x42ox\x12\x0c\n\x04left\x18\x01 \x01(\x02\x12\x0b\n\x03top\x18\x02 \x01(\x02\x12\r\n\x05width\x18\x03 \x01(\x02\x12\x0e\n\x06height\x18\x04 \x01(\x02\"\x1d\n\x05Point\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\"\x7f\n\rBallDetection\x12.\n\x0eplane_position\x18\x01 \x01(\x0b\x32\x16.serialized_shot.Point\x12(\n\nannotation\x18\x02 \x01(\x0b\x32\x14.serialized_shot.Box\x12\x14\n\x0cinterpolated\x18\x03 \x01(\x08\"T\n\x10RLEBallDetection\x12\x31\n\tdetection\x18\x01 \x01(\x0b\x32\x1e.serialized_shot.BallDetection\x12\r\n\x05\x63ount\x18\x02 \x01(\r\"L\n\x13RLEDetectionHistory\x12\x35\n\ndetections\x18\x01 \x03(\x0b\x32!.serialized_shot.RLEBallDetection\"F\n\x10\x44\x65tectionHistory\x12\x32\n\ndetections\x18\x01 \x03(\x0b\x32\x1e.serialized_shot.BallDetection\"\xfc\x01\n\rCollisionInfo\x12\x0e\n\x06source\x18\x01 \x01(\r\x12M\n\x10\x62\x61ll_identifiers\x18\x02 \x03(\x0b\x32\x33.serialized_shot.CollisionInfo.BallIdentifiersEntry\x12\x17\n\x0fwall_identifier\x18\x03 \x01(\r\x12\x13\n\x0b\x66rame_index\x18\x04 \x01(\r\x12\x0e\n\x06static\x18\x05 \x01(\x08\x1aN\n\x14\x42\x61llIdentifiersEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.serialized_shot.Point:\x02\x38\x01\"\xcc\x02\n\x04Path\x12\x13\n\x0bstart_frame\x18\x01 \x01(\r\x12\x11\n\tend_frame\x18\x02 \x01(\r\x12\x37\n\ndetections\x18\x03 \x01(\x0b\x32!.serialized_shot.DetectionHistoryH\x00\x12>\n\x0erle_detections\x18\x04 \x01(\x0b\x32$.serialized_shot.RLEDetectionHistoryH\x00\x12\x15\n\x0bnot_present\x18\x05 \x01(\x08H\x00\x12\x11\n\tis_static\x18\x06 \x01(\x08\x12\x32\n\nstart_info\x18\x07 \x01(\x0b\x32\x1e.serialized_shot.CollisionInfo\x12\x30\n\x08\x65nd_info\x18\x08 \x01(\x0b\x32\x1e.serialized_shot.CollisionInfoB\x13\n\x11\x64\x65tection_history\"R\n\x11IdentifierHistory\x12\x17\n\x0f\x62\x61ll_identifier\x18\x01 \x01(\r\x12$\n\x05paths\x18\x02 \x03(\x0b\x32\x15.serialized_shot.Path\"\xf4\x01\n\x12KeyBallIdentifiers\x12\x10\n\x08\x63ue_ball\x18\x01 \x01(\r\x12\x13\n\x0bobject_ball\x18\x02 \x01(\r\x12\x13\n\x0btarget_ball\x18\x03 \x01(\r\x12\x18\n\x10\x63ontact_sequence\x18\x04 \x03(\r\x12\x18\n\x0b\x63ue_ball_id\x18\x05 \x01(\rH\x00\x88\x01\x01\x12\x1b\n\x0eobject_ball_id\x18\x06 \x01(\rH\x01\x88\x01\x01\x12\x1b\n\x0etarget_ball_id\x18\x07 \x01(\rH\x02\x88\x01\x01\x42\x0e\n\x0c_cue_ball_idB\x11\n\x0f_object_ball_idB\x11\n\x0f_target_ball_id\"\xa8\x01\n\x04Shot\x12@\n\x14identifier_histories\x18\x03 \x03(\x0b\x32\".serialized_shot.IdentifierHistory\x12\x36\n\tkey_balls\x18\x04 \x01(\x0b\x32#.serialized_shot.KeyBallIdentifiers\x12\x13\n\x0bstart_index\x18\x05 \x01(\r\x12\x11\n\tend_index\x18\x06 \x01(\rb\x06proto3') | ||||||
|  |  | ||||||
| _globals = globals() | _globals = globals() | ||||||
| _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) | ||||||
| _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'shot_pb2', _globals) | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'shot_pb2', _globals) | ||||||
| if _descriptor._USE_C_DESCRIPTORS == False: | if _descriptor._USE_C_DESCRIPTORS == False: | ||||||
|   DESCRIPTOR._options = None |   DESCRIPTOR._options = None | ||||||
|   _globals['_POINT']._serialized_start=31 |   _globals['_COLLISIONINFO_BALLIDENTIFIERSENTRY']._options = None | ||||||
|   _globals['_POINT']._serialized_end=75 |   _globals['_COLLISIONINFO_BALLIDENTIFIERSENTRY']._serialized_options = b'8\001' | ||||||
|   _globals['_PATH']._serialized_start=77 |   _globals['_BOX']._serialized_start=31 | ||||||
|   _globals['_PATH']._serialized_end=182 |   _globals['_BOX']._serialized_end=94 | ||||||
|   _globals['_BALLPATHS']._serialized_start=184 |   _globals['_POINT']._serialized_start=96 | ||||||
|   _globals['_BALLPATHS']._serialized_end=258 |   _globals['_POINT']._serialized_end=125 | ||||||
|   _globals['_SHOT']._serialized_start=260 |   _globals['_BALLDETECTION']._serialized_start=127 | ||||||
|   _globals['_SHOT']._serialized_end=354 |   _globals['_BALLDETECTION']._serialized_end=254 | ||||||
|  |   _globals['_RLEBALLDETECTION']._serialized_start=256 | ||||||
|  |   _globals['_RLEBALLDETECTION']._serialized_end=340 | ||||||
|  |   _globals['_RLEDETECTIONHISTORY']._serialized_start=342 | ||||||
|  |   _globals['_RLEDETECTIONHISTORY']._serialized_end=418 | ||||||
|  |   _globals['_DETECTIONHISTORY']._serialized_start=420 | ||||||
|  |   _globals['_DETECTIONHISTORY']._serialized_end=490 | ||||||
|  |   _globals['_COLLISIONINFO']._serialized_start=493 | ||||||
|  |   _globals['_COLLISIONINFO']._serialized_end=745 | ||||||
|  |   _globals['_COLLISIONINFO_BALLIDENTIFIERSENTRY']._serialized_start=667 | ||||||
|  |   _globals['_COLLISIONINFO_BALLIDENTIFIERSENTRY']._serialized_end=745 | ||||||
|  |   _globals['_PATH']._serialized_start=748 | ||||||
|  |   _globals['_PATH']._serialized_end=1080 | ||||||
|  |   _globals['_IDENTIFIERHISTORY']._serialized_start=1082 | ||||||
|  |   _globals['_IDENTIFIERHISTORY']._serialized_end=1164 | ||||||
|  |   _globals['_KEYBALLIDENTIFIERS']._serialized_start=1167 | ||||||
|  |   _globals['_KEYBALLIDENTIFIERS']._serialized_end=1411 | ||||||
|  |   _globals['_SHOT']._serialized_start=1414 | ||||||
|  |   _globals['_SHOT']._serialized_end=1582 | ||||||
| # @@protoc_insertion_point(module_scope) | # @@protoc_insertion_point(module_scope) | ||||||
|   | |||||||
| @@ -5,29 +5,98 @@ from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Map | |||||||
|  |  | ||||||
| DESCRIPTOR: _descriptor.FileDescriptor | DESCRIPTOR: _descriptor.FileDescriptor | ||||||
|  |  | ||||||
|  | class Box(_message.Message): | ||||||
|  |     __slots__ = ["left", "top", "width", "height"] | ||||||
|  |     LEFT_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     TOP_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     WIDTH_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     HEIGHT_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     left: float | ||||||
|  |     top: float | ||||||
|  |     width: float | ||||||
|  |     height: float | ||||||
|  |     def __init__(self, left: _Optional[float] = ..., top: _Optional[float] = ..., width: _Optional[float] = ..., height: _Optional[float] = ...) -> None: ... | ||||||
|  |  | ||||||
| class Point(_message.Message): | class Point(_message.Message): | ||||||
|     __slots__ = ["x", "y", "count"] |     __slots__ = ["x", "y"] | ||||||
|     X_FIELD_NUMBER: _ClassVar[int] |     X_FIELD_NUMBER: _ClassVar[int] | ||||||
|     Y_FIELD_NUMBER: _ClassVar[int] |     Y_FIELD_NUMBER: _ClassVar[int] | ||||||
|     COUNT_FIELD_NUMBER: _ClassVar[int] |  | ||||||
|     x: float |     x: float | ||||||
|     y: float |     y: float | ||||||
|  |     def __init__(self, x: _Optional[float] = ..., y: _Optional[float] = ...) -> None: ... | ||||||
|  |  | ||||||
|  | class BallDetection(_message.Message): | ||||||
|  |     __slots__ = ["plane_position", "annotation", "interpolated"] | ||||||
|  |     PLANE_POSITION_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     ANNOTATION_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     INTERPOLATED_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     plane_position: Point | ||||||
|  |     annotation: Box | ||||||
|  |     interpolated: bool | ||||||
|  |     def __init__(self, plane_position: _Optional[_Union[Point, _Mapping]] = ..., annotation: _Optional[_Union[Box, _Mapping]] = ..., interpolated: bool = ...) -> None: ... | ||||||
|  |  | ||||||
|  | class RLEBallDetection(_message.Message): | ||||||
|  |     __slots__ = ["detection", "count"] | ||||||
|  |     DETECTION_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     COUNT_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     detection: BallDetection | ||||||
|     count: int |     count: int | ||||||
|     def __init__(self, x: _Optional[float] = ..., y: _Optional[float] = ..., count: _Optional[int] = ...) -> None: ... |     def __init__(self, detection: _Optional[_Union[BallDetection, _Mapping]] = ..., count: _Optional[int] = ...) -> None: ... | ||||||
|  |  | ||||||
|  | class RLEDetectionHistory(_message.Message): | ||||||
|  |     __slots__ = ["detections"] | ||||||
|  |     DETECTIONS_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     detections: _containers.RepeatedCompositeFieldContainer[RLEBallDetection] | ||||||
|  |     def __init__(self, detections: _Optional[_Iterable[_Union[RLEBallDetection, _Mapping]]] = ...) -> None: ... | ||||||
|  |  | ||||||
|  | class DetectionHistory(_message.Message): | ||||||
|  |     __slots__ = ["detections"] | ||||||
|  |     DETECTIONS_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     detections: _containers.RepeatedCompositeFieldContainer[BallDetection] | ||||||
|  |     def __init__(self, detections: _Optional[_Iterable[_Union[BallDetection, _Mapping]]] = ...) -> None: ... | ||||||
|  |  | ||||||
|  | class CollisionInfo(_message.Message): | ||||||
|  |     __slots__ = ["source", "ball_identifiers", "wall_identifier", "frame_index", "static"] | ||||||
|  |     class BallIdentifiersEntry(_message.Message): | ||||||
|  |         __slots__ = ["key", "value"] | ||||||
|  |         KEY_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |         VALUE_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |         key: int | ||||||
|  |         value: Point | ||||||
|  |         def __init__(self, key: _Optional[int] = ..., value: _Optional[_Union[Point, _Mapping]] = ...) -> None: ... | ||||||
|  |     SOURCE_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     BALL_IDENTIFIERS_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     WALL_IDENTIFIER_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     FRAME_INDEX_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     STATIC_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     source: int | ||||||
|  |     ball_identifiers: _containers.MessageMap[int, Point] | ||||||
|  |     wall_identifier: int | ||||||
|  |     frame_index: int | ||||||
|  |     static: bool | ||||||
|  |     def __init__(self, source: _Optional[int] = ..., ball_identifiers: _Optional[_Mapping[int, Point]] = ..., wall_identifier: _Optional[int] = ..., frame_index: _Optional[int] = ..., static: bool = ...) -> None: ... | ||||||
|  |  | ||||||
| class Path(_message.Message): | class Path(_message.Message): | ||||||
|     __slots__ = ["start_frame", "end_frame", "is_static", "points"] |     __slots__ = ["start_frame", "end_frame", "detections", "rle_detections", "not_present", "is_static", "start_info", "end_info"] | ||||||
|     START_FRAME_FIELD_NUMBER: _ClassVar[int] |     START_FRAME_FIELD_NUMBER: _ClassVar[int] | ||||||
|     END_FRAME_FIELD_NUMBER: _ClassVar[int] |     END_FRAME_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     DETECTIONS_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     RLE_DETECTIONS_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     NOT_PRESENT_FIELD_NUMBER: _ClassVar[int] | ||||||
|     IS_STATIC_FIELD_NUMBER: _ClassVar[int] |     IS_STATIC_FIELD_NUMBER: _ClassVar[int] | ||||||
|     POINTS_FIELD_NUMBER: _ClassVar[int] |     START_INFO_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     END_INFO_FIELD_NUMBER: _ClassVar[int] | ||||||
|     start_frame: int |     start_frame: int | ||||||
|     end_frame: int |     end_frame: int | ||||||
|  |     detections: DetectionHistory | ||||||
|  |     rle_detections: RLEDetectionHistory | ||||||
|  |     not_present: bool | ||||||
|     is_static: bool |     is_static: bool | ||||||
|     points: _containers.RepeatedCompositeFieldContainer[Point] |     start_info: CollisionInfo | ||||||
|     def __init__(self, start_frame: _Optional[int] = ..., end_frame: _Optional[int] = ..., is_static: bool = ..., points: _Optional[_Iterable[_Union[Point, _Mapping]]] = ...) -> None: ... |     end_info: CollisionInfo | ||||||
|  |     def __init__(self, start_frame: _Optional[int] = ..., end_frame: _Optional[int] = ..., detections: _Optional[_Union[DetectionHistory, _Mapping]] = ..., rle_detections: _Optional[_Union[RLEDetectionHistory, _Mapping]] = ..., not_present: bool = ..., is_static: bool = ..., start_info: _Optional[_Union[CollisionInfo, _Mapping]] = ..., end_info: _Optional[_Union[CollisionInfo, _Mapping]] = ...) -> None: ... | ||||||
|  |  | ||||||
| class BallPaths(_message.Message): | class IdentifierHistory(_message.Message): | ||||||
|     __slots__ = ["ball_identifier", "paths"] |     __slots__ = ["ball_identifier", "paths"] | ||||||
|     BALL_IDENTIFIER_FIELD_NUMBER: _ClassVar[int] |     BALL_IDENTIFIER_FIELD_NUMBER: _ClassVar[int] | ||||||
|     PATHS_FIELD_NUMBER: _ClassVar[int] |     PATHS_FIELD_NUMBER: _ClassVar[int] | ||||||
| @@ -35,12 +104,32 @@ class BallPaths(_message.Message): | |||||||
|     paths: _containers.RepeatedCompositeFieldContainer[Path] |     paths: _containers.RepeatedCompositeFieldContainer[Path] | ||||||
|     def __init__(self, ball_identifier: _Optional[int] = ..., paths: _Optional[_Iterable[_Union[Path, _Mapping]]] = ...) -> None: ... |     def __init__(self, ball_identifier: _Optional[int] = ..., paths: _Optional[_Iterable[_Union[Path, _Mapping]]] = ...) -> None: ... | ||||||
|  |  | ||||||
|  | class KeyBallIdentifiers(_message.Message): | ||||||
|  |     __slots__ = ["cue_ball", "object_ball", "target_ball", "contact_sequence", "cue_ball_id", "object_ball_id", "target_ball_id"] | ||||||
|  |     CUE_BALL_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     OBJECT_BALL_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     TARGET_BALL_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     CONTACT_SEQUENCE_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     CUE_BALL_ID_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     OBJECT_BALL_ID_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     TARGET_BALL_ID_FIELD_NUMBER: _ClassVar[int] | ||||||
|  |     cue_ball: int | ||||||
|  |     object_ball: int | ||||||
|  |     target_ball: int | ||||||
|  |     contact_sequence: _containers.RepeatedScalarFieldContainer[int] | ||||||
|  |     cue_ball_id: int | ||||||
|  |     object_ball_id: int | ||||||
|  |     target_ball_id: int | ||||||
|  |     def __init__(self, cue_ball: _Optional[int] = ..., object_ball: _Optional[int] = ..., target_ball: _Optional[int] = ..., contact_sequence: _Optional[_Iterable[int]] = ..., cue_ball_id: _Optional[int] = ..., object_ball_id: _Optional[int] = ..., target_ball_id: _Optional[int] = ...) -> None: ... | ||||||
|  |  | ||||||
| class Shot(_message.Message): | class Shot(_message.Message): | ||||||
|     __slots__ = ["start_frame", "end_frame", "ball_paths"] |     __slots__ = ["identifier_histories", "key_balls", "start_index", "end_index"] | ||||||
|     START_FRAME_FIELD_NUMBER: _ClassVar[int] |     IDENTIFIER_HISTORIES_FIELD_NUMBER: _ClassVar[int] | ||||||
|     END_FRAME_FIELD_NUMBER: _ClassVar[int] |     KEY_BALLS_FIELD_NUMBER: _ClassVar[int] | ||||||
|     BALL_PATHS_FIELD_NUMBER: _ClassVar[int] |     START_INDEX_FIELD_NUMBER: _ClassVar[int] | ||||||
|     start_frame: int |     END_INDEX_FIELD_NUMBER: _ClassVar[int] | ||||||
|     end_frame: int |     identifier_histories: _containers.RepeatedCompositeFieldContainer[IdentifierHistory] | ||||||
|     ball_paths: _containers.RepeatedCompositeFieldContainer[BallPaths] |     key_balls: KeyBallIdentifiers | ||||||
|     def __init__(self, start_frame: _Optional[int] = ..., end_frame: _Optional[int] = ..., ball_paths: _Optional[_Iterable[_Union[BallPaths, _Mapping]]] = ...) -> None: ... |     start_index: int | ||||||
|  |     end_index: int | ||||||
|  |     def __init__(self, identifier_histories: _Optional[_Iterable[_Union[IdentifierHistory, _Mapping]]] = ..., key_balls: _Optional[_Union[KeyBallIdentifiers, _Mapping]] = ..., start_index: _Optional[int] = ..., end_index: _Optional[int] = ...) -> None: ... | ||||||
|   | |||||||
| @@ -2,26 +2,76 @@ syntax = "proto3"; | |||||||
|  |  | ||||||
| package serialized_shot; | package serialized_shot; | ||||||
|  |  | ||||||
|  | message Box { | ||||||
|  |   float left = 1; | ||||||
|  |   float top = 2; | ||||||
|  |   float width = 3; | ||||||
|  |   float height = 4; | ||||||
|  | } | ||||||
|  |  | ||||||
| message Point { | message Point { | ||||||
|   float x = 1; |   float x = 1; | ||||||
|   float y = 2; |   float y = 2; | ||||||
|   int32 count = 3; | } | ||||||
|  |  | ||||||
|  | message BallDetection { | ||||||
|  |   Point plane_position = 1; | ||||||
|  |   Box annotation = 2; | ||||||
|  |   bool interpolated = 3; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | message RLEBallDetection { | ||||||
|  |   BallDetection detection = 1; | ||||||
|  |   uint32 count = 2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | message RLEDetectionHistory { repeated RLEBallDetection detections = 1; } | ||||||
|  |  | ||||||
|  | message DetectionHistory { repeated BallDetection detections = 1; } | ||||||
|  |  | ||||||
|  | message CollisionInfo { | ||||||
|  |   uint32 source = 1; | ||||||
|  |   map<uint32, Point> ball_identifiers = 2; | ||||||
|  |   uint32 wall_identifier = 3; | ||||||
|  |   uint32 frame_index = 4; | ||||||
|  |   bool static = 5; | ||||||
| } | } | ||||||
|  |  | ||||||
| message Path { | message Path { | ||||||
|   int32 start_frame = 1; |   uint32 start_frame = 1; | ||||||
|   int32 end_frame = 2; |   uint32 end_frame = 2; | ||||||
|   bool is_static = 3; |   oneof detection_history { | ||||||
|   repeated Point points = 4; |     DetectionHistory detections = 3; | ||||||
|  |     RLEDetectionHistory rle_detections = 4; | ||||||
|  |     bool not_present = 5; | ||||||
|  |   } | ||||||
|  |   bool is_static = 6; | ||||||
|  |   CollisionInfo start_info = 7; | ||||||
|  |   CollisionInfo end_info = 8; | ||||||
| } | } | ||||||
|  |  | ||||||
| message BallPaths { | message IdentifierHistory { | ||||||
|   int32 ball_identifier = 1; |   uint32 ball_identifier = 1; | ||||||
|   repeated Path paths = 2; |   repeated Path paths = 2; | ||||||
| } | } | ||||||
|  | message KeyBallIdentifiers { | ||||||
|  |   uint32 cue_ball = 1; | ||||||
|  |   uint32 object_ball = 2; | ||||||
|  |   uint32 target_ball = 3; | ||||||
|  |  | ||||||
|  |   // For now this will just be cue->object/target->target | ||||||
|  |   // Long term this will potentially represent a linked list | ||||||
|  |   // of all balls in a shot. | ||||||
|  |   repeated uint32 contact_sequence = 4; | ||||||
|  |  | ||||||
|  |   optional uint32 cue_ball_id = 5; | ||||||
|  |   optional uint32 object_ball_id = 6; | ||||||
|  |   optional uint32 target_ball_id = 7; | ||||||
|  | } | ||||||
|  |  | ||||||
| message Shot { | message Shot { | ||||||
|   int32 start_frame = 1; |   repeated IdentifierHistory identifier_histories = 3; | ||||||
|   int32 end_frame = 2; |   KeyBallIdentifiers key_balls = 4; | ||||||
|   repeated BallPaths ball_paths = 3; |   uint32 start_index = 5; | ||||||
| } |   uint32 end_index = 6; | ||||||
|  | } | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										25
									
								
								src/client-schema.gql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/client-schema.gql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | # see: https://www.apollographql.com/docs/react/local-state/managing-state-with-field-policies/ | ||||||
|  | directive @client on FIELD | ||||||
|  |  | ||||||
|  | extend type ShotGQL { | ||||||
|  |   startTime: Float! | ||||||
|  |   endTime: Float! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | extend type UploadStreamGQL { | ||||||
|  |   segmentEndFrames: [Int!]! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | extend type HLSPlaylistGQL { | ||||||
|  |   segmentStartTimes: [Float!]! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type SegmentEndFramesGQL { | ||||||
|  |   id: Int! | ||||||
|  |   segmentEndFrames: [Int!]! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type SegmentStartTimesGQL { | ||||||
|  |   id: Int! | ||||||
|  |   segmentStartTimes: [Float!]! | ||||||
|  | } | ||||||
							
								
								
									
										4613
									
								
								src/index.tsx
									
									
									
									
									
								
							
							
						
						
									
										4613
									
								
								src/index.tsx
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -4,5 +4,6 @@ query getDeployedConfig { | |||||||
|     devMode |     devMode | ||||||
|     environment |     environment | ||||||
|     firebase |     firebase | ||||||
|  |     minimumAllowedAppVersion | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -21,8 +21,10 @@ query GetFeed( | |||||||
|       elapsedTime |       elapsedTime | ||||||
|       screenshotUri |       screenshotUri | ||||||
|       stream { |       stream { | ||||||
|  |         id | ||||||
|         isCompleted |         isCompleted | ||||||
|       } |       } | ||||||
|  |       tableSize | ||||||
|       tags { |       tags { | ||||||
|         tagClasses { |         tagClasses { | ||||||
|           name |           name | ||||||
|   | |||||||
| @@ -1,38 +1,149 @@ | |||||||
| query GetShots( | query GetSerializedShotPaths($filterInput: FilterInput!) { | ||||||
|   $filterInput: FilterInput! |  | ||||||
|   $includeCreatedAt: Boolean! = false |  | ||||||
|   $includeUpdatedAt: Boolean! = false |  | ||||||
|   $includeCueObjectFeatures: Boolean! = false |  | ||||||
|   $includePocketingIntentionFeatures: Boolean! = false |  | ||||||
|   $includeCueObjectDistance: Boolean! = false |  | ||||||
|   $includeCueObjectAngle: Boolean! = false |  | ||||||
|   $includeCueBallSpeed: Boolean! = false |  | ||||||
|   $includeShotDirection: Boolean! = false |  | ||||||
|   $includeTargetPocketDistance: Boolean! = false |  | ||||||
|   $includeMake: Boolean! = false |  | ||||||
|   $includeIntendedPocketType: Boolean! = false |  | ||||||
| ) { |  | ||||||
|   getShots(filterInput: $filterInput) { |   getShots(filterInput: $filterInput) { | ||||||
|     id |     id | ||||||
|     videoId |     videoId | ||||||
|     startFrame |     startFrame | ||||||
|     endFrame |     endFrame | ||||||
|     user { |     serializedShotPaths { | ||||||
|       id |       b64EncodedBuffer | ||||||
|     } |  | ||||||
|     createdAt @include(if: $includeCreatedAt) |  | ||||||
|     updatedAt @include(if: $includeUpdatedAt) |  | ||||||
|     cueObjectFeatures @include(if: $includeCueObjectFeatures) { |  | ||||||
|       cueObjectDistance @include(if: $includeCueObjectDistance) |  | ||||||
|       cueObjectAngle @include(if: $includeCueObjectAngle) |  | ||||||
|       cueBallSpeed @include(if: $includeCueBallSpeed) |  | ||||||
|       shotDirection @include(if: $includeShotDirection) |  | ||||||
|     } |  | ||||||
|     pocketingIntentionFeatures |  | ||||||
|       @include(if: $includePocketingIntentionFeatures) { |  | ||||||
|       targetPocketDistance @include(if: $includeTargetPocketDistance) |  | ||||||
|       make @include(if: $includeMake) |  | ||||||
|       intendedPocketType @include(if: $includeIntendedPocketType) |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | query GetShotAnnotationTypes { | ||||||
|  |   getShotAnnotationTypes { | ||||||
|  |     id | ||||||
|  |     name | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | mutation UpdateShotAnnotations( | ||||||
|  |   $shotId: Int! | ||||||
|  |   $annotations: [UpdateAnnotationInputGQL!]! | ||||||
|  | ) { | ||||||
|  |   updateShotAnnotations(shotId: $shotId, annotations: $annotations) { | ||||||
|  |     shot { | ||||||
|  |       id | ||||||
|  |       annotations { | ||||||
|  |         shotId | ||||||
|  |         type { | ||||||
|  |           id | ||||||
|  |           name | ||||||
|  |         } | ||||||
|  |         notes | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     error { | ||||||
|  |       shotId | ||||||
|  |       msg | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | query GetShotsWithVideoGql($filterInput: FilterInput!, $limit: Int) { | ||||||
|  |   getShotsWithMetadata(filterInput: $filterInput, limit: $limit) { | ||||||
|  |     ids | ||||||
|  |     shots { | ||||||
|  |       id | ||||||
|  |       videoId | ||||||
|  |       video { | ||||||
|  |         screenshotUri | ||||||
|  |         endTime | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ## Reserved for playlists (which are created from a filter) | ||||||
|  | query GetShotsWithMetadataFilterResult( | ||||||
|  |   $filterInput: FilterInput! | ||||||
|  |   $shotsOrdering: GetShotsOrdering | ||||||
|  |   $limit: Int | ||||||
|  |   $ids: [Int!] | ||||||
|  | ) { | ||||||
|  |   getOrderedShots( | ||||||
|  |     filterInput: $filterInput | ||||||
|  |     shotsOrdering: $shotsOrdering | ||||||
|  |     limit: $limit | ||||||
|  |     ids: $ids | ||||||
|  |   ) { | ||||||
|  |     count | ||||||
|  |     shots { | ||||||
|  |       ...ShotWithAllFeatures | ||||||
|  |     } | ||||||
|  |     ids | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # TODO: Delete | ||||||
|  | query GetShotsWithMetadata( | ||||||
|  |   $filterInput: FilterInput! | ||||||
|  |   $shotsPagination: GetShotsPagination | ||||||
|  |   $limit: Int | ||||||
|  |   $ids: [Int!] | ||||||
|  | ) { | ||||||
|  |   getShotsWithMetadata( | ||||||
|  |     filterInput: $filterInput | ||||||
|  |     shotsPagination: $shotsPagination | ||||||
|  |     limit: $limit | ||||||
|  |     ids: $ids | ||||||
|  |   ) { | ||||||
|  |     count | ||||||
|  |     shots { | ||||||
|  |       ...ShotWithAllFeatures | ||||||
|  |     } | ||||||
|  |     ids | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | query GetShotsByIds($ids: [Int!]!) { | ||||||
|  |   getShotsByIds(ids: $ids) { | ||||||
|  |     ...ShotWithAllFeatures | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fragment ShotWithAllFeatures on ShotGQL { | ||||||
|  |   id | ||||||
|  |   videoId | ||||||
|  |   startFrame | ||||||
|  |   endFrame | ||||||
|  |   startTime @client | ||||||
|  |   endTime @client | ||||||
|  |   user { | ||||||
|  |     id | ||||||
|  |   } | ||||||
|  |   falsePositiveScore | ||||||
|  |   createdAt | ||||||
|  |   updatedAt | ||||||
|  |   cueObjectFeatures { | ||||||
|  |     cueObjectDistance | ||||||
|  |     cueObjectAngle | ||||||
|  |     cueBallSpeed | ||||||
|  |     shotDirection | ||||||
|  |     spinType | ||||||
|  |   } | ||||||
|  |   pocketingIntentionFeatures { | ||||||
|  |     make | ||||||
|  |     targetPocketDistance | ||||||
|  |     targetPocketAngle | ||||||
|  |     targetPocketAngleDirection | ||||||
|  |     marginOfErrorInDegrees | ||||||
|  |     intendedPocketType | ||||||
|  |   } | ||||||
|  |   pocketingIntentionInfo { | ||||||
|  |     ballId | ||||||
|  |     pocketId | ||||||
|  |     pathMetadataIndex | ||||||
|  |   } | ||||||
|  |   serializedShotPaths { | ||||||
|  |     b64EncodedBuffer | ||||||
|  |   } | ||||||
|  |   annotations { | ||||||
|  |     shotId | ||||||
|  |     type { | ||||||
|  |       id | ||||||
|  |       name | ||||||
|  |     } | ||||||
|  |     notes | ||||||
|  |   } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1,9 +1,20 @@ | |||||||
| mutation getProfileImageUploadLink($fileExt: String = ".png") { | mutation getProfileImageUploadLink($fileExt: String = ".png") { | ||||||
|   getProfileImageUploadLink(fileExt: $fileExt) { |   getProfileImageUploadLink(fileExt: $fileExt) { | ||||||
|     uploadUrl |     value { | ||||||
|     headers { |       ... on UploadLink { | ||||||
|       key |         uploadUrl | ||||||
|       value |         headers { | ||||||
|  |           key | ||||||
|  |           value | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       ... on GetProfileUploadLinkErrors { | ||||||
|  |         error { | ||||||
|  |           ... on TooManyProfileImageUploadsErr { | ||||||
|  |             linksRequested | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -24,6 +35,7 @@ query getLoggedInUser { | |||||||
|     id |     id | ||||||
|     firebaseUid |     firebaseUid | ||||||
|     username |     username | ||||||
|  |     isAdmin | ||||||
|     profileImageUri |     profileImageUri | ||||||
|     activeVideoId |     activeVideoId | ||||||
|     createdAt |     createdAt | ||||||
| @@ -36,3 +48,35 @@ query GetUserPlayTime($userId: Int!) { | |||||||
|     totalSeconds |     totalSeconds | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | query getUsernames( | ||||||
|  |   $matchString: String! | ||||||
|  |   $limit: Int = null | ||||||
|  |   $after: String = null | ||||||
|  | ) { | ||||||
|  |   getUsernames(matchString: $matchString, limit: $limit, after: $after) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | query getUsernamesAndFollowing( | ||||||
|  |   $userId: Int! | ||||||
|  |   $matchString: String! | ||||||
|  |   $limit: Int = null | ||||||
|  |   $after: String = null | ||||||
|  | ) { | ||||||
|  |   getUsernamesAndFollowing( | ||||||
|  |     userId: $userId | ||||||
|  |     matchString: $matchString | ||||||
|  |     limit: $limit | ||||||
|  |     after: $after | ||||||
|  |   ) { | ||||||
|  |     followers | ||||||
|  |     following | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | query GetUserTags { | ||||||
|  |   getUserTags { | ||||||
|  |     id | ||||||
|  |     name | ||||||
|  |   } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1,10 +1,10 @@ | |||||||
| query GetStreamMonitoringDetails($videoId: Int!) { | query GetStreamMonitoringDetails($videoId: Int!, $debuggingJson: JSON) { | ||||||
|   getVideo(videoId: $videoId) { |   getVideo(videoId: $videoId, debuggingJson: $debuggingJson) { | ||||||
|     id |     id | ||||||
|     totalShots |     totalShots | ||||||
|     makePercentage |     makePercentage | ||||||
|     elapsedTime |     elapsedTime | ||||||
|     homographyHistory { |     currentHomography { | ||||||
|       crop { |       crop { | ||||||
|         left |         left | ||||||
|         top |         top | ||||||
| @@ -45,12 +45,14 @@ query GetStreamMonitoringDetails($videoId: Int!) { | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     stream { |     stream { | ||||||
|  |       id | ||||||
|       linksRequested |       linksRequested | ||||||
|       uploadsCompleted |       uploadsCompleted | ||||||
|       segmentProcessingCursor |       segmentProcessingCursor | ||||||
|       isCompleted |       isCompleted | ||||||
|       uploadCompletionCursor |       uploadCompletionCursor | ||||||
|       lastIntendedSegmentBound |       lastIntendedSegmentBound | ||||||
|  |       initPlaylistUploadStatus | ||||||
|     } |     } | ||||||
|     currentProcessing { |     currentProcessing { | ||||||
|       errors { |       errors { | ||||||
| @@ -69,6 +71,7 @@ query GetVideoUpdatePageDetails($videoId: Int!) { | |||||||
|     totalShots |     totalShots | ||||||
|     makePercentage |     makePercentage | ||||||
|     elapsedTime |     elapsedTime | ||||||
|  |     tableSize | ||||||
|     tags { |     tags { | ||||||
|       tagClasses { |       tagClasses { | ||||||
|         name |         name | ||||||
| @@ -91,14 +94,13 @@ query GetVideoDetails($videoId: Int!) { | |||||||
|     elapsedTime |     elapsedTime | ||||||
|     endTime |     endTime | ||||||
|     makePercentage |     makePercentage | ||||||
|     makePercentage |  | ||||||
|     medianRun |     medianRun | ||||||
|     startTime |     startTime | ||||||
|     totalShots |     totalShots | ||||||
|     totalShots |  | ||||||
|     totalShotsMade |     totalShotsMade | ||||||
|     createdAt |     createdAt | ||||||
|     updatedAt |     updatedAt | ||||||
|  |     tableSize | ||||||
|     owner { |     owner { | ||||||
|       id |       id | ||||||
|       firebaseUid |       firebaseUid | ||||||
| @@ -116,21 +118,33 @@ query GetVideoDetails($videoId: Int!) { | |||||||
|  |  | ||||||
| query GetVideos($videoIds: [Int!]!) { | query GetVideos($videoIds: [Int!]!) { | ||||||
|   getVideos(videoIds: $videoIds) { |   getVideos(videoIds: $videoIds) { | ||||||
|  |     ...VideoStreamMetadata | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fragment VideoStreamMetadata on VideoGQL { | ||||||
|  |   id | ||||||
|  |   framesPerSecond | ||||||
|  |   stream { | ||||||
|     id |     id | ||||||
|     playlist { |     streamSegmentType | ||||||
|       segmentDurations |     segments { | ||||||
|     } |       uploaded | ||||||
|     stream { |       valid | ||||||
|       id |       segmentIndex | ||||||
|       segments { |       endFrameIndex | ||||||
|         uploaded |       framesPerSecond | ||||||
|         valid |  | ||||||
|         segmentIndex |  | ||||||
|         endFrameIndex |  | ||||||
|         framesPerSecond |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |   playlist { | ||||||
|  |     segmentDurations | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | query GetVideoForShotTime($videoId: Int!) { | ||||||
|  |   getVideo(videoId: $videoId) { | ||||||
|  |     ...VideoStreamMetadata | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| query GetVideo($videoId: Int!) { | query GetVideo($videoId: Int!) { | ||||||
| @@ -139,12 +153,138 @@ query GetVideo($videoId: Int!) { | |||||||
|     playlist { |     playlist { | ||||||
|       segmentDurations |       segmentDurations | ||||||
|     } |     } | ||||||
|  |     homographyHistory { | ||||||
|  |       frameIndex | ||||||
|  |       crop { | ||||||
|  |         left | ||||||
|  |         top | ||||||
|  |         width | ||||||
|  |         height | ||||||
|  |       } | ||||||
|  |       pockets { | ||||||
|  |         left | ||||||
|  |         top | ||||||
|  |         width | ||||||
|  |         height | ||||||
|  |       } | ||||||
|  |       sourcePoints { | ||||||
|  |         topLeft { | ||||||
|  |           x | ||||||
|  |           y | ||||||
|  |         } | ||||||
|  |         topSide { | ||||||
|  |           x | ||||||
|  |           y | ||||||
|  |         } | ||||||
|  |         topRight { | ||||||
|  |           x | ||||||
|  |           y | ||||||
|  |         } | ||||||
|  |         bottomLeft { | ||||||
|  |           x | ||||||
|  |           y | ||||||
|  |         } | ||||||
|  |         bottomSide { | ||||||
|  |           x | ||||||
|  |           y | ||||||
|  |         } | ||||||
|  |         bottomRight { | ||||||
|  |           x | ||||||
|  |           y | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|     stream { |     stream { | ||||||
|  |       id | ||||||
|  |       streamSegmentType | ||||||
|       segments { |       segments { | ||||||
|         segmentIndex |         segmentIndex | ||||||
|         endFrameIndex |         endFrameIndex | ||||||
|         framesPerSecond |         framesPerSecond | ||||||
|       } |       } | ||||||
|  |       resolution { | ||||||
|  |         width | ||||||
|  |         height | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | query GetAverageTimePerShotForVideo($videoId: Int!) { | ||||||
|  |   getVideo(videoId: $videoId) { | ||||||
|  |     id | ||||||
|  |     averageTimeBetweenShots | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | query GetElapsedTimeForVideo($videoId: Int!) { | ||||||
|  |   getVideo(videoId: $videoId) { | ||||||
|  |     id | ||||||
|  |     elapsedTime | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | query GetMedianRunForVideo($videoId: Int!) { | ||||||
|  |   getVideo(videoId: $videoId) { | ||||||
|  |     id | ||||||
|  |     medianRun | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fragment StreamWithEndFrames on UploadStreamGQL { | ||||||
|  |   id | ||||||
|  |   streamSegmentType | ||||||
|  |   segmentEndFrames @client | ||||||
|  |   resolution { | ||||||
|  |     width | ||||||
|  |     height | ||||||
|  |   } | ||||||
|  |   segments { | ||||||
|  |     uploaded | ||||||
|  |     valid | ||||||
|  |     segmentIndex | ||||||
|  |     endFrameIndex | ||||||
|  |     framesPerSecond | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fragment SegmentEndFrames on SegmentEndFramesGQL { | ||||||
|  |   id | ||||||
|  |   segmentEndFrames | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fragment SegmentStartTimes on SegmentStartTimesGQL { | ||||||
|  |   id | ||||||
|  |   segmentStartTimes | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fragment PlaylistWithSegmentStartTimes on HLSPlaylistGQL { | ||||||
|  |   videoId | ||||||
|  |   segmentDurations | ||||||
|  |   segmentStartTimes @client | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fragment VideoDurationData on VideoGQL { | ||||||
|  |   id | ||||||
|  |   framesPerSecond | ||||||
|  |   playlist { | ||||||
|  |     ...PlaylistWithSegmentStartTimes | ||||||
|  |   } | ||||||
|  |   stream { | ||||||
|  |     ...StreamWithEndFrames | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | query GetVideoForClipTimes($videoId: Int!) { | ||||||
|  |   getVideo(videoId: $videoId) { | ||||||
|  |     ...VideoDurationData | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | query GetHeaderInfoByVideoId($videoId: Int!) { | ||||||
|  |   getVideo(videoId: $videoId) { | ||||||
|  |     id | ||||||
|  |     name | ||||||
|  |     startTime | ||||||
|  |   } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -6,14 +6,79 @@ mutation CreateUploadStream($videoMetadataInput: VideoMetadataInput!) { | |||||||
|  |  | ||||||
| mutation GetUploadLink($videoId: Int!, $segmentIndex: Int!) { | mutation GetUploadLink($videoId: Int!, $segmentIndex: Int!) { | ||||||
|   getUploadLink(videoId: $videoId, segmentIndex: $segmentIndex) { |   getUploadLink(videoId: $videoId, segmentIndex: $segmentIndex) { | ||||||
|     uploadUrl |     value { | ||||||
|     headers { |       ... on UploadLink { | ||||||
|       key |         uploadUrl | ||||||
|       value |         headers { | ||||||
|  |           key | ||||||
|  |           value | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       ... on GetUploadLinkErrors { | ||||||
|  |         error { | ||||||
|  |           ... on MustHaveSetForUploadLinkErr { | ||||||
|  |             resolution | ||||||
|  |             framesPerSecond | ||||||
|  |           } | ||||||
|  |           ... on SegmentAlreadyUploadedErr { | ||||||
|  |             segmentId | ||||||
|  |           } | ||||||
|  |           ... on ProcessingFailedErr { | ||||||
|  |             processing { | ||||||
|  |               status | ||||||
|  |               errors { | ||||||
|  |                 message | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     stream { | ||||||
|  |       uploadCompletionCursor | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | mutation GetHlsInitUploadLink($videoId: Int!) { | ||||||
|  |   getHlsInitUploadLink(videoId: $videoId) { | ||||||
|  |     value { | ||||||
|  |       ... on UploadLink { | ||||||
|  |         uploadUrl | ||||||
|  |         headers { | ||||||
|  |           key | ||||||
|  |           value | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       ... on GetUploadLinkErrors { | ||||||
|  |         error { | ||||||
|  |           ... on NoInitForChunkedUploadErr { | ||||||
|  |             segmentType | ||||||
|  |           } | ||||||
|  |           ... on InitUploadAlreadyCompletedErr { | ||||||
|  |             segmentType | ||||||
|  |           } | ||||||
|  |           ... on TooManyInitUploadsErr { | ||||||
|  |             linksRequested | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | mutation SetSegmentDuration( | ||||||
|  |   $videoId: Int! | ||||||
|  |   $segmentIndex: Int! | ||||||
|  |   $duration: Float! | ||||||
|  | ) { | ||||||
|  |   setSegmentDuration( | ||||||
|  |     videoId: $videoId | ||||||
|  |     segmentIndex: $segmentIndex | ||||||
|  |     duration: $duration | ||||||
|  |   ) | ||||||
|  | } | ||||||
|  |  | ||||||
| mutation EditUploadStream( | mutation EditUploadStream( | ||||||
|   $videoId: Int! |   $videoId: Int! | ||||||
|   $videoMetadataInput: VideoMetadataInput! |   $videoMetadataInput: VideoMetadataInput! | ||||||
| @@ -50,6 +115,7 @@ query GetUploadStreamsWithDetails( | |||||||
|         isCompleted |         isCompleted | ||||||
|         lastIntendedSegmentBound |         lastIntendedSegmentBound | ||||||
|         uploadCompletionCursor |         uploadCompletionCursor | ||||||
|  |         uploadsCompleted | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     pageInfo { |     pageInfo { | ||||||
|   | |||||||
							
								
								
									
										495
									
								
								src/schema.gql
									
									
									
									
									
								
							
							
						
						
									
										495
									
								
								src/schema.gql
									
									
									
									
									
								
							| @@ -4,13 +4,43 @@ type Query { | |||||||
|   ): [AggregateResultGQL!]! |   ): [AggregateResultGQL!]! | ||||||
|   getBucketSet(keyName: String!): BucketSetGQL |   getBucketSet(keyName: String!): BucketSetGQL | ||||||
|   getDeployedConfig: DeployedConfigGQL! |   getDeployedConfig: DeployedConfigGQL! | ||||||
|  |   waitFor(duration: Float!): Float! | ||||||
|   getVideoMakePercentageIntervals( |   getVideoMakePercentageIntervals( | ||||||
|     videoId: ID! |     videoId: ID! | ||||||
|     intervalDuration: Int! = 300 |     intervalDuration: Int! = 300 | ||||||
|   ): [MakePercentageIntervalGQL!]! |   ): [MakePercentageIntervalGQL!]! | ||||||
|   getShots(filterInput: FilterInput!): [ShotGQL!]! |   getOrderedShots( | ||||||
|  |     filterInput: FilterInput! | ||||||
|  |     ids: [Int!] = null | ||||||
|  |     shotsOrdering: GetShotsOrdering = null | ||||||
|  |     limit: Int! = 500 | ||||||
|  |   ): GetShotsResult! | ||||||
|  |   getShotsWithMetadata( | ||||||
|  |     filterInput: FilterInput! | ||||||
|  |     ids: [Int!] = null | ||||||
|  |     shotsPagination: GetShotsPagination = null | ||||||
|  |     limit: Int! = 500 | ||||||
|  |   ): GetShotsResult! | ||||||
|  |   getShots( | ||||||
|  |     filterInput: FilterInput! | ||||||
|  |     shotsPagination: GetShotsPagination = null | ||||||
|  |     limit: Int! = 500 | ||||||
|  |   ): [ShotGQL!]! | ||||||
|  |   getShotsByIds(ids: [Int!]!): [ShotGQL!]! | ||||||
|  |   getShotAnnotationTypes(errorTypes: Boolean = false): [ShotAnnotationTypeGQL!]! | ||||||
|   getUser(userId: Int!): UserGQL |   getUser(userId: Int!): UserGQL | ||||||
|   getLoggedInUser: UserGQL |   getLoggedInUser: UserGQL | ||||||
|  |   getUsernames( | ||||||
|  |     matchString: String = null | ||||||
|  |     limit: Int = null | ||||||
|  |     after: String = null | ||||||
|  |   ): [String!]! | ||||||
|  |   getUsernamesAndFollowing( | ||||||
|  |     userId: Int! | ||||||
|  |     matchString: String = null | ||||||
|  |     limit: Int = 100 | ||||||
|  |     after: String = null | ||||||
|  |   ): UsernamesAndFollowingResponse! | ||||||
|   getPlayTime(userId: Int!): UserPlayTimeGQL! |   getPlayTime(userId: Int!): UserPlayTimeGQL! | ||||||
|   getUserVideos( |   getUserVideos( | ||||||
|     userId: Int = null |     userId: Int = null | ||||||
| @@ -18,8 +48,14 @@ type Query { | |||||||
|     after: String = null |     after: String = null | ||||||
|     filters: VideoFilterInput = null |     filters: VideoFilterInput = null | ||||||
|   ): VideoHistoryGQL! |   ): VideoHistoryGQL! | ||||||
|   getVideo(videoId: Int!): VideoGQL! |   getUserTags: [TagGQL!]! | ||||||
|  |   getVideo(videoId: Int!, debuggingJson: JSON = null): VideoGQL! | ||||||
|   getVideos(videoIds: [Int!]!): [VideoGQL!]! |   getVideos(videoIds: [Int!]!): [VideoGQL!]! | ||||||
|  |   getFeedVideos( | ||||||
|  |     limit: Int! = 5 | ||||||
|  |     after: String = null | ||||||
|  |     filters: VideoFilterInput = null | ||||||
|  |   ): VideoHistoryGQL! | ||||||
| } | } | ||||||
|  |  | ||||||
| type AggregateResultGQL { | type AggregateResultGQL { | ||||||
| @@ -36,6 +72,21 @@ type TargetMetricsGQL { | |||||||
|   count: Int! |   count: Int! | ||||||
|   makePercentage: Float |   makePercentage: Float | ||||||
|   averageDifficulty: Float |   averageDifficulty: Float | ||||||
|  |   spinTypeCounts: SpinTypeCountsGQL | ||||||
|  |   shotDirectionCounts: ShotDirectionCountsGQL | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type SpinTypeCountsGQL { | ||||||
|  |   follow: Int! | ||||||
|  |   draw: Int! | ||||||
|  |   center: Int! | ||||||
|  |   unknown: Int! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type ShotDirectionCountsGQL { | ||||||
|  |   left: Int! | ||||||
|  |   right: Int! | ||||||
|  |   straight: Int! | ||||||
| } | } | ||||||
|  |  | ||||||
| input AggregateInputGQL { | input AggregateInputGQL { | ||||||
| @@ -43,9 +94,10 @@ input AggregateInputGQL { | |||||||
|   filterInput: FilterInput |   filterInput: FilterInput | ||||||
| } | } | ||||||
|  |  | ||||||
| input AggregationInput { | input AggregationInput @oneOf { | ||||||
|   bucketSet: BucketSetInputGQL = null |   bucketSet: BucketSetInputGQL | ||||||
|   enum: EnumAggregation = null |   enum: EnumAggregation | ||||||
|  |   datetimeRange: DatetimeRangeAggregationInput | ||||||
| } | } | ||||||
|  |  | ||||||
| input BucketSetInputGQL { | input BucketSetInputGQL { | ||||||
| @@ -62,33 +114,87 @@ input EnumAggregation { | |||||||
|   feature: String! |   feature: String! | ||||||
| } | } | ||||||
|  |  | ||||||
| input FilterInput { | input DatetimeRangeAggregationInput { | ||||||
|   andFilters: AndFilter = null |   startDatetime: DateTime = null | ||||||
|   orFilters: OrFilter = null |   endDatetime: DateTime = null | ||||||
|   cueObjectDistance: RangeFilter = null |   interval: TimeInterval! | ||||||
|   targetPocketDistance: RangeFilter = null |   feature: String! = "created_at" | ||||||
|   cueObjectAngle: RangeFilter = null |  | ||||||
|   cueBallSpeed: RangeFilter = null |  | ||||||
|   difficulty: RangeFilter = null |  | ||||||
|   intendedPocketType: [PocketEnum!] = null |  | ||||||
|   shotDirection: [ShotDirectionEnum!] = null |  | ||||||
|   videoId: [Int!] = null |  | ||||||
|   userId: [Int!] = null |  | ||||||
|   make: [Boolean!] = null |  | ||||||
|   tags: [VideoTagInput!] = null |  | ||||||
| } | } | ||||||
|  |  | ||||||
| input AndFilter { | """ | ||||||
|   filters: [FilterInput!]! | Date with time (isoformat) | ||||||
|  | """ | ||||||
|  | scalar DateTime | ||||||
|  |  | ||||||
|  | input TimeInterval @oneOf { | ||||||
|  |   timedelta: TimeDeltaGQL | ||||||
|  |   aligned: AlignedIntervalEnum | ||||||
| } | } | ||||||
|  |  | ||||||
| input OrFilter { | input TimeDeltaGQL { | ||||||
|   filters: [FilterInput!]! |   days: Int = 0 | ||||||
|  |   weeks: Int = 0 | ||||||
|  |   months: Int = 0 | ||||||
|  |   years: Int = 0 | ||||||
| } | } | ||||||
|  |  | ||||||
| input RangeFilter { | enum AlignedIntervalEnum { | ||||||
|  |   MONTH | ||||||
|  |   YEAR | ||||||
|  |   WEEK | ||||||
|  |   DAY | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input FilterInput @oneOf { | ||||||
|  |   andFilters: [FilterInput!] | ||||||
|  |   orFilters: [FilterInput!] | ||||||
|  |   notFilter: FilterInput | ||||||
|  |   cueObjectDistance: FloatRangeFilter | ||||||
|  |   targetPocketDistance: FloatRangeFilter | ||||||
|  |   cueObjectAngle: FloatRangeFilter | ||||||
|  |   cueBallSpeed: FloatRangeFilter | ||||||
|  |   difficulty: FloatRangeFilter | ||||||
|  |   intendedPocketType: [PocketEnum!] | ||||||
|  |   shotDirection: [ShotDirectionEnum!] | ||||||
|  |   videoId: [Int!] | ||||||
|  |   userId: [Int!] | ||||||
|  |   username: [String!] | ||||||
|  |   fargoRating: FloatRangeFilter | ||||||
|  |   make: [Boolean!] | ||||||
|  |   tags: [VideoTagInput!] | ||||||
|  |   annotations: [ShotAnnotationInput!] | ||||||
|  |   isStraight: [Boolean!] | ||||||
|  |   isRight: [Boolean!] | ||||||
|  |   isLeft: [Boolean!] | ||||||
|  |   isLeftMiss: [Boolean!] | ||||||
|  |   isRightMiss: [Boolean!] | ||||||
|  |   isDirect: [Boolean!] | ||||||
|  |   tableSize: FloatRangeFilter | ||||||
|  |   bankAngle: FloatRangeFilter | ||||||
|  |   bankDistance: FloatRangeFilter | ||||||
|  |   kickAngle: FloatRangeFilter | ||||||
|  |   kickDistance: FloatRangeFilter | ||||||
|  |   cueAngleAfterObject: FloatRangeFilter | ||||||
|  |   spinType: [SpinTypeEnum!] | ||||||
|  |   cueSpeedAfterObject: FloatRangeFilter | ||||||
|  |   falsePositiveScore: FloatRangeFilter | ||||||
|  |   backcut: [Boolean!] | ||||||
|  |   targetPocketAngleDirection: [ShotDirectionEnum!] | ||||||
|  |   targetPocketAngle: FloatRangeFilter | ||||||
|  |   missAngleInDegrees: FloatRangeFilter | ||||||
|  |   marginOfErrorInDegrees: FloatRangeFilter | ||||||
|  |   createdAt: DateRangeFilter | ||||||
|  |   totalDistance: FloatRangeFilter | ||||||
|  |   runLength: FloatRangeFilter | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input FloatRangeFilter { | ||||||
|   lessThan: Float = null |   lessThan: Float = null | ||||||
|   greaterThanEqualTo: Float = null |   greaterThanEqualTo: Float = null | ||||||
|  |   greaterThan: Float = null | ||||||
|  |   includeOnNone: Boolean! = false | ||||||
|  |   lessThanInclusive: Boolean! = false | ||||||
|  |   greaterThanInclusive: Boolean! = true | ||||||
| } | } | ||||||
|  |  | ||||||
| enum PocketEnum { | enum PocketEnum { | ||||||
| @@ -111,6 +217,31 @@ input VideoTagClassInput { | |||||||
|   name: String! |   name: String! | ||||||
| } | } | ||||||
|  |  | ||||||
|  | input ShotAnnotationInput { | ||||||
|  |   name: String! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | enum SpinTypeEnum { | ||||||
|  |   DRAW | ||||||
|  |   FOLLOW | ||||||
|  |   CENTER | ||||||
|  |   UNKNOWN | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input DateRangeFilter { | ||||||
|  |   lessThan: Date = null | ||||||
|  |   greaterThanEqualTo: Date = null | ||||||
|  |   greaterThan: Date = null | ||||||
|  |   includeOnNone: Boolean! = false | ||||||
|  |   lessThanInclusive: Boolean! = false | ||||||
|  |   greaterThanInclusive: Boolean! = true | ||||||
|  | } | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | Date (isoformat) | ||||||
|  | """ | ||||||
|  | scalar Date | ||||||
|  |  | ||||||
| type BucketSetGQL { | type BucketSetGQL { | ||||||
|   keyName: String! |   keyName: String! | ||||||
|   feature: String! |   feature: String! | ||||||
| @@ -127,6 +258,7 @@ type DeployedConfigGQL { | |||||||
|   firebase: Boolean! |   firebase: Boolean! | ||||||
|   devMode: Boolean! |   devMode: Boolean! | ||||||
|   environment: String! |   environment: String! | ||||||
|  |   minimumAllowedAppVersion: String! | ||||||
| } | } | ||||||
|  |  | ||||||
| type MakePercentageIntervalGQL { | type MakePercentageIntervalGQL { | ||||||
| @@ -134,6 +266,12 @@ type MakePercentageIntervalGQL { | |||||||
|   elapsedTime: Float! |   elapsedTime: Float! | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type GetShotsResult { | ||||||
|  |   shots: [ShotGQL!]! | ||||||
|  |   count: Int | ||||||
|  |   ids: [Int!]! | ||||||
|  | } | ||||||
|  |  | ||||||
| type ShotGQL { | type ShotGQL { | ||||||
|   id: Int! |   id: Int! | ||||||
|   videoId: Int! |   videoId: Int! | ||||||
| @@ -143,21 +281,21 @@ type ShotGQL { | |||||||
|   updatedAt: DateTime |   updatedAt: DateTime | ||||||
|   cueObjectFeatures: CueObjectFeaturesGQL |   cueObjectFeatures: CueObjectFeaturesGQL | ||||||
|   pocketingIntentionFeatures: PocketingIntentionFeaturesGQL |   pocketingIntentionFeatures: PocketingIntentionFeaturesGQL | ||||||
|  |   pocketingIntentionInfo: PocketingIntentionInfoGQL | ||||||
|   bankFeatures: BankFeaturesGQL |   bankFeatures: BankFeaturesGQL | ||||||
|   serializedShotPaths: SerializedShotPathsGQL |   serializedShotPaths: SerializedShotPathsGQL | ||||||
|   user: UserGQL |   user: UserGQL | ||||||
|  |   annotations: [ShotAnnotationGQL!]! | ||||||
|  |   falsePositiveScore: Float | ||||||
|  |   video: VideoGQL | ||||||
| } | } | ||||||
|  |  | ||||||
| """ |  | ||||||
| Date with time (isoformat) |  | ||||||
| """ |  | ||||||
| scalar DateTime |  | ||||||
|  |  | ||||||
| type CueObjectFeaturesGQL { | type CueObjectFeaturesGQL { | ||||||
|   cueObjectDistance: Float |   cueObjectDistance: Float | ||||||
|   cueObjectAngle: Float |   cueObjectAngle: Float | ||||||
|   cueBallSpeed: Float |   cueBallSpeed: Float | ||||||
|   shotDirection: ShotDirectionEnum |   shotDirection: ShotDirectionEnum | ||||||
|  |   spinType: SpinTypeEnum | ||||||
| } | } | ||||||
|  |  | ||||||
| type PocketingIntentionFeaturesGQL { | type PocketingIntentionFeaturesGQL { | ||||||
| @@ -165,6 +303,25 @@ type PocketingIntentionFeaturesGQL { | |||||||
|   make: Boolean |   make: Boolean | ||||||
|   intendedPocketType: PocketEnum |   intendedPocketType: PocketEnum | ||||||
|   difficulty: Float |   difficulty: Float | ||||||
|  |   targetPocketAngle: Float | ||||||
|  |   targetPocketAngleDirection: ShotDirectionEnum | ||||||
|  |   marginOfErrorInDegrees: Float | ||||||
|  |   backcut: Boolean | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type PocketingIntentionInfoGQL { | ||||||
|  |   ballId: Int! | ||||||
|  |   pocketId: PocketIdentifier! | ||||||
|  |   pathMetadataIndex: Int! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | enum PocketIdentifier { | ||||||
|  |   TOP_LEFT | ||||||
|  |   TOP_SIDE | ||||||
|  |   TOP_RIGHT | ||||||
|  |   BOTTOM_LEFT | ||||||
|  |   BOTTOM_SIDE | ||||||
|  |   BOTTOM_RIGHT | ||||||
| } | } | ||||||
|  |  | ||||||
| type BankFeaturesGQL { | type BankFeaturesGQL { | ||||||
| @@ -186,19 +343,29 @@ type UserGQL { | |||||||
|   id: Int! |   id: Int! | ||||||
|   firebaseUid: String! |   firebaseUid: String! | ||||||
|   username: String! |   username: String! | ||||||
|  |   isAdmin: Boolean! | ||||||
|  |   fargoRating: Int | ||||||
|   activeVideoId: Int |   activeVideoId: Int | ||||||
|   profileImageUri: String |   profileImageUri: String | ||||||
|   createdAt: DateTime |   createdAt: DateTime | ||||||
|   updatedAt: DateTime |   updatedAt: DateTime | ||||||
|  |   following: [Int!] | ||||||
|  |   followers: [Int!] | ||||||
| } | } | ||||||
|  |  | ||||||
| type UserPlayTimeGQL { | type ShotAnnotationGQL { | ||||||
|   totalSeconds: Float! |   shotId: Int! | ||||||
|  |   type: ShotAnnotationTypeGQL! | ||||||
|  |   creator: UserGQL! | ||||||
|  |   notes: String! | ||||||
|  |   errorDefault: Boolean! | ||||||
|  |   createdAt: DateTime | ||||||
|  |   updatedAt: DateTime | ||||||
| } | } | ||||||
|  |  | ||||||
| type VideoHistoryGQL { | type ShotAnnotationTypeGQL { | ||||||
|   videos: [VideoGQL!]! |   id: Int! | ||||||
|   pageInfo: PageInfoGQL! |   name: String! | ||||||
| } | } | ||||||
|  |  | ||||||
| type VideoGQL { | type VideoGQL { | ||||||
| @@ -218,9 +385,11 @@ type VideoGQL { | |||||||
|   endTime: DateTime |   endTime: DateTime | ||||||
|   elapsedTime: Float |   elapsedTime: Float | ||||||
|   framesPerSecond: Float! |   framesPerSecond: Float! | ||||||
|  |   tableSize: Float! | ||||||
|   stream: UploadStreamGQL |   stream: UploadStreamGQL | ||||||
|   playlist: HLSPlaylistGQL |   playlist: HLSPlaylistGQL | ||||||
|   tags: [VideoTag!]! |   tags: [VideoTag!]! | ||||||
|  |   currentHomography: HomographyInfoGQL | ||||||
|   homographyHistory: [HomographyInfoGQL!]! |   homographyHistory: [HomographyInfoGQL!]! | ||||||
|   currentProcessing: VideoProcessingGQL |   currentProcessing: VideoProcessingGQL | ||||||
| } | } | ||||||
| @@ -232,12 +401,21 @@ type UploadStreamGQL { | |||||||
|   segmentProcessingCursor: Int! |   segmentProcessingCursor: Int! | ||||||
|   lastIntendedSegmentBound: Int |   lastIntendedSegmentBound: Int | ||||||
|   isCompleted: Boolean! |   isCompleted: Boolean! | ||||||
|  |   initPlaylistUploadStatus: InitPlaylistUploadStatusEnum | ||||||
|   lowestUnuploadedSegmentIndex: Int! |   lowestUnuploadedSegmentIndex: Int! | ||||||
|   uploadCompletionCursor: Int! |   uploadCompletionCursor: Int! | ||||||
|   errors: [StreamErrorGQL!]! |   errors: [StreamErrorGQL!]! | ||||||
|   createdAt: DateTime! |   createdAt: DateTime! | ||||||
|   updatedAt: DateTime! |   updatedAt: DateTime! | ||||||
|   segments: [UploadSegmentGQL!]! |   segments: [UploadSegmentGQL!]! | ||||||
|  |   resolution: VideoResolutionGQL! | ||||||
|  |   streamSegmentType: StreamSegmentTypeEnum! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | enum InitPlaylistUploadStatusEnum { | ||||||
|  |   NOT_APPLICABLE | ||||||
|  |   NOT_UPLOADED | ||||||
|  |   UPLOADED | ||||||
| } | } | ||||||
|  |  | ||||||
| type StreamErrorGQL { | type StreamErrorGQL { | ||||||
| @@ -250,10 +428,20 @@ type UploadSegmentGQL { | |||||||
|   valid: Boolean! |   valid: Boolean! | ||||||
|   endFrameIndex: Int |   endFrameIndex: Int | ||||||
|   framesPerSecond: Float |   framesPerSecond: Float | ||||||
|   durationsInSeconds: Float |   durationInSeconds: Float | ||||||
|   linksRequested: Int! |   linksRequested: Int! | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type VideoResolutionGQL { | ||||||
|  |   width: Int | ||||||
|  |   height: Int | ||||||
|  | } | ||||||
|  |  | ||||||
|  | enum StreamSegmentTypeEnum { | ||||||
|  |   FRAGMENTED_MP4 | ||||||
|  |   RB_CHUNKED_MP4 | ||||||
|  | } | ||||||
|  |  | ||||||
| type HLSPlaylistGQL { | type HLSPlaylistGQL { | ||||||
|   videoId: Int! |   videoId: Int! | ||||||
|   m3u8Text: String! |   m3u8Text: String! | ||||||
| @@ -300,6 +488,8 @@ type IntPoint2D { | |||||||
|  |  | ||||||
| type VideoProcessingGQL { | type VideoProcessingGQL { | ||||||
|   errors: [VideoProcessingErrorGQL!]! |   errors: [VideoProcessingErrorGQL!]! | ||||||
|  |   status: ProcessingStatusEnum! | ||||||
|  |   statuses: [VideoProcessingStatusGQL!]! | ||||||
| } | } | ||||||
|  |  | ||||||
| type VideoProcessingErrorGQL { | type VideoProcessingErrorGQL { | ||||||
| @@ -308,6 +498,77 @@ type VideoProcessingErrorGQL { | |||||||
|   endSegmentIndex: Int |   endSegmentIndex: Int | ||||||
| } | } | ||||||
|  |  | ||||||
|  | enum ProcessingStatusEnum { | ||||||
|  |   STARTED | ||||||
|  |   FAILED | ||||||
|  |   SUCCEEDED | ||||||
|  |   SUSPENDED | ||||||
|  |   CREATED | ||||||
|  |   QUEUED | ||||||
|  |   RUNNING | ||||||
|  |   REEXTRACTING_FEATURES | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type VideoProcessingStatusGQL { | ||||||
|  |   status: ProcessingStatusEnum! | ||||||
|  |   appVersion: String! | ||||||
|  |   sequenceId: Int! | ||||||
|  |   createdAt: DateTime | ||||||
|  |   updatedAt: DateTime | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input GetShotsOrdering { | ||||||
|  |   orderings: [ShotsOrderingComponent!]! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input ShotsOrderingComponent @oneOf { | ||||||
|  |   videoCreation: DatetimeShotOrdering | ||||||
|  |   marginOfError: FloatShotOrdering | ||||||
|  |   videoId: IntShotOrdering | ||||||
|  |   startFrame: IntShotOrdering | ||||||
|  |   runLength: IntShotOrdering | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input DatetimeShotOrdering { | ||||||
|  |   descending: Boolean! = true | ||||||
|  |   startingAt: DateTime = null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input FloatShotOrdering { | ||||||
|  |   descending: Boolean! = true | ||||||
|  |   startingAt: Float = null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input IntShotOrdering { | ||||||
|  |   descending: Boolean! = true | ||||||
|  |   startingAt: Int = null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input GetShotsPagination { | ||||||
|  |   createdAfter: CreatedAfter! | ||||||
|  |   startFrameAfter: Int! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input CreatedAfter @oneOf { | ||||||
|  |   videoId: Int | ||||||
|  |   createdAt: DateTime | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type UsernamesAndFollowingResponse { | ||||||
|  |   usernamesAndIds: [UserGQL!]! | ||||||
|  |   following: [Int!]! | ||||||
|  |   followers: [Int!]! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type UserPlayTimeGQL { | ||||||
|  |   totalSeconds: Float! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type VideoHistoryGQL { | ||||||
|  |   videos: [VideoGQL!]! | ||||||
|  |   pageInfo: PageInfoGQL! | ||||||
|  | } | ||||||
|  |  | ||||||
| type PageInfoGQL { | type PageInfoGQL { | ||||||
|   hasNextPage: Boolean! |   hasNextPage: Boolean! | ||||||
|   endCursor: String |   endCursor: String | ||||||
| @@ -318,15 +579,49 @@ input VideoFilterInput { | |||||||
|   requireCursorCompletion: Boolean! = true |   requireCursorCompletion: Boolean! = true | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type TagGQL { | ||||||
|  |   name: String! | ||||||
|  |   id: Int! | ||||||
|  |   group: String | ||||||
|  | } | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | The `JSON` scalar type represents JSON values as specified by [ECMA-404](https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf). | ||||||
|  | """ | ||||||
|  | scalar JSON | ||||||
|  |   @specifiedBy( | ||||||
|  |     url: "https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf" | ||||||
|  |   ) | ||||||
|  |  | ||||||
| type Mutation { | type Mutation { | ||||||
|   createBucketSet(params: CreateBucketSetInput!): BucketSetGQL! |   createBucketSet(params: CreateBucketSetInput!): BucketSetGQL! | ||||||
|   setLoggerLevel(path: String!, level: String!): Boolean! |   setLoggerLevel(path: String!, level: String!): Boolean! | ||||||
|   getProfileImageUploadLink(fileExt: String = ".png"): GetUploadLinkReturn! |   addAnnotationToShot( | ||||||
|  |     shotId: Int! | ||||||
|  |     annotationName: String! | ||||||
|  |     notes: String = null | ||||||
|  |   ): AddShotAnnotationReturn! | ||||||
|  |   updateShotAnnotations( | ||||||
|  |     shotId: Int! | ||||||
|  |     annotations: [UpdateAnnotationInputGQL!]! | ||||||
|  |   ): UpdateShotAnnotationReturn! | ||||||
|  |   getProfileImageUploadLink( | ||||||
|  |     fileExt: String = ".png" | ||||||
|  |   ): GetProfileUploadLinkReturn! | ||||||
|   editProfileImageUri(profileImageUri: String!): UserGQL! |   editProfileImageUri(profileImageUri: String!): UserGQL! | ||||||
|  |   editUser(input: EditUserInputGQL!): UserGQL! | ||||||
|  |   followUser(followedUserId: Int!): UserGQL! | ||||||
|  |   unfollowUser(followedUserId: Int!): UserGQL! | ||||||
|   createUploadStream( |   createUploadStream( | ||||||
|     videoMetadata: VideoMetadataInput! |     videoMetadata: VideoMetadataInput! | ||||||
|   ): CreateUploadStreamReturn! |   ): CreateUploadStreamReturn! | ||||||
|   getUploadLink(videoId: Int!, segmentIndex: Int!): GetUploadLinkReturn! |   getUploadLink(videoId: Int!, segmentIndex: Int!): GetUploadLinkReturn! | ||||||
|  |   getHlsInitUploadLink(videoId: Int!): GetUploadLinkReturn! | ||||||
|  |   setSegmentDuration( | ||||||
|  |     videoId: Int! | ||||||
|  |     segmentIndex: Int! | ||||||
|  |     duration: Float! | ||||||
|  |   ): Boolean! | ||||||
|   editUploadStream(videoId: Int!, videoMetadata: VideoMetadataInput!): Boolean! |   editUploadStream(videoId: Int!, videoMetadata: VideoMetadataInput!): Boolean! | ||||||
|   deleteVideo(videoId: Int!): Boolean! |   deleteVideo(videoId: Int!): Boolean! | ||||||
| } | } | ||||||
| @@ -337,7 +632,54 @@ input CreateBucketSetInput { | |||||||
|   buckets: [BucketInputGQL!]! |   buckets: [BucketInputGQL!]! | ||||||
| } | } | ||||||
|  |  | ||||||
| type GetUploadLinkReturn { | type AddShotAnnotationReturn { | ||||||
|  |   value: SuccessfulAddAddShotAnnotationErrors! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | union SuccessfulAddAddShotAnnotationErrors = | ||||||
|  |     SuccessfulAdd | ||||||
|  |   | AddShotAnnotationErrors | ||||||
|  |  | ||||||
|  | type SuccessfulAdd { | ||||||
|  |   value: Boolean! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type AddShotAnnotationErrors { | ||||||
|  |   error: DoesNotOwnShotErrOtherErrorNeedsNote! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | union DoesNotOwnShotErrOtherErrorNeedsNote = | ||||||
|  |     DoesNotOwnShotErr | ||||||
|  |   | OtherErrorNeedsNote | ||||||
|  |  | ||||||
|  | type DoesNotOwnShotErr { | ||||||
|  |   shotId: Int! | ||||||
|  |   msg: String | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type OtherErrorNeedsNote { | ||||||
|  |   msg: String | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type UpdateShotAnnotationReturn { | ||||||
|  |   shot: ShotGQL | ||||||
|  |   error: DoesNotOwnShotErr | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input UpdateAnnotationInputGQL { | ||||||
|  |   name: String! | ||||||
|  |   notes: String = null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type GetProfileUploadLinkReturn { | ||||||
|  |   value: UploadLinkGetProfileUploadLinkErrors! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | union UploadLinkGetProfileUploadLinkErrors = | ||||||
|  |     UploadLink | ||||||
|  |   | GetProfileUploadLinkErrors | ||||||
|  |  | ||||||
|  | type UploadLink { | ||||||
|   uploadUrl: String! |   uploadUrl: String! | ||||||
|   headers: [Header]! |   headers: [Header]! | ||||||
| } | } | ||||||
| @@ -347,6 +689,19 @@ type Header { | |||||||
|   value: String! |   value: String! | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type GetProfileUploadLinkErrors { | ||||||
|  |   error: TooManyProfileImageUploadsErr! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type TooManyProfileImageUploadsErr { | ||||||
|  |   linksRequested: Int! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input EditUserInputGQL { | ||||||
|  |   username: String = null | ||||||
|  |   fargoRating: Int = null | ||||||
|  | } | ||||||
|  |  | ||||||
| type CreateUploadStreamReturn { | type CreateUploadStreamReturn { | ||||||
|   videoId: Int! |   videoId: Int! | ||||||
| } | } | ||||||
| @@ -356,26 +711,60 @@ input VideoMetadataInput { | |||||||
|   startTime: DateTime = null |   startTime: DateTime = null | ||||||
|   endTime: DateTime = null |   endTime: DateTime = null | ||||||
|   gameType: String = null |   gameType: String = null | ||||||
|   tableSize: String = null |   tableSize: Float = null | ||||||
|   uploadStreamMetadataInput: UploadStreamMetadataInput = null |  | ||||||
|   lastIntendedSegmentBound: Int = null |   lastIntendedSegmentBound: Int = null | ||||||
|  |   streamSegmentType: StreamSegmentTypeEnum = null | ||||||
|   endStream: Boolean! = false |   endStream: Boolean! = false | ||||||
|  |   resolution: VideoResolution = null | ||||||
|  |   framesPerSecond: Float = null | ||||||
| } | } | ||||||
|  |  | ||||||
| input UploadStreamMetadataInput { | input VideoResolution { | ||||||
|   deviceType: DeviceTypeEnum = null |   width: Int! | ||||||
|   osVersion: String = null |   height: Int! | ||||||
|   appVersion: String = null |  | ||||||
|   browserName: String = null |  | ||||||
|   browserVersion: String = null |  | ||||||
|   locale: String = null |  | ||||||
|   timezone: String = null |  | ||||||
|   networkType: String = null |  | ||||||
|   ipAddress: String = null |  | ||||||
| } | } | ||||||
|  |  | ||||||
| enum DeviceTypeEnum { | type GetUploadLinkReturn { | ||||||
|   IOS |   value: UploadLinkGetUploadLinkErrors! | ||||||
|   ANDROID |   stream: UploadStreamGQL | ||||||
|   BROWSER | } | ||||||
|  |  | ||||||
|  | union UploadLinkGetUploadLinkErrors = UploadLink | GetUploadLinkErrors | ||||||
|  |  | ||||||
|  | type GetUploadLinkErrors { | ||||||
|  |   error: MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErr! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | union MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErr = | ||||||
|  |     MustHaveSetForUploadLinkErr | ||||||
|  |   | SegmentAlreadyUploadedErr | ||||||
|  |   | ProcessingFailedErr | ||||||
|  |   | NoInitForChunkedUploadErr | ||||||
|  |   | TooManyProfileImageUploadsErr | ||||||
|  |   | InitUploadAlreadyCompletedErr | ||||||
|  |   | TooManyInitUploadsErr | ||||||
|  |  | ||||||
|  | type MustHaveSetForUploadLinkErr { | ||||||
|  |   resolution: Boolean | ||||||
|  |   framesPerSecond: Boolean | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type SegmentAlreadyUploadedErr { | ||||||
|  |   segmentId: Int! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type ProcessingFailedErr { | ||||||
|  |   processing: VideoProcessingGQL! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type NoInitForChunkedUploadErr { | ||||||
|  |   segmentType: StreamSegmentTypeEnum! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type InitUploadAlreadyCompletedErr { | ||||||
|  |   segmentType: StreamSegmentTypeEnum! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type TooManyInitUploadsErr { | ||||||
|  |   linksRequested: Int! | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user