diff --git a/src/common/DialogTable.ts b/src/common/DialogTable.ts index 4a255ba..9d79527 100644 --- a/src/common/DialogTable.ts +++ b/src/common/DialogTable.ts @@ -1,4 +1,4 @@ -import { ListResult } from '../lib/client'; +import { ListResult } from '../lib/twhelp'; const translations: Record> = { pl_PL: { @@ -14,7 +14,7 @@ const t = (s: string) => { export type DialogTableColumn = { header: string; - accessor: (row: T) => string; + accessor: (row: T, index: number, rows: T[]) => string; }; export class DialogTable { @@ -74,10 +74,10 @@ export class DialogTable { ${data .map( - (r) => ` + (r, index) => ` ${this.columns - .map((col) => `${col.accessor(r)}`) + .map((col) => `${col.accessor(r, index, data)}`) .join('')} ` diff --git a/src/extendedPlayerProfile.ts b/src/extendedPlayerProfile.ts index 8267bb0..7b4f29a 100644 --- a/src/extendedPlayerProfile.ts +++ b/src/extendedPlayerProfile.ts @@ -1,12 +1,6 @@ // Extended player profile -import { - Ennoblement, - ListResult, - Player, - TribeChange, - TWHelpClient, -} from './lib/client'; +import { Player, TWHelpClient } from './lib/twhelp'; import { DialogTable } from './common/DialogTable'; import { buildURL } from './lib/twstats'; @@ -37,6 +31,13 @@ const translations: Record> = { Deleted: 'Usunięty', Yes: 'Tak', No: 'Nie', + Date: 'Data', + Tribe: 'Plemię', + Villages: 'Wioski', + OD: 'Pokonani ogólny', + ODA: 'Pokonani agresor', + ODD: 'Pokonani obrońca', + ODS: 'Pokonani wspierający', }, }; @@ -71,29 +72,27 @@ class TWHelpConnector { sort: ['createdAt:desc'], }); } + + playerHistory(page: number, limit: number) { + return this.client.playerHistory(this.version, this.server, this.id, { + offset: (page - 1) * limit, + limit: limit, + sort: ['date:desc'], + }); + } } enum DialogId { OTHER_SERVERS = 'kichiyaki_other_servers', TRIBE_CHANGES = 'kichiyaki_tribe_changes', ENNOBLEMENTS = 'kichiyaki_ennoblements', -} - -interface UIConnector { - playerTribeChanges( - page: number, - limit: number - ): Promise>; - playerEnnoblements( - page: number, - limit: number - ): Promise>; + HISTORY = 'kichiyaki_history', } class UI { constructor( private readonly player: Player, - private readonly connector: UIConnector + private readonly connector: TWHelpConnector ) {} public render() { @@ -242,8 +241,60 @@ class UI { ).render(); } - private showHistory(e: Event) { + private async showHistory(e: Event) { e.preventDefault(); + + await new DialogTable( + DialogId.HISTORY, + [ + { + header: t('Date'), + accessor: (s) => s.date, + }, + { + header: t('Tribe'), + accessor: (s) => + s.tribe + ? `${s.tribe.tag}` + : '-', + }, + { + header: t('Points'), + accessor: (s) => + `${s.points.toLocaleString()} (${s.rank})`, + }, + { + header: t('Villages'), + accessor: (s) => `${s.numVillages.toLocaleString()}`, + }, + { + header: t('OD'), + accessor: (s) => + `${s.scoreTotal.toLocaleString()} (${ + s.rankTotal + })`, + }, + { + header: t('ODA'), + accessor: (s) => + `${s.scoreAtt.toLocaleString()} (${s.rankAtt})`, + }, + { + header: t('ODD'), + accessor: (s) => + `${s.scoreDef.toLocaleString()} (${s.rankDef})`, + }, + { + header: t('ODS'), + accessor: (s) => + `${s.scoreSup.toLocaleString()} (${s.rankSup})`, + }, + ], + 30, + (page: number, limit: number) => { + return this.connector.playerHistory(page, limit); + } + ).render(); } private async showEnnoblements(e: Event) { diff --git a/src/lib/client.ts b/src/lib/twhelp.ts similarity index 75% rename from src/lib/client.ts rename to src/lib/twhelp.ts index 5807e99..3cad5b7 100644 --- a/src/lib/client.ts +++ b/src/lib/twhelp.ts @@ -67,6 +67,23 @@ export type Ennoblement = { createdAt: string; }; +export type PlayerSnapshot = { + id: number; + tribe: TribeMeta | null; + points: number; + numVillages: number; + rank: number; + rankAtt: number; + rankDef: number; + rankSup: number; + rankTotal: number; + scoreAtt: number; + scoreDef: number; + scoreSup: number; + scoreTotal: number; + date: string; +}; + export type ListResult = { data: T[]; total: number; @@ -84,6 +101,12 @@ export type ListEnnoblementsParams = { sort?: string[]; }; +export type ListPlayerSnapshotsParams = { + offset?: number; + limit?: number; + sort?: string[]; +}; + export type TWHelpClientOptions = { timeout?: number; }; @@ -178,4 +201,35 @@ export class TWHelpClient { total: parseInt(resp.headers[X_TOTAL_COUNT_HEADER] ?? '0'), }; } + + public async playerHistory( + version: string, + server: string, + id: number, + queryParams?: ListPlayerSnapshotsParams + ): Promise> { + const params = new URLSearchParams(); + + if (queryParams?.limit) { + params.set('limit', queryParams.limit.toString()); + } + + if (queryParams?.offset) { + params.set('offset', queryParams.offset.toString()); + } + + if (Array.isArray(queryParams?.sort)) { + queryParams?.sort.forEach((s) => { + params.append('sort', s); + }); + } + + const resp = await this.client.get( + `/api/v1/versions/${version}/servers/${server}/players/${id}/history?${params.toString()}` + ); + return { + data: resp.data.data, + total: parseInt(resp.headers[X_TOTAL_COUNT_HEADER] ?? '0'), + }; + } }