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 SummonerService from 'App/Services/SummonerService'
|
||||
import SummonerBasicValidator from 'App/Validators/SummonerBasicValidator'
|
||||
import SummonerChampionValidator from 'App/Validators/SummonerChampionValidator'
|
||||
|
||||
export default class SummonersController {
|
||||
/**
|
||||
|
|
@ -22,8 +23,8 @@ export default class SummonersController {
|
|||
*/
|
||||
public async basic ({ request, response }: HttpContextContract) {
|
||||
console.time('all')
|
||||
const { summoner, region} = await request.validate(SummonerBasicValidator)
|
||||
const finalJSON:any = {}
|
||||
const { summoner, region } = await request.validate(SummonerBasicValidator)
|
||||
const finalJSON: any = {}
|
||||
|
||||
try {
|
||||
const account = await SummonerService.getAccount(summoner, region)
|
||||
|
|
@ -36,7 +37,7 @@ export default class SummonersController {
|
|||
|
||||
// Summoner in DB
|
||||
let summonerDB = await Summoner.findOne({ puuid: account.puuid })
|
||||
if(!summonerDB) {
|
||||
if (!summonerDB) {
|
||||
summonerDB = await Summoner.create({ puuid: account.puuid })
|
||||
}
|
||||
|
||||
|
|
@ -69,4 +70,16 @@ export default class SummonersController {
|
|||
console.timeEnd('all')
|
||||
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'
|
||||
|
||||
class MatchRepository {
|
||||
private season?: number
|
||||
private collection: Collection
|
||||
|
||||
constructor () {
|
||||
this.getCollection()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get MongoDB matches collection
|
||||
*/
|
||||
private async getCollection () {
|
||||
this.collection = await mongodb.connection().collection('matches')
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic matchParams used in a lot of requests
|
||||
* @param puuid of the summoner
|
||||
*/
|
||||
private matchParams (puuid: string) {
|
||||
private matchParams (puuid: string, season?: number) {
|
||||
return {
|
||||
summoner_puuid: puuid,
|
||||
result: { $not: { $eq: 'Remake' } },
|
||||
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
|
||||
* @param puuid of the summoner
|
||||
*/
|
||||
public async seasons (puuid: string) {
|
||||
this.season = undefined
|
||||
return this.collection.aggregate([
|
||||
{
|
||||
$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
|
||||
}
|
||||
|
||||
public boot () {
|
||||
public async boot () {
|
||||
// IoC container is ready
|
||||
|
||||
// Load Match Collections
|
||||
await import('App/Repositories/MatchRepository')
|
||||
}
|
||||
|
||||
public shutdown () {
|
||||
|
|
|
|||
Loading…
Reference in a new issue