From b687c5aa0fcb1291755b9bd3d18330b89a21a0cc Mon Sep 17 00:00:00 2001 From: Natalie Rose Date: Tue, 18 Aug 2026 18:58:58 +1000 Subject: [PATCH] Add Stats module --- src/spec/paths.ts | 2 + src/spec/paths/stats.ts | 411 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 413 insertions(+) create mode 100644 src/spec/paths/stats.ts diff --git a/src/spec/paths.ts b/src/spec/paths.ts index 0d3ff04..72e4e33 100644 --- a/src/spec/paths.ts +++ b/src/spec/paths.ts @@ -111,6 +111,7 @@ import { spaceJunkPark } from './paths/buildings/spacejunkpark.ts'; import { spacePort } from './paths/buildings/spaceport.ts'; import { spaceStationLab } from './paths/buildings/spacestationlab.ts'; import { stationCommand } from './paths/modules/stationcommand.ts'; +import { stats } from './paths/stats.ts'; import { stockpile } from './paths/buildings/stockpile.ts'; import { subspaceSupplyDepot } from './paths/buildings/subspacesupplydepot.ts'; import { supplyPod } from './paths/buildings/supplypod.ts'; @@ -252,6 +253,7 @@ export const paths = { ...spacePort, ...spaceStationLab, ...stationCommand, + ...stats, ...stockpile, ...subspaceSupplyDepot, ...supplyPod, diff --git a/src/spec/paths/stats.ts b/src/spec/paths/stats.ts new file mode 100644 index 0000000..540b0e1 --- /dev/null +++ b/src/spec/paths/stats.ts @@ -0,0 +1,411 @@ +import { requestBodySchema, response200, response500, security, statusSchema } from '../chunks.ts'; + +const ALLIANCE_SORT_BY = [ + 'average_empire_size_rank', + 'offense_success_rate_rank', + 'defense_success_rate_rank', + 'dirtiest_rank', +]; + +const EMPIRE_SORT_BY = [ + 'empire_size_rank', + 'offense_success_rate_rank', + 'defense_success_rate_rank', + 'dirtiest_rank', +]; + +const COLONY_SORT_BY = ['population_rank']; + +const SPY_SORT_BY = ['level_rank', 'success_rate_rank', 'dirtiest_rank']; + +const pageNumberSchema = { + type: 'integer', + description: + "Optional. 25 records per page. Defaults to the page containing the current user's own rank.", +}; + +const allianceRankEntrySchema = { + type: 'object', + required: [ + 'alliance_id', + 'alliance_name', + 'member_count', + 'space_station_count', + 'influence', + 'colony_count', + 'population', + 'average_empire_size', + 'building_count', + 'average_building_level', + 'offense_success_rate', + 'defense_success_rate', + 'dirtiest', + ], + properties: { + alliance_id: { type: 'string' }, + alliance_name: { type: 'string' }, + member_count: { type: 'integer' }, + space_station_count: { type: 'integer' }, + influence: { type: 'integer' }, + colony_count: { type: 'integer' }, + population: { type: 'integer' }, + average_empire_size: { type: 'number' }, + building_count: { type: 'integer' }, + average_building_level: { type: 'number' }, + offense_success_rate: { type: 'number' }, + defense_success_rate: { type: 'number' }, + dirtiest: { type: 'integer' }, + }, +}; + +const empireRankEntrySchema = { + type: 'object', + required: [ + 'empire_id', + 'empire_name', + 'alliance_id', + 'alliance_name', + 'colony_count', + 'population', + 'empire_size', + 'building_count', + 'average_building_level', + 'offense_success_rate', + 'defense_success_rate', + 'dirtiest', + ], + properties: { + empire_id: { type: 'string' }, + empire_name: { type: 'string' }, + // Always present, but null when the empire is not in an alliance. + alliance_id: { type: ['string', 'null'] }, + alliance_name: { type: ['string', 'null'] }, + colony_count: { type: 'integer' }, + population: { type: 'integer' }, + empire_size: { type: 'integer' }, + building_count: { type: 'integer' }, + average_building_level: { type: 'number' }, + offense_success_rate: { type: 'number' }, + defense_success_rate: { type: 'number' }, + dirtiest: { type: 'integer' }, + }, +}; + +const colonyRankEntrySchema = { + type: 'object', + required: [ + 'empire_id', + 'empire_name', + 'planet_id', + 'planet_name', + 'population', + 'building_count', + 'average_building_level', + 'highest_building_level', + ], + properties: { + empire_id: { type: 'string' }, + empire_name: { type: 'string' }, + planet_id: { type: 'string' }, + planet_name: { type: 'string' }, + population: { type: 'integer' }, + building_count: { type: 'integer' }, + average_building_level: { type: 'number' }, + highest_building_level: { type: 'integer' }, + }, +}; + +const spyRankEntrySchema = { + type: 'object', + required: [ + 'empire_id', + 'empire_name', + 'spy_id', + 'spy_name', + 'age', + 'level', + 'success_rate', + 'dirtiest', + ], + properties: { + empire_id: { type: 'string' }, + empire_name: { type: 'string' }, + spy_id: { type: 'string' }, + spy_name: { type: 'string' }, + age: { type: 'integer' }, + level: { type: 'integer' }, + success_rate: { type: 'number' }, + dirtiest: { type: 'integer' }, + }, +}; + +const medalWinnerSchema = { + type: 'object', + required: ['empire_id', 'empire_name', 'medal_name', 'medal_image', 'times_earned'], + properties: { + empire_id: { type: 'string' }, + empire_name: { type: 'string' }, + medal_name: { type: 'string' }, + medal_image: { type: 'string' }, + times_earned: { type: 'integer' }, + }, +}; + +export const stats = { + '/v2/stats/credits': { + post: { + ...security(), + + responses: { + ...response200( + 'Retrieves the list of game credits. Each entry names a single contribution category and the people who worked on it.', + { + type: 'array', + items: { + type: 'object', + description: 'Keyed by contribution category, e.g. "Game Server" or "Play Testers".', + additionalProperties: { type: 'array', items: { type: 'string' } }, + }, + } + ), + ...response500(), + }, + }, + }, + + '/v2/stats/alliance_rank': { + post: { + ...security(), + + ...requestBodySchema({ + type: 'object', + properties: { + sort_by: { + type: 'string', + enum: ALLIANCE_SORT_BY, + description: 'Optional. Defaults to average_empire_size_rank.', + }, + page_number: pageNumberSchema, + }, + }), + + responses: { + ...response200('Returns a sorted list of alliances ranked by various statistics.', { + type: 'object', + required: ['alliances', 'total_alliances', 'page_number', 'status'], + properties: { + alliances: { type: 'array', items: allianceRankEntrySchema }, + total_alliances: { type: 'integer' }, + page_number: { type: 'integer' }, + status: statusSchema(), + }, + }), + ...response500(), + }, + }, + }, + + '/v2/stats/find_alliance_rank': { + post: { + ...security(), + + ...requestBodySchema({ + type: 'object', + required: ['sort_by', 'alliance_name'], + properties: { + sort_by: { + type: 'string', + enum: ALLIANCE_SORT_BY, + description: 'Determines which ranking the returned page numbers refer to.', + }, + alliance_name: { + type: 'string', + description: 'Full or partial name. Must be at least 3 characters.', + }, + }, + }), + + responses: { + ...response200( + 'Searches for a particular alliance within the alliance rankings, returning the page of the alliance_rank listing each match appears on.', + { + type: 'object', + required: ['alliances', 'status'], + properties: { + alliances: { + type: 'array', + items: { + type: 'object', + required: ['alliance_id', 'alliance_name', 'page_number'], + properties: { + alliance_id: { type: 'string' }, + alliance_name: { type: 'string' }, + page_number: { type: 'integer' }, + }, + }, + }, + status: statusSchema(), + }, + } + ), + ...response500(), + }, + }, + }, + + '/v2/stats/empire_rank': { + post: { + ...security(), + + ...requestBodySchema({ + type: 'object', + properties: { + sort_by: { + type: 'string', + enum: EMPIRE_SORT_BY, + description: 'Optional. Defaults to empire_size_rank.', + }, + page_number: pageNumberSchema, + }, + }), + + responses: { + ...response200('Returns a sorted list of empires ranked by various statistics.', { + type: 'object', + required: ['empires', 'total_empires', 'page_number', 'status'], + properties: { + empires: { type: 'array', items: empireRankEntrySchema }, + total_empires: { type: 'integer' }, + page_number: { type: 'integer' }, + status: statusSchema(), + }, + }), + ...response500(), + }, + }, + }, + + '/v2/stats/find_empire_rank': { + post: { + ...security(), + + ...requestBodySchema({ + type: 'object', + required: ['sort_by', 'empire_name'], + properties: { + sort_by: { + type: 'string', + enum: EMPIRE_SORT_BY, + description: 'Determines which ranking the returned page numbers refer to.', + }, + empire_name: { + type: 'string', + description: 'Full or partial name. Must be at least 3 characters.', + }, + }, + }), + + responses: { + ...response200( + 'Searches for a particular empire within the empire rankings, returning the page of the empire_rank listing each match appears on.', + { + type: 'object', + required: ['empires', 'status'], + properties: { + empires: { + type: 'array', + items: { + type: 'object', + required: ['empire_id', 'empire_name', 'page_number'], + properties: { + empire_id: { type: 'string' }, + empire_name: { type: 'string' }, + page_number: { type: 'integer' }, + }, + }, + }, + status: statusSchema(), + }, + } + ), + ...response500(), + }, + }, + }, + + '/v2/stats/colony_rank': { + post: { + ...security(), + + ...requestBodySchema({ + type: 'object', + properties: { + sort_by: { + type: 'string', + enum: COLONY_SORT_BY, + description: 'Optional. Defaults to population_rank.', + }, + }, + }), + + responses: { + ...response200('Returns a sorted list of planets ranked by various statistics.', { + type: 'object', + required: ['colonies', 'status'], + properties: { + colonies: { type: 'array', items: colonyRankEntrySchema }, + status: statusSchema(), + }, + }), + ...response500(), + }, + }, + }, + + '/v2/stats/spy_rank': { + post: { + ...security(), + + ...requestBodySchema({ + type: 'object', + properties: { + sort_by: { + type: 'string', + enum: SPY_SORT_BY, + description: 'Optional. Defaults to level_rank.', + }, + }, + }), + + responses: { + ...response200('Returns a sorted list of the top spies ranked by various statistics.', { + type: 'object', + required: ['spies', 'status'], + properties: { + spies: { type: 'array', items: spyRankEntrySchema }, + status: statusSchema(), + }, + }), + ...response500(), + }, + }, + }, + + '/v2/stats/weekly_medal_winners': { + post: { + ...security(), + + responses: { + ...response200("Returns the list of empires who won this week's weekly medals.", { + type: 'object', + required: ['winners', 'status'], + properties: { + winners: { type: 'array', items: medalWinnerSchema }, + status: statusSchema(), + }, + }), + ...response500(), + }, + }, + }, +}; -- 2.51.2