mirror of
https://github.com/vkaelin/LeagueStats.git
synced 2026-03-25 12:57:28 +00:00
Merge branch 'serializer' into V2
This commit is contained in:
commit
adf08ac779
5 changed files with 290 additions and 9 deletions
152
server-v2/app/Serializers/BasicMatchSerializer.ts
Normal file
152
server-v2/app/Serializers/BasicMatchSerializer.ts
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
import { getSeasonNumber, sortTeamByRole } from 'App/helpers'
|
||||||
|
import Match from 'App/Models/Match'
|
||||||
|
import MatchPlayer from 'App/Models/MatchPlayer'
|
||||||
|
import MatchSerializer from './MatchSerializer'
|
||||||
|
import {
|
||||||
|
SerializedMatch,
|
||||||
|
SerializedMatchChampion,
|
||||||
|
SerializedMatchItem,
|
||||||
|
SerializedMatchPerks,
|
||||||
|
SerializedMatchStats,
|
||||||
|
SerializedMatchTeamPlayer,
|
||||||
|
} from './SerializedTypes'
|
||||||
|
|
||||||
|
class BasicMatchSerializer extends MatchSerializer {
|
||||||
|
/**
|
||||||
|
* Get champion specific data
|
||||||
|
* @param id of the champion
|
||||||
|
*/
|
||||||
|
protected getChampion(id: number): SerializedMatchChampion {
|
||||||
|
const originalChampionData = this.champions.find((c) => c.id === id)
|
||||||
|
const icon =
|
||||||
|
'https://raw.communitydragon.org/latest/plugins/rcp-be-lol-game-data/global/default/' +
|
||||||
|
originalChampionData!.squarePortraitPath.split('/assets/')[1].toLowerCase()
|
||||||
|
|
||||||
|
return {
|
||||||
|
icon,
|
||||||
|
id: originalChampionData!.id,
|
||||||
|
name: originalChampionData!.name,
|
||||||
|
alias: originalChampionData!.alias,
|
||||||
|
roles: originalChampionData!.roles,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getPlayerSummary(player: MatchPlayer): SerializedMatchTeamPlayer {
|
||||||
|
return {
|
||||||
|
puuid: player.summonerPuuid,
|
||||||
|
champion: this.getChampion(player.championId),
|
||||||
|
name: player.summonerName,
|
||||||
|
role: player.teamPosition,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getTeamSummary(players: MatchPlayer[]): SerializedMatchTeamPlayer[] {
|
||||||
|
return players.map((p) => this.getPlayerSummary(p)).sort(sortTeamByRole)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getItems(player: MatchPlayer): Array<SerializedMatchItem | null> {
|
||||||
|
const items: (SerializedMatchItem | null)[] = []
|
||||||
|
for (let i = 0; i < 6; i++) {
|
||||||
|
const id = player['item' + i]
|
||||||
|
if (id === 0) {
|
||||||
|
items.push(null)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const item = this.items.find((i) => i.id === id)
|
||||||
|
if (!item) {
|
||||||
|
items.push(null)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemUrl = item.iconPath.split('/assets/')[1].toLowerCase()
|
||||||
|
items.push({
|
||||||
|
image: `https://raw.communitydragon.org/latest/plugins/rcp-be-lol-game-data/global/default/${itemUrl}`,
|
||||||
|
name: item.name,
|
||||||
|
description: item.description,
|
||||||
|
price: item.priceTotal,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getPerks(player: MatchPlayer): SerializedMatchPerks {
|
||||||
|
return {
|
||||||
|
primaryStyle: player.perksPrimaryStyle,
|
||||||
|
secondaryStyle: player.perksSecondaryStyle,
|
||||||
|
selected: player.perksSelected,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getStats(player: MatchPlayer): SerializedMatchStats {
|
||||||
|
return {
|
||||||
|
kills: player.kills,
|
||||||
|
deaths: player.deaths,
|
||||||
|
assists: player.assists,
|
||||||
|
minions: player.minions,
|
||||||
|
vision: player.visionScore,
|
||||||
|
gold: player.gold,
|
||||||
|
dmgChamp: player.damageDealtChampions,
|
||||||
|
dmgObj: player.damageDealtObjectives,
|
||||||
|
dmgTaken: player.damageTaken,
|
||||||
|
kp: player.kp,
|
||||||
|
kda: player.kills + player.assists !== 0 && player.deaths === 0 ? '∞' : player.kda,
|
||||||
|
realKda: player.kda,
|
||||||
|
criticalStrike: player.criticalStrike,
|
||||||
|
killingSpree: player.killingSpree,
|
||||||
|
doubleKills: player.doubleKills,
|
||||||
|
tripleKills: player.tripleKills,
|
||||||
|
quadraKills: player.quadraKills,
|
||||||
|
pentaKills: player.pentaKills,
|
||||||
|
heal: player.heal,
|
||||||
|
towers: player.turretKills,
|
||||||
|
longestLiving: player.timeSpentLiving,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public serializeOneMatch(match: Match, puuid: string): SerializedMatch {
|
||||||
|
const identity = match.players.find((p) => p.summonerPuuid === puuid)!
|
||||||
|
|
||||||
|
const allyTeamColor = identity.team === 100 ? 'blueTeam' : 'redTeam'
|
||||||
|
const allyTeam = match[allyTeamColor]
|
||||||
|
|
||||||
|
const allyPlayers: MatchPlayer[] = []
|
||||||
|
const enemyPlayers: MatchPlayer[] = []
|
||||||
|
|
||||||
|
for (const p of match.players) {
|
||||||
|
// TODO: remove Number() when Lazar push the updated migration
|
||||||
|
p.team === Number(allyTeam.color) ? allyPlayers.push(p) : enemyPlayers.push(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
allyTeam: this.getTeamSummary(allyPlayers),
|
||||||
|
champion: this.getChampion(identity.championId),
|
||||||
|
date: match.date,
|
||||||
|
enemyTeam: this.getTeamSummary(enemyPlayers),
|
||||||
|
firstSum: identity.summoner1Id,
|
||||||
|
matchId: match.id,
|
||||||
|
gamemode: match.gamemode,
|
||||||
|
items: this.getItems(identity),
|
||||||
|
level: identity.champLevel,
|
||||||
|
map: match.map,
|
||||||
|
name: identity.summonerName,
|
||||||
|
perks: this.getPerks(identity),
|
||||||
|
region: match.region,
|
||||||
|
result: allyTeam.result.toString(), // TODO: remove toString() when Lazar push the updated migration
|
||||||
|
role: identity.teamPosition,
|
||||||
|
season: getSeasonNumber(match.date),
|
||||||
|
secondSum: identity.summoner2Id,
|
||||||
|
stats: this.getStats(identity),
|
||||||
|
summonerId: identity.summonerId,
|
||||||
|
summonerPuuid: puuid,
|
||||||
|
time: match.gameDuration,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async serialize(matches: Match[], puuid: string): Promise<SerializedMatch[]> {
|
||||||
|
await super.getContext()
|
||||||
|
|
||||||
|
return matches.map((match) => this.serializeOneMatch(match, puuid))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new BasicMatchSerializer()
|
||||||
39
server-v2/app/Serializers/MatchSerializer.ts
Normal file
39
server-v2/app/Serializers/MatchSerializer.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
import Jax from 'App/Services/Jax'
|
||||||
|
import {
|
||||||
|
ChampionDTO,
|
||||||
|
ItemDTO,
|
||||||
|
PerkDTO,
|
||||||
|
PerkStyleDTO,
|
||||||
|
SummonerSpellDTO,
|
||||||
|
} from 'App/Services/Jax/src/Endpoints/CDragonEndpoint'
|
||||||
|
import RoleIdentificationService, {
|
||||||
|
ChampionsPlayRate,
|
||||||
|
} from 'App/Services/RoleIdentificationService'
|
||||||
|
|
||||||
|
export default abstract class MatchSerializer {
|
||||||
|
protected champions: ChampionDTO[]
|
||||||
|
protected items: ItemDTO[]
|
||||||
|
protected perks: PerkDTO[]
|
||||||
|
protected perkstyles: PerkStyleDTO[]
|
||||||
|
protected summonerSpells: SummonerSpellDTO[]
|
||||||
|
protected championRoles: ChampionsPlayRate
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get global Context with CDragon Data
|
||||||
|
*/
|
||||||
|
public async getContext() {
|
||||||
|
const items = await Jax.CDragon.items()
|
||||||
|
const champions = await Jax.CDragon.champions()
|
||||||
|
const perks = await Jax.CDragon.perks()
|
||||||
|
const perkstyles = await Jax.CDragon.perkstyles()
|
||||||
|
const summonerSpells = await Jax.CDragon.summonerSpells()
|
||||||
|
const championRoles = await RoleIdentificationService.pullData().catch(() => {})
|
||||||
|
|
||||||
|
this.champions = champions
|
||||||
|
this.items = items
|
||||||
|
this.perks = perks
|
||||||
|
this.perkstyles = perkstyles.styles
|
||||||
|
this.summonerSpells = summonerSpells
|
||||||
|
this.championRoles = championRoles as ChampionsPlayRate
|
||||||
|
}
|
||||||
|
}
|
||||||
75
server-v2/app/Serializers/SerializedTypes.ts
Normal file
75
server-v2/app/Serializers/SerializedTypes.ts
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
export interface SerializedMatch {
|
||||||
|
allyTeam: SerializedMatchTeamPlayer[]
|
||||||
|
champion: SerializedMatchChampion
|
||||||
|
date: number
|
||||||
|
enemyTeam: SerializedMatchTeamPlayer[]
|
||||||
|
firstSum: number
|
||||||
|
matchId: string
|
||||||
|
gamemode: number
|
||||||
|
items: Array<SerializedMatchItem | null>
|
||||||
|
level: number
|
||||||
|
map: number
|
||||||
|
name: string
|
||||||
|
perks: SerializedMatchPerks
|
||||||
|
region: string
|
||||||
|
result: string
|
||||||
|
role: string
|
||||||
|
season: number
|
||||||
|
secondSum: number
|
||||||
|
stats: SerializedMatchStats
|
||||||
|
summonerId: string
|
||||||
|
summonerPuuid: string
|
||||||
|
time: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SerializedMatchTeamPlayer {
|
||||||
|
puuid: string
|
||||||
|
champion: SerializedMatchChampion
|
||||||
|
name: string
|
||||||
|
role: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SerializedMatchChampion {
|
||||||
|
alias: string
|
||||||
|
icon: string
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
roles: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SerializedMatchItem {
|
||||||
|
description: string
|
||||||
|
image: string
|
||||||
|
name: string
|
||||||
|
price: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SerializedMatchPerks {
|
||||||
|
primaryStyle: number
|
||||||
|
secondaryStyle: number
|
||||||
|
selected: number[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SerializedMatchStats {
|
||||||
|
assists: number
|
||||||
|
criticalStrike: number
|
||||||
|
deaths: number
|
||||||
|
dmgChamp: number
|
||||||
|
dmgObj: number
|
||||||
|
dmgTaken: number
|
||||||
|
doubleKills: number
|
||||||
|
gold: number
|
||||||
|
heal: number
|
||||||
|
kda: number | string
|
||||||
|
killingSpree: number
|
||||||
|
kills: number
|
||||||
|
kp: number
|
||||||
|
longestLiving: number
|
||||||
|
minions: number
|
||||||
|
pentaKills: number
|
||||||
|
quadraKills: number
|
||||||
|
realKda: number
|
||||||
|
towers: number
|
||||||
|
tripleKills: number
|
||||||
|
vision: number
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,8 @@ import Summoner from 'App/Models/Summoner'
|
||||||
import Database from '@ioc:Adonis/Lucid/Database'
|
import Database from '@ioc:Adonis/Lucid/Database'
|
||||||
import SummonerMatchlist from 'App/Models/SummonerMatchlist'
|
import SummonerMatchlist from 'App/Models/SummonerMatchlist'
|
||||||
import MatchParser from 'App/Parsers/MatchParser'
|
import MatchParser from 'App/Parsers/MatchParser'
|
||||||
|
import BasicMatchSerializer from 'App/Serializers/BasicMatchSerializer'
|
||||||
|
import { SerializedMatch } from 'App/Serializers/SerializedTypes'
|
||||||
|
|
||||||
class MatchService {
|
class MatchService {
|
||||||
/**
|
/**
|
||||||
|
|
@ -76,21 +78,28 @@ class MatchService {
|
||||||
/**
|
/**
|
||||||
* Fetch list of matches for a specific Summoner
|
* Fetch list of matches for a specific Summoner
|
||||||
*/
|
*/
|
||||||
public async getMatches(region: string, matchList: SummonerMatchlist[], summonerDB: Summoner) {
|
public async getMatches(
|
||||||
|
region: string,
|
||||||
|
matchList: SummonerMatchlist[],
|
||||||
|
summonerDB: Summoner
|
||||||
|
): Promise<SerializedMatch[]> {
|
||||||
console.time('getMatches')
|
console.time('getMatches')
|
||||||
|
|
||||||
let matches: any[] = [] // Todo: add type of serialized matches here
|
let matches: SerializedMatch[] = []
|
||||||
const matchesToGetFromRiot: MatchlistDto = []
|
const matchesToGetFromRiot: MatchlistDto = []
|
||||||
for (let i = 0; i < matchList.length; ++i) {
|
for (let i = 0; i < matchList.length; ++i) {
|
||||||
const matchSaved = await summonerDB
|
const matchSaved = await summonerDB
|
||||||
.related('matches')
|
.related('matches')
|
||||||
.query()
|
.query()
|
||||||
.where('matchId', matchList[i].matchId)
|
.where('matchId', matchList[i].matchId)
|
||||||
.preload('match')
|
.preload('match', (preloader) => {
|
||||||
|
preloader.preload('blueTeam').preload('redTeam').preload('players')
|
||||||
|
})
|
||||||
.first()
|
.first()
|
||||||
|
|
||||||
if (matchSaved) {
|
if (matchSaved) {
|
||||||
// TODO: Serialize match from DB + put it in Redis + push it in "matches"
|
// TODO: Serialize match from DB + put it in Redis + push it in "matches"
|
||||||
|
matches.push(BasicMatchSerializer.serializeOneMatch(matchSaved.match, summonerDB.puuid))
|
||||||
} else {
|
} else {
|
||||||
matchesToGetFromRiot.push(matchList[i].matchId)
|
matchesToGetFromRiot.push(matchList[i].matchId)
|
||||||
}
|
}
|
||||||
|
|
@ -102,14 +111,20 @@ class MatchService {
|
||||||
/* If we have to store some matches in the db */
|
/* If we have to store some matches in the db */
|
||||||
if (matchesFromApi.length !== 0) {
|
if (matchesFromApi.length !== 0) {
|
||||||
// Transform raw matches data
|
// Transform raw matches data
|
||||||
const parsedMatches = await MatchParser.parse(matchesFromApi)
|
const parsedMatches: any = await MatchParser.parse(matchesFromApi)
|
||||||
|
|
||||||
// TODO: Serialize match from DB + put it in Redis + push it in "matches"
|
// TODO: Serialize match from DB + put it in Redis + push it in "matches"
|
||||||
|
const serializedMatches = await BasicMatchSerializer.serialize(
|
||||||
|
parsedMatches,
|
||||||
|
summonerDB.puuid
|
||||||
|
)
|
||||||
|
matches = [...matches, ...serializedMatches]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo: Sort and return "matches"
|
// Todo: check if we need to sort here
|
||||||
|
matches.sort((a, b) => (a.date < b.date ? 1 : -1))
|
||||||
console.timeEnd('getMatches')
|
console.timeEnd('getMatches')
|
||||||
|
return matches
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import MatchPlayer from './Models/MatchPlayer'
|
import { SerializedMatchTeamPlayer } from './Serializers/SerializedTypes'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All League of Legends regions used in Riot API
|
* All League of Legends regions used in Riot API
|
||||||
|
|
@ -104,7 +104,7 @@ export function getCurrentSeason(): number {
|
||||||
* @param a first player
|
* @param a first player
|
||||||
* @param b second player
|
* @param b second player
|
||||||
*/
|
*/
|
||||||
export function sortTeamByRole(a: MatchPlayer, b: MatchPlayer) {
|
export function sortTeamByRole(a: SerializedMatchTeamPlayer, b: SerializedMatchTeamPlayer) {
|
||||||
const sortingArr = ['TOP', 'JUNGLE', 'MIDDLE', 'BOTTOM', 'SUPPORT']
|
const sortingArr = ['TOP', 'JUNGLE', 'MIDDLE', 'BOTTOM', 'SUPPORT']
|
||||||
return sortingArr.indexOf(a.teamPosition) - sortingArr.indexOf(b.teamPosition)
|
return sortingArr.indexOf(a.role) - sortingArr.indexOf(b.role)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue