-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
47bd06e
commit 888853e
Showing
7 changed files
with
225 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +1,162 @@ | ||
import ApiClient from "./api/ApiClient" | ||
import {AxiosResponse} from "axios"; | ||
import ApiClient from './api/ApiClient'; | ||
|
||
export default class HiveToolsAPI extends ApiClient { | ||
constructor(cacheTimeout: number) { | ||
super(cacheTimeout); | ||
} | ||
public static async getMonthlyLeaderboard(game: string): Promise<any[]> { | ||
const params = { | ||
game, | ||
}; | ||
const response = await this.getData('/game/monthly/{game}', params); | ||
return this.calculateExtraLeaderboardStats(response.data); | ||
} | ||
|
||
public async getMonthlyLeaderboard(game: string, cache: boolean = true) { | ||
const params = { | ||
"game": game | ||
} | ||
public static async getSpecificMonthlyLeaderboard( | ||
game: string, | ||
year: string, | ||
month: string, | ||
amount?: string, | ||
skip?: string, | ||
): Promise<any[]> { | ||
const params = { | ||
game, | ||
year, | ||
month, | ||
amount, | ||
skip, | ||
}; | ||
const response = await this.getData('/game/monthly/{game}/{year}/{month}/{amount}/{skip}', params); | ||
|
||
return (await this.getData("/game/monthly/{game}", params, cache)).data; | ||
} | ||
return this.calculateExtraLeaderboardStats(response.data); | ||
} | ||
|
||
public async getSpecificMonthlyLeaderboard(game: string, year: string, month: string, amount?: string, skip?: string, cache: boolean = true) { | ||
const params = { | ||
'game': game, | ||
'year': year, | ||
'month': month, | ||
'amount': amount, | ||
'skip': skip | ||
} | ||
public static async getMonthlyPlayerStatistics(game: string, player: string): Promise<any> { | ||
const params = { | ||
game, | ||
player, | ||
}; | ||
const response = await this.getData('/game/monthly/player/{game}/{player}', params); | ||
return this.calculateExtraPlayerStats(response.data); | ||
} | ||
|
||
return (await this.getData("/game/monthly/{game}/{year}/{month}/{amount}/{skip}", params, cache)).data; | ||
} | ||
public static async getSpecificMonthlyPlayerStatistics( | ||
game: string, | ||
player: string, | ||
year: string, | ||
month: string, | ||
): Promise<any> { | ||
const params = { | ||
game, | ||
player, | ||
year, | ||
month, | ||
}; | ||
const response = await this.getData('/game/monthly/player/{game}/{player}/{year}/{month}', params); | ||
return this.calculateExtraPlayerStats(response.data); | ||
} | ||
|
||
public static async getAllTimeLeaderboard(game: string): Promise<any[]> { | ||
const params = { | ||
game, | ||
}; | ||
const response = await this.getData('/game/monthly/player/{game}/{player}/{year}/{month}', params); | ||
return this.calculateExtraLeaderboardStats(response.data); | ||
} | ||
|
||
public static async getAllTimePlayerStatistics(game: string, player: string): Promise<any> { | ||
const params = { | ||
game, | ||
player, | ||
}; | ||
const response = await this.getData('/game/all/{game}/{player}', params); | ||
return this.calculateExtraPlayerStats(response.data); | ||
} | ||
|
||
// Calculate extra statistics for a player. There are many obscure calculations for the Hive Tools website. | ||
public static calculateExtraPlayerStats(data: any): any { | ||
({ | ||
win_percentage: data.win_percentage, | ||
win_percentage_raw: data.win_percentage_raw, | ||
games_lost: data.games_lost, | ||
} = this.calculateWinLossInfo(data)); | ||
|
||
if (data.hasOwnProperty('kills') || data.hasOwnProperty('hider_kills')) { | ||
let kills; | ||
|
||
public async getMonthlyPlayerStatistics(game: string, player: string, cache: boolean = true): Promise<AxiosResponse> { | ||
const params = { | ||
'game': game, | ||
'player': player | ||
// Use either normal kills stat or Hide and Seek kills stat. | ||
if (data.hasOwnProperty('kills')) { | ||
kills = data.kills; | ||
} else { | ||
kills = data.hider_kills; | ||
} | ||
|
||
data.kpr = kills / data.played; | ||
|
||
if (data.hasOwnProperty('deaths')) { | ||
data.dpr = data.deaths / data.played; | ||
if (data.deaths === 0) { | ||
data.kdr = kills; | ||
if (data.hasOwnProperty('seeker_kills')) { | ||
data.skdr = data.seeker_kills; | ||
} | ||
if (data.hasOwnProperty('final_kills')) { | ||
data.fkdr = data.final_kills; | ||
} | ||
if (data.hasOwnProperty('treasure_destroyed')) { | ||
data.ddr = data.treasure_destroyed; | ||
} | ||
} else { | ||
data.kdr = (kills / data.deaths).toFixed(2); | ||
if (data.hasOwnProperty('seeker_kills')) { | ||
data.skdr = data.seeker_kills / data.deaths; | ||
} | ||
if (data.hasOwnProperty('final_kills')) { | ||
data.fkdr = (data.final_kills / data.deaths).toFixed(2); | ||
} | ||
if (data.hasOwnProperty('treasure_destroyed')) { | ||
data.ddr = data.treasure_destroyed / data.deaths; | ||
} | ||
} | ||
} | ||
|
||
return (await this.getData("/game/monthly/player/{game}/{player}", params, cache)).data; | ||
return data; | ||
} | ||
|
||
public async getSpecificMonthlyPlayerStatistics(game: string, player: string, year: string, month: string, cache: boolean = true): Promise<AxiosResponse> { | ||
const params = { | ||
'game': game, | ||
'player': player, | ||
'year': year, | ||
'month': month | ||
} | ||
if (data.hasOwnProperty('coins')) { | ||
data.cpr = data.coins / data.played; | ||
|
||
return (await this.getData("/game/monthly/player/{game}/{player}/{year}/{month}", params, cache)).data; | ||
// Just in case a new game ever has the "coins" statistic | ||
if (data.hasOwnProperty('murderer_eliminations')) { | ||
data.efficiency = data.murderer_eliminations / (data.coins / 10); | ||
} | ||
} | ||
|
||
public async getAllTimeLeaderboard(game: string, cache: boolean = true): Promise<AxiosResponse> { | ||
const params = { | ||
"game": game | ||
} | ||
return (await this.getData("/game/monthly/player/{game}/{player}/{year}/{month}", params, cache)).data; | ||
if (data.hasOwnProperty('deathmatches')) { | ||
data.dmpr = data.deathmatches / data.played; | ||
} | ||
|
||
public async getAllTimePlayerStatistics(game: string, player: string, cache: boolean = true) { | ||
const params = { | ||
'game': game, | ||
'player': player | ||
} | ||
return (await this.getData("/game/all/{game}/{player}", params, cache)).data; | ||
if (data.hasOwnProperty('checkpoints')) { | ||
data.cdr = data.checkpoints / data.deaths; | ||
} | ||
} | ||
} | ||
|
||
public static calculateExtraLeaderboardStats(data: any[]): any[] { | ||
data.forEach((player, index) => { | ||
data[index] = this.calculateExtraPlayerStats(player); | ||
}); | ||
|
||
return data; | ||
} | ||
|
||
private static calculateWinLossInfo(data: any): any { | ||
const returnData: any = {}; | ||
if (data.victories === 0) { | ||
returnData.win_percentage = '0%'; | ||
returnData.win_percentage_raw = 0; | ||
} else { | ||
returnData.win_percentage_raw = data.victories / data.played; | ||
returnData.win_percentage = `${(data.win_percentage_raw * 100).toFixed(2)}%`; | ||
} | ||
returnData.games_lost = data.played - data.victories; | ||
|
||
return returnData; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,79 +1,83 @@ | ||
import Axios, {AxiosResponse} from "axios"; | ||
import Axios, { AxiosResponse } from 'axios'; | ||
|
||
export interface Params { | ||
[key: string]: any; | ||
[key: string]: any; | ||
} | ||
|
||
interface CacheData { | ||
[key: string]: { | ||
timestamp: number, | ||
data: AxiosResponse | ||
} | ||
[key: string]: { | ||
expires: number; | ||
data: AxiosResponse; | ||
}; | ||
} | ||
|
||
export default class ApiClient { | ||
cacheTimeout: number; | ||
constructor(cacheTimeout: number) { | ||
this.cacheTimeout = cacheTimeout; | ||
} | ||
private basePath: string = "https://api.playhive.com/v0"; | ||
private static basePath: string = 'https://api.playhive.com/v0'; | ||
private static cacheTimeout: number = 0; | ||
|
||
public static async callApi(path: string, pathParams: object): Promise<AxiosResponse> { | ||
return await Axios.get(this.buildUrl(path, pathParams)); | ||
} | ||
|
||
public async callApi(path: string, pathParams: object):Promise<AxiosResponse> { | ||
return await Axios.get(this.buildUrl(path, pathParams)); | ||
public static buildUrl(path: string, pathParams: Params) { | ||
if (!path.match(/^\//)) { | ||
path = '/' + path; | ||
} | ||
|
||
public buildUrl(path: string, pathParams: Params) { | ||
if (!path.match(/^\//)) { | ||
path = '/' + path; | ||
} | ||
let url: string = ApiClient.buildPath(path, pathParams); | ||
url = this.basePath + url; | ||
|
||
let url: string = ApiClient.buildPath(path, pathParams); | ||
url = this.basePath + url; | ||
return url; | ||
} | ||
|
||
return url; | ||
public static paramToString(param: any): string { | ||
if (param === undefined) { | ||
return ''; | ||
} | ||
if (param instanceof Date) { | ||
return param.toJSON(); | ||
} | ||
|
||
public static paramToString(param: any): string { | ||
if (param === undefined) { | ||
return ''; | ||
} | ||
if (param instanceof Date) { | ||
return param.toJSON(); | ||
} | ||
return param.toString(); | ||
} | ||
|
||
return param.toString(); | ||
} | ||
public static buildPath(path: string, pathParams: Params): string { | ||
return path.replace(/\{([\w-]+)\}/g, (fullMatch, key) => { | ||
let value; | ||
if (pathParams.hasOwnProperty(key)) { | ||
value = ApiClient.paramToString(pathParams[key]); | ||
} else { | ||
value = fullMatch; | ||
} | ||
|
||
public static buildPath(path: string, pathParams: Params): string { | ||
return path.replace(/\{([\w-]+)\}/g, (fullMatch, key) => { | ||
let value; | ||
if (pathParams.hasOwnProperty(key)) { | ||
value = ApiClient.paramToString(pathParams[key]); | ||
} else { | ||
value = fullMatch; | ||
} | ||
return encodeURIComponent(value); | ||
}); | ||
} | ||
|
||
return encodeURIComponent(value); | ||
}); | ||
private static cacheData: CacheData = {}; | ||
public static async getData(path: string, pathParams: Params) { | ||
const key = ApiClient.buildPath(path, pathParams); | ||
const now = new Date().getTime(); | ||
if (this.cacheData.hasOwnProperty(key)) { | ||
if (this.cacheData[key].expires < now) { | ||
this.cacheData[key] = { | ||
expires: now + this.cacheTimeout * 1000, | ||
data: await this.callApi(path, pathParams), | ||
}; | ||
} | ||
} else { | ||
this.cacheData[key] = { | ||
expires: now + this.cacheTimeout * 1000, | ||
data: await this.callApi(path, pathParams), | ||
}; | ||
} | ||
|
||
cacheData: CacheData = {}; | ||
public async getData(path: string, pathParams: Params, cache: boolean) { | ||
const key = ApiClient.buildPath(path, pathParams); | ||
const now = new Date().getTime(); | ||
if (this.cacheData.hasOwnProperty(key) && cache) { | ||
if (this.cacheData[key].timestamp + (this.cacheTimeout * 1000) < now) { | ||
this.cacheData[key] = { | ||
timestamp: now, | ||
data: await this.callApi(path, pathParams) | ||
} | ||
} | ||
} else { | ||
this.cacheData[key] = { | ||
timestamp: now, | ||
data: await this.callApi(path, pathParams) | ||
} | ||
} | ||
return this.cacheData[key].data; | ||
} | ||
} | ||
// TODO: implement rate limit checks | ||
|
||
return this.cacheData[key].data; | ||
} | ||
|
||
public static setCacheTimeout(_cacheTimeout: number) { | ||
this.cacheTimeout = _cacheTimeout; | ||
} | ||
} |
Oops, something went wrong.