mirror of
https://github.com/vkaelin/LeagueStats.git
synced 2026-03-25 12:57:28 +00:00
feat: add filter by season back ✨
This commit is contained in:
parent
72cbc916bc
commit
80534a5ca3
3 changed files with 125 additions and 62 deletions
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,45 @@
|
||||||
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 = `
|
||||||
SELECT
|
SELECT
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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')
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue