From adf05e3c28880bdb278c043df38dfdae279810d3 Mon Sep 17 00:00:00 2001 From: Ivan Malison Date: Fri, 3 Jul 2026 01:44:02 -0700 Subject: [PATCH] Add computePotAim query and shot-simulation operations Schema: computePotAim(simulationInput, targetBallId, pocket) -> PotAimGQL, the spin/throw-compensated aim solver (regenerated from backend strawberry definitions; reuses the existing PocketIdentifier enum). Operations: GetTableState, SimulateShot, and ComputePotAim documents so both clients get generated hooks. Co-Authored-By: Claude Fable 5 --- src/index.tsx | 350 +++++++++++++++++++++++++++++ src/operations/shot_simulation.gql | 57 +++++ src/schema.gql | 16 ++ 3 files changed, 423 insertions(+) create mode 100644 src/operations/shot_simulation.gql diff --git a/src/index.tsx b/src/index.tsx index 42f73d7..3866493 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2844,6 +2844,18 @@ export type PocketingIntentionInfoGql = { pocketId: PocketIdentifier; }; +export type PotAimGql = { + __typename?: "PotAimGQL"; + converged: Scalars["Boolean"]["output"]; + cutAngle: Scalars["Float"]["output"]; + feasible: Scalars["Boolean"]["output"]; + geometricPhi: Scalars["Float"]["output"]; + occludingBallIds: Array; + phi: Scalars["Float"]["output"]; + potted: Scalars["Boolean"]["output"]; + requiredPrecision: Scalars["Float"]["output"]; +}; + export type ProcessingFailedErr = { __typename?: "ProcessingFailedErr"; processing: VideoProcessingGql; @@ -2865,6 +2877,7 @@ export type Query = { challenge?: Maybe; challengeLeaderboard: Array; challenges: Array; + computePotAim: PotAimGql; doesUsernameExist: Scalars["Boolean"]["output"]; getAggregatedShotMetrics: Array; getAppleAppAccountToken: Scalars["String"]["output"]; @@ -2927,6 +2940,12 @@ export type QueryChallengesArgs = { includeDismissed?: Scalars["Boolean"]["input"]; }; +export type QueryComputePotAimArgs = { + pocket: PocketIdentifier; + simulationInput: SimulateShotInputGql; + targetBallId: Scalars["Int"]["input"]; +}; + export type QueryDoesUsernameExistArgs = { candidateUsername: Scalars["String"]["input"]; }; @@ -5541,6 +5560,74 @@ export type FinalizePlayerAssignmentsMutation = { }>; }; +export type GetTableStateQueryVariables = Exact<{ + b64Image: Scalars["String"]["input"]; + tableSize?: InputMaybe; + useHomography?: InputMaybe; +}>; + +export type GetTableStateQuery = { + __typename?: "Query"; + getTableState: { + __typename?: "TableStateGQL"; + identifierToPosition: Array>; + }; +}; + +export type SimulateShotQueryVariables = Exact<{ + simulationInput: SimulateShotInputGql; +}>; + +export type SimulateShotQuery = { + __typename?: "Query"; + simulateShot: { + __typename?: "ShotProjectionGQL"; + pottedBallIds: Array; + trajectories: Array<{ + __typename?: "BallTrajectoryGQL"; + ballId: number; + points: Array<{ + __typename?: "TrajectoryPointGQL"; + time: number; + position: Array; + }>; + }>; + events: Array<{ + __typename?: "SimulationEventGQL"; + eventType: SimulationEventType; + time: number; + ballIds: Array; + position?: Array | null; + }>; + finalState: Array<{ + __typename?: "SimulationBallStateGQL"; + ballId: number; + position: Array; + }>; + }; +}; + +export type ComputePotAimQueryVariables = Exact<{ + simulationInput: SimulateShotInputGql; + targetBallId: Scalars["Int"]["input"]; + pocket: PocketIdentifier; +}>; + +export type ComputePotAimQuery = { + __typename?: "Query"; + computePotAim: { + __typename?: "PotAimGQL"; + phi: number; + geometricPhi: number; + cutAngle: number; + requiredPrecision: number; + feasible: boolean; + potted: boolean; + converged: boolean; + occludingBallIds: Array; + }; +}; + export type GetSerializedShotPathsQueryVariables = Exact<{ filterInput: FilterInput; }>; @@ -11800,6 +11887,269 @@ export type FinalizePlayerAssignmentsMutationOptions = FinalizePlayerAssignmentsMutation, FinalizePlayerAssignmentsMutationVariables >; +export const GetTableStateDocument = gql` + query GetTableState( + $b64Image: String! + $tableSize: Float + $useHomography: HomographyInputGQL + ) { + getTableState( + b64Image: $b64Image + tableSize: $tableSize + useHomography: $useHomography + ) { + identifierToPosition + } + } +`; + +/** + * __useGetTableStateQuery__ + * + * To run a query within a React component, call `useGetTableStateQuery` and pass it any options that fit your needs. + * When your component renders, `useGetTableStateQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetTableStateQuery({ + * variables: { + * b64Image: // value for 'b64Image' + * tableSize: // value for 'tableSize' + * useHomography: // value for 'useHomography' + * }, + * }); + */ +export function useGetTableStateQuery( + baseOptions: Apollo.QueryHookOptions< + GetTableStateQuery, + GetTableStateQueryVariables + >, +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useQuery( + GetTableStateDocument, + options, + ); +} +export function useGetTableStateLazyQuery( + baseOptions?: Apollo.LazyQueryHookOptions< + GetTableStateQuery, + GetTableStateQueryVariables + >, +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useLazyQuery( + GetTableStateDocument, + options, + ); +} +export function useGetTableStateSuspenseQuery( + baseOptions?: Apollo.SuspenseQueryHookOptions< + GetTableStateQuery, + GetTableStateQueryVariables + >, +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useSuspenseQuery< + GetTableStateQuery, + GetTableStateQueryVariables + >(GetTableStateDocument, options); +} +export type GetTableStateQueryHookResult = ReturnType< + typeof useGetTableStateQuery +>; +export type GetTableStateLazyQueryHookResult = ReturnType< + typeof useGetTableStateLazyQuery +>; +export type GetTableStateSuspenseQueryHookResult = ReturnType< + typeof useGetTableStateSuspenseQuery +>; +export type GetTableStateQueryResult = Apollo.QueryResult< + GetTableStateQuery, + GetTableStateQueryVariables +>; +export const SimulateShotDocument = gql` + query SimulateShot($simulationInput: SimulateShotInputGQL!) { + simulateShot(simulationInput: $simulationInput) { + trajectories { + ballId + points { + time + position + } + } + events { + eventType + time + ballIds + position + } + finalState { + ballId + position + } + pottedBallIds + } + } +`; + +/** + * __useSimulateShotQuery__ + * + * To run a query within a React component, call `useSimulateShotQuery` and pass it any options that fit your needs. + * When your component renders, `useSimulateShotQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useSimulateShotQuery({ + * variables: { + * simulationInput: // value for 'simulationInput' + * }, + * }); + */ +export function useSimulateShotQuery( + baseOptions: Apollo.QueryHookOptions< + SimulateShotQuery, + SimulateShotQueryVariables + >, +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useQuery( + SimulateShotDocument, + options, + ); +} +export function useSimulateShotLazyQuery( + baseOptions?: Apollo.LazyQueryHookOptions< + SimulateShotQuery, + SimulateShotQueryVariables + >, +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useLazyQuery( + SimulateShotDocument, + options, + ); +} +export function useSimulateShotSuspenseQuery( + baseOptions?: Apollo.SuspenseQueryHookOptions< + SimulateShotQuery, + SimulateShotQueryVariables + >, +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useSuspenseQuery( + SimulateShotDocument, + options, + ); +} +export type SimulateShotQueryHookResult = ReturnType< + typeof useSimulateShotQuery +>; +export type SimulateShotLazyQueryHookResult = ReturnType< + typeof useSimulateShotLazyQuery +>; +export type SimulateShotSuspenseQueryHookResult = ReturnType< + typeof useSimulateShotSuspenseQuery +>; +export type SimulateShotQueryResult = Apollo.QueryResult< + SimulateShotQuery, + SimulateShotQueryVariables +>; +export const ComputePotAimDocument = gql` + query ComputePotAim( + $simulationInput: SimulateShotInputGQL! + $targetBallId: Int! + $pocket: PocketIdentifier! + ) { + computePotAim( + simulationInput: $simulationInput + targetBallId: $targetBallId + pocket: $pocket + ) { + phi + geometricPhi + cutAngle + requiredPrecision + feasible + potted + converged + occludingBallIds + } + } +`; + +/** + * __useComputePotAimQuery__ + * + * To run a query within a React component, call `useComputePotAimQuery` and pass it any options that fit your needs. + * When your component renders, `useComputePotAimQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useComputePotAimQuery({ + * variables: { + * simulationInput: // value for 'simulationInput' + * targetBallId: // value for 'targetBallId' + * pocket: // value for 'pocket' + * }, + * }); + */ +export function useComputePotAimQuery( + baseOptions: Apollo.QueryHookOptions< + ComputePotAimQuery, + ComputePotAimQueryVariables + >, +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useQuery( + ComputePotAimDocument, + options, + ); +} +export function useComputePotAimLazyQuery( + baseOptions?: Apollo.LazyQueryHookOptions< + ComputePotAimQuery, + ComputePotAimQueryVariables + >, +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useLazyQuery( + ComputePotAimDocument, + options, + ); +} +export function useComputePotAimSuspenseQuery( + baseOptions?: Apollo.SuspenseQueryHookOptions< + ComputePotAimQuery, + ComputePotAimQueryVariables + >, +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useSuspenseQuery< + ComputePotAimQuery, + ComputePotAimQueryVariables + >(ComputePotAimDocument, options); +} +export type ComputePotAimQueryHookResult = ReturnType< + typeof useComputePotAimQuery +>; +export type ComputePotAimLazyQueryHookResult = ReturnType< + typeof useComputePotAimLazyQuery +>; +export type ComputePotAimSuspenseQueryHookResult = ReturnType< + typeof useComputePotAimSuspenseQuery +>; +export type ComputePotAimQueryResult = Apollo.QueryResult< + ComputePotAimQuery, + ComputePotAimQueryVariables +>; export const GetSerializedShotPathsDocument = gql` query GetSerializedShotPaths($filterInput: FilterInput!) { getShots(filterInput: $filterInput) { diff --git a/src/operations/shot_simulation.gql b/src/operations/shot_simulation.gql new file mode 100644 index 0000000..75281bd --- /dev/null +++ b/src/operations/shot_simulation.gql @@ -0,0 +1,57 @@ +query GetTableState( + $b64Image: String! + $tableSize: Float + $useHomography: HomographyInputGQL +) { + getTableState( + b64Image: $b64Image + tableSize: $tableSize + useHomography: $useHomography + ) { + identifierToPosition + } +} + +query SimulateShot($simulationInput: SimulateShotInputGQL!) { + simulateShot(simulationInput: $simulationInput) { + trajectories { + ballId + points { + time + position + } + } + events { + eventType + time + ballIds + position + } + finalState { + ballId + position + } + pottedBallIds + } +} + +query ComputePotAim( + $simulationInput: SimulateShotInputGQL! + $targetBallId: Int! + $pocket: PocketIdentifier! +) { + computePotAim( + simulationInput: $simulationInput + targetBallId: $targetBallId + pocket: $pocket + ) { + phi + geometricPhi + cutAngle + requiredPrecision + feasible + potted + converged + occludingBallIds + } +} diff --git a/src/schema.gql b/src/schema.gql index 2630ac2..37b5f81 100644 --- a/src/schema.gql +++ b/src/schema.gql @@ -67,6 +67,11 @@ type Query { useHomography: HomographyInputGQL = null ): TableStateGQL! simulateShot(simulationInput: SimulateShotInputGQL!): ShotProjectionGQL! + computePotAim( + simulationInput: SimulateShotInputGQL! + targetBallId: Int! + pocket: PocketIdentifier! + ): PotAimGQL! getOrderedShots( filterInput: FilterInput! ids: [Int!] = null @@ -1030,6 +1035,17 @@ input SimulationBallStateInputGQL { position: [Float!]! } +type PotAimGQL { + phi: Float! + geometricPhi: Float! + cutAngle: Float! + requiredPrecision: Float! + feasible: Boolean! + potted: Boolean! + converged: Boolean! + occludingBallIds: [Int!]! +} + type GetShotsResult { shots: [ShotGQL!]! count: Int