Compare commits
1 Commits
sql-php-re
...
main
Author | SHA1 | Date |
---|---|---|
Benjamin Kraft | 5b703187ce | 5 months ago |
13 changed files with 292 additions and 429 deletions
@ -1,187 +0,0 @@ |
|||||||
import {PlatformId, RiotAPI, RiotAPITypes} from "@fightmegg/riot-api" |
|
||||||
import {RowDataPacket} from "mysql2/promise"; |
|
||||||
import {getMySQLConnection} from "./util"; |
|
||||||
import AccountDTO = RiotAPITypes.Account.AccountDTO; |
|
||||||
|
|
||||||
const riotAPI = new RiotAPI(process.env["RIOT_API_KEY"] ?? ""); |
|
||||||
|
|
||||||
export class Account { |
|
||||||
|
|
||||||
puuid: string |
|
||||||
gameName?: string |
|
||||||
tagLine?: string |
|
||||||
|
|
||||||
currentElo?: Elo |
|
||||||
startElo?: Elo |
|
||||||
|
|
||||||
constructor(puuid: string) { |
|
||||||
this.puuid = puuid; |
|
||||||
} |
|
||||||
|
|
||||||
getProgress(){ |
|
||||||
return eloToNumber(this.currentElo) - eloToNumber(this.startElo); |
|
||||||
} |
|
||||||
|
|
||||||
async isAdded() { |
|
||||||
const conn = await getMySQLConnection(); |
|
||||||
const [rows] = await conn.execute<RowDataPacket[]>(` |
|
||||||
SELECT 1
|
|
||||||
FROM accounts |
|
||||||
WHERE puuid = ? |
|
||||||
LIMIT 1 |
|
||||||
`, [this.puuid]);
|
|
||||||
return rows.length == 1; |
|
||||||
} |
|
||||||
|
|
||||||
async addToDB(){ |
|
||||||
const conn = await getMySQLConnection(); |
|
||||||
await conn.execute(` |
|
||||||
INSERT INTO accounts
|
|
||||||
(puuid, gameName, tagLine) |
|
||||||
VALUES (?, ?, ?) |
|
||||||
`, [this.puuid, this.gameName, this.tagLine]);
|
|
||||||
} |
|
||||||
|
|
||||||
async removeFromDB(){ |
|
||||||
const conn = await getMySQLConnection(); |
|
||||||
await conn.execute(` |
|
||||||
DELETE FROM accounts
|
|
||||||
WHERE puuid = ? |
|
||||||
`, [this.puuid]);
|
|
||||||
} |
|
||||||
|
|
||||||
async update(){ |
|
||||||
const conn = await getMySQLConnection(); |
|
||||||
const fetchedAccount = await riotAPI.account.getByPUUID({ |
|
||||||
region: PlatformId.EUROPE, |
|
||||||
puuid: this.puuid |
|
||||||
}); |
|
||||||
this.gameName = fetchedAccount.gameName; |
|
||||||
this.tagLine = fetchedAccount.tagLine; |
|
||||||
await conn.execute(` |
|
||||||
UPDATE accounts |
|
||||||
SET gameName = ?, tagLine = ? |
|
||||||
WHERE puuid = ? |
|
||||||
`, [this.gameName, this.tagLine, this.puuid]);
|
|
||||||
|
|
||||||
const fetchedElo = await this.fetchCurrentElo(); |
|
||||||
if (fetchedElo && (!this.currentElo || |
|
||||||
this.currentElo.tier !== fetchedElo.tier || |
|
||||||
this.currentElo.rank !== fetchedElo.rank || |
|
||||||
this.currentElo.points !== fetchedElo.points |
|
||||||
)){ |
|
||||||
this.currentElo = fetchedElo; |
|
||||||
const date = new Date(Date.now()).toISOString().slice(0, 19).replace('T', ' '); |
|
||||||
|
|
||||||
const [[row]] = await conn.execute<RowDataPacket[]>(` |
|
||||||
SELECT id |
|
||||||
FROM accounts |
|
||||||
WHERE puuid = ? |
|
||||||
`, [this.puuid]);
|
|
||||||
const sqlAccountId = row["id"]; |
|
||||||
|
|
||||||
await conn.execute(` |
|
||||||
INSERT INTO elo_entries |
|
||||||
(accountId, date, tier, \`rank\`, points)
|
|
||||||
VALUES (?, ?, ?, ?, ?) |
|
||||||
`, [sqlAccountId, date, this.currentElo.tier, this.currentElo.rank, this.currentElo.points]);
|
|
||||||
|
|
||||||
console.log(`Added new elo entry for ${this}.`); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
async fetchCurrentElo() { |
|
||||||
const tryRegion = async (region: RiotAPITypes.LoLRegion) => { |
|
||||||
return await riotAPI.league.getEntriesBySummonerId({ |
|
||||||
region: region, |
|
||||||
summonerId: (await riotAPI.summoner.getByPUUID({ |
|
||||||
region: region, |
|
||||||
puuid: this.puuid |
|
||||||
})).id |
|
||||||
}); |
|
||||||
}; |
|
||||||
|
|
||||||
let entries; |
|
||||||
|
|
||||||
try { |
|
||||||
entries = await tryRegion(PlatformId.EUW1); |
|
||||||
} catch (error){ |
|
||||||
try { |
|
||||||
entries = await tryRegion(PlatformId.EUNE1); |
|
||||||
} catch (error){ |
|
||||||
let response = error as Response; |
|
||||||
console.error(await response.json()); |
|
||||||
return; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
let soloQ = entries.find(e => e.queueType == "RANKED_SOLO_5x5"); |
|
||||||
if (soloQ && ((soloQ.wins + soloQ.losses) >= 5)){ |
|
||||||
return { |
|
||||||
tier: soloQ.tier, |
|
||||||
rank: soloQ.rank, |
|
||||||
points: soloQ.leaguePoints |
|
||||||
} as Elo; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
static async fetchFromRiotID(gameName: string, tagLine: string){ |
|
||||||
let fetchedAccount: AccountDTO; |
|
||||||
try { |
|
||||||
fetchedAccount = await riotAPI.account.getByRiotId({ |
|
||||||
region: PlatformId.EUROPE, |
|
||||||
gameName: gameName, |
|
||||||
tagLine: tagLine |
|
||||||
}); |
|
||||||
} catch (error) { |
|
||||||
console.error(`Riot ID not found: ${gameName}#${tagLine}!`); |
|
||||||
return; |
|
||||||
} |
|
||||||
let account = new Account(fetchedAccount.puuid); |
|
||||||
account.gameName = fetchedAccount.gameName; |
|
||||||
account.tagLine = fetchedAccount.tagLine; |
|
||||||
|
|
||||||
return account; |
|
||||||
} |
|
||||||
|
|
||||||
toString() { |
|
||||||
return `${this.gameName}#${this.tagLine}`; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
interface Elo { |
|
||||||
tier: string, |
|
||||||
rank: string, |
|
||||||
points: number |
|
||||||
} |
|
||||||
|
|
||||||
export function eloToNumber(elo?: Elo){ |
|
||||||
if (!elo) |
|
||||||
return 0; |
|
||||||
let tiers: Record<string, number> = { |
|
||||||
"CHALLENGER": 2800, |
|
||||||
"GRANDMASTER": 2800, |
|
||||||
"MASTER": 2800, |
|
||||||
"DIAMOND": 2400, |
|
||||||
"EMERALD": 2000, |
|
||||||
"PLATINUM": 1600, |
|
||||||
"GOLD": 1200, |
|
||||||
"SILVER": 800, |
|
||||||
"BRONZE": 400, |
|
||||||
"IRON": 0, |
|
||||||
}; |
|
||||||
|
|
||||||
let ranks: Record<string, number> = { |
|
||||||
"I": 300, |
|
||||||
"II": 200, |
|
||||||
"III": 100, |
|
||||||
"IV": 0, |
|
||||||
}; |
|
||||||
|
|
||||||
let tier = elo.tier; |
|
||||||
if (tier === "MASTER" || tier === "GRANDMASTER" || tier === "CHALLENGER") |
|
||||||
return tiers[tier] + elo.points; |
|
||||||
|
|
||||||
return tiers[tier] + ranks[elo.rank] + elo.points; |
|
||||||
} |
|
@ -1,98 +0,0 @@ |
|||||||
import {Account} from "./account"; |
|
||||||
import {getMySQLConnection} from "./util"; |
|
||||||
import {RowDataPacket} from "mysql2/promise"; |
|
||||||
import {Collection} from "discord.js"; |
|
||||||
|
|
||||||
export class DataManager { |
|
||||||
async updateAllAccounts(){ |
|
||||||
let accounts = await this.getProgressedAccountList(); |
|
||||||
for (let account of accounts){ |
|
||||||
await account.update(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
async addAccount(gameName: string, tagLine: string) { |
|
||||||
let account = await Account.fetchFromRiotID(gameName, tagLine); |
|
||||||
if (!account) |
|
||||||
return; |
|
||||||
|
|
||||||
if (!await account.isAdded()){ |
|
||||||
await account.addToDB(); |
|
||||||
await account.update(); |
|
||||||
return account; |
|
||||||
} else { |
|
||||||
console.error(`Account ${account} already added.`); |
|
||||||
return; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
async removeAccount(gameName: string, tagLine: string) { |
|
||||||
let account = await Account.fetchFromRiotID(gameName, tagLine); |
|
||||||
if (!account) |
|
||||||
return; |
|
||||||
|
|
||||||
if (await account.isAdded()){ |
|
||||||
await account.removeFromDB(); |
|
||||||
return account; |
|
||||||
} else { |
|
||||||
console.error(`Account ${account} was not added.`); |
|
||||||
return; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
async getAccountMap(){ |
|
||||||
const conn = await getMySQLConnection(); |
|
||||||
|
|
||||||
const [sqlAccounts] = await conn.query<RowDataPacket[]>(`SELECT * FROM accounts`); |
|
||||||
|
|
||||||
let accounts = new Collection<string, Account>(); |
|
||||||
|
|
||||||
for (const sqlAccount of sqlAccounts){ |
|
||||||
let account = new Account(sqlAccount["puuid"]); |
|
||||||
account.gameName = sqlAccount["gameName"]; |
|
||||||
account.tagLine = sqlAccount["tagLine"]; |
|
||||||
accounts.set(account.puuid, account); |
|
||||||
} |
|
||||||
|
|
||||||
return accounts; |
|
||||||
} |
|
||||||
|
|
||||||
async getProgressedAccountList() { |
|
||||||
const conn = await getMySQLConnection(); |
|
||||||
|
|
||||||
const [[, starts, ends]] = await conn.query<RowDataPacket[][]>(` |
|
||||||
CREATE TEMPORARY TABLE limits AS |
|
||||||
SELECT MIN(date) AS start, MAX(date) AS end, accountId, gameName, tagLine, puuid |
|
||||||
FROM accounts JOIN elo_entries ON id = accountId |
|
||||||
GROUP BY accountId, gameName, tagLine, puuid; |
|
||||||
|
|
||||||
SELECT tier, \`rank\`, points, gameName, tagLine, puuid
|
|
||||||
FROM elo_entries JOIN limits ON elo_entries.date = start AND limits.accountId = elo_entries.accountId; |
|
||||||
|
|
||||||
SELECT tier, \`rank\`, points, gameName, tagLine, puuid
|
|
||||||
FROM elo_entries JOIN limits ON elo_entries.date = end AND limits.accountId = elo_entries.accountId; |
|
||||||
`);
|
|
||||||
|
|
||||||
let accounts = await this.getAccountMap(); |
|
||||||
|
|
||||||
for (const start of starts){ |
|
||||||
let account = accounts.get(start["puuid"]) as Account; |
|
||||||
account.startElo = { |
|
||||||
rank: start["rank"], |
|
||||||
tier: start["tier"], |
|
||||||
points: start["points"] |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
for (const end of ends){ |
|
||||||
let account = accounts.get(end["puuid"]) as Account; |
|
||||||
account.currentElo = { |
|
||||||
rank: end["rank"], |
|
||||||
tier: end["tier"], |
|
||||||
points: end["points"] |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
return Array.from(accounts.values()); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,144 @@ |
|||||||
|
import {PlatformId, RiotAPI, RiotAPITypes} from "@fightmegg/riot-api" |
||||||
|
import AccountDTO = RiotAPITypes.Account.AccountDTO; |
||||||
|
|
||||||
|
const riotAPI = new RiotAPI(process.env["RIOT_API_KEY"] as string); |
||||||
|
|
||||||
|
export class Player { |
||||||
|
|
||||||
|
puuid: string |
||||||
|
|
||||||
|
gameName?: string |
||||||
|
tagLine?: string |
||||||
|
startElo?: Elo |
||||||
|
currentElo?: Elo |
||||||
|
|
||||||
|
constructor(puuid: string) { |
||||||
|
this.puuid = puuid; |
||||||
|
} |
||||||
|
|
||||||
|
static Load(raw: any): Player { |
||||||
|
let p = new Player(raw.puuid); |
||||||
|
p.startElo = raw.startElo; |
||||||
|
p.gameName = raw.gameName; |
||||||
|
p.tagLine = raw.tagLine; |
||||||
|
return p; |
||||||
|
} |
||||||
|
|
||||||
|
static async TryCreateFrom(gameName: string, tagLine: string) { |
||||||
|
let account: AccountDTO; |
||||||
|
try { |
||||||
|
account = await riotAPI.account.getByRiotId({ |
||||||
|
region: PlatformId.EUROPE, |
||||||
|
gameName: gameName, |
||||||
|
tagLine: tagLine |
||||||
|
}); |
||||||
|
} catch (error) { |
||||||
|
console.error(`Riot ID not found: ${gameName}#${tagLine}!`); |
||||||
|
return; |
||||||
|
} |
||||||
|
let p = new Player(account.puuid); |
||||||
|
p.gameName = account.gameName; |
||||||
|
p.tagLine = account.tagLine; |
||||||
|
await p.updateCurrentElo(); |
||||||
|
p.startElo = p.currentElo; |
||||||
|
return p; |
||||||
|
} |
||||||
|
|
||||||
|
async updateFullName(){ |
||||||
|
const account = await riotAPI.account.getByPUUID({ |
||||||
|
region: PlatformId.EUROPE, |
||||||
|
puuid: this.puuid |
||||||
|
}); |
||||||
|
this.gameName = account.gameName; |
||||||
|
this.tagLine = account.tagLine; |
||||||
|
} |
||||||
|
|
||||||
|
async updateCurrentElo() { |
||||||
|
const tryRegion = async (region: RiotAPITypes.LoLRegion) => { |
||||||
|
return await riotAPI.league.getEntriesBySummonerId({ |
||||||
|
region: region, |
||||||
|
summonerId: (await riotAPI.summoner.getByPUUID({ |
||||||
|
region: region, |
||||||
|
puuid: this.puuid |
||||||
|
})).id |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
let entries; |
||||||
|
|
||||||
|
try { |
||||||
|
entries = await tryRegion(PlatformId.EUW1); |
||||||
|
} catch (error){ |
||||||
|
try { |
||||||
|
entries = await tryRegion(PlatformId.EUNE1); |
||||||
|
} catch (error){ |
||||||
|
let response = error as Response; |
||||||
|
console.error(await response.json()); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
let soloQ = entries.find(e => e.queueType == "RANKED_SOLO_5x5"); |
||||||
|
if (soloQ && ((soloQ.wins + soloQ.losses) >= 5)){ |
||||||
|
this.currentElo = { |
||||||
|
tier: soloQ.tier, |
||||||
|
rank: soloQ.rank, |
||||||
|
points: soloQ.leaguePoints |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
getProgress(){ |
||||||
|
return eloToNumber(this.currentElo) - eloToNumber(this.startElo); |
||||||
|
} |
||||||
|
|
||||||
|
toString() { |
||||||
|
return `${this.gameName}#${this.tagLine}`; |
||||||
|
} |
||||||
|
|
||||||
|
// noinspection JSUnusedGlobalSymbols
|
||||||
|
toJSON(){ |
||||||
|
return { |
||||||
|
puuid: this.puuid, |
||||||
|
gameName: this.gameName, |
||||||
|
tagLine: this.tagLine, |
||||||
|
startElo: this.startElo |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
interface Elo { |
||||||
|
tier: string, |
||||||
|
rank: string, |
||||||
|
points: number |
||||||
|
} |
||||||
|
|
||||||
|
export function eloToNumber(elo: Elo | undefined){ |
||||||
|
if (!elo) |
||||||
|
return 0; |
||||||
|
let tiers: Record<string, number> = { |
||||||
|
"CHALLENGER": 2800, |
||||||
|
"GRANDMASTER": 2800, |
||||||
|
"MASTER": 2800, |
||||||
|
"DIAMOND": 2400, |
||||||
|
"EMERALD": 2000, |
||||||
|
"PLATINUM": 1600, |
||||||
|
"GOLD": 1200, |
||||||
|
"SILVER": 800, |
||||||
|
"BRONZE": 400, |
||||||
|
"IRON": 0, |
||||||
|
}; |
||||||
|
|
||||||
|
let ranks: Record<string, number> = { |
||||||
|
"I": 300, |
||||||
|
"II": 200, |
||||||
|
"III": 100, |
||||||
|
"IV": 0, |
||||||
|
}; |
||||||
|
|
||||||
|
let tier = elo.tier; |
||||||
|
if (tier === "MASTER" || tier === "GRANDMASTER" || tier === "CHALLENGER") |
||||||
|
return tiers[tier] + elo.points; |
||||||
|
|
||||||
|
return tiers[tier] + ranks[elo.rank] + elo.points; |
||||||
|
} |
Loading…
Reference in new issue