diff --git a/api/src/openapi.ts b/api/src/openapi.ts index 641b8e4..b8f2643 100644 --- a/api/src/openapi.ts +++ b/api/src/openapi.ts @@ -667,13 +667,13 @@ export const RecalculateLeaderboardSchema = { export const UserResultsResponseComponent = z .object({ - user_name: z.string(), - user_id: z.number(), + userName: z.string(), + userId: z.number(), rank: z.number(), - seasonId: z.number().optional(), - seasonName: z.string().optional(), - format: FormatComponent.optional(), - factionCode: z.string().optional(), + seasonId: z.number().optional().nullable(), + seasonName: z.string().optional().nullable(), + format: FormatComponent.optional().nullable(), + factionCode: z.string().optional().nullable(), results: z.array(ResultComponent), }) .openapi("UserResultsResponse"); diff --git a/api/src/routes/users.ts b/api/src/routes/users.ts index 25458a2..652f672 100644 --- a/api/src/routes/users.ts +++ b/api/src/routes/users.ts @@ -17,6 +17,7 @@ import { ResultComponent, type UpdateUserComponentType, UserComponent, + UserResultsResponseComponent, } from "../openapi.js"; import type { FactionCode, Format } from "../schema.js"; import type { Env, RequestWithDB } from "../types.d.js"; @@ -133,15 +134,17 @@ export class GetUserResults extends OpenAPIRoute { } } - return json({ - user_id: user.id, - user_name: user.name, - season_id: seasonId || null, - seasonName: seasonName, - format: format, - factionCode: faction?.code || null, - rank: currentRank, - results: results.map((result) => ResultComponent.parse(result)), - }); + return json( + UserResultsResponseComponent.parse({ + userId: user.id, + userName: user.name, + seasonId: seasonId || null, + seasonName: seasonName, + format: format, + factionCode: faction?.code || null, + rank: currentRank, + results: results.map((result) => ResultComponent.parse(result)), + }), + ); } } diff --git a/app/src/client/models/UserResultsResponse.ts b/app/src/client/models/UserResultsResponse.ts index 87b7bf5..4b2eacf 100644 --- a/app/src/client/models/UserResultsResponse.ts +++ b/app/src/client/models/UserResultsResponse.ts @@ -7,8 +7,8 @@ import type { Format } from './Format'; import type { Result } from './Result'; export type UserResultsResponse = { - user_name: string; - user_id: number; + userName: string; + userId: number; rank: number; seasonId?: number; seasonName?: string; diff --git a/app/src/output.css b/app/src/output.css index 922edfc..630e756 100644 --- a/app/src/output.css +++ b/app/src/output.css @@ -1,5 +1,5 @@ /* -! tailwindcss v3.4.4 | MIT License | https://tailwindcss.com +! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com */ /* diff --git a/spec.json b/spec.json index f65b6dc..628207b 100644 --- a/spec.json +++ b/spec.json @@ -1 +1 @@ -{"openapi":"3.1.0","info":{"version":"1.0.0","title":"OpenAPI"},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"TokenResponse":{"type":"object","properties":{"access_token":{"type":"string"},"refresh_token":{"type":"string"},"expires_in":{"type":"number"},"token_type":{"type":"string"}},"required":["access_token","refresh_token","expires_in","token_type"]},"User":{"type":"object","properties":{"id":{"type":"number","description":"User ID"},"name":{"type":["string","null"],"description":"User name"},"email":{"type":["string","null"],"description":"User email"},"disabled":{"type":["boolean","null"],"description":"Flag indicating if the user has opted-out"},"is_admin":{"type":["boolean","null"],"description":"Flag indicating that the user is an Admin user"}},"required":["id","name","email"]},"UpdateUser":{"type":"object","properties":{"email":{"type":"string","description":"User email"},"disabled":{"type":["boolean","null"],"description":"Flag indicating if the user has opted-out"}}},"Format":{"type":"string","enum":["standard","startup","eternal","other"]},"TournamentType":{"type":"string","enum":["GNK / seasonal","asynchronous tournament","circuit breaker","circuit opener","community tournament","continental championship","infinite recursion","intercontinental championship","national championship","online event","store championship","team tournament","worlds championship","regional championship","players circuit"]},"Result":{"type":"object","properties":{"rank_swiss":{"type":"number"},"rank_cut":{"type":["number","null"]},"season_id":{"type":["number","null"]},"points_earned":{"type":"number"},"tournament_id":{"type":"number"},"tournament_name":{"type":"string"},"tournament_type":{"$ref":"#/components/schemas/TournamentType"},"players_count":{"type":"number"},"corp_deck_identity_id":{"type":"number"},"corp_deck_identity_name":{"type":["string","null"]},"corp_deck_faction":{"type":["string","null"]},"corp_deck_url":{"type":["string","null"]},"runner_deck_identity_id":{"type":"number"},"runner_deck_identity_name":{"type":["string","null"]},"runner_deck_faction":{"type":["string","null"]},"runner_deck_url":{"type":["string","null"]},"user_id":{"type":"number"},"user_name":{"type":["string","null"]},"format":{"$ref":"#/components/schemas/Format"},"count_for_tournament_type":{"type":"number","default":0},"is_valid":{"type":"boolean"}},"required":["rank_swiss","points_earned","tournament_id","tournament_name","tournament_type","players_count","corp_deck_identity_id","runner_deck_identity_id","user_id","user_name","format","is_valid"]},"UserResultsResponse":{"type":"object","properties":{"user_name":{"type":"string"},"user_id":{"type":"number"},"rank":{"type":"number"},"seasonId":{"type":"number"},"seasonName":{"type":"string"},"format":{"$ref":"#/components/schemas/Format"},"factionCode":{"type":"string"},"results":{"type":"array","items":{"$ref":"#/components/schemas/Result"}}},"required":["user_name","user_id","rank","results"]},"LeaderboardRow":{"type":"object","properties":{"points":{"type":"number"},"rank":{"type":"number"},"user_id":{"type":"number"},"user_name":{"type":["string","null"]},"disabled":{"type":["boolean","null"]},"attended":{"type":"number"}},"required":["points","rank","user_id","user_name","attended"]},"GetPointDistributionResponse":{"type":"object","properties":{"totalPoints":{"type":"number"},"pointDistribution":{"type":"array","items":{"type":"object","properties":{"placement":{"type":"number"},"points":{"type":"number"},"cumulative":{"type":"number"}},"required":["placement","points","cumulative"]}}},"required":["totalPoints","pointDistribution"]},"Faction":{"type":"object","properties":{"code":{"type":"string"},"color":{"type":"string"},"is_mini":{"type":"boolean"},"name":{"type":"string"},"side_code":{"type":"string"}},"required":["code","color","is_mini","name","side_code"]},"Season":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"started_at":{"type":"string","format":"date-time"},"ended_at":{"type":["string","null"]}},"required":["id","name","started_at"]},"Tournament":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":["string","null"]},"date":{"type":["string","null"],"format":"date-time"},"players_count":{"type":"number"},"location":{"type":"string"},"concluded":{"type":["boolean","null"]},"format":{"type":"string"},"type":{"type":"string"},"season_id":{"type":["number","null"]},"season_name":{"type":["string","null"]},"season_tier":{"type":["string","null"]}},"required":["id","name","date","players_count","location","format","type","season_id"]},"TournamentConfig":{"type":"object","properties":{"code":{"$ref":"#/components/schemas/TournamentType"},"name":{"type":"string"},"tournament_limit":{"type":"number"},"min_players_to_be_legal":{"type":"number"},"baseline_points":{"type":"number"},"points_per_player":{"type":"number"},"percent_receiving_points":{"type":"number"},"additional_top_cut_percentage":{"type":"number"}},"required":["code","name","tournament_limit","min_players_to_be_legal","baseline_points","points_per_player","percent_receiving_points","additional_top_cut_percentage"]},"RankingConfig":{"type":"object","properties":{"bottom_threshold":{"type":"number"},"tournament_configs":{"type":"object","properties":{"GNK / seasonal":{"$ref":"#/components/schemas/TournamentConfig"},"asynchronous tournament":{"$ref":"#/components/schemas/TournamentConfig"},"circuit breaker":{"$ref":"#/components/schemas/TournamentConfig"},"circuit opener":{"$ref":"#/components/schemas/TournamentConfig"},"community tournament":{"$ref":"#/components/schemas/TournamentConfig"},"continental championship":{"$ref":"#/components/schemas/TournamentConfig"},"infinite recursion":{"$ref":"#/components/schemas/TournamentConfig"},"intercontinental championship":{"$ref":"#/components/schemas/TournamentConfig"},"national championship":{"$ref":"#/components/schemas/TournamentConfig"},"online event":{"$ref":"#/components/schemas/TournamentConfig"},"store championship":{"$ref":"#/components/schemas/TournamentConfig"},"team tournament":{"$ref":"#/components/schemas/TournamentConfig"},"worlds championship":{"$ref":"#/components/schemas/TournamentConfig"},"regional championship":{"$ref":"#/components/schemas/TournamentConfig"},"players circuit":{"$ref":"#/components/schemas/TournamentConfig"}}}},"required":["bottom_threshold","tournament_configs"]},"GetTagsResponse":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"normalized":{"type":"string"},"owner_id":{"type":"number"},"owner_name":{"type":"string"},"count":{"type":"number"},"use_tournament_limits":{"type":["boolean","null"]}},"required":["id","name","normalized","owner_id","owner_name","count"]},"Tag":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"normalized":{"type":"string"},"owner_id":{"type":"number"},"use_tournament_limits":{"type":["boolean","null"]}},"required":["id","name","normalized","owner_id"]},"TagTournament":{"type":"object","properties":{"tournament_id":{"type":"number"},"tag_id":{"type":"number"}},"required":["tournament_id","tag_id"]}},"parameters":{}},"paths":{"/api/auth/login_url":{"get":{"tags":["Auth"],"summary":"Fetches the NRDB login url","operationId":"get_GetLoginUrl","responses":{"200":{"description":"Object containing the auth_url","content":{"application/json":{"schema":{"type":"string"}}}}}}},"/api/auth/token":{"get":{"tags":["Auth"],"summary":"From the code supplied during the OAuth redirect, perform the secret exchange and create a token","operationId":"get_GetTokenFromCode","parameters":[{"schema":{"type":"string"},"required":true,"name":"code","in":"query"}],"responses":{"200":{"description":"Blob containing the token and refresh_token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}}}}},"/api/auth/refresh_token":{"get":{"tags":["Auth"],"summary":"Attempts to create a new token from the given refresh_token","operationId":"get_RefreshToken","parameters":[{"schema":{"type":"string"},"required":true,"name":"refresh_token","in":"query"}],"responses":{"200":{"description":"Blob containing the token and refresh_token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}}}}},"/api/users/@me":{"get":{"tags":["User"],"summary":"Gets your own profile","security":[{"bearerAuth":[]}],"operationId":"get_Me","responses":{"200":{"description":"Your own user profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}}}},"patch":{"tags":["User"],"summary":"Updates your profile","security":[{"bearerAuth":[]}],"operationId":"patch_PatchMe","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUser"}}}},"responses":{"200":{"description":"Your updated user profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}}}}},"/api/users":{"get":{"tags":["User"],"summary":"Gets a list of all users.","operationId":"get_GetUsers","responses":{"200":{"description":"List of all users","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/User"}}}}}}}},"/api/users/{userID}":{"get":{"tags":["User"],"summary":"Gets a single user","operationId":"get_GetUser","parameters":[{"schema":{"type":"integer","description":"User ID (integer)"},"required":true,"description":"User ID (integer)","name":"userID","in":"path"}],"responses":{"200":{"description":"User Object","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}}}}},"/api/users/{user}/results":{"get":{"tags":["Results"],"summary":"Gets the results for the given user","operationId":"get_GetUserResults","parameters":[{"schema":{"type":"string","description":"Name or ID of the user"},"required":true,"description":"Name or ID of the user","name":"user","in":"path"},{"schema":{"type":["number","null"]},"required":false,"name":"season","in":"query"},{"schema":{"type":"string"},"required":false,"name":"factionCode","in":"query"},{"schema":{"$ref":"#/components/schemas/Format"},"required":false,"name":"format","in":"query"},{"schema":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"required":false,"name":"tags","in":"query"}],"responses":{"200":{"description":"Gets a list of all results for the given user and supplied filters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResultsResponse"}}}}}}},"/api/leaderboard":{"get":{"tags":["Leaderboard"],"summary":"Gets the current season's leaderboard","operationId":"get_GetLeaderboard","parameters":[{"schema":{"type":["number","null"]},"required":false,"name":"seasonId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"factionCode","in":"query"},{"schema":{"$ref":"#/components/schemas/Format"},"required":false,"name":"format","in":"query"},{"schema":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"required":false,"name":"tags","in":"query"}],"responses":{"200":{"description":"Returns a array of rows compromising the full leaderboard for the given season","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/LeaderboardRow"}}}}}}}},"/api/point-distribution":{"get":{"tags":["Leaderboard"],"summary":"Tool to show distribution of points from various given parameters","operationId":"get_GetPointDistribution","parameters":[{"schema":{"type":["number","null"]},"required":false,"name":"numPlayers","in":"query"},{"schema":{"$ref":"#/components/schemas/TournamentType"},"required":false,"name":"type","in":"query"}],"responses":{"200":{"description":"Returns a array of numbers representing the point distribution of the simulated tournament","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetPointDistributionResponse"}}}}}}},"/api/factions":{"get":{"tags":["Leaderboard"],"summary":"Returns a list of Netrunner Factions","operationId":"get_GetFactions","responses":{"200":{"description":"Returns an array Factions","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Faction"}}}}}}}},"/api/formats":{"get":{"tags":["Leaderboard"],"summary":"Returns a list of supported Netrunner Formats","operationId":"get_GetFormats","responses":{"200":{"description":"Returns an array supported Formats","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Format"}}}}}}}},"/api/seasons":{"get":{"tags":["Seasons"],"summary":"Gets a list of all existing and past Seasons.","operationId":"get_GetSeasons","responses":{"200":{"description":"list of Seasons","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Season"}}}}}}}},"/api/seasons/{seasonId}/tournaments":{"get":{"tags":["Seasons"],"summary":"Gets a list of all existing and past Seasons.","operationId":"get_GetSeasonTournaments","parameters":[{"schema":{"type":"number","description":"Season ID"},"required":true,"description":"Season ID","name":"seasonId","in":"path"}],"responses":{"200":{"description":"list of Tournaments for the given season","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Tournament"}}}}}}}},"/api/tournaments":{"get":{"tags":["Tournament"],"summary":"Gets a list of all Tournaments","operationId":"get_GetTournaments","responses":{"200":{"description":"list of Tournaments","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Tournament"}}}}}}}},"/api/tournaments/config":{"get":{"tags":["Leaderboard"],"summary":"Returns an object containing configuration data for determining the leaderboard","operationId":"get_GetRankingConfig","responses":{"200":{"description":"Returns a RankingConfig object","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RankingConfig"}}}}}}},"/api/tournaments/{tournamentId}":{"get":{"tags":["Tournament"],"summary":"Gets a single tournament","operationId":"get_GetTournament","parameters":[{"schema":{"type":"number","description":"Tournament ID"},"required":true,"description":"Tournament ID","name":"tournamentId","in":"path"}],"responses":{"200":{"description":"Full Tournament object","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Tournament"}}}}}}},"/api/tournaments/{tournamentId}/results":{"get":{"tags":["Tournament"],"summary":"Gets a list of results from the given tournament","operationId":"get_GetTournamentResults","parameters":[{"schema":{"type":"number","description":"Tournament ID"},"required":true,"description":"Tournament ID","name":"tournamentId","in":"path"}],"responses":{"200":{"description":"List of Results from the supplied tournament","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Result"}}}}}}}},"/api/tags":{"get":{"tags":["Tags"],"summary":"Gets the list of tags with a count of tournaments associated with that tag","operationId":"get_GetTags","parameters":[{"schema":{"type":["number","null"]},"required":false,"name":"owner_id","in":"query"}],"responses":{"200":{"description":"Returns a array of rows showing all tags, the owners, and the count of tournaments associated with each tag","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GetTagsResponse"}}}}}}},"put":{"tags":["Tags"],"summary":"Inserts a tag","operationId":"put_InsertTags","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]}}}},"responses":{"201":{"description":"Returns the inserted tag","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Tag"}}}}}}},"/api/tags/{tag_id}":{"delete":{"tags":["Tags"],"summary":"Deletes a tag","operationId":"delete_DeleteTag","parameters":[{"schema":{"type":"number","description":"Tag ID"},"required":true,"description":"Tag ID","name":"tag_id","in":"path"}],"responses":{"200":{"description":"Empty object indicates deleted tag","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}},"post":{"tags":["Tags"],"summary":"Updates a tag","operationId":"post_UpdateTag","parameters":[{"schema":{"type":"number","description":"Tag ID"},"required":true,"description":"Tag ID","name":"tag_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"use_tournament_limits":{"type":"boolean"}},"required":["use_tournament_limits"]}}}},"responses":{"200":{"description":"Empty object indicates deleted tag","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/tags/{tag_id}/tournament":{"put":{"tags":["Tags"],"summary":"Inserts a tournament tag","operationId":"put_InsertTagTournament","parameters":[{"schema":{"type":"number","description":"Tag ID you are using to tag the given tournament"},"required":true,"description":"Tag ID you are using to tag the given tournament","name":"tag_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"tournament_id":{"type":"number"}},"required":["tournament_id"]}}}},"responses":{"200":{"description":"Returns a array of rows showing all tags, the owners, and the count of tournaments associated with each tag","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagTournament"}}}}}},"get":{"tags":["Tags"],"summary":"Gets a list of tag tournaments","operationId":"get_GetTagTournaments","parameters":[{"schema":{"type":"number","description":"Tag ID"},"required":true,"description":"Tag ID","name":"tag_id","in":"path"}],"responses":{"200":{"description":"List of tag tournaments","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TagTournament"}}}}}}}},"/api/tags/{tag_id}/tournament/{tag_tournament_id}":{"delete":{"tags":["Tags"],"summary":"Deletes the given tag tournament","operationId":"delete_DeleteTagTournament","parameters":[{"schema":{"type":"number","description":"Tag ID"},"required":true,"description":"Tag ID","name":"tag_id","in":"path"},{"schema":{"type":"number","description":"Tag Tournament ID"},"required":true,"description":"Tag Tournament ID","name":"tag_tournament_id","in":"path"}],"responses":{"200":{"description":"Empty object indicating tag tournament was deleted","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/assets/ids/{id}":{"get":{"tags":["Assets"],"summary":"Gets a cached ID image","operationId":"get_GetIdImg","parameters":[{"schema":{"type":"number","description":"Identity card ID"},"required":true,"description":"Identity card ID","name":"id","in":"path"}],"responses":{"200":{"description":"Identity image PNG"}}}},"/api/admin/updateNRDBNames":{"get":{"tags":["Admin"],"summary":"Triggers updating all users names from nrdb","security":[{"bearerAuth":[]}],"operationId":"get_UpdateUsers","responses":{"200":{"description":"Updates all user accounts to pull from NRDB","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/admin/ingestTournament":{"post":{"tags":["Admin"],"summary":"Triggers a background job to ingest tournament data from ABR.","security":[{"bearerAuth":[]}],"operationId":"post_IngestTournament","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"number"},"tournamentType":{"type":"integer","enum":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]}}}}}},"responses":{"200":{"description":"Empty object indicates success on triggering ingestion.","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/admin/ingestTournaments":{"post":{"tags":["Admin"],"summary":"Triggers a background job to ingest all tournament data from ABR.","security":[{"bearerAuth":[]}],"operationId":"post_IngestTournaments","responses":{"200":{"description":"Empty object indicates success on triggering ingestion.","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/admin/updateCards":{"post":{"tags":["Admin"],"summary":"Fetches and updates the KV that stores the NRDB cards","security":[{"bearerAuth":[]}],"operationId":"post_UpdateCards","responses":{"200":{"description":"Empty object indicates success on updating nrdb cards.","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/admin/updateTournamentsSeason":{"post":{"tags":["Admin"],"summary":"Triggers a Season start & end date update across all tournaments.","security":[{"bearerAuth":[]}],"operationId":"post_UpdateTournamentSeasons","responses":{"200":{"description":"How many tournaments were updated","content":{"application/json":{"schema":{"type":"object","properties":{"tournamentsUpdated":{"type":"number"}},"required":["tournamentsUpdated"]}}}}}}}},"webhooks":{}} \ No newline at end of file +{"openapi":"3.1.0","info":{"version":"1.0.0","title":"OpenAPI"},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"TokenResponse":{"type":"object","properties":{"access_token":{"type":"string"},"refresh_token":{"type":"string"},"expires_in":{"type":"number"},"token_type":{"type":"string"}},"required":["access_token","refresh_token","expires_in","token_type"]},"User":{"type":"object","properties":{"id":{"type":"number","description":"User ID"},"name":{"type":["string","null"],"description":"User name"},"email":{"type":["string","null"],"description":"User email"},"disabled":{"type":["boolean","null"],"description":"Flag indicating if the user has opted-out"},"is_admin":{"type":["boolean","null"],"description":"Flag indicating that the user is an Admin user"}},"required":["id","name","email"]},"UpdateUser":{"type":"object","properties":{"email":{"type":"string","description":"User email"},"disabled":{"type":["boolean","null"],"description":"Flag indicating if the user has opted-out"}}},"Format":{"type":"string","enum":["standard","startup","eternal","other"]},"TournamentType":{"type":"string","enum":["GNK / seasonal","asynchronous tournament","circuit breaker","circuit opener","community tournament","continental championship","infinite recursion","intercontinental championship","national championship","online event","store championship","team tournament","worlds championship","regional championship","players circuit"]},"Result":{"type":"object","properties":{"rank_swiss":{"type":"number"},"rank_cut":{"type":["number","null"]},"season_id":{"type":["number","null"]},"points_earned":{"type":"number"},"tournament_id":{"type":"number"},"tournament_name":{"type":"string"},"tournament_type":{"$ref":"#/components/schemas/TournamentType"},"players_count":{"type":"number"},"corp_deck_identity_id":{"type":"number"},"corp_deck_identity_name":{"type":["string","null"]},"corp_deck_faction":{"type":["string","null"]},"corp_deck_url":{"type":["string","null"]},"runner_deck_identity_id":{"type":"number"},"runner_deck_identity_name":{"type":["string","null"]},"runner_deck_faction":{"type":["string","null"]},"runner_deck_url":{"type":["string","null"]},"user_id":{"type":"number"},"user_name":{"type":["string","null"]},"format":{"$ref":"#/components/schemas/Format"},"count_for_tournament_type":{"type":"number","default":0},"is_valid":{"type":"boolean"}},"required":["rank_swiss","points_earned","tournament_id","tournament_name","tournament_type","players_count","corp_deck_identity_id","runner_deck_identity_id","user_id","user_name","format","is_valid"]},"UserResultsResponse":{"type":"object","properties":{"userName":{"type":"string"},"userId":{"type":"number"},"rank":{"type":"number"},"seasonId":{"type":"number"},"seasonName":{"type":"string"},"format":{"$ref":"#/components/schemas/Format"},"factionCode":{"type":"string"},"results":{"type":"array","items":{"$ref":"#/components/schemas/Result"}}},"required":["userName","userId","rank","results"]},"LeaderboardRow":{"type":"object","properties":{"points":{"type":"number"},"rank":{"type":"number"},"user_id":{"type":"number"},"user_name":{"type":["string","null"]},"disabled":{"type":["boolean","null"]},"attended":{"type":"number"}},"required":["points","rank","user_id","user_name","attended"]},"GetPointDistributionResponse":{"type":"object","properties":{"totalPoints":{"type":"number"},"pointDistribution":{"type":"array","items":{"type":"object","properties":{"placement":{"type":"number"},"points":{"type":"number"},"cumulative":{"type":"number"}},"required":["placement","points","cumulative"]}}},"required":["totalPoints","pointDistribution"]},"Faction":{"type":"object","properties":{"code":{"type":"string"},"color":{"type":"string"},"is_mini":{"type":"boolean"},"name":{"type":"string"},"side_code":{"type":"string"}},"required":["code","color","is_mini","name","side_code"]},"Season":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"started_at":{"type":"string","format":"date-time"},"ended_at":{"type":["string","null"]}},"required":["id","name","started_at"]},"Tournament":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":["string","null"]},"date":{"type":["string","null"],"format":"date-time"},"players_count":{"type":"number"},"location":{"type":"string"},"concluded":{"type":["boolean","null"]},"format":{"type":"string"},"type":{"type":"string"},"season_id":{"type":["number","null"]},"season_name":{"type":["string","null"]},"season_tier":{"type":["string","null"]}},"required":["id","name","date","players_count","location","format","type","season_id"]},"TournamentConfig":{"type":"object","properties":{"code":{"$ref":"#/components/schemas/TournamentType"},"name":{"type":"string"},"tournament_limit":{"type":"number"},"min_players_to_be_legal":{"type":"number"},"baseline_points":{"type":"number"},"points_per_player":{"type":"number"},"percent_receiving_points":{"type":"number"},"additional_top_cut_percentage":{"type":"number"}},"required":["code","name","tournament_limit","min_players_to_be_legal","baseline_points","points_per_player","percent_receiving_points","additional_top_cut_percentage"]},"RankingConfig":{"type":"object","properties":{"bottom_threshold":{"type":"number"},"tournament_configs":{"type":"object","properties":{"GNK / seasonal":{"$ref":"#/components/schemas/TournamentConfig"},"asynchronous tournament":{"$ref":"#/components/schemas/TournamentConfig"},"circuit breaker":{"$ref":"#/components/schemas/TournamentConfig"},"circuit opener":{"$ref":"#/components/schemas/TournamentConfig"},"community tournament":{"$ref":"#/components/schemas/TournamentConfig"},"continental championship":{"$ref":"#/components/schemas/TournamentConfig"},"infinite recursion":{"$ref":"#/components/schemas/TournamentConfig"},"intercontinental championship":{"$ref":"#/components/schemas/TournamentConfig"},"national championship":{"$ref":"#/components/schemas/TournamentConfig"},"online event":{"$ref":"#/components/schemas/TournamentConfig"},"store championship":{"$ref":"#/components/schemas/TournamentConfig"},"team tournament":{"$ref":"#/components/schemas/TournamentConfig"},"worlds championship":{"$ref":"#/components/schemas/TournamentConfig"},"regional championship":{"$ref":"#/components/schemas/TournamentConfig"},"players circuit":{"$ref":"#/components/schemas/TournamentConfig"}}}},"required":["bottom_threshold","tournament_configs"]},"GetTagsResponse":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"normalized":{"type":"string"},"owner_id":{"type":"number"},"owner_name":{"type":"string"},"count":{"type":"number"},"use_tournament_limits":{"type":["boolean","null"]}},"required":["id","name","normalized","owner_id","owner_name","count"]},"Tag":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"normalized":{"type":"string"},"owner_id":{"type":"number"},"use_tournament_limits":{"type":["boolean","null"]}},"required":["id","name","normalized","owner_id"]},"TagTournament":{"type":"object","properties":{"tournament_id":{"type":"number"},"tag_id":{"type":"number"}},"required":["tournament_id","tag_id"]}},"parameters":{}},"paths":{"/api/auth/login_url":{"get":{"tags":["Auth"],"summary":"Fetches the NRDB login url","operationId":"get_GetLoginUrl","responses":{"200":{"description":"Object containing the auth_url","content":{"application/json":{"schema":{"type":"string"}}}}}}},"/api/auth/token":{"get":{"tags":["Auth"],"summary":"From the code supplied during the OAuth redirect, perform the secret exchange and create a token","operationId":"get_GetTokenFromCode","parameters":[{"schema":{"type":"string"},"required":true,"name":"code","in":"query"}],"responses":{"200":{"description":"Blob containing the token and refresh_token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}}}}},"/api/auth/refresh_token":{"get":{"tags":["Auth"],"summary":"Attempts to create a new token from the given refresh_token","operationId":"get_RefreshToken","parameters":[{"schema":{"type":"string"},"required":true,"name":"refresh_token","in":"query"}],"responses":{"200":{"description":"Blob containing the token and refresh_token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}}}}},"/api/users/@me":{"get":{"tags":["User"],"summary":"Gets your own profile","security":[{"bearerAuth":[]}],"operationId":"get_Me","responses":{"200":{"description":"Your own user profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}}}},"patch":{"tags":["User"],"summary":"Updates your profile","security":[{"bearerAuth":[]}],"operationId":"patch_PatchMe","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUser"}}}},"responses":{"200":{"description":"Your updated user profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}}}}},"/api/users":{"get":{"tags":["User"],"summary":"Gets a list of all users.","operationId":"get_GetUsers","responses":{"200":{"description":"List of all users","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/User"}}}}}}}},"/api/users/{userID}":{"get":{"tags":["User"],"summary":"Gets a single user","operationId":"get_GetUser","parameters":[{"schema":{"type":"integer","description":"User ID (integer)"},"required":true,"description":"User ID (integer)","name":"userID","in":"path"}],"responses":{"200":{"description":"User Object","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}}}}},"/api/users/{user}/results":{"get":{"tags":["Results"],"summary":"Gets the results for the given user","operationId":"get_GetUserResults","parameters":[{"schema":{"type":"string","description":"Name or ID of the user"},"required":true,"description":"Name or ID of the user","name":"user","in":"path"},{"schema":{"type":["number","null"]},"required":false,"name":"season","in":"query"},{"schema":{"type":"string"},"required":false,"name":"factionCode","in":"query"},{"schema":{"$ref":"#/components/schemas/Format"},"required":false,"name":"format","in":"query"},{"schema":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"required":false,"name":"tags","in":"query"}],"responses":{"200":{"description":"Gets a list of all results for the given user and supplied filters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResultsResponse"}}}}}}},"/api/leaderboard":{"get":{"tags":["Leaderboard"],"summary":"Gets the current season's leaderboard","operationId":"get_GetLeaderboard","parameters":[{"schema":{"type":["number","null"]},"required":false,"name":"seasonId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"factionCode","in":"query"},{"schema":{"$ref":"#/components/schemas/Format"},"required":false,"name":"format","in":"query"},{"schema":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"required":false,"name":"tags","in":"query"}],"responses":{"200":{"description":"Returns a array of rows compromising the full leaderboard for the given season","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/LeaderboardRow"}}}}}}}},"/api/point-distribution":{"get":{"tags":["Leaderboard"],"summary":"Tool to show distribution of points from various given parameters","operationId":"get_GetPointDistribution","parameters":[{"schema":{"type":["number","null"]},"required":false,"name":"numPlayers","in":"query"},{"schema":{"$ref":"#/components/schemas/TournamentType"},"required":false,"name":"type","in":"query"}],"responses":{"200":{"description":"Returns a array of numbers representing the point distribution of the simulated tournament","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetPointDistributionResponse"}}}}}}},"/api/factions":{"get":{"tags":["Leaderboard"],"summary":"Returns a list of Netrunner Factions","operationId":"get_GetFactions","responses":{"200":{"description":"Returns an array Factions","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Faction"}}}}}}}},"/api/formats":{"get":{"tags":["Leaderboard"],"summary":"Returns a list of supported Netrunner Formats","operationId":"get_GetFormats","responses":{"200":{"description":"Returns an array supported Formats","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Format"}}}}}}}},"/api/seasons":{"get":{"tags":["Seasons"],"summary":"Gets a list of all existing and past Seasons.","operationId":"get_GetSeasons","responses":{"200":{"description":"list of Seasons","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Season"}}}}}}}},"/api/seasons/{seasonId}/tournaments":{"get":{"tags":["Seasons"],"summary":"Gets a list of all existing and past Seasons.","operationId":"get_GetSeasonTournaments","parameters":[{"schema":{"type":"number","description":"Season ID"},"required":true,"description":"Season ID","name":"seasonId","in":"path"}],"responses":{"200":{"description":"list of Tournaments for the given season","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Tournament"}}}}}}}},"/api/tournaments":{"get":{"tags":["Tournament"],"summary":"Gets a list of all Tournaments","operationId":"get_GetTournaments","responses":{"200":{"description":"list of Tournaments","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Tournament"}}}}}}}},"/api/tournaments/config":{"get":{"tags":["Leaderboard"],"summary":"Returns an object containing configuration data for determining the leaderboard","operationId":"get_GetRankingConfig","responses":{"200":{"description":"Returns a RankingConfig object","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RankingConfig"}}}}}}},"/api/tournaments/{tournamentId}":{"get":{"tags":["Tournament"],"summary":"Gets a single tournament","operationId":"get_GetTournament","parameters":[{"schema":{"type":"number","description":"Tournament ID"},"required":true,"description":"Tournament ID","name":"tournamentId","in":"path"}],"responses":{"200":{"description":"Full Tournament object","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Tournament"}}}}}}},"/api/tournaments/{tournamentId}/results":{"get":{"tags":["Tournament"],"summary":"Gets a list of results from the given tournament","operationId":"get_GetTournamentResults","parameters":[{"schema":{"type":"number","description":"Tournament ID"},"required":true,"description":"Tournament ID","name":"tournamentId","in":"path"}],"responses":{"200":{"description":"List of Results from the supplied tournament","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Result"}}}}}}}},"/api/tags":{"get":{"tags":["Tags"],"summary":"Gets the list of tags with a count of tournaments associated with that tag","operationId":"get_GetTags","parameters":[{"schema":{"type":["number","null"]},"required":false,"name":"owner_id","in":"query"}],"responses":{"200":{"description":"Returns a array of rows showing all tags, the owners, and the count of tournaments associated with each tag","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GetTagsResponse"}}}}}}},"put":{"tags":["Tags"],"summary":"Inserts a tag","operationId":"put_InsertTags","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]}}}},"responses":{"201":{"description":"Returns the inserted tag","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Tag"}}}}}}},"/api/tags/{tag_id}":{"delete":{"tags":["Tags"],"summary":"Deletes a tag","operationId":"delete_DeleteTag","parameters":[{"schema":{"type":"number","description":"Tag ID"},"required":true,"description":"Tag ID","name":"tag_id","in":"path"}],"responses":{"200":{"description":"Empty object indicates deleted tag","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}},"post":{"tags":["Tags"],"summary":"Updates a tag","operationId":"post_UpdateTag","parameters":[{"schema":{"type":"number","description":"Tag ID"},"required":true,"description":"Tag ID","name":"tag_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"use_tournament_limits":{"type":"boolean"}},"required":["use_tournament_limits"]}}}},"responses":{"200":{"description":"Empty object indicates deleted tag","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/tags/{tag_id}/tournament":{"put":{"tags":["Tags"],"summary":"Inserts a tournament tag","operationId":"put_InsertTagTournament","parameters":[{"schema":{"type":"number","description":"Tag ID you are using to tag the given tournament"},"required":true,"description":"Tag ID you are using to tag the given tournament","name":"tag_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"tournament_id":{"type":"number"}},"required":["tournament_id"]}}}},"responses":{"200":{"description":"Returns a array of rows showing all tags, the owners, and the count of tournaments associated with each tag","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagTournament"}}}}}},"get":{"tags":["Tags"],"summary":"Gets a list of tag tournaments","operationId":"get_GetTagTournaments","parameters":[{"schema":{"type":"number","description":"Tag ID"},"required":true,"description":"Tag ID","name":"tag_id","in":"path"}],"responses":{"200":{"description":"List of tag tournaments","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TagTournament"}}}}}}}},"/api/tags/{tag_id}/tournament/{tag_tournament_id}":{"delete":{"tags":["Tags"],"summary":"Deletes the given tag tournament","operationId":"delete_DeleteTagTournament","parameters":[{"schema":{"type":"number","description":"Tag ID"},"required":true,"description":"Tag ID","name":"tag_id","in":"path"},{"schema":{"type":"number","description":"Tag Tournament ID"},"required":true,"description":"Tag Tournament ID","name":"tag_tournament_id","in":"path"}],"responses":{"200":{"description":"Empty object indicating tag tournament was deleted","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/assets/ids/{id}":{"get":{"tags":["Assets"],"summary":"Gets a cached ID image","operationId":"get_GetIdImg","parameters":[{"schema":{"type":"number","description":"Identity card ID"},"required":true,"description":"Identity card ID","name":"id","in":"path"}],"responses":{"200":{"description":"Identity image PNG"}}}},"/api/admin/updateNRDBNames":{"get":{"tags":["Admin"],"summary":"Triggers updating all users names from nrdb","security":[{"bearerAuth":[]}],"operationId":"get_UpdateUsers","responses":{"200":{"description":"Updates all user accounts to pull from NRDB","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/admin/ingestTournament":{"post":{"tags":["Admin"],"summary":"Triggers a background job to ingest tournament data from ABR.","security":[{"bearerAuth":[]}],"operationId":"post_IngestTournament","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"number"},"tournamentType":{"type":"integer","enum":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]}}}}}},"responses":{"200":{"description":"Empty object indicates success on triggering ingestion.","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/admin/ingestTournaments":{"post":{"tags":["Admin"],"summary":"Triggers a background job to ingest all tournament data from ABR.","security":[{"bearerAuth":[]}],"operationId":"post_IngestTournaments","responses":{"200":{"description":"Empty object indicates success on triggering ingestion.","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/admin/updateCards":{"post":{"tags":["Admin"],"summary":"Fetches and updates the KV that stores the NRDB cards","security":[{"bearerAuth":[]}],"operationId":"post_UpdateCards","responses":{"200":{"description":"Empty object indicates success on updating nrdb cards.","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/admin/updateTournamentsSeason":{"post":{"tags":["Admin"],"summary":"Triggers a Season start & end date update across all tournaments.","security":[{"bearerAuth":[]}],"operationId":"post_UpdateTournamentSeasons","responses":{"200":{"description":"How many tournaments were updated","content":{"application/json":{"schema":{"type":"object","properties":{"tournamentsUpdated":{"type":"number"}},"required":["tournamentsUpdated"]}}}}}}}},"webhooks":{}} \ No newline at end of file