Skip to content

Commit

Permalink
try adding indices; add complex query
Browse files Browse the repository at this point in the history
  • Loading branch information
bananahampster committed Feb 24, 2024
1 parent d3f48f4 commit 4248b74
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/beta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,5 @@ jobs:
cp -rfL ~/hampalyzer/frontend/* -t /var/www/beta.hampalyzer.com/html
cp -rf ~/hampalyzer/parsedlogs/assets/ -t /var/www/beta.hampalyzer.com/html/
cd ~/hampalyzer/dist
pm2 restart hampalyzer -- server parsedlogs /var/www/beta.hampalyzer.com/html --reparse
pm2 restart hampalyzer -- server parsedlogs /var/www/beta.hampalyzer.com/html
7 changes: 7 additions & 0 deletions db-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ CREATE TABLE event (
ON DELETE NO ACTION
);

CREATE INDEX idx_event_logid on event (logid)
CREATE INDEX idx_event_playerfrom on event(playerFrom);
CREATE INDEX idx_event_playerto on event(playerTo);
CREATE INDEX idx_event_eventtype on event(eventType);

PLAYER table (table is new)

Expand Down Expand Up @@ -89,6 +93,9 @@ CREATE TABLE match (
ON DELETE NO ACTION
);

CREATE INDEX idx_match_logid ON match (logid)


LOGS table (* are new columns)

| name | type | values | notes |
Expand Down
12 changes: 11 additions & 1 deletion src/App.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,17 @@ class App {
if (isNaN(page_num))
page_num = 1;

this.database.getLogs(page_num);
try {
const result = await this.database.getLogs(page_num);
res.status(200).json(result);
}
catch (e: any) {
const error = e as ParsingError;
if (error.name)
res.status(500).json({ error: `${error.name}: ${error.message}`});
else
res.status(500).json({ error: e });
}
});

this.express.use('/', router);
Expand Down
148 changes: 146 additions & 2 deletions src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ export class DB {
}

/** Gets a list of logs, limited to a 20-log limit */
public async getLogs(pageNumber = 1): Promise<any[]> {
return await this.query<any>(
public async getLogs(pageNumber = 1): Promise<MatchMetadata[]> {
return await this.query<MatchMetadata>(
'SELECT * FROM logs ORDER BY date_parsed DESC LIMIT $1 OFFSET (($2 - 1) * $1)',
DB.PAGE_SIZE,
pageNumber
Expand Down Expand Up @@ -178,6 +178,34 @@ export class DB {
return true;
}

public async defenseTkDamage(filters: EventFilters = {}): Promise<PlayerDamage[]> {
const query = `
SELECT p.alias
, COUNT(DISTINCT m.logid) as num_games
, SUM((e.extraData::json->>'value')::integer) / COUNT(DISTINCT m.logid) as dmg
FROM event as e
JOIN logs as g
ON g.id = e.logid
JOIN match as m
ON m.logid = e.logid
AND m.playerid = e.playerTo
JOIN match as m2
ON m2.logid = e.logid
AND m2.playerid = e.playerFrom
JOIN player as p
ON p.id = e.playerFrom
WHERE ((m2.team = 2 AND e.isFirstLog = true) OR (m2.team = 1 AND e.isFirstLog = false))
AND e.eventType = 64
AND m2.team = m.team
AND e.playerFrom <> e.playerTo
AND g.server = 'Inhouse'
AND g.num_players >= 8
GROUP BY e.playerFrom, p.alias
ORDER BY dmg DESC`;

return this.query(query)
}

private async ensurePlayers(client: pg.PoolClient, playerLists: PlayerList[]): Promise<Record<string, number>> {
let players: Player[] = [];
for (const playerList of playerLists)
Expand Down Expand Up @@ -299,6 +327,94 @@ export class DB {
]
)
}

static readonly defaultFilters: EventFilters = {
logValid: true,
logMinPlayers: 8,
};
private addFilters(matchFilters: EventFilters): EventFilterResult {
matchFilters = { ...DB.defaultFilters, ...matchFilters };
const keys = Object.keys(matchFilters) as EventFilterTypes[];

let filterString = "";
let filterParams: any[] = [];
let paramIndex = 0;

for (const filter of keys) {
const filterValue = matchFilters[filter];
if (filterValue != null) {
switch (filter) {
case 'logValid':
filterString += `g.is_valid = $${paramIndex}`;
filterParams[paramIndex++] = filterValue;
break;
case 'logMap':
filterString += `g.map = $${paramIndex}`;
filterParams[paramIndex++] = filterValue;
break;
case 'logMinPlayers':
filterString += `g.num_players = $${paramIndex}`;
filterParams[paramIndex++] = filterValue;
break;
case 'logServer':
filterString += `g.server = $${paramIndex}`;
filterParams[paramIndex++] = filterValue;
break;
case 'eventPlayerFrom':
filterString += `e.playerFrom = $${paramIndex}`;
filterParams[paramIndex++] = filterValue;
break;
case 'eventPlayerTo':
filterString += `e.playerTo = $${paramIndex}`;
filterParams[paramIndex++] = filterValue;
break;
case 'eventClassFrom':
filterString += `e.playerFromClass = $${paramIndex}`;
filterParams[paramIndex++] = filterValue;
break;
case 'eventClassTo':
filterString += `e.playerToClass = $${paramIndex}`;
filterParams[paramIndex++] = filterValue;
break;
case 'eventAgainstSelf':
filterString += 'e.playerTo = e.playerFrom';
break;
case 'eventPlayerFromBlue':
if (filterValue)
filterString = '((m2.team = 1 AND e.isFirstLog = true) OR (m2.team = 2 AND e.isFirstLog = false))';
else
filterString = '((m2.team = 2 AND e.isFirstLog = true) OR (m2.team = 1 AND e.isFirstLog = false))';
break;
case 'eventPlayerToBlue':
if (filterValue)
filterString = '((m.team = 1 AND e.isFirstLog = true) OR (m.team = 2 AND e.isFirstLog = false))';
else
filterString = '((m.team = 2 AND e.isFirstLog = true) OR (m.team = 1 AND e.isFirstLog = false))';
break;
case 'matchAgainstEnemy':
filterString += 'm2.team <> m.team';
break;
case 'matchAgainstTeammate':
filterString += 'm2.team = m.team';
break;
default:
// compiler assertion: all cases handled:
const badFilter: never = filter;
throw new ParsingError({
name: 'LOGIC_FAILURE',
message: `unknown filter key/value: ${badFilter} / ${filterValue}`,
});
}

filterString += ' ';
}
}

return {
whereClause: filterString,
params: filterParams,
}
}
}

export interface ReparseMetadata {
Expand All @@ -317,3 +433,31 @@ export interface MatchMetadata {
num_players: number | undefined;
score: TeamScore;
}

export interface PlayerDamage {
alias: string;
num_games: number,
dmg: number,
}

export interface EventFilters {
logValid?: boolean;
logMinPlayers?: number;
logMap?: string;
logServer?: string;
eventPlayerFrom?: number;
eventPlayerTo?: number;
eventClassFrom?: number;
eventClassTo?: number;
eventPlayerFromBlue?: boolean;
eventPlayerToBlue?: boolean;
matchAgainstEnemy?: boolean;
matchAgainstTeammate?: boolean;
eventAgainstSelf?: boolean;
}
type EventFilterTypes = keyof EventFilters;

export interface EventFilterResult {
whereClause: string;
params: any[];
}

0 comments on commit 4248b74

Please sign in to comment.