From 9bb02463dad517bbbec4878478ed0f34ab10196b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Gremaud?= Date: Sun, 25 Oct 2026 10:25:29 +0100 Subject: [PATCH] feat: heatmap + evo + decay --- polylan_submitter/place/api.py | 53 +++++ polylan_submitter/place/heatmap.py | 198 ++++++++++++++++++ .../src/api/@tanstack/vue-query.gen.ts | 75 ++++++- polylan_submitter/src/api/index.ts | 4 +- polylan_submitter/src/api/sdk.gen.ts | 58 ++++- polylan_submitter/src/api/types.gen.ts | 76 +++++++ 6 files changed, 459 insertions(+), 5 deletions(-) create mode 100644 polylan_submitter/place/heatmap.py diff --git a/polylan_submitter/place/api.py b/polylan_submitter/place/api.py index 613209b..0f645e8 100644 --- a/polylan_submitter/place/api.py +++ b/polylan_submitter/place/api.py @@ -11,6 +11,11 @@ from games.decorators import require_game_enabled from .canvas import read_canvas from .gif import build_evolution_gif +from .heatmap import ( + build_heatmap_decay_gif, + build_heatmap_evolution_gif, + build_heatmap_png, +) from .models import PixelPlacement, PlaceSettings router = Router() @@ -47,6 +52,54 @@ def evolution_gif(request: HttpRequest, event_path: str, players: str = ""): ) +@router.get(f"{PREFIX}/heatmap.png", auth=django_auth_is_staff) +@decorate_view(require_game_enabled(path="place")) +def heatmap_png(request: HttpRequest, event_path: str, players: str = ""): + """Admin-only: how many times each pixel was placed, as a heatmap PNG. + + `players` is an optional comma-separated list of usernames to only + count those players' placements (combined).""" + usernames = [name.strip() for name in players.split(",") if name.strip()] + return HttpResponse( + build_heatmap_png(request.event, usernames), content_type="image/png" + ) + + +@router.get(f"{PREFIX}/heatmap-evolution.gif", auth=django_auth_is_staff) +@decorate_view(require_game_enabled(path="place")) +def heatmap_evolution_gif(request: HttpRequest, event_path: str, players: str = ""): + """Admin-only: the heatmap building up over time, as an animated GIF. + + `players` is an optional comma-separated list of usernames to only + count those players' placements (combined).""" + usernames = [name.strip() for name in players.split(",") if name.strip()] + return HttpResponse( + build_heatmap_evolution_gif(request.event, usernames), + content_type="image/gif", + ) + + +@router.get(f"{PREFIX}/heatmap-decay.gif", auth=django_auth_is_staff) +@decorate_view(require_game_enabled(path="place")) +def heatmap_decay_gif( + request: HttpRequest, + event_path: str, + players: str = "", + half_life: int | None = None, +): + """Admin-only: the heatmap over time, but heat decays so pixels nobody + touches anymore fade back to white. + + `players` is an optional comma-separated list of usernames to only + count those players' placements (combined). `half_life` is in + placements, defaults to 10 frames' worth.""" + usernames = [name.strip() for name in players.split(",") if name.strip()] + return HttpResponse( + build_heatmap_decay_gif(request.event, usernames, half_life), + content_type="image/gif", + ) + + @router.get(f"{PREFIX}/placements.csv", auth=django_auth_is_staff) @decorate_view(require_game_enabled(path="place")) def placements_csv(request: HttpRequest, event_path: str): diff --git a/polylan_submitter/place/heatmap.py b/polylan_submitter/place/heatmap.py new file mode 100644 index 0000000..cec6e01 --- /dev/null +++ b/polylan_submitter/place/heatmap.py @@ -0,0 +1,198 @@ +"""Renders one event's pixel placement history as a heatmap. + +Same source as gif.py (the durable PixelPlacement history), but instead of +replaying colors, counts how many times each pixel was placed and maps that +count to a white -> red gradient, so an admin can see +where the action was - either as a single PNG of the final counts, as an +animated GIF of the counts building up over time, or as an animated GIF +where the heat decays so only recent activity stays red. +""" + +import math +from io import BytesIO + +from django.db.models import Count +from PIL import Image + +from events.models import Event + +from .gif import FINAL_FRAME_HOLD_MS, FRAME_DURATION_MS, MAX_FRAMES +from .models import PixelPlacement, PlaceSettings + +SCALE = 8 + +# Gradient stops, from "never placed" to "most placed" +_GRADIENT = [ + (255, 255, 255), + (193, 1, 2), +] + + +def build_heatmap_png(event: Event, usernames: list[str] | None = None) -> bytes: + """Renders `event`'s placement counts per pixel as a PNG heatmap, + upscaled for visibility. Returns PNG bytes, even if there are zero + placements (all white). + + If `usernames` is given, only those players' placements are counted + (combined on the same board). + + Counts are log-scaled, otherwise a few heavily fought-over pixels make + everything else look white. Placements outside the *current* grid + dimensions are skipped, like in gif.py.""" + place_settings = PlaceSettings.current(event) + width, height = place_settings.width, place_settings.height + + placements = _placements(event, usernames) + counts = placements.values("x", "y").annotate(count=Count("id")).order_by() + + grid = [0] * (width * height) + for row in counts: + if row["x"] >= width or row["y"] >= height: + continue + grid[row["y"] * width + row["x"]] = row["count"] + + colors = _color_table(max(grid, default=0)) + buffer = BytesIO() + _render_frame(grid, width, height, colors).save(buffer, format="PNG") + return buffer.getvalue() + + +def build_heatmap_evolution_gif( + event: Event, usernames: list[str] | None = None +) -> bytes: + """Same as build_heatmap_png, but as an animated GIF where the counts + accumulate placement by placement (sampled down to MAX_FRAMES, like + gif.py). Returns GIF bytes, even if there are zero placements. + + Every frame uses the *final* max count for its color scale, so a pixel's + color only ever heats up - otherwise early frames would look as hot as + the end.""" + place_settings = PlaceSettings.current(event) + width, height = place_settings.width, place_settings.height + + placements = [ + (x, y) + for x, y in _placements(event, usernames) + .order_by("placed_at") + .values_list("x", "y") + if x < width and y < height + ] + + final_grid = [0] * (width * height) + for x, y in placements: + final_grid[y * width + x] += 1 + colors = _color_table(max(final_grid, default=0)) + + grid = [0] * (width * height) + frames: list[Image.Image] = [] + + step = max(1, len(placements) // MAX_FRAMES) + for i, (x, y) in enumerate(placements): + grid[y * width + x] += 1 + if i % step == 0 or i == len(placements) - 1: + frames.append(_render_frame(grid, width, height, colors)) + + if not frames: + frames.append(_render_frame(grid, width, height, colors)) + + return _save_gif(frames) + + +def build_heatmap_decay_gif( + event: Event, usernames: list[str] | None = None, half_life: int | None = None +) -> bytes: + """Like build_heatmap_evolution_gif, but every pixel's heat decays + exponentially, so a pixel nobody touches anymore fades back to white + and the GIF shows where the activity is *right now*. + + `half_life` is in placements (after that many more placements anywhere + on the board, a pixel's heat is halved). Defaults to 10 frames' worth. + + Every frame shares the same color scale (the hottest pixel across the + whole replay), so a quiet period actually looks quiet.""" + place_settings = PlaceSettings.current(event) + width, height = place_settings.width, place_settings.height + + placements = [ + (x, y) + for x, y in _placements(event, usernames) + .order_by("placed_at") + .values_list("x", "y") + if x < width and y < height + ] + + step = max(1, len(placements) // MAX_FRAMES) + decay = 0.5 ** (1 / max(1, half_life or step * 10)) + + # Decay is applied lazily: each pixel stores its heat as of the + # placement index it was last touched at, so a placement is O(1) + # instead of decaying the whole grid every time. + heat = [0.0] * (width * height) + touched_at = [0] * (width * height) + snapshots: list[list[float]] = [] + for i, (x, y) in enumerate(placements): + index = y * width + x + heat[index] = heat[index] * decay ** (i - touched_at[index]) + 1 + touched_at[index] = i + if i % step == 0 or i == len(placements) - 1: + snapshots.append([h * decay ** (i - t) for h, t in zip(heat, touched_at)]) + + if not snapshots: + snapshots.append(heat) + + max_log = math.log1p(max(max(snapshot) for snapshot in snapshots)) or 1 + colors = [_gradient(i / 255) for i in range(256)] + frames = [] + for snapshot in snapshots: + image = Image.new("RGB", (width, height)) + image.putdata([colors[round(math.log1p(h) / max_log * 255)] for h in snapshot]) + frames.append(image.resize((width * SCALE, height * SCALE), Image.NEAREST)) + + return _save_gif(frames) + + +def _save_gif(frames: list[Image.Image]) -> bytes: + buffer = BytesIO() + durations = [FRAME_DURATION_MS] * len(frames) + durations[-1] = FINAL_FRAME_HOLD_MS + frames[0].save( + buffer, + format="GIF", + save_all=True, + append_images=frames[1:], + duration=durations, + loop=0, + disposal=2, + ) + return buffer.getvalue() + + +def _placements(event: Event, usernames: list[str] | None): + placements = PixelPlacement.objects.filter(event=event) + if usernames: + placements = placements.filter(player__username__in=usernames) + return placements + + +def _color_table(max_count: int) -> list[tuple[int, int, int]]: + """Color for every count in [0, max_count], log-scaled.""" + max_log = math.log1p(max_count) or 1 + return [_gradient(math.log1p(count) / max_log) for count in range(max_count + 1)] + + +def _render_frame( + grid: list[int], width: int, height: int, colors: list[tuple[int, int, int]] +) -> Image.Image: + image = Image.new("RGB", (width, height)) + image.putdata([colors[count] for count in grid]) + return image.resize((width * SCALE, height * SCALE), Image.NEAREST) + + +def _gradient(t: float) -> tuple[int, int, int]: + """Linearly interpolates `_GRADIENT` at `t` in [0, 1].""" + position = t * (len(_GRADIENT) - 1) + index = min(int(position), len(_GRADIENT) - 2) + frac = position - index + start, end = _GRADIENT[index], _GRADIENT[index + 1] + r, g, b = (round(a + (z - a) * frac) for a, z in zip(start, end)) + return r, g, b diff --git a/polylan_submitter/src/api/@tanstack/vue-query.gen.ts b/polylan_submitter/src/api/@tanstack/vue-query.gen.ts index ee4e764..16e9f93 100644 --- a/polylan_submitter/src/api/@tanstack/vue-query.gen.ts +++ b/polylan_submitter/src/api/@tanstack/vue-query.gen.ts @@ -3,8 +3,8 @@ import { type DefaultError, type InfiniteData, infiniteQueryOptions, queryOptions, type UseMutationOptions } from '@tanstack/vue-query'; import { client } from '../client.gen'; -import { animationsApiPuzzleResults, animationsApiResults, animationsApiTopSubmissions, clockApiCurrentState, clockApiMyStats, gamesApiListEventGames, gamesApiListEventPlanning, gamesApiListEventSteamGames, gamesApiListGames, marketApiBetHistory, marketApiCloseMarket, marketApiCreateBet, marketApiGetUserPoints, marketApiListMarkets, marketApiListUserBets, marketApiResolveMarket, noitaApiGetLeaderboard, noitaApiGetResults, noitaApiSubmitLogFile, type Options, opusMagnumApiCreateSubmission, opusMagnumApiDeleteSubmission, opusMagnumApiGetCollection, opusMagnumApiGetStats, opusMagnumApiGetSubmission, opusMagnumApiListPuzzles, opusMagnumApiListResponseFiles, opusMagnumApiListResponsesNeedingValidation, opusMagnumApiListSubmissions, opusMagnumApiValidateAuto, opusMagnumApiValidateResponse, opusMagnumApiValidateSubmission, placeApiCanvas, placeApiEvolutionGif, placeApiPlacementsCsv, polylanSubmitterApiClearCache, polylanSubmitterApiGetUserInfo, polylanSubmitterApiHealthCheck, submissionsApiCreateImageCrop, submissionsApiCreateSubmission, submissionsApiDeleteImageCrop, submissionsApiGetSubmission, submissionsApiListAvailableScopes, submissionsApiListMyScopes, submissionsApiListSubmissionsByGame, submissionsApiListUserSubmissions, submissionsApiProcessCropOcr, submissionsApiProcessFileOcr, submissionsApiStopSyncScopes, submissionsApiSyncScopes, submissionsApiSyncScopesStatus } from '../sdk.gen'; -import type { AnimationsApiPuzzleResultsData, AnimationsApiPuzzleResultsResponse, AnimationsApiResultsData, AnimationsApiResultsResponse, AnimationsApiTopSubmissionsData, AnimationsApiTopSubmissionsResponse, ClockApiCurrentStateData, ClockApiCurrentStateResponse, ClockApiMyStatsData, ClockApiMyStatsResponse, GamesApiListEventGamesData, GamesApiListEventGamesResponse, GamesApiListEventPlanningData, GamesApiListEventPlanningResponse, GamesApiListEventSteamGamesData, GamesApiListEventSteamGamesResponse, GamesApiListGamesData, GamesApiListGamesResponse, MarketApiBetHistoryData, MarketApiBetHistoryResponse, MarketApiCloseMarketData, MarketApiCreateBetData, MarketApiCreateBetResponse, MarketApiGetUserPointsData, MarketApiGetUserPointsResponse, MarketApiListMarketsData, MarketApiListMarketsResponse, MarketApiListUserBetsData, MarketApiListUserBetsResponse, MarketApiResolveMarketData, MarketApiResolveMarketResponse, NoitaApiGetLeaderboardData, NoitaApiGetLeaderboardResponse, NoitaApiGetResultsData, NoitaApiGetResultsResponse, NoitaApiSubmitLogFileData, NoitaApiSubmitLogFileError, NoitaApiSubmitLogFileResponse, OpusMagnumApiCreateSubmissionData, OpusMagnumApiCreateSubmissionError, OpusMagnumApiCreateSubmissionResponse, OpusMagnumApiDeleteSubmissionData, OpusMagnumApiDeleteSubmissionError, OpusMagnumApiDeleteSubmissionResponse, OpusMagnumApiGetCollectionData, OpusMagnumApiGetCollectionResponse, OpusMagnumApiGetStatsData, OpusMagnumApiGetSubmissionData, OpusMagnumApiGetSubmissionResponse, OpusMagnumApiListPuzzlesData, OpusMagnumApiListPuzzlesResponse, OpusMagnumApiListResponseFilesData, OpusMagnumApiListResponseFilesError, OpusMagnumApiListResponseFilesResponse, OpusMagnumApiListResponsesNeedingValidationData, OpusMagnumApiListResponsesNeedingValidationError, OpusMagnumApiListResponsesNeedingValidationResponse, OpusMagnumApiListSubmissionsData, OpusMagnumApiListSubmissionsResponse, OpusMagnumApiValidateAutoData, OpusMagnumApiValidateAutoError, OpusMagnumApiValidateAutoResponse, OpusMagnumApiValidateResponseData, OpusMagnumApiValidateResponseError, OpusMagnumApiValidateResponseResponse, OpusMagnumApiValidateSubmissionData, OpusMagnumApiValidateSubmissionError, OpusMagnumApiValidateSubmissionResponse, PlaceApiCanvasData, PlaceApiEvolutionGifData, PlaceApiPlacementsCsvData, PolylanSubmitterApiClearCacheData, PolylanSubmitterApiClearCacheError, PolylanSubmitterApiClearCacheResponse, PolylanSubmitterApiGetUserInfoData, PolylanSubmitterApiGetUserInfoResponse, PolylanSubmitterApiHealthCheckData, PolylanSubmitterApiHealthCheckResponse, SubmissionsApiCreateImageCropData, SubmissionsApiCreateImageCropError, SubmissionsApiCreateImageCropResponse, SubmissionsApiCreateSubmissionData, SubmissionsApiCreateSubmissionError, SubmissionsApiCreateSubmissionResponse, SubmissionsApiDeleteImageCropData, SubmissionsApiDeleteImageCropError, SubmissionsApiDeleteImageCropResponse, SubmissionsApiGetSubmissionData, SubmissionsApiGetSubmissionError, SubmissionsApiGetSubmissionResponse, SubmissionsApiListAvailableScopesData, SubmissionsApiListAvailableScopesError, SubmissionsApiListAvailableScopesResponse, SubmissionsApiListMyScopesData, SubmissionsApiListMyScopesError, SubmissionsApiListMyScopesResponse, SubmissionsApiListSubmissionsByGameData, SubmissionsApiListSubmissionsByGameError, SubmissionsApiListSubmissionsByGameResponse, SubmissionsApiListUserSubmissionsData, SubmissionsApiListUserSubmissionsError, SubmissionsApiListUserSubmissionsResponse, SubmissionsApiProcessCropOcrData, SubmissionsApiProcessCropOcrError, SubmissionsApiProcessCropOcrResponse, SubmissionsApiProcessFileOcrData, SubmissionsApiProcessFileOcrError, SubmissionsApiProcessFileOcrResponse, SubmissionsApiStopSyncScopesData, SubmissionsApiStopSyncScopesError, SubmissionsApiStopSyncScopesResponse, SubmissionsApiSyncScopesData, SubmissionsApiSyncScopesError, SubmissionsApiSyncScopesResponse, SubmissionsApiSyncScopesStatusData, SubmissionsApiSyncScopesStatusError, SubmissionsApiSyncScopesStatusResponse } from '../types.gen'; +import { animationsApiPuzzleResults, animationsApiResults, animationsApiTopSubmissions, clockApiCurrentState, clockApiMyStats, gamesApiListEventGames, gamesApiListEventPlanning, gamesApiListEventSteamGames, gamesApiListGames, marketApiBetHistory, marketApiCloseMarket, marketApiCreateBet, marketApiGetUserPoints, marketApiListMarkets, marketApiListUserBets, marketApiResolveMarket, noitaApiGetLeaderboard, noitaApiGetResults, noitaApiSubmitLogFile, type Options, opusMagnumApiCreateSubmission, opusMagnumApiDeleteSubmission, opusMagnumApiGetCollection, opusMagnumApiGetStats, opusMagnumApiGetSubmission, opusMagnumApiListPuzzles, opusMagnumApiListResponseFiles, opusMagnumApiListResponsesNeedingValidation, opusMagnumApiListSubmissions, opusMagnumApiValidateAuto, opusMagnumApiValidateResponse, opusMagnumApiValidateSubmission, placeApiCanvas, placeApiEvolutionGif, placeApiHeatmapDecayGif, placeApiHeatmapEvolutionGif, placeApiHeatmapPng, placeApiPlacementsCsv, polylanSubmitterApiClearCache, polylanSubmitterApiGetUserInfo, polylanSubmitterApiHealthCheck, submissionsApiCreateImageCrop, submissionsApiCreateSubmission, submissionsApiDeleteImageCrop, submissionsApiGetSubmission, submissionsApiListAvailableScopes, submissionsApiListMyScopes, submissionsApiListSubmissionsByGame, submissionsApiListUserSubmissions, submissionsApiProcessCropOcr, submissionsApiProcessFileOcr, submissionsApiStopSyncScopes, submissionsApiSyncScopes, submissionsApiSyncScopesStatus } from '../sdk.gen'; +import type { AnimationsApiPuzzleResultsData, AnimationsApiPuzzleResultsResponse, AnimationsApiResultsData, AnimationsApiResultsResponse, AnimationsApiTopSubmissionsData, AnimationsApiTopSubmissionsResponse, ClockApiCurrentStateData, ClockApiCurrentStateResponse, ClockApiMyStatsData, ClockApiMyStatsResponse, GamesApiListEventGamesData, GamesApiListEventGamesResponse, GamesApiListEventPlanningData, GamesApiListEventPlanningResponse, GamesApiListEventSteamGamesData, GamesApiListEventSteamGamesResponse, GamesApiListGamesData, GamesApiListGamesResponse, MarketApiBetHistoryData, MarketApiBetHistoryResponse, MarketApiCloseMarketData, MarketApiCreateBetData, MarketApiCreateBetResponse, MarketApiGetUserPointsData, MarketApiGetUserPointsResponse, MarketApiListMarketsData, MarketApiListMarketsResponse, MarketApiListUserBetsData, MarketApiListUserBetsResponse, MarketApiResolveMarketData, MarketApiResolveMarketResponse, NoitaApiGetLeaderboardData, NoitaApiGetLeaderboardResponse, NoitaApiGetResultsData, NoitaApiGetResultsResponse, NoitaApiSubmitLogFileData, NoitaApiSubmitLogFileError, NoitaApiSubmitLogFileResponse, OpusMagnumApiCreateSubmissionData, OpusMagnumApiCreateSubmissionError, OpusMagnumApiCreateSubmissionResponse, OpusMagnumApiDeleteSubmissionData, OpusMagnumApiDeleteSubmissionError, OpusMagnumApiDeleteSubmissionResponse, OpusMagnumApiGetCollectionData, OpusMagnumApiGetCollectionResponse, OpusMagnumApiGetStatsData, OpusMagnumApiGetSubmissionData, OpusMagnumApiGetSubmissionResponse, OpusMagnumApiListPuzzlesData, OpusMagnumApiListPuzzlesResponse, OpusMagnumApiListResponseFilesData, OpusMagnumApiListResponseFilesError, OpusMagnumApiListResponseFilesResponse, OpusMagnumApiListResponsesNeedingValidationData, OpusMagnumApiListResponsesNeedingValidationError, OpusMagnumApiListResponsesNeedingValidationResponse, OpusMagnumApiListSubmissionsData, OpusMagnumApiListSubmissionsResponse, OpusMagnumApiValidateAutoData, OpusMagnumApiValidateAutoError, OpusMagnumApiValidateAutoResponse, OpusMagnumApiValidateResponseData, OpusMagnumApiValidateResponseError, OpusMagnumApiValidateResponseResponse, OpusMagnumApiValidateSubmissionData, OpusMagnumApiValidateSubmissionError, OpusMagnumApiValidateSubmissionResponse, PlaceApiCanvasData, PlaceApiEvolutionGifData, PlaceApiHeatmapDecayGifData, PlaceApiHeatmapEvolutionGifData, PlaceApiHeatmapPngData, PlaceApiPlacementsCsvData, PolylanSubmitterApiClearCacheData, PolylanSubmitterApiClearCacheError, PolylanSubmitterApiClearCacheResponse, PolylanSubmitterApiGetUserInfoData, PolylanSubmitterApiGetUserInfoResponse, PolylanSubmitterApiHealthCheckData, PolylanSubmitterApiHealthCheckResponse, SubmissionsApiCreateImageCropData, SubmissionsApiCreateImageCropError, SubmissionsApiCreateImageCropResponse, SubmissionsApiCreateSubmissionData, SubmissionsApiCreateSubmissionError, SubmissionsApiCreateSubmissionResponse, SubmissionsApiDeleteImageCropData, SubmissionsApiDeleteImageCropError, SubmissionsApiDeleteImageCropResponse, SubmissionsApiGetSubmissionData, SubmissionsApiGetSubmissionError, SubmissionsApiGetSubmissionResponse, SubmissionsApiListAvailableScopesData, SubmissionsApiListAvailableScopesError, SubmissionsApiListAvailableScopesResponse, SubmissionsApiListMyScopesData, SubmissionsApiListMyScopesError, SubmissionsApiListMyScopesResponse, SubmissionsApiListSubmissionsByGameData, SubmissionsApiListSubmissionsByGameError, SubmissionsApiListSubmissionsByGameResponse, SubmissionsApiListUserSubmissionsData, SubmissionsApiListUserSubmissionsError, SubmissionsApiListUserSubmissionsResponse, SubmissionsApiProcessCropOcrData, SubmissionsApiProcessCropOcrError, SubmissionsApiProcessCropOcrResponse, SubmissionsApiProcessFileOcrData, SubmissionsApiProcessFileOcrError, SubmissionsApiProcessFileOcrResponse, SubmissionsApiStopSyncScopesData, SubmissionsApiStopSyncScopesError, SubmissionsApiStopSyncScopesResponse, SubmissionsApiSyncScopesData, SubmissionsApiSyncScopesError, SubmissionsApiSyncScopesResponse, SubmissionsApiSyncScopesStatusData, SubmissionsApiSyncScopesStatusError, SubmissionsApiSyncScopesStatusResponse } from '../types.gen'; export type QueryKey = [ Pick & { @@ -914,6 +914,77 @@ export const placeApiEvolutionGifOptions = (options: Options) => createQueryKey('placeApiHeatmapPng', options); + +/** + * Heatmap Png + * + * Admin-only: how many times each pixel was placed, as a heatmap PNG. + * + * `players` is an optional comma-separated list of usernames to only + * count those players' placements (combined). + */ +export const placeApiHeatmapPngOptions = (options: Options) => queryOptions>({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await placeApiHeatmapPng({ + ...options, + ...queryKey[0], + signal, + throwOnError: true + }); + return data; + }, + queryKey: placeApiHeatmapPngQueryKey(options) +}); + +export const placeApiHeatmapEvolutionGifQueryKey = (options: Options) => createQueryKey('placeApiHeatmapEvolutionGif', options); + +/** + * Heatmap Evolution Gif + * + * Admin-only: the heatmap building up over time, as an animated GIF. + * + * `players` is an optional comma-separated list of usernames to only + * count those players' placements (combined). + */ +export const placeApiHeatmapEvolutionGifOptions = (options: Options) => queryOptions>({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await placeApiHeatmapEvolutionGif({ + ...options, + ...queryKey[0], + signal, + throwOnError: true + }); + return data; + }, + queryKey: placeApiHeatmapEvolutionGifQueryKey(options) +}); + +export const placeApiHeatmapDecayGifQueryKey = (options: Options) => createQueryKey('placeApiHeatmapDecayGif', options); + +/** + * Heatmap Decay Gif + * + * Admin-only: the heatmap over time, but heat decays so pixels nobody + * touches anymore fade back to white. + * + * `players` is an optional comma-separated list of usernames to only + * count those players' placements (combined). `half_life` is in + * placements, defaults to 10 frames' worth. + */ +export const placeApiHeatmapDecayGifOptions = (options: Options) => queryOptions>({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await placeApiHeatmapDecayGif({ + ...options, + ...queryKey[0], + signal, + throwOnError: true + }); + return data; + }, + queryKey: placeApiHeatmapDecayGifQueryKey(options) +}); + export const placeApiPlacementsCsvQueryKey = (options: Options) => createQueryKey('placeApiPlacementsCsv', options); /** diff --git a/polylan_submitter/src/api/index.ts b/polylan_submitter/src/api/index.ts index 88c2881..e012019 100644 --- a/polylan_submitter/src/api/index.ts +++ b/polylan_submitter/src/api/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { animationsApiPuzzleResults, animationsApiResults, animationsApiTopSubmissions, clockApiCurrentState, clockApiMyStats, gamesApiListEventGames, gamesApiListEventPlanning, gamesApiListEventSteamGames, gamesApiListGames, marketApiBetHistory, marketApiCloseMarket, marketApiCreateBet, marketApiGetUserPoints, marketApiListMarkets, marketApiListUserBets, marketApiResolveMarket, noitaApiGetLeaderboard, noitaApiGetResults, noitaApiSubmitLogFile, type Options, opusMagnumApiCreateSubmission, opusMagnumApiDeleteSubmission, opusMagnumApiGetCollection, opusMagnumApiGetStats, opusMagnumApiGetSubmission, opusMagnumApiListPuzzles, opusMagnumApiListResponseFiles, opusMagnumApiListResponsesNeedingValidation, opusMagnumApiListSubmissions, opusMagnumApiValidateAuto, opusMagnumApiValidateResponse, opusMagnumApiValidateSubmission, placeApiCanvas, placeApiEvolutionGif, placeApiPlacementsCsv, polylanSubmitterApiClearCache, polylanSubmitterApiGetUserInfo, polylanSubmitterApiHealthCheck, submissionsApiCreateImageCrop, submissionsApiCreateSubmission, submissionsApiDeleteImageCrop, submissionsApiGetSubmission, submissionsApiListAvailableScopes, submissionsApiListMyScopes, submissionsApiListSubmissionsByGame, submissionsApiListUserSubmissions, submissionsApiProcessCropOcr, submissionsApiProcessFileOcr, submissionsApiStopSyncScopes, submissionsApiSyncScopes, submissionsApiSyncScopesStatus } from './sdk.gen'; -export type { AnimationsApiPuzzleResultsData, AnimationsApiPuzzleResultsResponse, AnimationsApiPuzzleResultsResponses, AnimationsApiResultsData, AnimationsApiResultsResponse, AnimationsApiResultsResponses, AnimationsApiTopSubmissionsData, AnimationsApiTopSubmissionsResponse, AnimationsApiTopSubmissionsResponses, BetHistoryPointSchema, ClientOptions, ClockApiCurrentStateData, ClockApiCurrentStateResponse, ClockApiCurrentStateResponses, ClockApiMyStatsData, ClockApiMyStatsResponse, ClockApiMyStatsResponses, ClockStateOut, GameOut, GamesApiListEventGamesData, GamesApiListEventGamesResponse, GamesApiListEventGamesResponses, GamesApiListEventPlanningData, GamesApiListEventPlanningResponse, GamesApiListEventPlanningResponses, GamesApiListEventSteamGamesData, GamesApiListEventSteamGamesResponse, GamesApiListEventSteamGamesResponses, GamesApiListGamesData, GamesApiListGamesResponse, GamesApiListGamesResponses, ImageCropIn, ImageCropOut, Input, LeaderboardEntryOut, LeaderboardOut, MarketApiBetHistoryData, MarketApiBetHistoryResponse, MarketApiBetHistoryResponses, MarketApiCloseMarketData, MarketApiCloseMarketResponses, MarketApiCreateBetData, MarketApiCreateBetResponse, MarketApiCreateBetResponses, MarketApiGetUserPointsData, MarketApiGetUserPointsResponse, MarketApiGetUserPointsResponses, MarketApiListMarketsData, MarketApiListMarketsResponse, MarketApiListMarketsResponses, MarketApiListUserBetsData, MarketApiListUserBetsResponse, MarketApiListUserBetsResponses, MarketApiResolveMarketData, MarketApiResolveMarketResponse, MarketApiResolveMarketResponses, MarketListSchema, MarketOptionSchema, NoitaApiGetLeaderboardData, NoitaApiGetLeaderboardResponse, NoitaApiGetLeaderboardResponses, NoitaApiGetResultsData, NoitaApiGetResultsResponse, NoitaApiGetResultsResponses, NoitaApiSubmitLogFileData, NoitaApiSubmitLogFileError, NoitaApiSubmitLogFileErrors, NoitaApiSubmitLogFileResponse, NoitaApiSubmitLogFileResponses, NoitaSubmissionOut, ObjectivResultOut, OpusMagnumApiCreateSubmissionData, OpusMagnumApiCreateSubmissionError, OpusMagnumApiCreateSubmissionErrors, OpusMagnumApiCreateSubmissionResponse, OpusMagnumApiCreateSubmissionResponses, OpusMagnumApiDeleteSubmissionData, OpusMagnumApiDeleteSubmissionError, OpusMagnumApiDeleteSubmissionErrors, OpusMagnumApiDeleteSubmissionResponse, OpusMagnumApiDeleteSubmissionResponses, OpusMagnumApiGetCollectionData, OpusMagnumApiGetCollectionResponse, OpusMagnumApiGetCollectionResponses, OpusMagnumApiGetStatsData, OpusMagnumApiGetStatsResponses, OpusMagnumApiGetSubmissionData, OpusMagnumApiGetSubmissionResponse, OpusMagnumApiGetSubmissionResponses, OpusMagnumApiListPuzzlesData, OpusMagnumApiListPuzzlesResponse, OpusMagnumApiListPuzzlesResponses, OpusMagnumApiListResponseFilesData, OpusMagnumApiListResponseFilesError, OpusMagnumApiListResponseFilesErrors, OpusMagnumApiListResponseFilesResponse, OpusMagnumApiListResponseFilesResponses, OpusMagnumApiListResponsesNeedingValidationData, OpusMagnumApiListResponsesNeedingValidationError, OpusMagnumApiListResponsesNeedingValidationErrors, OpusMagnumApiListResponsesNeedingValidationResponse, OpusMagnumApiListResponsesNeedingValidationResponses, OpusMagnumApiListSubmissionsData, OpusMagnumApiListSubmissionsResponse, OpusMagnumApiListSubmissionsResponses, OpusMagnumApiValidateAutoData, OpusMagnumApiValidateAutoError, OpusMagnumApiValidateAutoErrors, OpusMagnumApiValidateAutoResponse, OpusMagnumApiValidateAutoResponses, OpusMagnumApiValidateResponseData, OpusMagnumApiValidateResponseError, OpusMagnumApiValidateResponseErrors, OpusMagnumApiValidateResponseResponse, OpusMagnumApiValidateResponseResponses, OpusMagnumApiValidateSubmissionData, OpusMagnumApiValidateSubmissionError, OpusMagnumApiValidateSubmissionErrors, OpusMagnumApiValidateSubmissionResponse, OpusMagnumApiValidateSubmissionResponses, PagedSubmissionOut, PlaceApiCanvasData, PlaceApiCanvasResponses, PlaceApiEvolutionGifData, PlaceApiEvolutionGifResponses, PlaceApiPlacementsCsvData, PlaceApiPlacementsCsvResponses, PlanningGameOut, PlanningSlotOut, PlayerStatsOut, PolylanSubmitterApiClearCacheData, PolylanSubmitterApiClearCacheError, PolylanSubmitterApiClearCacheErrors, PolylanSubmitterApiClearCacheResponse, PolylanSubmitterApiClearCacheResponses, PolylanSubmitterApiGetUserInfoData, PolylanSubmitterApiGetUserInfoResponse, PolylanSubmitterApiGetUserInfoResponses, PolylanSubmitterApiHealthCheckData, PolylanSubmitterApiHealthCheckResponse, PolylanSubmitterApiHealthCheckResponses, PuzzlePointsFactorOut, PuzzleResponseIn, PuzzleResponseOut, PuzzleResponseRankingOut, PuzzleResultsOut, PuzzleSubmissionsOut, PuzzleSubmissionWithRankOut, RankingSchema, ResolveMarketSchema, ResultsOut, ScopeOut, SteamCollectionItemOut, SteamCollectionOut, SteamGameOut, SubmissionFileOut, SubmissionIn, SubmissionOut, SubmissionsApiCreateImageCropData, SubmissionsApiCreateImageCropError, SubmissionsApiCreateImageCropErrors, SubmissionsApiCreateImageCropResponse, SubmissionsApiCreateImageCropResponses, SubmissionsApiCreateSubmissionData, SubmissionsApiCreateSubmissionError, SubmissionsApiCreateSubmissionErrors, SubmissionsApiCreateSubmissionResponse, SubmissionsApiCreateSubmissionResponses, SubmissionsApiDeleteImageCropData, SubmissionsApiDeleteImageCropError, SubmissionsApiDeleteImageCropErrors, SubmissionsApiDeleteImageCropResponse, SubmissionsApiDeleteImageCropResponses, SubmissionsApiGetSubmissionData, SubmissionsApiGetSubmissionError, SubmissionsApiGetSubmissionErrors, SubmissionsApiGetSubmissionResponse, SubmissionsApiGetSubmissionResponses, SubmissionsApiListAvailableScopesData, SubmissionsApiListAvailableScopesError, SubmissionsApiListAvailableScopesErrors, SubmissionsApiListAvailableScopesResponse, SubmissionsApiListAvailableScopesResponses, SubmissionsApiListMyScopesData, SubmissionsApiListMyScopesError, SubmissionsApiListMyScopesErrors, SubmissionsApiListMyScopesResponse, SubmissionsApiListMyScopesResponses, SubmissionsApiListSubmissionsByGameData, SubmissionsApiListSubmissionsByGameError, SubmissionsApiListSubmissionsByGameErrors, SubmissionsApiListSubmissionsByGameResponse, SubmissionsApiListSubmissionsByGameResponses, SubmissionsApiListUserSubmissionsData, SubmissionsApiListUserSubmissionsError, SubmissionsApiListUserSubmissionsErrors, SubmissionsApiListUserSubmissionsResponse, SubmissionsApiListUserSubmissionsResponses, SubmissionsApiProcessCropOcrData, SubmissionsApiProcessCropOcrError, SubmissionsApiProcessCropOcrErrors, SubmissionsApiProcessCropOcrResponse, SubmissionsApiProcessCropOcrResponses, SubmissionsApiProcessFileOcrData, SubmissionsApiProcessFileOcrError, SubmissionsApiProcessFileOcrErrors, SubmissionsApiProcessFileOcrResponse, SubmissionsApiProcessFileOcrResponses, SubmissionsApiStopSyncScopesData, SubmissionsApiStopSyncScopesError, SubmissionsApiStopSyncScopesErrors, SubmissionsApiStopSyncScopesResponse, SubmissionsApiStopSyncScopesResponses, SubmissionsApiSyncScopesData, SubmissionsApiSyncScopesError, SubmissionsApiSyncScopesErrors, SubmissionsApiSyncScopesResponse, SubmissionsApiSyncScopesResponses, SubmissionsApiSyncScopesStatusData, SubmissionsApiSyncScopesStatusError, SubmissionsApiSyncScopesStatusErrors, SubmissionsApiSyncScopesStatusResponse, SubmissionsApiSyncScopesStatusResponses, SyncScopesIn, SyncScopesOut, SyncScopesStatusOut, SyncScopesStopOut, TournamentPuzzleResultsOut, TournamentSubmissionsOut, UserBetCreateSchema, UserBetSchema, UserDisplayOut, UserInfoOut, UserPointsSchema, ValidationIn, WinnerFileOut, WinnerResponseOut } from './types.gen'; +export { animationsApiPuzzleResults, animationsApiResults, animationsApiTopSubmissions, clockApiCurrentState, clockApiMyStats, gamesApiListEventGames, gamesApiListEventPlanning, gamesApiListEventSteamGames, gamesApiListGames, marketApiBetHistory, marketApiCloseMarket, marketApiCreateBet, marketApiGetUserPoints, marketApiListMarkets, marketApiListUserBets, marketApiResolveMarket, noitaApiGetLeaderboard, noitaApiGetResults, noitaApiSubmitLogFile, type Options, opusMagnumApiCreateSubmission, opusMagnumApiDeleteSubmission, opusMagnumApiGetCollection, opusMagnumApiGetStats, opusMagnumApiGetSubmission, opusMagnumApiListPuzzles, opusMagnumApiListResponseFiles, opusMagnumApiListResponsesNeedingValidation, opusMagnumApiListSubmissions, opusMagnumApiValidateAuto, opusMagnumApiValidateResponse, opusMagnumApiValidateSubmission, placeApiCanvas, placeApiEvolutionGif, placeApiHeatmapDecayGif, placeApiHeatmapEvolutionGif, placeApiHeatmapPng, placeApiPlacementsCsv, polylanSubmitterApiClearCache, polylanSubmitterApiGetUserInfo, polylanSubmitterApiHealthCheck, submissionsApiCreateImageCrop, submissionsApiCreateSubmission, submissionsApiDeleteImageCrop, submissionsApiGetSubmission, submissionsApiListAvailableScopes, submissionsApiListMyScopes, submissionsApiListSubmissionsByGame, submissionsApiListUserSubmissions, submissionsApiProcessCropOcr, submissionsApiProcessFileOcr, submissionsApiStopSyncScopes, submissionsApiSyncScopes, submissionsApiSyncScopesStatus } from './sdk.gen'; +export type { AnimationsApiPuzzleResultsData, AnimationsApiPuzzleResultsResponse, AnimationsApiPuzzleResultsResponses, AnimationsApiResultsData, AnimationsApiResultsResponse, AnimationsApiResultsResponses, AnimationsApiTopSubmissionsData, AnimationsApiTopSubmissionsResponse, AnimationsApiTopSubmissionsResponses, BetHistoryPointSchema, ClientOptions, ClockApiCurrentStateData, ClockApiCurrentStateResponse, ClockApiCurrentStateResponses, ClockApiMyStatsData, ClockApiMyStatsResponse, ClockApiMyStatsResponses, ClockStateOut, GameOut, GamesApiListEventGamesData, GamesApiListEventGamesResponse, GamesApiListEventGamesResponses, GamesApiListEventPlanningData, GamesApiListEventPlanningResponse, GamesApiListEventPlanningResponses, GamesApiListEventSteamGamesData, GamesApiListEventSteamGamesResponse, GamesApiListEventSteamGamesResponses, GamesApiListGamesData, GamesApiListGamesResponse, GamesApiListGamesResponses, ImageCropIn, ImageCropOut, Input, LeaderboardEntryOut, LeaderboardOut, MarketApiBetHistoryData, MarketApiBetHistoryResponse, MarketApiBetHistoryResponses, MarketApiCloseMarketData, MarketApiCloseMarketResponses, MarketApiCreateBetData, MarketApiCreateBetResponse, MarketApiCreateBetResponses, MarketApiGetUserPointsData, MarketApiGetUserPointsResponse, MarketApiGetUserPointsResponses, MarketApiListMarketsData, MarketApiListMarketsResponse, MarketApiListMarketsResponses, MarketApiListUserBetsData, MarketApiListUserBetsResponse, MarketApiListUserBetsResponses, MarketApiResolveMarketData, MarketApiResolveMarketResponse, MarketApiResolveMarketResponses, MarketListSchema, MarketOptionSchema, NoitaApiGetLeaderboardData, NoitaApiGetLeaderboardResponse, NoitaApiGetLeaderboardResponses, NoitaApiGetResultsData, NoitaApiGetResultsResponse, NoitaApiGetResultsResponses, NoitaApiSubmitLogFileData, NoitaApiSubmitLogFileError, NoitaApiSubmitLogFileErrors, NoitaApiSubmitLogFileResponse, NoitaApiSubmitLogFileResponses, NoitaSubmissionOut, ObjectivResultOut, OpusMagnumApiCreateSubmissionData, OpusMagnumApiCreateSubmissionError, OpusMagnumApiCreateSubmissionErrors, OpusMagnumApiCreateSubmissionResponse, OpusMagnumApiCreateSubmissionResponses, OpusMagnumApiDeleteSubmissionData, OpusMagnumApiDeleteSubmissionError, OpusMagnumApiDeleteSubmissionErrors, OpusMagnumApiDeleteSubmissionResponse, OpusMagnumApiDeleteSubmissionResponses, OpusMagnumApiGetCollectionData, OpusMagnumApiGetCollectionResponse, OpusMagnumApiGetCollectionResponses, OpusMagnumApiGetStatsData, OpusMagnumApiGetStatsResponses, OpusMagnumApiGetSubmissionData, OpusMagnumApiGetSubmissionResponse, OpusMagnumApiGetSubmissionResponses, OpusMagnumApiListPuzzlesData, OpusMagnumApiListPuzzlesResponse, OpusMagnumApiListPuzzlesResponses, OpusMagnumApiListResponseFilesData, OpusMagnumApiListResponseFilesError, OpusMagnumApiListResponseFilesErrors, OpusMagnumApiListResponseFilesResponse, OpusMagnumApiListResponseFilesResponses, OpusMagnumApiListResponsesNeedingValidationData, OpusMagnumApiListResponsesNeedingValidationError, OpusMagnumApiListResponsesNeedingValidationErrors, OpusMagnumApiListResponsesNeedingValidationResponse, OpusMagnumApiListResponsesNeedingValidationResponses, OpusMagnumApiListSubmissionsData, OpusMagnumApiListSubmissionsResponse, OpusMagnumApiListSubmissionsResponses, OpusMagnumApiValidateAutoData, OpusMagnumApiValidateAutoError, OpusMagnumApiValidateAutoErrors, OpusMagnumApiValidateAutoResponse, OpusMagnumApiValidateAutoResponses, OpusMagnumApiValidateResponseData, OpusMagnumApiValidateResponseError, OpusMagnumApiValidateResponseErrors, OpusMagnumApiValidateResponseResponse, OpusMagnumApiValidateResponseResponses, OpusMagnumApiValidateSubmissionData, OpusMagnumApiValidateSubmissionError, OpusMagnumApiValidateSubmissionErrors, OpusMagnumApiValidateSubmissionResponse, OpusMagnumApiValidateSubmissionResponses, PagedSubmissionOut, PlaceApiCanvasData, PlaceApiCanvasResponses, PlaceApiEvolutionGifData, PlaceApiEvolutionGifResponses, PlaceApiHeatmapDecayGifData, PlaceApiHeatmapDecayGifResponses, PlaceApiHeatmapEvolutionGifData, PlaceApiHeatmapEvolutionGifResponses, PlaceApiHeatmapPngData, PlaceApiHeatmapPngResponses, PlaceApiPlacementsCsvData, PlaceApiPlacementsCsvResponses, PlanningGameOut, PlanningSlotOut, PlayerStatsOut, PolylanSubmitterApiClearCacheData, PolylanSubmitterApiClearCacheError, PolylanSubmitterApiClearCacheErrors, PolylanSubmitterApiClearCacheResponse, PolylanSubmitterApiClearCacheResponses, PolylanSubmitterApiGetUserInfoData, PolylanSubmitterApiGetUserInfoResponse, PolylanSubmitterApiGetUserInfoResponses, PolylanSubmitterApiHealthCheckData, PolylanSubmitterApiHealthCheckResponse, PolylanSubmitterApiHealthCheckResponses, PuzzlePointsFactorOut, PuzzleResponseIn, PuzzleResponseOut, PuzzleResponseRankingOut, PuzzleResultsOut, PuzzleSubmissionsOut, PuzzleSubmissionWithRankOut, RankingSchema, ResolveMarketSchema, ResultsOut, ScopeOut, SteamCollectionItemOut, SteamCollectionOut, SteamGameOut, SubmissionFileOut, SubmissionIn, SubmissionOut, SubmissionsApiCreateImageCropData, SubmissionsApiCreateImageCropError, SubmissionsApiCreateImageCropErrors, SubmissionsApiCreateImageCropResponse, SubmissionsApiCreateImageCropResponses, SubmissionsApiCreateSubmissionData, SubmissionsApiCreateSubmissionError, SubmissionsApiCreateSubmissionErrors, SubmissionsApiCreateSubmissionResponse, SubmissionsApiCreateSubmissionResponses, SubmissionsApiDeleteImageCropData, SubmissionsApiDeleteImageCropError, SubmissionsApiDeleteImageCropErrors, SubmissionsApiDeleteImageCropResponse, SubmissionsApiDeleteImageCropResponses, SubmissionsApiGetSubmissionData, SubmissionsApiGetSubmissionError, SubmissionsApiGetSubmissionErrors, SubmissionsApiGetSubmissionResponse, SubmissionsApiGetSubmissionResponses, SubmissionsApiListAvailableScopesData, SubmissionsApiListAvailableScopesError, SubmissionsApiListAvailableScopesErrors, SubmissionsApiListAvailableScopesResponse, SubmissionsApiListAvailableScopesResponses, SubmissionsApiListMyScopesData, SubmissionsApiListMyScopesError, SubmissionsApiListMyScopesErrors, SubmissionsApiListMyScopesResponse, SubmissionsApiListMyScopesResponses, SubmissionsApiListSubmissionsByGameData, SubmissionsApiListSubmissionsByGameError, SubmissionsApiListSubmissionsByGameErrors, SubmissionsApiListSubmissionsByGameResponse, SubmissionsApiListSubmissionsByGameResponses, SubmissionsApiListUserSubmissionsData, SubmissionsApiListUserSubmissionsError, SubmissionsApiListUserSubmissionsErrors, SubmissionsApiListUserSubmissionsResponse, SubmissionsApiListUserSubmissionsResponses, SubmissionsApiProcessCropOcrData, SubmissionsApiProcessCropOcrError, SubmissionsApiProcessCropOcrErrors, SubmissionsApiProcessCropOcrResponse, SubmissionsApiProcessCropOcrResponses, SubmissionsApiProcessFileOcrData, SubmissionsApiProcessFileOcrError, SubmissionsApiProcessFileOcrErrors, SubmissionsApiProcessFileOcrResponse, SubmissionsApiProcessFileOcrResponses, SubmissionsApiStopSyncScopesData, SubmissionsApiStopSyncScopesError, SubmissionsApiStopSyncScopesErrors, SubmissionsApiStopSyncScopesResponse, SubmissionsApiStopSyncScopesResponses, SubmissionsApiSyncScopesData, SubmissionsApiSyncScopesError, SubmissionsApiSyncScopesErrors, SubmissionsApiSyncScopesResponse, SubmissionsApiSyncScopesResponses, SubmissionsApiSyncScopesStatusData, SubmissionsApiSyncScopesStatusError, SubmissionsApiSyncScopesStatusErrors, SubmissionsApiSyncScopesStatusResponse, SubmissionsApiSyncScopesStatusResponses, SyncScopesIn, SyncScopesOut, SyncScopesStatusOut, SyncScopesStopOut, TournamentPuzzleResultsOut, TournamentSubmissionsOut, UserBetCreateSchema, UserBetSchema, UserDisplayOut, UserInfoOut, UserPointsSchema, ValidationIn, WinnerFileOut, WinnerResponseOut } from './types.gen'; diff --git a/polylan_submitter/src/api/sdk.gen.ts b/polylan_submitter/src/api/sdk.gen.ts index 4bae6ad..4184021 100644 --- a/polylan_submitter/src/api/sdk.gen.ts +++ b/polylan_submitter/src/api/sdk.gen.ts @@ -2,7 +2,7 @@ import { type Client, formDataBodySerializer, type Options as Options2, type TDataShape } from './client'; import { client } from './client.gen'; -import type { AnimationsApiPuzzleResultsData, AnimationsApiPuzzleResultsResponses, AnimationsApiResultsData, AnimationsApiResultsResponses, AnimationsApiTopSubmissionsData, AnimationsApiTopSubmissionsResponses, ClockApiCurrentStateData, ClockApiCurrentStateResponses, ClockApiMyStatsData, ClockApiMyStatsResponses, GamesApiListEventGamesData, GamesApiListEventGamesResponses, GamesApiListEventPlanningData, GamesApiListEventPlanningResponses, GamesApiListEventSteamGamesData, GamesApiListEventSteamGamesResponses, GamesApiListGamesData, GamesApiListGamesResponses, MarketApiBetHistoryData, MarketApiBetHistoryResponses, MarketApiCloseMarketData, MarketApiCloseMarketResponses, MarketApiCreateBetData, MarketApiCreateBetResponses, MarketApiGetUserPointsData, MarketApiGetUserPointsResponses, MarketApiListMarketsData, MarketApiListMarketsResponses, MarketApiListUserBetsData, MarketApiListUserBetsResponses, MarketApiResolveMarketData, MarketApiResolveMarketResponses, NoitaApiGetLeaderboardData, NoitaApiGetLeaderboardResponses, NoitaApiGetResultsData, NoitaApiGetResultsResponses, NoitaApiSubmitLogFileData, NoitaApiSubmitLogFileErrors, NoitaApiSubmitLogFileResponses, OpusMagnumApiCreateSubmissionData, OpusMagnumApiCreateSubmissionErrors, OpusMagnumApiCreateSubmissionResponses, OpusMagnumApiDeleteSubmissionData, OpusMagnumApiDeleteSubmissionErrors, OpusMagnumApiDeleteSubmissionResponses, OpusMagnumApiGetCollectionData, OpusMagnumApiGetCollectionResponses, OpusMagnumApiGetStatsData, OpusMagnumApiGetStatsResponses, OpusMagnumApiGetSubmissionData, OpusMagnumApiGetSubmissionResponses, OpusMagnumApiListPuzzlesData, OpusMagnumApiListPuzzlesResponses, OpusMagnumApiListResponseFilesData, OpusMagnumApiListResponseFilesErrors, OpusMagnumApiListResponseFilesResponses, OpusMagnumApiListResponsesNeedingValidationData, OpusMagnumApiListResponsesNeedingValidationErrors, OpusMagnumApiListResponsesNeedingValidationResponses, OpusMagnumApiListSubmissionsData, OpusMagnumApiListSubmissionsResponses, OpusMagnumApiValidateAutoData, OpusMagnumApiValidateAutoErrors, OpusMagnumApiValidateAutoResponses, OpusMagnumApiValidateResponseData, OpusMagnumApiValidateResponseErrors, OpusMagnumApiValidateResponseResponses, OpusMagnumApiValidateSubmissionData, OpusMagnumApiValidateSubmissionErrors, OpusMagnumApiValidateSubmissionResponses, PlaceApiCanvasData, PlaceApiCanvasResponses, PlaceApiEvolutionGifData, PlaceApiEvolutionGifResponses, PlaceApiPlacementsCsvData, PlaceApiPlacementsCsvResponses, PolylanSubmitterApiClearCacheData, PolylanSubmitterApiClearCacheErrors, PolylanSubmitterApiClearCacheResponses, PolylanSubmitterApiGetUserInfoData, PolylanSubmitterApiGetUserInfoResponses, PolylanSubmitterApiHealthCheckData, PolylanSubmitterApiHealthCheckResponses, SubmissionsApiCreateImageCropData, SubmissionsApiCreateImageCropErrors, SubmissionsApiCreateImageCropResponses, SubmissionsApiCreateSubmissionData, SubmissionsApiCreateSubmissionErrors, SubmissionsApiCreateSubmissionResponses, SubmissionsApiDeleteImageCropData, SubmissionsApiDeleteImageCropErrors, SubmissionsApiDeleteImageCropResponses, SubmissionsApiGetSubmissionData, SubmissionsApiGetSubmissionErrors, SubmissionsApiGetSubmissionResponses, SubmissionsApiListAvailableScopesData, SubmissionsApiListAvailableScopesErrors, SubmissionsApiListAvailableScopesResponses, SubmissionsApiListMyScopesData, SubmissionsApiListMyScopesErrors, SubmissionsApiListMyScopesResponses, SubmissionsApiListSubmissionsByGameData, SubmissionsApiListSubmissionsByGameErrors, SubmissionsApiListSubmissionsByGameResponses, SubmissionsApiListUserSubmissionsData, SubmissionsApiListUserSubmissionsErrors, SubmissionsApiListUserSubmissionsResponses, SubmissionsApiProcessCropOcrData, SubmissionsApiProcessCropOcrErrors, SubmissionsApiProcessCropOcrResponses, SubmissionsApiProcessFileOcrData, SubmissionsApiProcessFileOcrErrors, SubmissionsApiProcessFileOcrResponses, SubmissionsApiStopSyncScopesData, SubmissionsApiStopSyncScopesErrors, SubmissionsApiStopSyncScopesResponses, SubmissionsApiSyncScopesData, SubmissionsApiSyncScopesErrors, SubmissionsApiSyncScopesResponses, SubmissionsApiSyncScopesStatusData, SubmissionsApiSyncScopesStatusErrors, SubmissionsApiSyncScopesStatusResponses } from './types.gen'; +import type { AnimationsApiPuzzleResultsData, AnimationsApiPuzzleResultsResponses, AnimationsApiResultsData, AnimationsApiResultsResponses, AnimationsApiTopSubmissionsData, AnimationsApiTopSubmissionsResponses, ClockApiCurrentStateData, ClockApiCurrentStateResponses, ClockApiMyStatsData, ClockApiMyStatsResponses, GamesApiListEventGamesData, GamesApiListEventGamesResponses, GamesApiListEventPlanningData, GamesApiListEventPlanningResponses, GamesApiListEventSteamGamesData, GamesApiListEventSteamGamesResponses, GamesApiListGamesData, GamesApiListGamesResponses, MarketApiBetHistoryData, MarketApiBetHistoryResponses, MarketApiCloseMarketData, MarketApiCloseMarketResponses, MarketApiCreateBetData, MarketApiCreateBetResponses, MarketApiGetUserPointsData, MarketApiGetUserPointsResponses, MarketApiListMarketsData, MarketApiListMarketsResponses, MarketApiListUserBetsData, MarketApiListUserBetsResponses, MarketApiResolveMarketData, MarketApiResolveMarketResponses, NoitaApiGetLeaderboardData, NoitaApiGetLeaderboardResponses, NoitaApiGetResultsData, NoitaApiGetResultsResponses, NoitaApiSubmitLogFileData, NoitaApiSubmitLogFileErrors, NoitaApiSubmitLogFileResponses, OpusMagnumApiCreateSubmissionData, OpusMagnumApiCreateSubmissionErrors, OpusMagnumApiCreateSubmissionResponses, OpusMagnumApiDeleteSubmissionData, OpusMagnumApiDeleteSubmissionErrors, OpusMagnumApiDeleteSubmissionResponses, OpusMagnumApiGetCollectionData, OpusMagnumApiGetCollectionResponses, OpusMagnumApiGetStatsData, OpusMagnumApiGetStatsResponses, OpusMagnumApiGetSubmissionData, OpusMagnumApiGetSubmissionResponses, OpusMagnumApiListPuzzlesData, OpusMagnumApiListPuzzlesResponses, OpusMagnumApiListResponseFilesData, OpusMagnumApiListResponseFilesErrors, OpusMagnumApiListResponseFilesResponses, OpusMagnumApiListResponsesNeedingValidationData, OpusMagnumApiListResponsesNeedingValidationErrors, OpusMagnumApiListResponsesNeedingValidationResponses, OpusMagnumApiListSubmissionsData, OpusMagnumApiListSubmissionsResponses, OpusMagnumApiValidateAutoData, OpusMagnumApiValidateAutoErrors, OpusMagnumApiValidateAutoResponses, OpusMagnumApiValidateResponseData, OpusMagnumApiValidateResponseErrors, OpusMagnumApiValidateResponseResponses, OpusMagnumApiValidateSubmissionData, OpusMagnumApiValidateSubmissionErrors, OpusMagnumApiValidateSubmissionResponses, PlaceApiCanvasData, PlaceApiCanvasResponses, PlaceApiEvolutionGifData, PlaceApiEvolutionGifResponses, PlaceApiHeatmapDecayGifData, PlaceApiHeatmapDecayGifResponses, PlaceApiHeatmapEvolutionGifData, PlaceApiHeatmapEvolutionGifResponses, PlaceApiHeatmapPngData, PlaceApiHeatmapPngResponses, PlaceApiPlacementsCsvData, PlaceApiPlacementsCsvResponses, PolylanSubmitterApiClearCacheData, PolylanSubmitterApiClearCacheErrors, PolylanSubmitterApiClearCacheResponses, PolylanSubmitterApiGetUserInfoData, PolylanSubmitterApiGetUserInfoResponses, PolylanSubmitterApiHealthCheckData, PolylanSubmitterApiHealthCheckResponses, SubmissionsApiCreateImageCropData, SubmissionsApiCreateImageCropErrors, SubmissionsApiCreateImageCropResponses, SubmissionsApiCreateSubmissionData, SubmissionsApiCreateSubmissionErrors, SubmissionsApiCreateSubmissionResponses, SubmissionsApiDeleteImageCropData, SubmissionsApiDeleteImageCropErrors, SubmissionsApiDeleteImageCropResponses, SubmissionsApiGetSubmissionData, SubmissionsApiGetSubmissionErrors, SubmissionsApiGetSubmissionResponses, SubmissionsApiListAvailableScopesData, SubmissionsApiListAvailableScopesErrors, SubmissionsApiListAvailableScopesResponses, SubmissionsApiListMyScopesData, SubmissionsApiListMyScopesErrors, SubmissionsApiListMyScopesResponses, SubmissionsApiListSubmissionsByGameData, SubmissionsApiListSubmissionsByGameErrors, SubmissionsApiListSubmissionsByGameResponses, SubmissionsApiListUserSubmissionsData, SubmissionsApiListUserSubmissionsErrors, SubmissionsApiListUserSubmissionsResponses, SubmissionsApiProcessCropOcrData, SubmissionsApiProcessCropOcrErrors, SubmissionsApiProcessCropOcrResponses, SubmissionsApiProcessFileOcrData, SubmissionsApiProcessFileOcrErrors, SubmissionsApiProcessFileOcrResponses, SubmissionsApiStopSyncScopesData, SubmissionsApiStopSyncScopesErrors, SubmissionsApiStopSyncScopesResponses, SubmissionsApiSyncScopesData, SubmissionsApiSyncScopesErrors, SubmissionsApiSyncScopesResponses, SubmissionsApiSyncScopesStatusData, SubmissionsApiSyncScopesStatusErrors, SubmissionsApiSyncScopesStatusResponses } from './types.gen'; export type Options = Options2 & { /** @@ -356,6 +356,62 @@ export const placeApiEvolutionGif = (optio ...options }); +/** + * Heatmap Png + * + * Admin-only: how many times each pixel was placed, as a heatmap PNG. + * + * `players` is an optional comma-separated list of usernames to only + * count those players' placements (combined). + */ +export const placeApiHeatmapPng = (options: Options) => (options.client ?? client).get({ + security: [{ + in: 'cookie', + name: 'sessionid', + type: 'apiKey' + }], + url: '/api/events/{event_path}/place/heatmap.png', + ...options +}); + +/** + * Heatmap Evolution Gif + * + * Admin-only: the heatmap building up over time, as an animated GIF. + * + * `players` is an optional comma-separated list of usernames to only + * count those players' placements (combined). + */ +export const placeApiHeatmapEvolutionGif = (options: Options) => (options.client ?? client).get({ + security: [{ + in: 'cookie', + name: 'sessionid', + type: 'apiKey' + }], + url: '/api/events/{event_path}/place/heatmap-evolution.gif', + ...options +}); + +/** + * Heatmap Decay Gif + * + * Admin-only: the heatmap over time, but heat decays so pixels nobody + * touches anymore fade back to white. + * + * `players` is an optional comma-separated list of usernames to only + * count those players' placements (combined). `half_life` is in + * placements, defaults to 10 frames' worth. + */ +export const placeApiHeatmapDecayGif = (options: Options) => (options.client ?? client).get({ + security: [{ + in: 'cookie', + name: 'sessionid', + type: 'apiKey' + }], + url: '/api/events/{event_path}/place/heatmap-decay.gif', + ...options +}); + /** * Placements Csv * diff --git a/polylan_submitter/src/api/types.gen.ts b/polylan_submitter/src/api/types.gen.ts index 04fcd7f..90e67d0 100644 --- a/polylan_submitter/src/api/types.gen.ts +++ b/polylan_submitter/src/api/types.gen.ts @@ -2743,6 +2743,82 @@ export type PlaceApiEvolutionGifResponses = { 200: unknown; }; +export type PlaceApiHeatmapPngData = { + body?: never; + path: { + /** + * Event Path + */ + event_path: string; + }; + query?: { + /** + * Players + */ + players?: string; + }; + url: '/api/events/{event_path}/place/heatmap.png'; +}; + +export type PlaceApiHeatmapPngResponses = { + /** + * OK + */ + 200: unknown; +}; + +export type PlaceApiHeatmapEvolutionGifData = { + body?: never; + path: { + /** + * Event Path + */ + event_path: string; + }; + query?: { + /** + * Players + */ + players?: string; + }; + url: '/api/events/{event_path}/place/heatmap-evolution.gif'; +}; + +export type PlaceApiHeatmapEvolutionGifResponses = { + /** + * OK + */ + 200: unknown; +}; + +export type PlaceApiHeatmapDecayGifData = { + body?: never; + path: { + /** + * Event Path + */ + event_path: string; + }; + query?: { + /** + * Players + */ + players?: string; + /** + * Half Life + */ + half_life?: number | null; + }; + url: '/api/events/{event_path}/place/heatmap-decay.gif'; +}; + +export type PlaceApiHeatmapDecayGifResponses = { + /** + * OK + */ + 200: unknown; +}; + export type PlaceApiPlacementsCsvData = { body?: never; path: {