feat: add filter by season back

This commit is contained in:
Valentin Kaelin 2022-01-08 00:16:49 +01:00
parent 72cbc916bc
commit 80534a5ca3
3 changed files with 125 additions and 62 deletions

View file

@ -15,6 +15,19 @@ import SummonerOverviewValidator from 'App/Validators/SummonerOverviewValidator'
import SummonerRecordValidator from 'App/Validators/SummonerRecordValidator' import SummonerRecordValidator from 'App/Validators/SummonerRecordValidator'
export default class SummonersController { export default class SummonersController {
/**
* Get all played seasons for a summoner
* @param puuid of the summoner
*/
private async getSeasons(puuid: string): Promise<number[]> {
const seasons = await MatchRepository.seasons(puuid)
return seasons.length ? seasons.map((s) => s.season) : [getCurrentSeason()]
}
/**
* POST: get basic summoner data
* @param ctx
*/
public async basic({ request, response }: HttpContextContract) { public async basic({ request, response }: HttpContextContract) {
console.time('BASIC_REQUEST') console.time('BASIC_REQUEST')
const { summoner, region } = await request.validate(SummonerBasicValidator) const { summoner, region } = await request.validate(SummonerBasicValidator)
@ -39,7 +52,7 @@ export default class SummonersController {
// All seasons the summoner has played // All seasons the summoner has played
// TODO: check if there is a way to do that with V5... // TODO: check if there is a way to do that with V5...
finalJSON.seasons = [getCurrentSeason()] finalJSON.seasons = await this.getSeasons(account.puuid)
// CURRENT GAME // CURRENT GAME
console.time('playing') console.time('playing')
@ -65,6 +78,10 @@ export default class SummonersController {
return response.json(finalJSON) return response.json(finalJSON)
} }
/**
* POST: get overview view summoner data
* @param ctx
*/
public async overview({ request, response }: HttpContextContract) { public async overview({ request, response }: HttpContextContract) {
console.time('OVERVIEW_REQUEST') console.time('OVERVIEW_REQUEST')
const { puuid, region, season } = await request.validate(SummonerOverviewValidator) const { puuid, region, season } = await request.validate(SummonerOverviewValidator)
@ -74,12 +91,13 @@ export default class SummonersController {
const summonerDB = await Summoner.firstOrCreate({ puuid: puuid }) const summonerDB = await Summoner.firstOrCreate({ puuid: puuid })
// MATCHES BASIC // MATCHES BASIC
const matchlist = await summonerDB const matchListQuery = summonerDB.related('matchList').query().select('matchId')
.related('matchList') if (season) {
.query() matchListQuery
.select('matchId') .join('matches', 'summoner_matchlist.match_id', 'matches.id')
.orderBy('matchId', 'desc') .where('matches.season', season)
.limit(10) }
const matchlist = await matchListQuery.orderBy('matchId', 'desc').limit(10)
const matchIds = matchlist.map((m) => m.matchId) const matchIds = matchlist.map((m) => m.matchId)
finalJSON.matchesDetails = await MatchService.getMatches(region, matchIds, puuid) finalJSON.matchesDetails = await MatchService.getMatches(region, matchIds, puuid)
@ -117,7 +135,7 @@ export default class SummonersController {
public async records({ request, response }: HttpContextContract) { public async records({ request, response }: HttpContextContract) {
console.time('recordsRequest') console.time('recordsRequest')
const { puuid, season } = await request.validate(SummonerRecordValidator) const { puuid, season } = await request.validate(SummonerRecordValidator)
const records = await MatchRepository.records(puuid) const records = await MatchRepository.records(puuid, season)
const recordsSerialized = records.map((record) => { const recordsSerialized = records.map((record) => {
return { return {
...record, ...record,

View file

@ -1,16 +1,44 @@
import Database from '@ioc:Adonis/Lucid/Database' import Database from '@ioc:Adonis/Lucid/Database'
export interface SelectFilters {
puuid: string
season?: number
limit?: number
queue?: number
}
class MatchRepository { class MatchRepository {
private readonly JOIN_MATCHES = 'INNER JOIN matches ON matches.id = match_players.match_id' private readonly JOIN_MATCHES = 'INNER JOIN matches ON matches.id = match_players.match_id'
private readonly JOIN_TEAMS = private readonly JOIN_TEAMS =
'INNER JOIN match_teams ON match_players.match_id = match_teams.match_id AND match_players.team = match_teams.color' 'INNER JOIN match_teams ON match_players.match_id = match_teams.match_id AND match_players.team = match_teams.color'
private readonly JOIN_ALL = `${this.JOIN_MATCHES} ${this.JOIN_TEAMS}` private readonly JOIN_ALL = `${this.JOIN_MATCHES} ${this.JOIN_TEAMS}`
private readonly GLOBAL_FILTERS = ` private globalFilters(filters: SelectFilters) {
let query = `
match_players.summoner_puuid = :puuid match_players.summoner_puuid = :puuid
AND match_players.remake = 0 AND match_players.remake = 0
AND matches.gamemode NOT IN (800, 810, 820, 830, 840, 850, 2000, 2010, 2020) AND matches.gamemode NOT IN (800, 810, 820, 830, 840, 850, 2000, 2010, 2020)
` `
if (filters.season) query += ' AND matches.season = :season '
if (filters.queue) query += ' AND matches.gamemode = :queue '
return query
}
public async seasons(puuid: string) {
const query = `
SELECT DISTINCT
matches.season
FROM
match_players
${this.JOIN_MATCHES}
WHERE
match_players.summoner_puuid = :puuid
`
const { rows } = await Database.rawQuery(query, { puuid })
return rows
}
public async recentActivity(puuid: string) { public async recentActivity(puuid: string) {
const query = ` const query = `
@ -32,7 +60,7 @@ class MatchRepository {
return rows return rows
} }
public async globalStats(puuid: string) { public async globalStats(filters: SelectFilters) {
const query = ` const query = `
SELECT SELECT
SUM(match_players.kills) as kills, SUM(match_players.kills) as kills,
@ -49,15 +77,16 @@ class MatchRepository {
match_players match_players
${this.JOIN_MATCHES} ${this.JOIN_MATCHES}
WHERE WHERE
${this.GLOBAL_FILTERS} ${this.globalFilters(filters)}
LIMIT LIMIT
1 1
` `
const { rows } = await Database.rawQuery(query, { puuid })
const { rows } = await Database.rawQuery(query, filters as any)
return rows[0] return rows[0]
} }
public async gamemodeStats(puuid: string) { public async gamemodeStats(filters: SelectFilters) {
const query = ` const query = `
SELECT SELECT
matches.gamemode as id, matches.gamemode as id,
@ -68,17 +97,18 @@ class MatchRepository {
match_players match_players
${this.JOIN_MATCHES} ${this.JOIN_MATCHES}
WHERE WHERE
${this.GLOBAL_FILTERS} ${this.globalFilters(filters)}
GROUP BY GROUP BY
matches.gamemode matches.gamemode
ORDER BY ORDER BY
count DESC count DESC
` `
const { rows } = await Database.rawQuery(query, { puuid })
const { rows } = await Database.rawQuery(query, filters as any)
return rows return rows
} }
public async roleStats(puuid: string) { public async roleStats(filters: SelectFilters) {
const query = ` const query = `
SELECT SELECT
match_players.team_position as role, match_players.team_position as role,
@ -89,16 +119,17 @@ class MatchRepository {
match_players match_players
${this.JOIN_MATCHES} ${this.JOIN_MATCHES}
WHERE WHERE
${this.GLOBAL_FILTERS} ${this.globalFilters(filters)}
AND match_players.team_position != 0 AND match_players.team_position != 0
GROUP BY GROUP BY
role role
` `
const { rows } = await Database.rawQuery(query, { puuid })
const { rows } = await Database.rawQuery(query, filters as any)
return rows return rows
} }
public async championStats(puuid: string, limit: number) { public async championStats(filters: SelectFilters) {
const query = ` const query = `
SELECT SELECT
match_players.champion_id as id, match_players.champion_id as id,
@ -112,7 +143,7 @@ class MatchRepository {
match_players match_players
${this.JOIN_MATCHES} ${this.JOIN_MATCHES}
WHERE WHERE
${this.GLOBAL_FILTERS} ${this.globalFilters(filters)}
GROUP BY GROUP BY
match_players.champion_id match_players.champion_id
ORDER BY ORDER BY
@ -120,11 +151,12 @@ class MatchRepository {
LIMIT LIMIT
:limit :limit
` `
const { rows } = await Database.rawQuery(query, { puuid, limit })
const { rows } = await Database.rawQuery(query, filters as any)
return rows return rows
} }
public async championClassStats(puuid: string) { public async championClassStats(filters: SelectFilters) {
const query = ` const query = `
SELECT SELECT
match_players.champion_role as id, match_players.champion_role as id,
@ -135,17 +167,49 @@ class MatchRepository {
match_players match_players
${this.JOIN_MATCHES} ${this.JOIN_MATCHES}
WHERE WHERE
${this.GLOBAL_FILTERS} ${this.globalFilters(filters)}
GROUP BY GROUP BY
match_players.champion_role match_players.champion_role
ORDER BY ORDER BY
count DESC count DESC
` `
const { rows } = await Database.rawQuery(query, { puuid })
const { rows } = await Database.rawQuery(query, filters as any)
return rows return rows
} }
public async mates(filters: SelectFilters) {
const query = `
SELECT
(array_agg(mates.summoner_name ORDER BY mates.match_id DESC))[1] as name,
COUNT(match_players.id) as count,
SUM(match_players.win) as wins,
SUM(match_players.loss) as losses
FROM
match_players
${this.JOIN_ALL}
INNER JOIN match_players as mates ON match_players.match_id = mates.match_id AND match_players.team = mates.team
WHERE
${this.globalFilters(filters)}
GROUP BY
mates.summoner_puuid
ORDER BY
count DESC, wins DESC
LIMIT
15
`
const { rows } = await Database.rawQuery(query, filters as any)
// Remove the Summoner himself + unique game mates
return rows.splice(1).filter((row) => row.count > 1)
}
public async championCompleteStats(puuid: string, queue?: number, season?: number) { public async championCompleteStats(puuid: string, queue?: number, season?: number) {
const filters: SelectFilters = { puuid }
if (queue) filters.queue = queue
if (season) filters.season = season
const query = ` const query = `
SELECT SELECT
match_players.champion_id as id, match_players.champion_id as id,
@ -166,43 +230,21 @@ class MatchRepository {
match_players match_players
${this.JOIN_MATCHES} ${this.JOIN_MATCHES}
WHERE WHERE
${this.GLOBAL_FILTERS} ${this.globalFilters(filters)}
GROUP BY GROUP BY
match_players.champion_id match_players.champion_id
ORDER BY ORDER BY
count DESC, match_players.champion_id count DESC, match_players.champion_id
` `
const { rows } = await Database.rawQuery(query, { puuid })
const { rows } = await Database.rawQuery(query, filters as any)
return rows return rows
} }
public async mates(puuid: string) { public async records(puuid: string, season?: number) {
const query = ` const filters: SelectFilters = { puuid }
SELECT if (season) filters.season = season
(array_agg(mates.summoner_name ORDER BY mates.match_id DESC))[1] as name,
COUNT(match_players.id) as count,
SUM(match_players.win) as wins,
SUM(match_players.loss) as losses
FROM
match_players
${this.JOIN_ALL}
INNER JOIN match_players as mates ON match_players.match_id = mates.match_id AND match_players.team = mates.team
WHERE
${this.GLOBAL_FILTERS}
GROUP BY
mates.summoner_puuid
ORDER BY
count DESC, wins DESC
LIMIT
15
`
const { rows } = await Database.rawQuery(query, { puuid })
// Remove the Summoner himself + unique game mates
return rows.splice(1).filter((row) => row.count > 1)
}
public async records(puuid: string) {
const fields = [ const fields = [
'match_players.kills', 'match_players.kills',
'match_players.deaths', 'match_players.deaths',
@ -242,7 +284,7 @@ class MatchRepository {
match_players match_players
${this.JOIN_MATCHES} ${this.JOIN_MATCHES}
WHERE WHERE
${this.GLOBAL_FILTERS} ${this.globalFilters(filters)}
ORDER BY ORDER BY
${field} DESC, matches.id ${field} DESC, matches.id
LIMIT LIMIT
@ -251,7 +293,7 @@ class MatchRepository {
}) })
.join('UNION ALL ') .join('UNION ALL ')
const { rows } = await Database.rawQuery(query, { puuid }) const { rows } = await Database.rawQuery(query, filters as any)
return rows return rows
} }
} }

View file

@ -1,6 +1,6 @@
import { sortTeamByRole } from 'App/helpers' import { sortTeamByRole } from 'App/helpers'
import { ChampionRoles, TeamPosition } from 'App/Parsers/ParsedType' import { ChampionRoles, TeamPosition } from 'App/Parsers/ParsedType'
import MatchRepository from 'App/Repositories/MatchRepository' import MatchRepository, { SelectFilters } from 'App/Repositories/MatchRepository'
import BasicMatchSerializer from 'App/Serializers/BasicMatchSerializer' import BasicMatchSerializer from 'App/Serializers/BasicMatchSerializer'
class StatsService { class StatsService {
@ -11,14 +11,17 @@ class StatsService {
return recentActivity return recentActivity
} }
public async getSummonerStats(puuid: string, season?: number) { public async getSummonerStats(puuid: string, season?: number) {
const filters: SelectFilters = { puuid }
if (season) filters.season = season
console.time('GLOBAL') console.time('GLOBAL')
const globalStats = await MatchRepository.globalStats(puuid) const globalStats = await MatchRepository.globalStats(filters)
console.timeEnd('GLOBAL') console.timeEnd('GLOBAL')
console.time('GAMEMODE') console.time('GAMEMODE')
const gamemodeStats = await MatchRepository.gamemodeStats(puuid) const gamemodeStats = await MatchRepository.gamemodeStats(filters)
console.timeEnd('GAMEMODE') console.timeEnd('GAMEMODE')
console.time('ROLE') console.time('ROLE')
const roleStats = await MatchRepository.roleStats(puuid) const roleStats = await MatchRepository.roleStats(filters)
// Check if all roles are in the array // Check if all roles are in the array
const roles = ['TOP', 'JUNGLE', 'MIDDLE', 'BOTTOM', 'UTILITY'] const roles = ['TOP', 'JUNGLE', 'MIDDLE', 'BOTTOM', 'UTILITY']
for (const role of roles) { for (const role of roles) {
@ -36,19 +39,19 @@ class StatsService {
} }
console.timeEnd('ROLE') console.timeEnd('ROLE')
console.time('CHAMPION') console.time('CHAMPION')
const championStats = await MatchRepository.championStats(puuid, 5) const championStats = await MatchRepository.championStats({ ...filters, limit: 5 })
for (const champ of championStats) { for (const champ of championStats) {
champ.champion = BasicMatchSerializer.getChampion(champ.id) champ.champion = BasicMatchSerializer.getChampion(champ.id)
} }
console.timeEnd('CHAMPION') console.timeEnd('CHAMPION')
console.time('CHAMPION-CLASS') console.time('CHAMPION-CLASS')
const championClassStats = await MatchRepository.championClassStats(puuid) const championClassStats = await MatchRepository.championClassStats(filters)
for (const champ of championClassStats) { for (const champ of championClassStats) {
champ.id = ChampionRoles[champ.id] champ.id = ChampionRoles[champ.id]
} }
console.timeEnd('CHAMPION-CLASS') console.timeEnd('CHAMPION-CLASS')
console.time('MATES') console.time('MATES')
const mates = await MatchRepository.mates(puuid) const mates = await MatchRepository.mates(filters)
console.timeEnd('MATES') console.timeEnd('MATES')
console.time('RECENT_ACTIVITY') console.time('RECENT_ACTIVITY')