import Jax from './Jax' import Logger from '@ioc:Adonis/Core/Logger' import { MatchlistDto } from './Jax/src/Endpoints/MatchlistEndpoint' import { SummonerDTO } from './Jax/src/Endpoints/SummonerEndpoint' import { SummonerModel } from 'App/Models/Summoner' import Match, { MatchModel } from 'App/Models/Match' import BasicMatchTransformer from 'App/Transformers/BasicMatchTransformer' class MatchService { /** * Add 100 matches at a time to MatchList until the stopFetching condition is true * @param account of the summoner * @param stopFetching condition to stop fetching the MatchList */ private async _fetchMatchListUntil (account: SummonerDTO, stopFetching: any) { let matchList: MatchlistDto = [] let alreadyIn = false let index = 0 do { let newMatchList = await Jax.Matchlist.puuid(account.puuid, account.region as string, index) // Error while fetching Riot API if (!newMatchList) { // matchList = matchList.map(m => { // m.season = getSeasonNumber(m.timestamp) // return m // }) return matchList } matchList = [...matchList, ...newMatchList] alreadyIn = newMatchList.length === 0 || stopFetching(newMatchList) // If the match is made in another region : we stop fetching // if (matchList[matchList.length - 1].platformId.toLowerCase() !== account.region) { // TODO: check if region has changed // alreadyIn = true // } index += 100 } while (!alreadyIn) // Remove matches from MatchList made in another region and tutorial games // const tutorialModes = [2000, 2010, 2020] // matchList = matchList // .filter(m => { // const sameRegion = m.platformId.toLowerCase() === account.region // const notATutorialGame = !tutorialModes.includes(m.queue) // return sameRegion && notATutorialGame // }) // .map(m => { // m.seasonMatch = getSeasonNumber(m.timestamp) // return m // }) return matchList } /** * Update the full MatchList of the summoner (min. 4 months) * @param account of the summoner * @param summonerDB summoner in the database */ public async updateMatchList (account: SummonerDTO, summonerDB: SummonerModel) { console.time('matchList') // Summoner has already been searched : we already have a MatchList and we need to update it if (summonerDB.matchList) { // Get MatchList const matchList = await this._fetchMatchListUntil(account, (newMatchList: MatchlistDto) => { return summonerDB.matchList!.some(m => m === newMatchList[newMatchList.length - 1]) }) // Update Summoner's MatchList for (const match of matchList.reverse()) { if (!summonerDB.matchList.some(m => m === match)) { summonerDB.matchList.unshift(match) } } } else { // First search of the Summoner // const today = Date.now() // Get MatchList const matchList = await this._fetchMatchListUntil(account, (newMatchList: MatchlistDto) => { // return (newMatchList.length !== 100 || today - newMatchList[newMatchList.length - 1].timestamp > 10368000000) return newMatchList.length === 0 // TODO: useless }) // Create Summoner's MatchList in Database summonerDB.matchList = matchList } console.timeEnd('matchList') } /** * Fetch list of matches for a specific Summoner * @param puuid * @param accountId * @param region * @param gameIds * @param summonerDB */ public async getMatches (puuid: string, accountId: string, region: string, matchIds: MatchlistDto, summonerDB: SummonerModel) { console.time('getMatches') let matchesDetails: MatchModel[] = [] const matchesToGetFromRiot: MatchlistDto = [] for (let i = 0; i < matchIds.length; ++i) { const matchSaved = await Match.findOne({ summoner_puuid: puuid, matchId: matchIds[i], }) if (matchSaved) { matchesDetails.push(matchSaved) } else { matchesToGetFromRiot.push(matchIds[i]) } } const requests = matchesToGetFromRiot.map(gameId => Jax.Match.get(gameId, region)) let matchesFromApi = await Promise.all(requests) /* If we have to store some matches in the db */ if (matchesFromApi.length !== 0) { // Try to see why matches are sometimes undefined matchesFromApi.filter(m => { if (m === undefined) { Logger.info(`Match undefined, summoner: ${summonerDB.puuid}`, m) } }) // Transform raw matches data const transformedMatches = await BasicMatchTransformer.transform(matchesFromApi, { puuid, accountId }) /* Save all matches from Riot Api in db */ for (const match of transformedMatches) { await Match.create(match) match.newMatch = true } matchesDetails = [...matchesDetails, ...transformedMatches] } /* Sort matches */ matchesDetails.sort((a, b) => (a.date < b.date) ? 1 : -1) console.timeEnd('getMatches') return matchesDetails } } export default new MatchService()