feat: extended player profile

This commit is contained in:
Dawid Wysokiński 2023-01-19 13:57:11 +01:00
parent 4b0dbabf02
commit 89f71f319d
Signed by: Kichiyaki
GPG Key ID: B5445E357FB8B892
3 changed files with 129 additions and 24 deletions

View File

@ -1,4 +1,4 @@
import { ListResult } from '../lib/client'; import { ListResult } from '../lib/twhelp';
const translations: Record<string, Record<string, string>> = { const translations: Record<string, Record<string, string>> = {
pl_PL: { pl_PL: {
@ -14,7 +14,7 @@ const t = (s: string) => {
export type DialogTableColumn<T> = { export type DialogTableColumn<T> = {
header: string; header: string;
accessor: (row: T) => string; accessor: (row: T, index: number, rows: T[]) => string;
}; };
export class DialogTable<T> { export class DialogTable<T> {
@ -74,10 +74,10 @@ export class DialogTable<T> {
</tr> </tr>
${data ${data
.map( .map(
(r) => ` (r, index) => `
<tr> <tr>
${this.columns ${this.columns
.map((col) => `<td>${col.accessor(r)}</td>`) .map((col) => `<td>${col.accessor(r, index, data)}</td>`)
.join('')} .join('')}
</tr> </tr>
` `

View File

@ -1,12 +1,6 @@
// Extended player profile // Extended player profile
import { import { Player, TWHelpClient } from './lib/twhelp';
Ennoblement,
ListResult,
Player,
TribeChange,
TWHelpClient,
} from './lib/client';
import { DialogTable } from './common/DialogTable'; import { DialogTable } from './common/DialogTable';
import { buildURL } from './lib/twstats'; import { buildURL } from './lib/twstats';
@ -37,6 +31,13 @@ const translations: Record<string, Record<string, string>> = {
Deleted: 'Usunięty', Deleted: 'Usunięty',
Yes: 'Tak', Yes: 'Tak',
No: 'Nie', 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'], 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 { enum DialogId {
OTHER_SERVERS = 'kichiyaki_other_servers', OTHER_SERVERS = 'kichiyaki_other_servers',
TRIBE_CHANGES = 'kichiyaki_tribe_changes', TRIBE_CHANGES = 'kichiyaki_tribe_changes',
ENNOBLEMENTS = 'kichiyaki_ennoblements', ENNOBLEMENTS = 'kichiyaki_ennoblements',
} HISTORY = 'kichiyaki_history',
interface UIConnector {
playerTribeChanges(
page: number,
limit: number
): Promise<ListResult<TribeChange>>;
playerEnnoblements(
page: number,
limit: number
): Promise<ListResult<Ennoblement>>;
} }
class UI { class UI {
constructor( constructor(
private readonly player: Player, private readonly player: Player,
private readonly connector: UIConnector private readonly connector: TWHelpConnector
) {} ) {}
public render() { public render() {
@ -242,8 +241,60 @@ class UI {
).render(); ).render();
} }
private showHistory(e: Event) { private async showHistory(e: Event) {
e.preventDefault(); e.preventDefault();
await new DialogTable(
DialogId.HISTORY,
[
{
header: t('Date'),
accessor: (s) => s.date,
},
{
header: t('Tribe'),
accessor: (s) =>
s.tribe
? `<a href="${s.tribe.profileUrl}">${s.tribe.tag}</a>`
: '-',
},
{
header: t('Points'),
accessor: (s) =>
`${s.points.toLocaleString()} (<strong>${s.rank}</strong>)`,
},
{
header: t('Villages'),
accessor: (s) => `${s.numVillages.toLocaleString()}`,
},
{
header: t('OD'),
accessor: (s) =>
`${s.scoreTotal.toLocaleString()} (<strong>${
s.rankTotal
}</strong>)`,
},
{
header: t('ODA'),
accessor: (s) =>
`${s.scoreAtt.toLocaleString()} (<strong>${s.rankAtt}</strong>)`,
},
{
header: t('ODD'),
accessor: (s) =>
`${s.scoreDef.toLocaleString()} (<strong>${s.rankDef}</strong>)`,
},
{
header: t('ODS'),
accessor: (s) =>
`${s.scoreSup.toLocaleString()} (<strong>${s.rankSup}</strong>)`,
},
],
30,
(page: number, limit: number) => {
return this.connector.playerHistory(page, limit);
}
).render();
} }
private async showEnnoblements(e: Event) { private async showEnnoblements(e: Event) {

View File

@ -67,6 +67,23 @@ export type Ennoblement = {
createdAt: string; 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<T> = { export type ListResult<T> = {
data: T[]; data: T[];
total: number; total: number;
@ -84,6 +101,12 @@ export type ListEnnoblementsParams = {
sort?: string[]; sort?: string[];
}; };
export type ListPlayerSnapshotsParams = {
offset?: number;
limit?: number;
sort?: string[];
};
export type TWHelpClientOptions = { export type TWHelpClientOptions = {
timeout?: number; timeout?: number;
}; };
@ -178,4 +201,35 @@ export class TWHelpClient {
total: parseInt(resp.headers[X_TOTAL_COUNT_HEADER] ?? '0'), total: parseInt(resp.headers[X_TOTAL_COUNT_HEADER] ?? '0'),
}; };
} }
public async playerHistory(
version: string,
server: string,
id: number,
queryParams?: ListPlayerSnapshotsParams
): Promise<ListResult<PlayerSnapshot>> {
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'),
};
}
} }