Compare commits

..

1 Commits

Author SHA1 Message Date
9c97e46d57 Update schema for ground truth admin workflow
All checks were successful
Tests / Tests (pull_request) Successful in 11s
2026-03-18 12:10:52 -07:00
6 changed files with 362 additions and 218 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -31,26 +31,41 @@ fragment VideoCardFields on VideoGQL {
}
name
screenshotUri
totalShotsMade
totalShots
makePercentage
averageTimeBetweenShots
averageDifficulty
createdAt
updatedAt
startTime
endTime
private
elapsedTime
screenshotUri
stream {
id
lastIntendedSegmentBound
isCompleted
streamSegmentType
}
tableSize
pocketSize
tags {
tagClasses {
name
}
name
}
currentProcessing {
id
errors {
message
}
status
statuses {
status
}
}
reactions {
videoId

View File

@@ -92,17 +92,6 @@ query GetUserTags {
}
}
query GetGameTypeTagMetrics($input: GameTypeTagMetricsInput!) {
getGameTypeTagMetrics(input: $input) {
tagName
tagLabel
tableSize
shotCount
madeShots
makeRate
}
}
mutation followUser($followedUserId: Int!) {
followUser(followedUserId: $followedUserId) {
id

View File

@@ -10,7 +10,6 @@ query GetStreamMonitoringDetails($videoId: Int!, $debuggingJson: JSON) {
stream {
id
linksRequested
lowestUnuploadedSegmentIndex
uploadsCompleted
segmentProcessingCursor
isCompleted

View File

@@ -1,11 +1,5 @@
mutation CreateUploadStream(
$videoMetadataInput: VideoMetadataInput!
$expectedDurationSeconds: Float = null
) {
createUploadStream(
videoMetadata: $videoMetadataInput
expectedDurationSeconds: $expectedDurationSeconds
) {
mutation CreateUploadStream($videoMetadataInput: VideoMetadataInput!) {
createUploadStream(videoMetadata: $videoMetadataInput) {
videoId
}
}

View File

@@ -28,7 +28,7 @@ type Query {
getLongestRunsLeaderboard(
interval: TimeInterval = null
when: DateTime = null
limit: Int! = 50
limit: Int! = 100
requiredTags: [String!] = null
): RunLeaderboardGQL!
getMakesLeaderboard(
@@ -61,6 +61,8 @@ type Query {
shotsOrdering: GetShotsOrdering = null
limit: Int! = 500
countRespectsLimit: Boolean! = false
processingId: Int = null
includeExcluded: Boolean! = false
): GetShotsResult!
getShotsWithMetadata(
filterInput: FilterInput!
@@ -68,12 +70,16 @@ type Query {
shotsPagination: GetShotsPagination = null
limit: Int! = 500
countRespectsLimit: Boolean! = false
processingId: Int = null
includeExcluded: Boolean! = false
): GetShotsResult!
getShots(
filterInput: FilterInput!
shotsPagination: GetShotsPagination = null
limit: Int! = 500
countRespectsLimit: Boolean! = false
processingId: Int = null
includeExcluded: Boolean! = false
): [ShotGQL!]!
getShotsByIds(ids: [Int!]!): [ShotGQL!]!
getUser(userId: Int!): UserGQL
@@ -106,9 +112,13 @@ type Query {
filters: VideoFilterInput = null
): VideoHistoryGQL!
getUserTags(includeRetiredTags: Boolean = false): [TagGQL!]!
getGameTypeTagMetrics(input: GameTypeTagMetricsInput!): [GameTypeTagMetric!]!
getVideo(videoId: Int!, debuggingJson: JSON = null): VideoGQL!
getVideos(videoIds: [Int!]!): [VideoGQL!]!
getVideoProcessings(videoId: Int!): [VideoProcessingGQL!]!
assessVideoProcessing(
processingId: Int!
groundTruthProcessingId: Int = null
): VideoProcessingAssessmentGQL!
}
type AggregateResultGQL {
@@ -210,6 +220,7 @@ input FilterInput @oneOf {
intendedPocketType: [PocketEnum!]
shotDirection: [ShotDirectionEnum!]
videoId: [Int!]
processingId: [Int!]
userId: [Int!]
runId: [Int!]
username: [String!]
@@ -962,9 +973,6 @@ type StripePriceGQL {
type UserSubscriptionStatusGQL {
hasActiveSubscription: Boolean!
entitlementSource: EntitlementSourceTypeEnum
entitlementStartsAt: DateTime
entitlementEndsAt: DateTime
subscriptionStatus: StripeSubscriptionStatusEnum
currentPeriodStart: DateTime
currentPeriodEnd: DateTime
@@ -973,13 +981,6 @@ type UserSubscriptionStatusGQL {
stripeSubscriptionId: String
}
enum EntitlementSourceTypeEnum {
ADMIN
MANUAL
STRIPE
ALPHA_LEGACY
}
enum StripeSubscriptionStatusEnum {
INCOMPLETE
INCOMPLETE_EXPIRED
@@ -1018,25 +1019,6 @@ type TagClassGQL {
name: String!
}
type GameTypeTagMetric {
tagName: String!
tagLabel: String!
tableSize: Float
shotCount: Int!
madeShots: Int!
makeRate: Float!
}
input GameTypeTagMetricsInput {
userId: Int!
createdAt: DateRangeFilter = null
maxTags: Int = null
groupByTableSize: Boolean! = true
includeUnknown: Boolean! = true
tagClass: String = "game_type"
includePrivate: IncludePrivateEnum! = MINE
}
"""
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).
"""
@@ -1045,6 +1027,37 @@ scalar JSON
url: "https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf"
)
type VideoProcessingAssessmentGQL {
processingId: Int!
groundTruthProcessingId: Int!
sourceShotCount: Int!
sourceFalsePositiveCount: Int!
groundTruthShotCount: Int!
groundTruthPositiveShotCount: Int!
groundTruthFalsePositiveCount: Int!
matchedGroundTruthShots: Int!
missedGroundTruthShots: Int!
unexpectedShots: Int!
correctlyFlaggedFalsePositives: Int!
unflaggedFalsePositives: Int!
extraFlaggedFalsePositives: Int!
groundTruthShotsFlaggedFalsePositive: Int!
makeDisagreements: Int!
matchedGroundTruthPairs: [VideoProcessingAssessmentShotPairGQL!]!
missedGroundTruthShotIds: [Int!]!
unexpectedShotIds: [Int!]!
correctlyFlaggedFalsePositivePairs: [VideoProcessingAssessmentShotPairGQL!]!
unflaggedFalsePositivePairs: [VideoProcessingAssessmentShotPairGQL!]!
extraFlaggedFalsePositiveShotIds: [Int!]!
groundTruthShotsFlaggedFalsePositivePairs: [VideoProcessingAssessmentShotPairGQL!]!
makeDisagreementPairs: [VideoProcessingAssessmentShotPairGQL!]!
}
type VideoProcessingAssessmentShotPairGQL {
processingShotId: Int!
groundTruthShotId: Int!
}
type Mutation {
createBucketSet(params: CreateBucketSetInput!): BucketSetGQL!
createRuleSet(name: String!, description: String = null): RuleSet!
@@ -1106,6 +1119,19 @@ type Mutation {
shotId: Int!
fieldsToEdit: EditableShotFieldInputGQL!
): EditShotReturn!
createGroundTruthShot(input: CreateGroundTruthShotInputGQL!): ShotGQL!
updateGroundTruthShotFrameRange(
shotId: Int!
startFrame: Int = null
endFrame: Int = null
notes: String = null
): ShotGQL!
splitGroundTruthShot(
shotId: Int!
splitFrame: Int!
notes: String = null
): SplitGroundTruthShotReturn!
deleteGroundTruthShot(shotId: Int!): DeleteGroundTruthShotReturn!
getProfileImageUploadLink(
fileExt: String = ".png"
): GetProfileUploadLinkReturn!
@@ -1118,14 +1144,6 @@ type Mutation {
deleteUser: Boolean!
createSubscription(priceId: String!): CreateSubscriptionResultGQL!
cancelSubscription: UserSubscriptionStatusGQL!
grantManualEntitlement(
userId: Int!
tierName: String! = "pro"
startsAt: DateTime = null
endsAt: DateTime = null
reason: String = null
): UserSubscriptionStatusGQL!
revokeManualEntitlement(userId: Int!): UserSubscriptionStatusGQL!
submitCancellationFeedback(
reasons: [CancellationReasonEnum!] = null
feedback: String = null
@@ -1136,6 +1154,11 @@ type Mutation {
videoMetadata: VideoMetadataInput!
expectedDurationSeconds: Float = null
): CreateUploadStreamReturn!
getOrCreateGroundTruthProcessing(
videoId: Int!
sourceProcessingId: Int = null
): VideoProcessingGQL!
promoteGroundTruthProcessing(processingId: Int!): VideoProcessingGQL!
getUploadLink(videoId: Int!, segmentIndex: Int!): GetUploadLinkReturn!
getHlsInitUploadLink(videoId: Int!): GetUploadLinkReturn!
setSegmentDuration(
@@ -1212,12 +1235,32 @@ input EditableShotFieldInputGQL {
shotDirection: ShotDirectionEnum
spinType: SpinTypeEnum
targetPocketAngleDirection: ShotDirectionEnum
intendedBallId: Int
intendedPocketId: PocketIdentifier
pathMetadataIndex: Int
make: Boolean
backcut: Boolean
excludeFromStats: Boolean
notes: String
}
input CreateGroundTruthShotInputGQL {
processingId: Int!
startFrame: Int!
endFrame: Int!
make: Boolean
notes: String
}
type SplitGroundTruthShotReturn {
originalShot: ShotGQL!
createdShot: ShotGQL!
}
type DeleteGroundTruthShotReturn {
deletedShotId: Int!
}
type GetProfileUploadLinkReturn {
value: UploadLinkGetProfileUploadLinkErrors!
}