mirror of
https://github.com/vkaelin/LeagueStats.git
synced 2026-03-25 12:57:28 +00:00
feat: add summoner/champions endpoint
This commit is contained in:
parent
3862043980
commit
8184f17fbb
4 changed files with 160 additions and 15 deletions
|
|
@ -5,6 +5,7 @@ import Jax from 'App/Services/Jax'
|
||||||
import MatchService from 'App/Services/MatchService'
|
import MatchService from 'App/Services/MatchService'
|
||||||
import SummonerService from 'App/Services/SummonerService'
|
import SummonerService from 'App/Services/SummonerService'
|
||||||
import SummonerBasicValidator from 'App/Validators/SummonerBasicValidator'
|
import SummonerBasicValidator from 'App/Validators/SummonerBasicValidator'
|
||||||
|
import SummonerChampionValidator from 'App/Validators/SummonerChampionValidator'
|
||||||
|
|
||||||
export default class SummonersController {
|
export default class SummonersController {
|
||||||
/**
|
/**
|
||||||
|
|
@ -22,8 +23,8 @@ export default class SummonersController {
|
||||||
*/
|
*/
|
||||||
public async basic ({ request, response }: HttpContextContract) {
|
public async basic ({ request, response }: HttpContextContract) {
|
||||||
console.time('all')
|
console.time('all')
|
||||||
const { summoner, region} = await request.validate(SummonerBasicValidator)
|
const { summoner, region } = await request.validate(SummonerBasicValidator)
|
||||||
const finalJSON:any = {}
|
const finalJSON: any = {}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const account = await SummonerService.getAccount(summoner, region)
|
const account = await SummonerService.getAccount(summoner, region)
|
||||||
|
|
@ -36,7 +37,7 @@ export default class SummonersController {
|
||||||
|
|
||||||
// Summoner in DB
|
// Summoner in DB
|
||||||
let summonerDB = await Summoner.findOne({ puuid: account.puuid })
|
let summonerDB = await Summoner.findOne({ puuid: account.puuid })
|
||||||
if(!summonerDB) {
|
if (!summonerDB) {
|
||||||
summonerDB = await Summoner.create({ puuid: account.puuid })
|
summonerDB = await Summoner.create({ puuid: account.puuid })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,4 +70,16 @@ export default class SummonersController {
|
||||||
console.timeEnd('all')
|
console.timeEnd('all')
|
||||||
return response.json(finalJSON)
|
return response.json(finalJSON)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST: get champions view summoner data
|
||||||
|
* @param ctx
|
||||||
|
*/
|
||||||
|
public async champions ({ request, response }) {
|
||||||
|
console.time('championsRequest')
|
||||||
|
const { puuid, queue, season } = await request.validate(SummonerChampionValidator)
|
||||||
|
const championStats = await MatchRepository.championCompleteStats(puuid, queue, season)
|
||||||
|
console.timeEnd('championsRequest')
|
||||||
|
return response.json(championStats)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,39 +2,114 @@ import mongodb from '@ioc:Mongodb/Database'
|
||||||
import { Collection } from 'mongodb'
|
import { Collection } from 'mongodb'
|
||||||
|
|
||||||
class MatchRepository {
|
class MatchRepository {
|
||||||
private season?: number
|
|
||||||
private collection: Collection
|
private collection: Collection
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
this.getCollection()
|
this.getCollection()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get MongoDB matches collection
|
|
||||||
*/
|
|
||||||
private async getCollection () {
|
|
||||||
this.collection = await mongodb.connection().collection('matches')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic matchParams used in a lot of requests
|
* Basic matchParams used in a lot of requests
|
||||||
* @param puuid of the summoner
|
* @param puuid of the summoner
|
||||||
*/
|
*/
|
||||||
private matchParams (puuid: string) {
|
private matchParams (puuid: string, season?: number) {
|
||||||
return {
|
return {
|
||||||
summoner_puuid: puuid,
|
summoner_puuid: puuid,
|
||||||
result: { $not: { $eq: 'Remake' } },
|
result: { $not: { $eq: 'Remake' } },
|
||||||
gamemode: { $nin: [800, 810, 820, 830, 840, 850] },
|
gamemode: { $nin: [800, 810, 820, 830, 840, 850] },
|
||||||
season: this.season ? this.season : { $exists: true },
|
season: season ? season : { $exists: true },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the aggregate mongo query
|
||||||
|
* @param puuid
|
||||||
|
* @param matchParams
|
||||||
|
* @param intermediateSteps
|
||||||
|
* @param groupId
|
||||||
|
* @param groupParams
|
||||||
|
* @param finalSteps
|
||||||
|
*/
|
||||||
|
private async aggregate (
|
||||||
|
puuid: string,
|
||||||
|
matchParams: object,
|
||||||
|
intermediateSteps: any[],
|
||||||
|
groupId: any,
|
||||||
|
groupParams: object,
|
||||||
|
finalSteps: any[],
|
||||||
|
season?: number,
|
||||||
|
) {
|
||||||
|
return this.collection.aggregate([
|
||||||
|
{
|
||||||
|
$match: {
|
||||||
|
...this.matchParams(puuid, season),
|
||||||
|
...matchParams,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...intermediateSteps,
|
||||||
|
{
|
||||||
|
$group: {
|
||||||
|
_id: groupId,
|
||||||
|
count: { $sum: 1 },
|
||||||
|
wins: {
|
||||||
|
$sum: {
|
||||||
|
$cond: [{ $eq: ['$result', 'Win'] }, 1, 0],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
losses: {
|
||||||
|
$sum: {
|
||||||
|
$cond: [{ $eq: ['$result', 'Fail'] }, 1, 0],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...groupParams,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...finalSteps,
|
||||||
|
]).toArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get MongoDB matches collection
|
||||||
|
*/
|
||||||
|
public async getCollection () {
|
||||||
|
if (!this.collection) {
|
||||||
|
this.collection = await mongodb.connection().collection('matches')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Summoner's complete statistics for the all played champs
|
||||||
|
* @param puuid of the summoner
|
||||||
|
* @param queue of the matches to fetch, if not set: get all matches
|
||||||
|
* @param season of the matches to fetch, if not set: get all seasons
|
||||||
|
*/
|
||||||
|
public async championCompleteStats (puuid: string, queue?: number, season?: number) {
|
||||||
|
const matchParams = queue ? { gamemode: { $eq: Number(queue) } } : {}
|
||||||
|
const groupParams = {
|
||||||
|
time: { $sum: '$time' },
|
||||||
|
gameLength: { $avg: '$time' },
|
||||||
|
date: { $max: '$date' },
|
||||||
|
champion: { $first: '$champion' },
|
||||||
|
kills: { $sum: '$stats.kills' },
|
||||||
|
deaths: { $sum: '$stats.deaths' },
|
||||||
|
assists: { $sum: '$stats.assists' },
|
||||||
|
minions: { $avg: '$stats.minions' },
|
||||||
|
gold: { $avg: '$stats.gold' },
|
||||||
|
dmgChamp: { $avg: '$stats.dmgChamp' },
|
||||||
|
dmgTaken: { $avg: '$stats.dmgTaken' },
|
||||||
|
kp: { $avg: '$stats.kp' },
|
||||||
|
}
|
||||||
|
const finalSteps = [
|
||||||
|
{ $sort: { 'count': -1, 'champion.name': 1 } },
|
||||||
|
]
|
||||||
|
return this.aggregate(puuid, matchParams, [], '$champion.id', groupParams, finalSteps, season)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Summoner's played seasons
|
* Get Summoner's played seasons
|
||||||
* @param puuid of the summoner
|
* @param puuid of the summoner
|
||||||
*/
|
*/
|
||||||
public async seasons (puuid: string) {
|
public async seasons (puuid: string) {
|
||||||
this.season = undefined
|
|
||||||
return this.collection.aggregate([
|
return this.collection.aggregate([
|
||||||
{
|
{
|
||||||
$match: {
|
$match: {
|
||||||
|
|
|
||||||
54
server-new/app/Validators/SummonerChampionValidator.ts
Normal file
54
server-new/app/Validators/SummonerChampionValidator.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
|
||||||
|
import { schema } from '@ioc:Adonis/Core/Validator'
|
||||||
|
|
||||||
|
export default class SummonerChampionValidator {
|
||||||
|
constructor (private ctx: HttpContextContract) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defining a schema to validate the "shape", "type", "formatting" and "integrity" of data.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* 1. The username must be of data type string. But then also, it should
|
||||||
|
* not contain special characters or numbers.
|
||||||
|
* ```
|
||||||
|
* schema.string({}, [ rules.alpha() ])
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* 2. The email must be of data type string, formatted as a valid
|
||||||
|
* email. But also, not used by any other user.
|
||||||
|
* ```
|
||||||
|
* schema.string({}, [
|
||||||
|
* rules.email(),
|
||||||
|
* rules.unique({ table: 'users', column: 'email' }),
|
||||||
|
* ])
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
public schema = schema.create({
|
||||||
|
puuid: schema.string(),
|
||||||
|
queue: schema.number.optional(),
|
||||||
|
season: schema.number.optional(),
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `schema` first gets compiled to a reusable function and then that compiled
|
||||||
|
* function validates the data at runtime.
|
||||||
|
*
|
||||||
|
* Since, compiling the schema is an expensive operation, you must always cache it by
|
||||||
|
* defining a unique cache key. The simplest way is to use the current request route
|
||||||
|
* key, which is a combination of the route pattern and HTTP method.
|
||||||
|
*/
|
||||||
|
public cacheKey = this.ctx.routeKey
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom messages for validation failures. You can make use of dot notation `(.)`
|
||||||
|
* for targeting nested fields and array expressions `(*)` for targeting all
|
||||||
|
* children of an array. For example:
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* 'profile.username.required': 'Username is required',
|
||||||
|
* 'scores.*.number': 'Define scores as valid numbers'
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
public messages = {}
|
||||||
|
}
|
||||||
|
|
@ -8,8 +8,11 @@ export default class AppProvider {
|
||||||
// Register your own bindings
|
// Register your own bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
public boot () {
|
public async boot () {
|
||||||
// IoC container is ready
|
// IoC container is ready
|
||||||
|
|
||||||
|
// Load Match Collections
|
||||||
|
await import('App/Repositories/MatchRepository')
|
||||||
}
|
}
|
||||||
|
|
||||||
public shutdown () {
|
public shutdown () {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue