From 29ae462b1f928eb61dfc6a219148ddc0bbcd04e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Wysoki=C5=84ski?= Date: Wed, 18 Jan 2023 07:46:16 +0100 Subject: [PATCH] feat: extended player profile --- src/extendedPlayerProfile.ts | 229 +++++++++++++++++++++++++++++------ src/lib/client.ts | 60 ++++++++- 2 files changed, 250 insertions(+), 39 deletions(-) diff --git a/src/extendedPlayerProfile.ts b/src/extendedPlayerProfile.ts index 4cbe21b..41d5df1 100644 --- a/src/extendedPlayerProfile.ts +++ b/src/extendedPlayerProfile.ts @@ -1,41 +1,74 @@ // Extended player profile -import { Player, TWHelpClient } from './lib/client'; +import { ListResult, Player, TribeChange, TWHelpClient } from './lib/client'; const SCREEN = 'info_player'; +const MODE = null; const translations: Record> = { - pl_PL: {}, + pl_PL: { + 'Joined at': 'Dołączył o', + 'Last activity at': 'Ostatnio aktywny o', + 'Best rank': 'Najlepszy ranking', + 'Most points': 'Najwięcej punktów', + 'Most villages': 'Najwięcej wiosek', + 'Show tribe changes': 'Pokaż zmiany plemion', + 'Show history': 'Pokaż historię', + 'Show ennoblements': 'Pokaż przejęcia', + 'Fetching data': 'Pobieranie danych', + 'Old tribe': 'Stare plemię', + 'New tribe': 'Nowe plemię', + 'Date/time': 'Data/czas', + }, }; const t = (s: string) => { return translations[window.game_data.locale]?.[s] ?? s; }; -const getPlayerId = () => { - const str = new URLSearchParams(window.location.search).get('id'); - if (!str) { - return window.game_data.player.id; - } - return parseInt(str); -}; +class TWHelpConnector { + constructor( + private readonly client: TWHelpClient, + private readonly version: string, + private readonly server: string, + private readonly id: number + ) {} -class ExtendedPlayerProfile { - constructor(private readonly client: TWHelpClient) {} - - async render() { - const player = await this.client.player( - window.game_data.market, - window.game_data.world, - getPlayerId() - ); - console.log(player); - - this.renderAdditionalInfo(player); - this.renderActions(player); + player() { + return this.client.player(this.version, this.server, this.id); } - private renderAdditionalInfo(player: Player) { + tribeChanges(page: number, limit: number) { + return this.client.tribeChanges(this.version, this.server, this.id, { + offset: (page - 1) * limit, + limit: limit, + sort: ['createdAt:desc', 'id:asc'], + }); + } +} + +interface UIConnector { + tribeChanges(page: number, limit: number): Promise>; +} + +enum DialogId { + TRIBE_CHANGES_LOADING = 'kichiyaki_tribe_changes_loading', + TRIBE_CHANGES = 'kichiyaki_tribe_changes', +} + +class UI { + private static readonly TRIBE_CHANGES_LIMIT = 30; + constructor( + private readonly player: Player, + private readonly connector: UIConnector + ) {} + + public render() { + this.renderAdditionalInfo(); + this.renderActions(); + } + + private renderAdditionalInfo() { const tbody = document.querySelector('#player_info tbody'); if (!(tbody instanceof HTMLTableSectionElement)) { return; @@ -46,35 +79,35 @@ class ExtendedPlayerProfile { ` ${t('Joined at')}: - ${new Date(player.createdAt).toLocaleString()} + ${new Date(this.player.createdAt).toLocaleString()} ${t('Last activity at')}: - ${new Date(player.lastActivityAt).toLocaleString()} + ${new Date(this.player.lastActivityAt).toLocaleString()} ${t('Best rank')}: - ${player.bestRank} (${new Date( - player.bestRankAt + ${this.player.bestRank} (${new Date( + this.player.bestRankAt ).toLocaleString()}) ${t('Most points')}: - ${player.mostPoints.toLocaleString()} (${new Date( - player.mostPointsAt + ${this.player.mostPoints.toLocaleString()} (${new Date( + this.player.mostPointsAt ).toLocaleString()}) ${t('Most villages')}: - ${player.mostVillages.toLocaleString()} (${new Date( - player.mostVillagesAt + ${this.player.mostVillages.toLocaleString()} (${new Date( + this.player.mostVillagesAt ).toLocaleString()}) ` ); } - private renderActions(player: Player) { + private renderActions() { const tbody = document .querySelector('#content_value a[href*="twstats"]') ?.closest('tbody'); @@ -83,26 +116,146 @@ class ExtendedPlayerProfile { } [ - { name: t('Show tribe changes') }, - { name: t('Show history') }, - { name: t('Show ennoblements') }, - ].forEach(({ name }) => { + { + name: t('Show tribe changes'), + handler: this.showTribeChanges.bind(this), + }, + { name: t('Show history'), handler: this.showHistory.bind(this) }, + { + name: t('Show ennoblements'), + handler: this.showEnnoblements.bind(this), + }, + ].forEach(({ name, handler }) => { const tr = document.createElement('tr'); const td = document.createElement('td'); td.colSpan = 2; const a = document.createElement('a'); a.innerText = name; a.href = '#'; - a.setAttribute('data-player-id', player.id.toString()); + a.addEventListener('click', handler); + a.setAttribute('data-player-id', this.player.id.toString()); td.appendChild(a); tr.appendChild(td); tbody.appendChild(tr); }); } + + private async showTribeChanges(e: Event) { + e.preventDefault(); + + await this._showTribeChanges(1); + } + + private async _showTribeChanges(page: number) { + window.Dialog.show( + DialogId.TRIBE_CHANGES_LOADING, + `

${t('Fetching data')}...

` + ); + + const tcs = await this.connector.tribeChanges(page, UI.TRIBE_CHANGES_LIMIT); + + const maxPage = Math.ceil(tcs.total / UI.TRIBE_CHANGES_LIMIT); + const pageOpts = []; + for (let i = 1; i <= (page > maxPage ? page : maxPage); i++) { + pageOpts.push( + `${i}` + ); + } + + const selectId = `${DialogId.TRIBE_CHANGES}_page`; + + window.Dialog.show( + DialogId.TRIBE_CHANGES, + ` +
+ +
+ + + + + + + + ${tcs.data + .map( + (tc) => ` + + + + + + ` + ) + .join('')} + +
${t('Old tribe')}${t('New tribe')}${t('Date/time')}
${ + tc.player.tribe + ? `${tc.player.tribe.tag}` + : '-' + }${ + tc.newTribe + ? `${tc.newTribe.tag}` + : '-' + }${new Date(tc.createdAt).toLocaleString()}
+ ` + ); + + document + .querySelector('#' + selectId) + ?.addEventListener('change', (e: Event) => { + console.log(e.currentTarget); + if (!(e.currentTarget instanceof HTMLSelectElement)) { + return; + } + + this._showTribeChanges(parseInt(e.currentTarget.value)); + }); + } + + private showHistory(e: Event) { + e.preventDefault(); + } + + private showEnnoblements(e: Event) { + e.preventDefault(); + } +} + +class ExtendedPlayerProfile { + connector: TWHelpConnector; + constructor(client: TWHelpClient) { + this.connector = new TWHelpConnector( + client, + window.game_data.market, + window.game_data.world, + this.getPlayerId() + ); + } + + async render() { + const player = await this.connector.player(); + new UI(player, this.connector).render(); + } + + private getPlayerId() { + const str = new URLSearchParams(window.location.search).get('id'); + if (!str) { + return window.game_data.player.id; + } + return parseInt(str); + } } (async () => { - if (window.game_data.screen !== SCREEN || window.game_data.mode) { + if (window.game_data.screen !== SCREEN || window.game_data.mode !== MODE) { return; } diff --git a/src/lib/client.ts b/src/lib/client.ts index 5ee1654..571bd32 100644 --- a/src/lib/client.ts +++ b/src/lib/client.ts @@ -1,7 +1,7 @@ import axios, { AxiosInstance } from 'axios'; const DEFAULT_TIMEOUT = 10000; -const X_TOTAL_COUNT_HEADER = 'X-Total-Count'; +const X_TOTAL_COUNT_HEADER = 'x-total-count'; export type Version = { code: string; @@ -22,11 +22,38 @@ export type Player = { createdAt: string; }; +export type TribeMeta = { + id: number; + name: string; + tag: string; + profileUrl: string; +}; + +export type PlayerMeta = { + id: number; + name: string; + profileUrl: string; + tribe: TribeMeta | null; +}; + +export type TribeChange = { + id: number; + newTribe: TribeMeta | null; + player: PlayerMeta; + createdAt: string; +}; + export type ListResult = { data: T[]; total: number; }; +export type ListTribeChangesQueryParams = { + offset?: number; + limit?: number; + sort?: string[]; +}; + export type TWHelpClientOptions = { timeout?: number; }; @@ -59,4 +86,35 @@ export class TWHelpClient { ); return resp.data.data; } + + public async tribeChanges( + version: string, + server: string, + id: number, + queryParams?: ListTribeChangesQueryParams + ): 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}/tribe-changes?${params.toString()}` + ); + return { + data: resp.data.data, + total: parseInt(resp.headers[X_TOTAL_COUNT_HEADER] ?? '0'), + }; + } }