mirror of
https://github.com/vkaelin/LeagueStats.git
synced 2026-03-25 12:57:28 +00:00
refactor: use db transactions when inserting matches to prevent errors
This commit is contained in:
parent
ec6319ec3b
commit
4811f95aa0
3 changed files with 170 additions and 141 deletions
|
|
@ -29,6 +29,8 @@ Vue.filter('kilo', (value) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
Vue.filter('secToTime', (sec, dotNotation = false) => {
|
Vue.filter('secToTime', (sec, dotNotation = false) => {
|
||||||
|
if (isNaN(sec)) return 0
|
||||||
|
|
||||||
const min = Math.floor(sec / 60)
|
const min = Math.floor(sec / 60)
|
||||||
let newSec = Math.floor(sec - min * 60)
|
let newSec = Math.floor(sec - min * 60)
|
||||||
newSec = newSec < 10 ? '0' + newSec : newSec
|
newSec = newSec < 10 ? '0' + newSec : newSec
|
||||||
|
|
@ -41,6 +43,8 @@ Vue.filter('percent', (value) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
Vue.filter('round', (value, decimals = 2) => {
|
Vue.filter('round', (value, decimals = 2) => {
|
||||||
|
if (isNaN(value)) return 0
|
||||||
|
|
||||||
return parseFloat(value.toFixed(decimals))
|
return parseFloat(value.toFixed(decimals))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import Database from '@ioc:Adonis/Lucid/Database'
|
import Database, { TransactionClientContract } from '@ioc:Adonis/Lucid/Database'
|
||||||
import { MatchDto } from 'App/Services/Jax/src/Endpoints/MatchEndpoint'
|
import { MatchDto } from 'App/Services/Jax/src/Endpoints/MatchEndpoint'
|
||||||
import Match from 'App/Models/Match'
|
import Match from 'App/Models/Match'
|
||||||
import { getSeasonNumber, queuesWithRole } from 'App/helpers'
|
import { getSeasonNumber, queuesWithRole } from 'App/helpers'
|
||||||
|
|
@ -6,14 +6,23 @@ import CDragonService from 'App/Services/CDragonService'
|
||||||
import { ChampionRoles, TeamPosition } from './ParsedType'
|
import { ChampionRoles, TeamPosition } from './ParsedType'
|
||||||
class MatchParser {
|
class MatchParser {
|
||||||
public async parseOneMatch(match: MatchDto) {
|
public async parseOneMatch(match: MatchDto) {
|
||||||
// Parse + store in database
|
let parsedMatch: Match | null = null
|
||||||
|
let trx: TransactionClientContract | undefined
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Start transaction
|
||||||
|
trx = await Database.transaction()
|
||||||
|
|
||||||
const gameDuration =
|
const gameDuration =
|
||||||
match.info.gameDuration > 100_000
|
match.info.gameDuration > 100_000
|
||||||
? Math.round(match.info.gameDuration / 1000)
|
? Math.round(match.info.gameDuration / 1000)
|
||||||
: match.info.gameDuration
|
: match.info.gameDuration
|
||||||
|
|
||||||
|
const isRemake = gameDuration < 300
|
||||||
|
|
||||||
// - 1x Match
|
// - 1x Match
|
||||||
const parsedMatch = await Match.create({
|
parsedMatch = await Match.create(
|
||||||
|
{
|
||||||
id: match.metadata.matchId,
|
id: match.metadata.matchId,
|
||||||
gameId: match.info.gameId,
|
gameId: match.info.gameId,
|
||||||
map: match.info.mapId,
|
map: match.info.mapId,
|
||||||
|
|
@ -23,9 +32,9 @@ class MatchParser {
|
||||||
result: match.info.teams[0].win ? match.info.teams[0].teamId : match.info.teams[1].teamId,
|
result: match.info.teams[0].win ? match.info.teams[0].teamId : match.info.teams[1].teamId,
|
||||||
season: getSeasonNumber(match.info.gameCreation),
|
season: getSeasonNumber(match.info.gameCreation),
|
||||||
gameDuration,
|
gameDuration,
|
||||||
})
|
},
|
||||||
|
{ client: trx }
|
||||||
const isRemake = gameDuration < 300
|
)
|
||||||
|
|
||||||
// - 2x MatchTeam : Red and Blue
|
// - 2x MatchTeam : Red and Blue
|
||||||
for (const team of match.info.teams) {
|
for (const team of match.info.teams) {
|
||||||
|
|
@ -53,13 +62,15 @@ class MatchParser {
|
||||||
const kda =
|
const kda =
|
||||||
player.kills + player.assists !== 0 && player.deaths === 0
|
player.kills + player.assists !== 0 && player.deaths === 0
|
||||||
? player.kills + player.assists
|
? player.kills + player.assists
|
||||||
: +(player.deaths === 0 ? 0 : (player.kills + player.assists) / player.deaths).toFixed(2)
|
: +(player.deaths === 0 ? 0 : (player.kills + player.assists) / player.deaths).toFixed(
|
||||||
|
2
|
||||||
|
)
|
||||||
|
|
||||||
const team =
|
const team =
|
||||||
match.info.teams[0].teamId === player.teamId ? match.info.teams[0] : match.info.teams[1]
|
match.info.teams[0].teamId === player.teamId ? match.info.teams[0] : match.info.teams[1]
|
||||||
const teamKills = team.objectives.champion.kills
|
const teamKills = team.objectives.champion.kills
|
||||||
|
|
||||||
const kp =
|
let kp =
|
||||||
teamKills === 0 ? 0 : +(((player.kills + player.assists) * 100) / teamKills).toFixed(1)
|
teamKills === 0 ? 0 : +(((player.kills + player.assists) * 100) / teamKills).toFixed(1)
|
||||||
|
|
||||||
const primaryStyle = player.perks.styles.find((s) => s.description === 'primaryStyle')
|
const primaryStyle = player.perks.styles.find((s) => s.description === 'primaryStyle')
|
||||||
|
|
@ -149,14 +160,28 @@ class MatchParser {
|
||||||
await parsedMatch.load((loader) => {
|
await parsedMatch.load((loader) => {
|
||||||
loader.load('teams').load('players')
|
loader.load('teams').load('players')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (!trx.isCompleted) {
|
||||||
|
await trx.commit()
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error in MatchParser transaction.')
|
||||||
|
if (trx && trx.isTransaction) {
|
||||||
|
await trx.rollback()
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return parsedMatch
|
return parsedMatch
|
||||||
}
|
}
|
||||||
|
|
||||||
public async parse(matches: MatchDto[]) {
|
public async parse(matches: MatchDto[]) {
|
||||||
// Loop on all matches and call .parseOneMatch on it
|
|
||||||
const parsedMatches: Match[] = []
|
const parsedMatches: Match[] = []
|
||||||
for (const match of matches) {
|
for (const match of matches) {
|
||||||
parsedMatches.push(await this.parseOneMatch(match))
|
const parsed = await this.parseOneMatch(match)
|
||||||
|
if (parsed) {
|
||||||
|
parsedMatches.push(parsed)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return parsedMatches
|
return parsedMatches
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,16 +77,16 @@ class MatchRepository {
|
||||||
public async globalStats(filters: SelectFilters) {
|
public async globalStats(filters: SelectFilters) {
|
||||||
const query = `
|
const query = `
|
||||||
SELECT
|
SELECT
|
||||||
SUM(match_players.kills) as kills,
|
COALESCE(SUM(match_players.kills), 0) as kills,
|
||||||
SUM(match_players.deaths) as deaths,
|
COALESCE(SUM(match_players.deaths), 0) as deaths,
|
||||||
SUM(match_players.assists) as assists,
|
COALESCE(SUM(match_players.assists), 0) as assists,
|
||||||
SUM(match_players.minions) as minions,
|
COALESCE(SUM(match_players.minions), 0) as minions,
|
||||||
SUM(matches.game_duration) as time,
|
COALESCE(SUM(matches.game_duration), 0) as time,
|
||||||
SUM(match_players.vision_score) as vision,
|
COALESCE(SUM(match_players.vision_score), 0) as vision,
|
||||||
COUNT(match_players.id) as count,
|
COUNT(match_players.id) as count,
|
||||||
AVG(match_players.kp) as kp,
|
COALESCE(AVG(match_players.kp), 0) as kp,
|
||||||
SUM(match_players.win) as wins,
|
COALESCE(SUM(match_players.win), 0) as wins,
|
||||||
SUM(match_players.loss) as losses
|
COALESCE(SUM(match_players.loss), 0) as losses
|
||||||
FROM
|
FROM
|
||||||
match_players
|
match_players
|
||||||
${this.JOIN_MATCHES}
|
${this.JOIN_MATCHES}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue