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>> = {
pl_PL: {
@ -14,7 +14,7 @@ const t = (s: string) => {
export type DialogTableColumn<T> = {
header: string;
accessor: (row: T) => string;
accessor: (row: T, index: number, rows: T[]) => string;
};
export class DialogTable<T> {
@ -74,10 +74,10 @@ export class DialogTable<T> {
</tr>
${data
.map(
(r) => `
(r, index) => `
<tr>
${this.columns
.map((col) => `<td>${col.accessor(r)}</td>`)
.map((col) => `<td>${col.accessor(r, index, data)}</td>`)
.join('')}
</tr>
`

View File

@ -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<string, Record<string, string>> = {
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<ListResult<TribeChange>>;
playerEnnoblements(
page: number,
limit: number
): Promise<ListResult<Ennoblement>>;
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
? `<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) {

View File

@ -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<T> = {
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<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'),
};
}
}