More stats and faces
51
api/db.js
|
|
@ -68,6 +68,8 @@ export const AVATAR = Object.freeze({
|
||||||
NAME: Symbol("name"),
|
NAME: Symbol("name"),
|
||||||
BEP: Symbol("bep"),
|
BEP: Symbol("bep"),
|
||||||
CEP: Symbol("cep"),
|
CEP: Symbol("cep"),
|
||||||
|
GENDER: Symbol("gender_id"),
|
||||||
|
HEAD: Symbol("head_id"),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const WEAPONSTAT = Object.freeze({
|
export const WEAPONSTAT = Object.freeze({
|
||||||
|
|
@ -348,12 +350,24 @@ export async function get_weaponstats_by_avatar(id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function get_killstats() {
|
export async function get_avatar(id) {
|
||||||
try {
|
try {
|
||||||
const kills = await pool.query('SELECT count(killactivity.killer_id), killactivity.killer_id, avatar.name, avatar.bep, avatar.cep, avatar.faction_id' +
|
const avatar = await pool.query('SELECT id, name, faction_id, bep, cep, gender_id, head_id FROM avatar WHERE id=$1', [id])
|
||||||
|
return avatar.rows[0];
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code)
|
||||||
|
e.code = pg_error_inv[e.code]
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function get_top_kills() {
|
||||||
|
try {
|
||||||
|
const kills = await pool.query('SELECT count(killactivity.killer_id), killactivity.killer_id, avatar.name, avatar.bep,' +
|
||||||
|
' avatar.cep, avatar.faction_id, avatar.gender_id, avatar.head_id' +
|
||||||
' FROM killactivity' +
|
' FROM killactivity' +
|
||||||
' INNER JOIN avatar ON killactivity.killer_id = avatar.id' +
|
' INNER JOIN avatar ON killactivity.killer_id = avatar.id' +
|
||||||
' GROUP BY killactivity.killer_id, avatar.name, avatar.bep, avatar.cep, avatar.faction_id' +
|
' GROUP BY killactivity.killer_id, avatar.name, avatar.bep, avatar.cep, avatar.faction_id, avatar.gender_id, avatar.head_id' +
|
||||||
' ORDER BY count(killer_id) DESC')
|
' ORDER BY count(killer_id) DESC')
|
||||||
return kills.rows;
|
return kills.rows;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -363,6 +377,37 @@ export async function get_killstats() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function get_avatar_kd_byDate(id) {
|
||||||
|
try {
|
||||||
|
const kd = await pool.query("SELECT TO_CHAR(timestamp, 'FMMon DD, YYYY') AS date," +
|
||||||
|
' SUM(CASE WHEN killer_id = $1 THEN 1 ELSE 0 END)::int AS kills,' +
|
||||||
|
' SUM(CASE WHEN victim_id = $1 THEN 1 ELSE 0 END)::int AS deaths' +
|
||||||
|
' FROM killactivity GROUP BY date HAVING' +
|
||||||
|
' SUM(CASE WHEN killer_id = $1 THEN 1 ELSE 0 END) > 0 OR SUM(CASE WHEN victim_id = $1 THEN 1 ELSE 0 END) > 0' +
|
||||||
|
' ORDER BY date DESC', [id])
|
||||||
|
return kd.rows;
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code)
|
||||||
|
e.code = pg_error_inv[e.code]
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function get_top_kills_byDate() {
|
||||||
|
try {
|
||||||
|
const kills = await pool.query('WITH RankedKills AS (SELECT COUNT(*)::int AS kill_count,' +
|
||||||
|
' killer_id, DATE(timestamp) AS kill_date, ROW_NUMBER() OVER (PARTITION BY killer_id ORDER BY COUNT(*) DESC)::int AS row_num' +
|
||||||
|
' FROM killactivity GROUP BY killer_id, DATE(timestamp)) SELECT rk.kill_count, rk.killer_id,' +
|
||||||
|
" TO_CHAR(rk.kill_date, 'FMMon DD, YYYY') AS f_kill_date, rk.row_num, av.name, av.faction_id FROM RankedKills rk" +
|
||||||
|
' JOIN avatar av ON rk.killer_id = av.id WHERE rk.row_num = 1 ORDER BY rk.kill_count DESC LIMIT 30')
|
||||||
|
return kills.rows;
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code)
|
||||||
|
e.code = pg_error_inv[e.code]
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function get_characters_by_account(account_id) {
|
export async function get_characters_by_account(account_id) {
|
||||||
try {
|
try {
|
||||||
const characters = await pool.query('SELECT * FROM avatar WHERE account_id=$1 AND deleted=false', [account_id])
|
const characters = await pool.query('SELECT * FROM avatar WHERE account_id=$1 AND deleted=false', [account_id])
|
||||||
|
|
|
||||||
58
api/stats.js
|
|
@ -58,9 +58,9 @@ api.get('/char_stats_cep/:batch', async (req, res, next) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
api.get('/char_stats_kills', async (req, res, next) => {
|
api.get('/top_kills', async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const kills = await db.get_killstats();
|
const kills = await db.get_top_kills();
|
||||||
res.status(200).json({ kills: kills });
|
res.status(200).json({ kills: kills });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
|
|
@ -68,4 +68,58 @@ api.get('/char_stats_kills', async (req, res, next) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
api.get('/top_kills_byDate', async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const kills = await db.get_top_kills_byDate();
|
||||||
|
res.status(200).json({ kills: kills });
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
res.status(500).json({ message: 'error' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
api.get('/weaponstats/:avatar', async (req, res, next) => {
|
||||||
|
const avatar = req.params.avatar;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const weapons = await db.get_weaponstats_by_avatar(avatar);
|
||||||
|
res.status(200).json({ weapons: weapons });
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
res.status(500).json({ message: 'error' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
api.get('/avatar/:avatar', async (req, res, next) => {
|
||||||
|
const avatar = req.params.avatar;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const avatarData = await db.get_avatar(avatar);
|
||||||
|
res.status(200).json({
|
||||||
|
id: avatarData.id,
|
||||||
|
name: avatarData.name,
|
||||||
|
bep: avatarData.bep,
|
||||||
|
cep: avatarData.cep,
|
||||||
|
faction: avatarData.faction_id,
|
||||||
|
gender: avatarData.gender_id,
|
||||||
|
head: avatarData.head_id
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
res.status(500).json({ message: 'error' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
api.get('/avatar/:avatar/kd_byDate', async (req, res, next) => {
|
||||||
|
const avatar = req.params.avatar;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const kd = await db.get_avatar_kd_byDate(avatar);
|
||||||
|
res.status(200).json({ kd: kd });
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
res.status(500).json({ message: 'error' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default api;
|
export default api;
|
||||||
12
api/user.js
|
|
@ -62,16 +62,4 @@ api.get('/user/:user/logins', NEED_SESSION, async (req, res, next) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
api.get('/avatar/:avatar/weaponstats', async (req, res, next) => {
|
|
||||||
const avatar = req.params.avatar;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const weapons = await db.get_weaponstats_by_avatar(avatar);
|
|
||||||
res.status(200).json({ weapons: weapons });
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
res.status(500).json({ message: 'error' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export default api;
|
export default api;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
import { writable } from 'svelte/store';
|
|
||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
// Create a writable store to hold the selected player data
|
|
||||||
export const selectedPlayer = writable({});
|
|
||||||
270
app/statFunctions.js
Normal file
|
|
@ -0,0 +1,270 @@
|
||||||
|
|
||||||
|
export const bepRanges = [
|
||||||
|
{ rank: 1, minBEP: 0, maxBEP: 999 },
|
||||||
|
{ rank: 2, minBEP: 1000, maxBEP: 2999 },
|
||||||
|
{ rank: 3, minBEP: 3000, maxBEP: 7499 },
|
||||||
|
{ rank: 4, minBEP: 7500, maxBEP: 14999 },
|
||||||
|
{ rank: 5, minBEP: 15000, maxBEP: 29999 },
|
||||||
|
{ rank: 6, minBEP: 30000, maxBEP: 44999 },
|
||||||
|
{ rank: 7, minBEP: 45000, maxBEP: 67499 },
|
||||||
|
{ rank: 8, minBEP: 67500, maxBEP: 101249 },
|
||||||
|
{ rank: 9, minBEP: 101250, maxBEP: 126562 },
|
||||||
|
{ rank: 10, minBEP: 126563, maxBEP: 158202 },
|
||||||
|
{ rank: 11, minBEP: 158203, maxBEP: 197753 },
|
||||||
|
{ rank: 12, minBEP: 197754, maxBEP: 247191 },
|
||||||
|
{ rank: 13, minBEP: 247192, maxBEP: 308989 },
|
||||||
|
{ rank: 14, minBEP: 308990, maxBEP: 386238 },
|
||||||
|
{ rank: 15, minBEP: 368239, maxBEP: 482797 },
|
||||||
|
{ rank: 16, minBEP: 482798, maxBEP: 603496 },
|
||||||
|
{ rank: 17, minBEP: 603497, maxBEP: 754370 },
|
||||||
|
{ rank: 18, minBEP: 754371, maxBEP: 942963 },
|
||||||
|
{ rank: 19, minBEP: 942964, maxBEP: 1178704 },
|
||||||
|
{ rank: 20, minBEP: 1178705, maxBEP: 1438019 },
|
||||||
|
{ rank: 21, minBEP: 1438020, maxBEP: 1710300 },
|
||||||
|
{ rank: 22, minBEP: 1710301, maxBEP: 1988026 },
|
||||||
|
{ rank: 23, minBEP: 1988027, maxBEP: 2286230 },
|
||||||
|
{ rank: 24, minBEP: 2286231, maxBEP: 2583440 },
|
||||||
|
{ rank: 25, minBEP: 2583441, maxBEP: 2908441 },
|
||||||
|
{ rank: 26, minBEP: 2908442, maxBEP: 3237941 },
|
||||||
|
{ rank: 27, minBEP: 3237942, maxBEP: 3618441 },
|
||||||
|
{ rank: 28, minBEP: 3618442, maxBEP: 3988841 },
|
||||||
|
{ rank: 29, minBEP: 3988842, maxBEP: 4479541 },
|
||||||
|
{ rank: 30, minBEP: 4479542, maxBEP: 5027341 },
|
||||||
|
{ rank: 31, minBEP: 5027342, maxBEP: 5789641 },
|
||||||
|
{ rank: 32, minBEP: 5789642, maxBEP: 6861341 },
|
||||||
|
{ rank: 33, minBEP: 6861342, maxBEP: 8229241 },
|
||||||
|
{ rank: 34, minBEP: 8229242, maxBEP: 10000541 },
|
||||||
|
{ rank: 35, minBEP: 10000542, maxBEP: 11501741 },
|
||||||
|
{ rank: 36, minBEP: 11501742, maxBEP: 12982641 },
|
||||||
|
{ rank: 37, minBEP: 12982642, maxBEP: 14897141 },
|
||||||
|
{ rank: 38, minBEP: 14897142, maxBEP: 16894541 },
|
||||||
|
{ rank: 39, minBEP: 16894542, maxBEP: 19994541 }
|
||||||
|
];
|
||||||
|
|
||||||
|
// Define command rank ranges
|
||||||
|
export const cepRanges = [
|
||||||
|
{ rank: 0, minCEP: 0, maxCEP: 9999 },
|
||||||
|
{ rank: 1, minCEP: 10000, maxCEP: 49999 },
|
||||||
|
{ rank: 2, minCEP: 50000, maxCEP: 149999 },
|
||||||
|
{ rank: 3, minCEP: 150000, maxCEP: 299999 },
|
||||||
|
{ rank: 4, minCEP: 300000, maxCEP: 599999 }
|
||||||
|
];
|
||||||
|
|
||||||
|
// Function to calculate rank based on BEP
|
||||||
|
export function calculateBr(bep) {
|
||||||
|
// Iterate through rank ranges to find the appropriate rank
|
||||||
|
for (const range of bepRanges) {
|
||||||
|
if (bep >= range.minBEP && bep <= range.maxBEP) {
|
||||||
|
return range.rank;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Default rank if BEP doesn't match any range
|
||||||
|
return 40;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to calculate rank based on CEP
|
||||||
|
export function calculateCr(cep) {
|
||||||
|
// Iterate through rank ranges to find the appropriate rank
|
||||||
|
for (const range of cepRanges) {
|
||||||
|
if (cep >= range.minCEP && cep <= range.maxCEP) {
|
||||||
|
return range.rank;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Default rank if CEP doesn't match any range
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFactionIcon(factionId) {
|
||||||
|
if (factionId === 0) {
|
||||||
|
return "/img/tr_icon.png";
|
||||||
|
} else if (factionId === 1) {
|
||||||
|
return "/img/nc_icon.png";
|
||||||
|
} else {
|
||||||
|
return "/img/vs_icon.png";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFactionName(factionId) {
|
||||||
|
if (factionId === 0) {
|
||||||
|
return "Terran Republic";
|
||||||
|
} else if (factionId === 1) {
|
||||||
|
return "New Conglomerate";
|
||||||
|
} else {
|
||||||
|
return "Vanu Sovereignty";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to get weapon name from id
|
||||||
|
export function getWeaponName(weapon_id) {
|
||||||
|
// Iterate through weapons
|
||||||
|
for (const weapon of weaponNames) {
|
||||||
|
if (weapon_id === weapon.id) {
|
||||||
|
return weapon.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Missing
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
export const weaponNames = [
|
||||||
|
{ id: 2, name: '12mm_chaingun type weapon' },
|
||||||
|
{ id: 8, name: '15mm_chaingun type weapon' },
|
||||||
|
{ id: 12, name: '20mm_cannon type weapon' },
|
||||||
|
{ id: 13, name: '20mm_cannon_deliverer type weapon' },
|
||||||
|
{ id: 14, name: '20mm_cannon_dropship type weapon' },
|
||||||
|
{ id: 15, name: '20mm_cannon_dropship_l type weapon' },
|
||||||
|
{ id: 23, name: '75mm_cannon type weapon' },
|
||||||
|
{ id: 24, name: '75mm_lightning type weapon' },
|
||||||
|
{ id: 32, name: 'ace type weapon' },
|
||||||
|
{ id: 33, name: 'ace_deployable type weapon' },
|
||||||
|
{ id: 39, name: 'advanced_ace type weapon' },
|
||||||
|
{ id: 40, name: 'advanced_missile_launcher_t type weapon' },
|
||||||
|
{ id: 55, name: 'Spear' },
|
||||||
|
{ id: 56, name: 'Stinger' },
|
||||||
|
{ id: 57, name: 'Eraser' },
|
||||||
|
{ id: 63, name: 'apc_ballgun_l type weapon' },
|
||||||
|
{ id: 64, name: 'apc_ballgun_r type weapon' },
|
||||||
|
{ id: 69, name: 'apc_weapon_systema type weapon' },
|
||||||
|
{ id: 70, name: 'apc_weapon_systemb type weapon' },
|
||||||
|
{ id: 71, name: 'apc_weapon_systemc type weapon' },
|
||||||
|
{ id: 72, name: 'apc_weapon_systemc_nc type weapon' },
|
||||||
|
{ id: 73, name: 'apc_weapon_systemc_tr type weapon' },
|
||||||
|
{ id: 74, name: 'apc_weapon_systemc_vs type weapon' },
|
||||||
|
{ id: 75, name: 'apc_weapon_systemd type weapon' },
|
||||||
|
{ id: 76, name: 'apc_weapon_systemd_nc type weapon' },
|
||||||
|
{ id: 77, name: 'apc_weapon_systemd_tr type weapon' },
|
||||||
|
{ id: 78, name: 'apc_weapon_systemd_vs type weapon' },
|
||||||
|
{ id: 85, name: 'aphelion_immolation_cannon type weapon' },
|
||||||
|
{ id: 88, name: 'aphelion_laser type weapon' },
|
||||||
|
{ id: 90, name: 'aphelion_laser_left type weapon' },
|
||||||
|
{ id: 92, name: 'aphelion_laser_right type weapon' },
|
||||||
|
{ id: 98, name: 'aphelion_plasma_rocket_pod type weapon' },
|
||||||
|
{ id: 100, name: 'aphelion_ppa type weapon' },
|
||||||
|
{ id: 102, name: 'aphelion_ppa_left type weapon' },
|
||||||
|
{ id: 104, name: 'aphelion_ppa_right type weapon' },
|
||||||
|
{ id: 105, name: 'aphelion_starfire type weapon' },
|
||||||
|
{ id: 107, name: 'aphelion_starfire_left type weapon' },
|
||||||
|
{ id: 109, name: 'aphelion_starfire_right type weapon' },
|
||||||
|
{ id: 119, name: 'aurora_weapon_systema type weapon' },
|
||||||
|
{ id: 120, name: 'aurora_weapon_systemb type weapon' },
|
||||||
|
{ id: 136, name: 'battlewagon_weapon_systema type weapon' },
|
||||||
|
{ id: 137, name: 'battlewagon_weapon_systemb type weapon' },
|
||||||
|
{ id: 138, name: 'battlewagon_weapon_systemc type weapon' },
|
||||||
|
{ id: 139, name: 'battlewagon_weapon_systemd type weapon' },
|
||||||
|
{ id: 140, name: 'Beamer' },
|
||||||
|
{ id: 146, name: 'Bolt Driver' },
|
||||||
|
{ id: 175, name: 'Knife (TR)' },
|
||||||
|
{ id: 177, name: 'chaingun_p type weapon' },
|
||||||
|
{ id: 185, name: 'colossus_burster type weapon' },
|
||||||
|
{ id: 187, name: 'colossus_burster_left type weapon' },
|
||||||
|
{ id: 189, name: 'colossus_burster_right type weapon' },
|
||||||
|
{ id: 190, name: 'colossus_chaingun type weapon' },
|
||||||
|
{ id: 192, name: 'colossus_chaingun_left type weapon' },
|
||||||
|
{ id: 194, name: 'colossus_chaingun_right type weapon' },
|
||||||
|
{ id: 196, name: 'colossus_cluster_bomb_pod type weapon' },
|
||||||
|
{ id: 198, name: 'colossus_dual_100mm_cannons type weapon' },
|
||||||
|
{ id: 204, name: 'colossus_tank_cannon type weapon' },
|
||||||
|
{ id: 206, name: 'colossus_tank_cannon_left type weapon' },
|
||||||
|
{ id: 208, name: 'colossus_tank_cannon_right type weapon' },
|
||||||
|
{ id: 233, name: 'Cycler' },
|
||||||
|
{ id: 234, name: 'cycler_v2 type weapon' },
|
||||||
|
{ id: 235, name: 'cycler_v3 type weapon' },
|
||||||
|
{ id: 236, name: 'cycler_v4 type weapon' },
|
||||||
|
{ id: 262, name: 'dropship_rear_turret type weapon' },
|
||||||
|
{ id: 274, name: 'energy_gun type weapon' },
|
||||||
|
{ id: 276, name: 'energy_gun_nc type weapon' },
|
||||||
|
{ id: 278, name: 'energy_gun_tr type weapon' },
|
||||||
|
{ id: 280, name: 'energy_gun_vs type weapon' },
|
||||||
|
{ id: 298, name: 'flail_weapon type weapon' },
|
||||||
|
{ id: 299, name: 'Dragon' },
|
||||||
|
{ id: 304, name: 'Sweeper' },
|
||||||
|
{ id: 306, name: 'flux_cannon_thresher type weapon' },
|
||||||
|
{ id: 309, name: 'fluxpod type weapon' },
|
||||||
|
{ id: 324, name: 'Knife (VS)' },
|
||||||
|
{ id: 334, name: 'Frag Grenade' },
|
||||||
|
{ id: 336, name: 'fury_weapon_systema type weapon' },
|
||||||
|
{ id: 339, name: 'galaxy_gunship_cannon type weapon' },
|
||||||
|
{ id: 340, name: 'galaxy_gunship_gun type weapon' },
|
||||||
|
{ id: 342, name: 'galaxy_gunship_tailgun type weapon' },
|
||||||
|
{ id: 345, name: 'Gauss' },
|
||||||
|
{ id: 346, name: 'gauss_cannon type weapon' },
|
||||||
|
{ id: 371, name: 'grenade_launcher_marauder type weapon' },
|
||||||
|
{ id: 394, name: 'heavy_rail_beam_magrider type weapon' },
|
||||||
|
{ id: 396, name: 'Heavy Scout Rifle' },
|
||||||
|
{ id: 398, name: 'hellfire type weapon' },
|
||||||
|
{ id: 406, name: 'Phoenix' },
|
||||||
|
{ id: 407, name: 'AMP' },
|
||||||
|
{ id: 411, name: 'Scatter Pistol' },
|
||||||
|
{ id: 421, name: 'katana type weapon' },
|
||||||
|
{ id: 425, name: 'Lancer' },
|
||||||
|
{ id: 429, name: 'Lasher' },
|
||||||
|
{ id: 433, name: 'liberator_25mm_cannon type weapon' },
|
||||||
|
{ id: 435, name: 'liberator_bomb_bay type weapon' },
|
||||||
|
{ id: 440, name: 'iberator_weapon_system type weapon' },
|
||||||
|
{ id: 445, name: 'lightgunship_weapon_system type weapon' },
|
||||||
|
{ id: 448, name: 'lightning_weapon_system type weapon' },
|
||||||
|
{ id: 462, name: 'Maelstrom' },
|
||||||
|
{ id: 468, name: 'Knife (NC)' },
|
||||||
|
{ id: 534, name: 'mediumtransport_weapon_systemA type weapon' },
|
||||||
|
{ id: 535, name: 'mediumtransport_weapon_systemB type weapon' },
|
||||||
|
{ id: 556, name: 'Mini-Chaingun' },
|
||||||
|
{ id: 587, name: 'Falcon MAX' },
|
||||||
|
{ id: 588, name: 'Scattercannon MAX' },
|
||||||
|
{ id: 589, name: 'Sparrow MAX' },
|
||||||
|
{ id: 599, name: 'Scorpion' },
|
||||||
|
{ id: 628, name: 'particle_beam_magrider type weapon' },
|
||||||
|
{ id: 629, name: 'pellet_gun type weapon' },
|
||||||
|
{ id: 636, name: 'peregrine_dual_machine_gun type weapon' },
|
||||||
|
{ id: 638, name: 'peregrine_dual_machine_gun_left type weapon' },
|
||||||
|
{ id: 640, name: 'peregrine_dual_machine_gun_right type weapon' },
|
||||||
|
{ id: 641, name: 'peregrine_dual_rocket_pods type weapon' },
|
||||||
|
{ id: 644, name: 'peregrine_mechhammer type weapon' },
|
||||||
|
{ id: 646, name: 'peregrine_mechhammer_left type weapon' },
|
||||||
|
{ id: 648, name: 'peregrine_mechhammer_right type weapon' },
|
||||||
|
{ id: 652, name: 'peregrine_particle_cannon type weapon' },
|
||||||
|
{ id: 658, name: 'peregrine_sparrow type weapon' },
|
||||||
|
{ id: 660, name: 'peregrine_sparrow_left type weapon' },
|
||||||
|
{ id: 662, name: 'peregrine_sparrow_right type weapon' },
|
||||||
|
{ id: 666, name: 'phalanx_avcombo type weapon' },
|
||||||
|
{ id: 668, name: 'phalanx_flakcombo type weapon' },
|
||||||
|
{ id: 670, name: 'phalanx_sgl_hevgatcan type weapon' },
|
||||||
|
{ id: 672, name: 'phantasm_12mm_machinegun type weapon' },
|
||||||
|
{ id: 673, name: 'Decimator' },
|
||||||
|
{ id: 680, name: 'Plasma Grenade' },
|
||||||
|
{ id: 699, name: 'prowler_weapon_systemA type weapon' },
|
||||||
|
{ id: 700, name: 'prowler_weapon_systemB type weapon' },
|
||||||
|
{ id: 701, name: 'Pulsar' },
|
||||||
|
{ id: 705, name: 'pulsed_particle_accelerator type weapon' },
|
||||||
|
{ id: 706, name: 'Punisher' },
|
||||||
|
{ id: 709, name: 'quadassault_weapon_system type weapon' },
|
||||||
|
{ id: 714, name: 'Jackhammer' },
|
||||||
|
{ id: 716, name: 'Radiator' },
|
||||||
|
{ id: 730, name: 'Repeater' },
|
||||||
|
{ id: 737, name: 'Rocklet Rifle' },
|
||||||
|
{ id: 740, name: 'rotarychaingun_mosquito type weapon' },
|
||||||
|
{ id: 743, name: 'router_telepad type weapon' },
|
||||||
|
{ id: 747, name: 'scythe type weapon' },
|
||||||
|
{ id: 761, name: 'six_shooter type weapon' },
|
||||||
|
{ id: 788, name: 'skyguard_weapon_system type weapon' },
|
||||||
|
{ id: 817, name: 'Spiker' },
|
||||||
|
{ id: 822, name: 'spitfire_aa_weapon type weapon' },
|
||||||
|
{ id: 827, name: 'spitfire_weapon type weapon' },
|
||||||
|
{ id: 838, name: 'Striker' },
|
||||||
|
{ id: 845, name: 'Suppressor' },
|
||||||
|
{ id: 864, name: 'Thumper' },
|
||||||
|
{ id: 866, name: 'thunderer_weapon_systema type weapon' },
|
||||||
|
{ id: 867, name: 'thunderer_weapon_systemb type weapon' },
|
||||||
|
{ id: 888, name: 'Burster MAX' },
|
||||||
|
{ id: 889, name: 'Dual Cycler MAX' },
|
||||||
|
{ id: 890, name: 'Pounder MAX' },
|
||||||
|
{ id: 927, name: 'vanguard_weapon_system type weapon' },
|
||||||
|
{ id: 945, name: 'vanu_sentry_turret_weapon type weapon' },
|
||||||
|
{ id: 968, name: 'Comet MAX' },
|
||||||
|
{ id: 969, name: 'Quasar MAX' },
|
||||||
|
{ id: 970, name: 'Starfire MAX' },
|
||||||
|
{ id: 987, name: 'vulture_bomb_bay type weapon' },
|
||||||
|
{ id: 990, name: 'vulture_nose_weapon_system type weapon' },
|
||||||
|
{ id: 992, name: 'vulture_tail_cannon type weapon' },
|
||||||
|
{ id: 1002, name: 'wasp_weapon_system type weapon' },
|
||||||
|
{ id: 1003, name: 'winchester type weapon' }
|
||||||
|
]
|
||||||
|
|
@ -2,31 +2,66 @@
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import Alert from '../components/Alert'
|
import Alert from '../components/Alert'
|
||||||
import FactionIcon from '../components/FactionIcon'
|
import { bepRanges, cepRanges, calculateBr, calculateCr, getFactionIcon, getFactionName,
|
||||||
import { selectedPlayer } from '../player';
|
weaponNames, getWeaponName } from '../statFunctions';
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
get_iWeaponStats();
|
get_iWeaponStats();
|
||||||
|
get_avatar();
|
||||||
|
get_avatarKdByDate();
|
||||||
});
|
});
|
||||||
|
|
||||||
let player; // Define player variable to hold player data
|
export let params;
|
||||||
|
|
||||||
let iWeapons = [];
|
let iWeapons = [];
|
||||||
let alert;
|
let alert;
|
||||||
|
let avatar = {};
|
||||||
let iWeaponsKillsSum
|
let iWeaponsKillsSum
|
||||||
|
let kdByDate = [];
|
||||||
|
let url = params.id || avatar.id
|
||||||
|
let face;
|
||||||
|
let totalKills
|
||||||
|
let totalDeaths
|
||||||
|
|
||||||
// Subscribe to the selectedPlayer store to get the selected player data
|
const weaponstatsUrl = "/api/weaponstats/"+url
|
||||||
selectedPlayer.subscribe(value => {
|
const avatarUrl = "/api/avatar/"+url
|
||||||
player = value; // Assign selected player data to player variable
|
const avatarKdUrl = "/api/avatar/"+url+"/kd_byDate"
|
||||||
});
|
|
||||||
|
|
||||||
const url = "/api/avatar/"+$selectedPlayer.id+"/weaponstats"
|
async function get_avatar() {
|
||||||
|
try {
|
||||||
|
const resp = await axios.get(avatarUrl);
|
||||||
|
avatar = resp.data
|
||||||
|
const head = avatar.gender.toString() + avatar.head.toString();
|
||||||
|
face = "/img/faces/" + head + ".png";
|
||||||
|
// Reset alert message if needed
|
||||||
|
alert.message("");
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
alert.message("Failed to fetch stats from server");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function get_avatarKdByDate() {
|
||||||
|
try {
|
||||||
|
const resp = await axios.get(avatarKdUrl);
|
||||||
|
const stats = resp.data;
|
||||||
|
kdByDate = stats.kd;
|
||||||
|
totalKills = kdByDate.reduce((total, kd) => total + kd.kills, 0);
|
||||||
|
totalDeaths = kdByDate.reduce((total, kd) => total + kd.deaths, 0);
|
||||||
|
// Reset alert message if needed
|
||||||
|
alert.message("");
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
alert.message("Failed to fetch stats from server");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function get_iWeaponStats() {
|
async function get_iWeaponStats() {
|
||||||
try {
|
try {
|
||||||
const ids = [55, 56, 57, 140, 146, 175, 233, 299, 304, 324, 334, 345, 396, 406,
|
const ids = [55, 56, 57, 140, 146, 175, 233, 299, 304, 324, 334, 345, 396, 406,
|
||||||
407, 411, 425, 429, 462, 468, 556, 587, 588, 589, 599, 673, 680, 701, 706, 714,
|
407, 411, 425, 429, 462, 468, 556, 587, 588, 589, 599, 673, 680, 701, 706, 714,
|
||||||
716, 730, 737, 817, 838, 845, 864, 888, 889, 890, 968, 969, 970];
|
716, 730, 737, 817, 838, 845, 864, 888, 889, 890, 968, 969, 970];
|
||||||
const resp = await axios.get(url);
|
const resp = await axios.get(weaponstatsUrl);
|
||||||
const stats = resp.data;
|
const stats = resp.data;
|
||||||
const filteredWeapons = stats.weapons.filter(weapon => {
|
const filteredWeapons = stats.weapons.filter(weapon => {
|
||||||
return ids.includes(weapon.weapon_id);
|
return ids.includes(weapon.weapon_id);
|
||||||
|
|
@ -65,208 +100,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to get weapon name from id
|
|
||||||
function getWeaponName(weapon_id) {
|
|
||||||
// Iterate through weapons
|
|
||||||
for (const weapon of weaponNames) {
|
|
||||||
if (weapon_id === weapon.id) {
|
|
||||||
return weapon.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Missing
|
|
||||||
return "unknown";
|
|
||||||
}
|
|
||||||
|
|
||||||
const weaponNames = [
|
|
||||||
{ id: 2, name: '12mm_chaingun type weapon' },
|
|
||||||
{ id: 8, name: '15mm_chaingun type weapon' },
|
|
||||||
{ id: 12, name: '20mm_cannon type weapon' },
|
|
||||||
{ id: 13, name: '20mm_cannon_deliverer type weapon' },
|
|
||||||
{ id: 14, name: '20mm_cannon_dropship type weapon' },
|
|
||||||
{ id: 15, name: '20mm_cannon_dropship_l type weapon' },
|
|
||||||
{ id: 23, name: '75mm_cannon type weapon' },
|
|
||||||
{ id: 24, name: '75mm_lightning type weapon' },
|
|
||||||
{ id: 32, name: 'ace type weapon' },
|
|
||||||
{ id: 33, name: 'ace_deployable type weapon' },
|
|
||||||
{ id: 39, name: 'advanced_ace type weapon' },
|
|
||||||
{ id: 40, name: 'advanced_missile_launcher_t type weapon' },
|
|
||||||
{ id: 55, name: 'Spear' },
|
|
||||||
{ id: 56, name: 'Stinger' },
|
|
||||||
{ id: 57, name: 'Eraser' },
|
|
||||||
{ id: 63, name: 'apc_ballgun_l type weapon' },
|
|
||||||
{ id: 64, name: 'apc_ballgun_r type weapon' },
|
|
||||||
{ id: 69, name: 'apc_weapon_systema type weapon' },
|
|
||||||
{ id: 70, name: 'apc_weapon_systemb type weapon' },
|
|
||||||
{ id: 71, name: 'apc_weapon_systemc type weapon' },
|
|
||||||
{ id: 72, name: 'apc_weapon_systemc_nc type weapon' },
|
|
||||||
{ id: 73, name: 'apc_weapon_systemc_tr type weapon' },
|
|
||||||
{ id: 74, name: 'apc_weapon_systemc_vs type weapon' },
|
|
||||||
{ id: 75, name: 'apc_weapon_systemd type weapon' },
|
|
||||||
{ id: 76, name: 'apc_weapon_systemd_nc type weapon' },
|
|
||||||
{ id: 77, name: 'apc_weapon_systemd_tr type weapon' },
|
|
||||||
{ id: 78, name: 'apc_weapon_systemd_vs type weapon' },
|
|
||||||
{ id: 85, name: 'aphelion_immolation_cannon type weapon' },
|
|
||||||
{ id: 88, name: 'aphelion_laser type weapon' },
|
|
||||||
{ id: 90, name: 'aphelion_laser_left type weapon' },
|
|
||||||
{ id: 92, name: 'aphelion_laser_right type weapon' },
|
|
||||||
{ id: 98, name: 'aphelion_plasma_rocket_pod type weapon' },
|
|
||||||
{ id: 100, name: 'aphelion_ppa type weapon' },
|
|
||||||
{ id: 102, name: 'aphelion_ppa_left type weapon' },
|
|
||||||
{ id: 104, name: 'aphelion_ppa_right type weapon' },
|
|
||||||
{ id: 105, name: 'aphelion_starfire type weapon' },
|
|
||||||
{ id: 107, name: 'aphelion_starfire_left type weapon' },
|
|
||||||
{ id: 109, name: 'aphelion_starfire_right type weapon' },
|
|
||||||
{ id: 119, name: 'aurora_weapon_systema type weapon' },
|
|
||||||
{ id: 120, name: 'aurora_weapon_systemb type weapon' },
|
|
||||||
{ id: 136, name: 'battlewagon_weapon_systema type weapon' },
|
|
||||||
{ id: 137, name: 'battlewagon_weapon_systemb type weapon' },
|
|
||||||
{ id: 138, name: 'battlewagon_weapon_systemc type weapon' },
|
|
||||||
{ id: 139, name: 'battlewagon_weapon_systemd type weapon' },
|
|
||||||
{ id: 140, name: 'Beamer' },
|
|
||||||
{ id: 146, name: 'Bolt Driver' },
|
|
||||||
{ id: 175, name: 'Knife (TR)' },
|
|
||||||
{ id: 177, name: 'chaingun_p type weapon' },
|
|
||||||
{ id: 185, name: 'colossus_burster type weapon' },
|
|
||||||
{ id: 187, name: 'colossus_burster_left type weapon' },
|
|
||||||
{ id: 189, name: 'colossus_burster_right type weapon' },
|
|
||||||
{ id: 190, name: 'colossus_chaingun type weapon' },
|
|
||||||
{ id: 192, name: 'colossus_chaingun_left type weapon' },
|
|
||||||
{ id: 194, name: 'colossus_chaingun_right type weapon' },
|
|
||||||
{ id: 196, name: 'colossus_cluster_bomb_pod type weapon' },
|
|
||||||
{ id: 198, name: 'colossus_dual_100mm_cannons type weapon' },
|
|
||||||
{ id: 204, name: 'colossus_tank_cannon type weapon' },
|
|
||||||
{ id: 206, name: 'colossus_tank_cannon_left type weapon' },
|
|
||||||
{ id: 208, name: 'colossus_tank_cannon_right type weapon' },
|
|
||||||
{ id: 233, name: 'Cycler' },
|
|
||||||
{ id: 234, name: 'cycler_v2 type weapon' },
|
|
||||||
{ id: 235, name: 'cycler_v3 type weapon' },
|
|
||||||
{ id: 236, name: 'cycler_v4 type weapon' },
|
|
||||||
{ id: 262, name: 'dropship_rear_turret type weapon' },
|
|
||||||
{ id: 274, name: 'energy_gun type weapon' },
|
|
||||||
{ id: 276, name: 'energy_gun_nc type weapon' },
|
|
||||||
{ id: 278, name: 'energy_gun_tr type weapon' },
|
|
||||||
{ id: 280, name: 'energy_gun_vs type weapon' },
|
|
||||||
{ id: 298, name: 'flail_weapon type weapon' },
|
|
||||||
{ id: 299, name: 'Dragon' },
|
|
||||||
{ id: 304, name: 'Sweeper' },
|
|
||||||
{ id: 306, name: 'flux_cannon_thresher type weapon' },
|
|
||||||
{ id: 309, name: 'fluxpod type weapon' },
|
|
||||||
{ id: 324, name: 'Knife (VS)' },
|
|
||||||
{ id: 334, name: 'Frag Grenade' },
|
|
||||||
{ id: 336, name: 'fury_weapon_systema type weapon' },
|
|
||||||
{ id: 339, name: 'galaxy_gunship_cannon type weapon' },
|
|
||||||
{ id: 340, name: 'galaxy_gunship_gun type weapon' },
|
|
||||||
{ id: 342, name: 'galaxy_gunship_tailgun type weapon' },
|
|
||||||
{ id: 345, name: 'Gauss' },
|
|
||||||
{ id: 346, name: 'gauss_cannon type weapon' },
|
|
||||||
{ id: 371, name: 'grenade_launcher_marauder type weapon' },
|
|
||||||
{ id: 394, name: 'heavy_rail_beam_magrider type weapon' },
|
|
||||||
{ id: 396, name: 'Heavy Scout Rifle' },
|
|
||||||
{ id: 398, name: 'hellfire type weapon' },
|
|
||||||
{ id: 406, name: 'Phoenix' },
|
|
||||||
{ id: 407, name: 'AMP' },
|
|
||||||
{ id: 411, name: 'Scatter Pistol' },
|
|
||||||
{ id: 421, name: 'katana type weapon' },
|
|
||||||
{ id: 425, name: 'Lancer' },
|
|
||||||
{ id: 429, name: 'Lasher' },
|
|
||||||
{ id: 433, name: 'liberator_25mm_cannon type weapon' },
|
|
||||||
{ id: 435, name: 'liberator_bomb_bay type weapon' },
|
|
||||||
{ id: 440, name: 'iberator_weapon_system type weapon' },
|
|
||||||
{ id: 445, name: 'lightgunship_weapon_system type weapon' },
|
|
||||||
{ id: 448, name: 'lightning_weapon_system type weapon' },
|
|
||||||
{ id: 462, name: 'Maelstrom' },
|
|
||||||
{ id: 468, name: 'Knife (NC)' },
|
|
||||||
{ id: 534, name: 'mediumtransport_weapon_systemA type weapon' },
|
|
||||||
{ id: 535, name: 'mediumtransport_weapon_systemB type weapon' },
|
|
||||||
{ id: 556, name: 'Mini-Chaingun' },
|
|
||||||
{ id: 587, name: 'Falcon MAX' },
|
|
||||||
{ id: 588, name: 'Scattercannon MAX' },
|
|
||||||
{ id: 589, name: 'Sparrow MAX' },
|
|
||||||
{ id: 599, name: 'Scorpion' },
|
|
||||||
{ id: 628, name: 'particle_beam_magrider type weapon' },
|
|
||||||
{ id: 629, name: 'pellet_gun type weapon' },
|
|
||||||
{ id: 636, name: 'peregrine_dual_machine_gun type weapon' },
|
|
||||||
{ id: 638, name: 'peregrine_dual_machine_gun_left type weapon' },
|
|
||||||
{ id: 640, name: 'peregrine_dual_machine_gun_right type weapon' },
|
|
||||||
{ id: 641, name: 'peregrine_dual_rocket_pods type weapon' },
|
|
||||||
{ id: 644, name: 'peregrine_mechhammer type weapon' },
|
|
||||||
{ id: 646, name: 'peregrine_mechhammer_left type weapon' },
|
|
||||||
{ id: 648, name: 'peregrine_mechhammer_right type weapon' },
|
|
||||||
{ id: 652, name: 'peregrine_particle_cannon type weapon' },
|
|
||||||
{ id: 658, name: 'peregrine_sparrow type weapon' },
|
|
||||||
{ id: 660, name: 'peregrine_sparrow_left type weapon' },
|
|
||||||
{ id: 662, name: 'peregrine_sparrow_right type weapon' },
|
|
||||||
{ id: 666, name: 'phalanx_avcombo type weapon' },
|
|
||||||
{ id: 668, name: 'phalanx_flakcombo type weapon' },
|
|
||||||
{ id: 670, name: 'phalanx_sgl_hevgatcan type weapon' },
|
|
||||||
{ id: 672, name: 'phantasm_12mm_machinegun type weapon' },
|
|
||||||
{ id: 673, name: 'Decimator' },
|
|
||||||
{ id: 680, name: 'Plasma Grenade' },
|
|
||||||
{ id: 699, name: 'prowler_weapon_systemA type weapon' },
|
|
||||||
{ id: 700, name: 'prowler_weapon_systemB type weapon' },
|
|
||||||
{ id: 701, name: 'Pulsar' },
|
|
||||||
{ id: 705, name: 'pulsed_particle_accelerator type weapon' },
|
|
||||||
{ id: 706, name: 'Punisher' },
|
|
||||||
{ id: 709, name: 'quadassault_weapon_system type weapon' },
|
|
||||||
{ id: 714, name: 'Jackhammer' },
|
|
||||||
{ id: 716, name: 'Radiator' },
|
|
||||||
{ id: 730, name: 'Repeater' },
|
|
||||||
{ id: 737, name: 'Rocklet Rifle' },
|
|
||||||
{ id: 740, name: 'rotarychaingun_mosquito type weapon' },
|
|
||||||
{ id: 743, name: 'router_telepad type weapon' },
|
|
||||||
{ id: 747, name: 'scythe type weapon' },
|
|
||||||
{ id: 761, name: 'six_shooter type weapon' },
|
|
||||||
{ id: 788, name: 'skyguard_weapon_system type weapon' },
|
|
||||||
{ id: 817, name: 'Spiker' },
|
|
||||||
{ id: 822, name: 'spitfire_aa_weapon type weapon' },
|
|
||||||
{ id: 827, name: 'spitfire_weapon type weapon' },
|
|
||||||
{ id: 838, name: 'Striker' },
|
|
||||||
{ id: 845, name: 'Suppressor' },
|
|
||||||
{ id: 864, name: 'Thumper' },
|
|
||||||
{ id: 866, name: 'thunderer_weapon_systema type weapon' },
|
|
||||||
{ id: 867, name: 'thunderer_weapon_systemb type weapon' },
|
|
||||||
{ id: 888, name: 'Burster MAX' },
|
|
||||||
{ id: 889, name: 'Dual Cycler MAX' },
|
|
||||||
{ id: 890, name: 'Pounder MAX' },
|
|
||||||
{ id: 927, name: 'vanguard_weapon_system type weapon' },
|
|
||||||
{ id: 945, name: 'vanu_sentry_turret_weapon type weapon' },
|
|
||||||
{ id: 968, name: 'Comet MAX' },
|
|
||||||
{ id: 969, name: 'Quasar MAX' },
|
|
||||||
{ id: 970, name: 'Starfire MAX' },
|
|
||||||
{ id: 987, name: 'vulture_bomb_bay type weapon' },
|
|
||||||
{ id: 990, name: 'vulture_nose_weapon_system type weapon' },
|
|
||||||
{ id: 992, name: 'vulture_tail_cannon type weapon' },
|
|
||||||
{ id: 1002, name: 'wasp_weapon_system type weapon' },
|
|
||||||
{ id: 1003, name: 'winchester type weapon' }
|
|
||||||
]
|
|
||||||
|
|
||||||
function getFactionIcon(factionId) {
|
|
||||||
if (factionId === 0) {
|
|
||||||
return "/img/tr_icon.png";
|
|
||||||
} else if (factionId === 1) {
|
|
||||||
return "/img/nc_icon.png";
|
|
||||||
} else {
|
|
||||||
return "/img/vs_icon.png";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFactionName(factionId) {
|
|
||||||
if (factionId === 0) {
|
|
||||||
return "Terran Republic";
|
|
||||||
} else if (factionId === 1) {
|
|
||||||
return "New Conglomerate";
|
|
||||||
} else {
|
|
||||||
return "Vanu Sovereignty";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<title>Player Stats</title>
|
<title>Player Stats</title>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<table>
|
<table width="70%">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="%50" valign="top">
|
<td width="%50" valign="top">
|
||||||
|
|
@ -274,20 +114,33 @@ const weaponNames = [
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<span style="color:lightgrey;">Character Name:</span> {$selectedPlayer.name}<br>
|
<span style="color:lightgrey;">Character Name:</span> {avatar.name}<br>
|
||||||
<span style="color:lightgrey;">Empire:</span> {getFactionName($selectedPlayer.faction_id)}<br>
|
<span style="color:lightgrey;">Empire:</span> {getFactionName(avatar.faction)}
|
||||||
</td>
|
</td>
|
||||||
<td><img height="60" src={getFactionIcon($selectedPlayer.faction_id)} alt={selectedPlayer.faction_id} /></td>
|
<td><img height="60" src={getFactionIcon(avatar.faction)} alt={avatar.faction}/></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img height="100" src={face} alt="{face} not found"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<span style="color:lightgrey;">Battle Rank:</span> {$selectedPlayer.br}<br>
|
<span style="color:lightgrey;">Battle Rank:</span> {calculateBr(avatar.bep)}<br>
|
||||||
<span style="color:lightgrey;">Command Rank:</span> {$selectedPlayer.cr}<br>
|
<span style="color:lightgrey;">Command Rank:</span> {calculateCr(avatar.cep)}<br>
|
||||||
|
<span style="color:lightgrey;">Kills:</span> {totalKills}<br>
|
||||||
|
<span style="color:lightgrey;">Deaths:</span> {totalDeaths}<br>
|
||||||
|
<span style="color:lightgrey;">KDR:</span>
|
||||||
|
{#if totalDeaths !== 0}
|
||||||
|
{(totalKills / totalDeaths).toFixed(2)}
|
||||||
|
{:else}
|
||||||
|
{totalKills}
|
||||||
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<br>
|
<br>
|
||||||
|
<br>
|
||||||
|
<span style="color:lightgrey;">Kills by Weapon - Total: </span>{iWeaponsKillsSum}
|
||||||
<table class="table table-sm table-dark table-responsive-md table-striped table-hover">
|
<table class="table table-sm table-dark table-responsive-md table-striped table-hover">
|
||||||
<thead class="thead-light">
|
<thead class="thead-light">
|
||||||
<th>Weapon</th>
|
<th>Weapon</th>
|
||||||
|
|
@ -310,4 +163,28 @@ const weaponNames = [
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<span style="color:lightgrey;">Total Kills: </span>{iWeaponsKillsSum}
|
<br>
|
||||||
|
<span style="color:lightgrey;">Daily Stats</span>
|
||||||
|
<table class="table table-sm table-dark table-responsive-md table-striped table-hover">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<th>Date</th>
|
||||||
|
<th>Kills</th>
|
||||||
|
<th>Deaths</th>
|
||||||
|
<th>KDR</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each kdByDate as date}
|
||||||
|
<tr>
|
||||||
|
<td>{date.date}</td>
|
||||||
|
<td>{date.kills}</td>
|
||||||
|
<td>{date.deaths}</td>
|
||||||
|
<td>{#if date.deaths !== 0}
|
||||||
|
{(date.kills / date.deaths).toFixed(2)}
|
||||||
|
{:else}
|
||||||
|
{date.kills}
|
||||||
|
{/if}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,19 @@
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import Alert from '../components/Alert'
|
import Alert from '../components/Alert'
|
||||||
import FactionIcon from '../components/FactionIcon'
|
import { bepRanges, cepRanges, calculateBr, calculateCr, getFactionIcon } from '../statFunctions';
|
||||||
import { selectedPlayer } from '../player';
|
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
get_BEPleaderboard();
|
get_BEPleaderboard();
|
||||||
get_CEPleaderboard();
|
get_CEPleaderboard();
|
||||||
get_kills();
|
get_kills();
|
||||||
|
get_topDateKills();
|
||||||
});
|
});
|
||||||
|
|
||||||
let bepPlayers = [];
|
let bepPlayers = [];
|
||||||
let cepPlayers = [];
|
let cepPlayers = [];
|
||||||
let kills = [];
|
let kills = [];
|
||||||
|
let dateKills = [];
|
||||||
let alert;
|
let alert;
|
||||||
|
|
||||||
async function get_BEPleaderboard() {
|
async function get_BEPleaderboard() {
|
||||||
|
|
@ -44,7 +45,7 @@
|
||||||
|
|
||||||
async function get_kills() {
|
async function get_kills() {
|
||||||
try {
|
try {
|
||||||
const resp = await axios.get("/api/char_stats_kills");
|
const resp = await axios.get("/api/top_kills");
|
||||||
const stats = resp.data;
|
const stats = resp.data;
|
||||||
kills = stats.kills;
|
kills = stats.kills;
|
||||||
// Reset alert message if needed
|
// Reset alert message if needed
|
||||||
|
|
@ -55,101 +56,19 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define battle rank ranges
|
async function get_topDateKills() {
|
||||||
const rankRanges = [
|
try {
|
||||||
{ rank: 1, minBEP: 0, maxBEP: 999 },
|
const resp = await axios.get("/api/top_kills_byDate");
|
||||||
{ rank: 2, minBEP: 1000, maxBEP: 2999 },
|
const stats = resp.data;
|
||||||
{ rank: 3, minBEP: 3000, maxBEP: 7499 },
|
dateKills = stats.kills;
|
||||||
{ rank: 4, minBEP: 7500, maxBEP: 14999 },
|
// Reset alert message if needed
|
||||||
{ rank: 5, minBEP: 15000, maxBEP: 29999 },
|
alert.message("");
|
||||||
{ rank: 6, minBEP: 30000, maxBEP: 44999 },
|
} catch (e) {
|
||||||
{ rank: 7, minBEP: 45000, maxBEP: 67499 },
|
console.log(e);
|
||||||
{ rank: 8, minBEP: 67500, maxBEP: 101249 },
|
alert.message("Failed to fetch stats from server");
|
||||||
{ rank: 9, minBEP: 101250, maxBEP: 126562 },
|
|
||||||
{ rank: 10, minBEP: 126563, maxBEP: 158202 },
|
|
||||||
{ rank: 11, minBEP: 158203, maxBEP: 197753 },
|
|
||||||
{ rank: 12, minBEP: 197754, maxBEP: 247191 },
|
|
||||||
{ rank: 13, minBEP: 247192, maxBEP: 308989 },
|
|
||||||
{ rank: 14, minBEP: 308990, maxBEP: 386238 },
|
|
||||||
{ rank: 15, minBEP: 368239, maxBEP: 482797 },
|
|
||||||
{ rank: 16, minBEP: 482798, maxBEP: 603496 },
|
|
||||||
{ rank: 17, minBEP: 603497, maxBEP: 754370 },
|
|
||||||
{ rank: 18, minBEP: 754371, maxBEP: 942963 },
|
|
||||||
{ rank: 19, minBEP: 942964, maxBEP: 1178704 },
|
|
||||||
{ rank: 20, minBEP: 1178705, maxBEP: 1438019 },
|
|
||||||
{ rank: 21, minBEP: 1438020, maxBEP: 1710300 },
|
|
||||||
{ rank: 22, minBEP: 1710301, maxBEP: 1988026 },
|
|
||||||
{ rank: 23, minBEP: 1988027, maxBEP: 2286230 },
|
|
||||||
{ rank: 24, minBEP: 2286231, maxBEP: 2583440 },
|
|
||||||
{ rank: 25, minBEP: 2583441, maxBEP: 2908441 },
|
|
||||||
{ rank: 26, minBEP: 2908442, maxBEP: 3237941 },
|
|
||||||
{ rank: 27, minBEP: 3237942, maxBEP: 3618441 },
|
|
||||||
{ rank: 28, minBEP: 3618442, maxBEP: 3988841 },
|
|
||||||
{ rank: 29, minBEP: 3988842, maxBEP: 4479541 },
|
|
||||||
{ rank: 30, minBEP: 4479542, maxBEP: 5027341 },
|
|
||||||
{ rank: 31, minBEP: 5027342, maxBEP: 5789641 },
|
|
||||||
{ rank: 32, minBEP: 5789642, maxBEP: 6861341 },
|
|
||||||
{ rank: 33, minBEP: 6861342, maxBEP: 8229241 },
|
|
||||||
{ rank: 34, minBEP: 8229242, maxBEP: 10000541 },
|
|
||||||
{ rank: 35, minBEP: 10000542, maxBEP: 11501741 },
|
|
||||||
{ rank: 36, minBEP: 11501742, maxBEP: 12982641 },
|
|
||||||
{ rank: 37, minBEP: 12982642, maxBEP: 14897141 },
|
|
||||||
{ rank: 38, minBEP: 14897142, maxBEP: 16894541 },
|
|
||||||
{ rank: 39, minBEP: 16894542, maxBEP: 19994541 }
|
|
||||||
];
|
|
||||||
|
|
||||||
// Define command rank ranges
|
|
||||||
const crRankRanges = [
|
|
||||||
{ rank: 0, minCEP: 0, maxCEP: 9999 },
|
|
||||||
{ rank: 1, minCEP: 10000, maxCEP: 49999 },
|
|
||||||
{ rank: 2, minCEP: 50000, maxCEP: 149999 },
|
|
||||||
{ rank: 3, minCEP: 150000, maxCEP: 299999 },
|
|
||||||
{ rank: 4, minCEP: 300000, maxCEP: 599999 }
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
function getFactionIcon(factionId) {
|
|
||||||
if (factionId === 0) {
|
|
||||||
return "/img/tr_icon.png";
|
|
||||||
} else if (factionId === 1) {
|
|
||||||
return "/img/nc_icon.png";
|
|
||||||
} else {
|
|
||||||
return "/img/vs_icon.png";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to calculate rank based on BEP
|
|
||||||
function calculateRank(bep) {
|
|
||||||
// Iterate through rank ranges to find the appropriate rank
|
|
||||||
for (const range of rankRanges) {
|
|
||||||
if (bep >= range.minBEP && bep <= range.maxBEP) {
|
|
||||||
return range.rank;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Default rank if BEP doesn't match any range
|
|
||||||
return 40;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to calculate rank based on CEP
|
|
||||||
function calculateCrRank(cep) {
|
|
||||||
// Iterate through rank ranges to find the appropriate rank
|
|
||||||
for (const range of crRankRanges) {
|
|
||||||
if (cep >= range.minCEP && cep <= range.maxCEP) {
|
|
||||||
return range.rank;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Default rank if CEP doesn't match any range
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleClick = (clickedPlayer) => {
|
|
||||||
selectedPlayer.set({id: clickedPlayer.id, name: clickedPlayer.name, faction_id: clickedPlayer.faction_id, br: calculateRank(clickedPlayer.bep), cr: calculateCrRank(clickedPlayer.cep)});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleKillClick = (clickedPlayer) => {
|
|
||||||
selectedPlayer.set({id: clickedPlayer.killer_id, name: clickedPlayer.name, faction_id: clickedPlayer.faction_id, br: calculateRank(clickedPlayer.bep), cr: calculateCrRank(clickedPlayer.cep)});
|
|
||||||
};
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
|
@ -167,6 +86,9 @@
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" id="cr-tab" data-toggle="tab" href="#cr" role="tab" aria-controls="cr" aria-selected="false">Command Rank</a>
|
<a class="nav-link" id="cr-tab" data-toggle="tab" href="#cr" role="tab" aria-controls="cr" aria-selected="false">Command Rank</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" id="top-tab" data-toggle="tab" href="#top" role="tab" aria-controls="top" aria-selected="false">Top X</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="tab-content" id="tabs-tabContent">
|
<div class="tab-content" id="tabs-tabContent">
|
||||||
|
|
@ -184,10 +106,10 @@
|
||||||
<td>{$index + 1}</td>
|
<td>{$index + 1}</td>
|
||||||
<td>
|
<td>
|
||||||
<img height="24" src={getFactionIcon(player.faction_id)} alt={player.faction_id} />
|
<img height="24" src={getFactionIcon(player.faction_id)} alt={player.faction_id} />
|
||||||
<a href="/avatar/{player.id}" on:click={() => handleClick(player)}>{player.name}</a>
|
<a href="/avatar/{player.id}">{player.name}</a>
|
||||||
</td>
|
</td>
|
||||||
<td>{calculateRank(player.bep)}</td>
|
<td>{calculateBr(player.bep)}</td>
|
||||||
<td>{calculateCrRank(player.cep)}</td>
|
<td>{calculateCr(player.cep)}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
@ -208,10 +130,10 @@
|
||||||
<td>{$index + 1}</td>
|
<td>{$index + 1}</td>
|
||||||
<td>
|
<td>
|
||||||
<img height="24" src={getFactionIcon(player.faction_id)} alt={player.faction_id} />
|
<img height="24" src={getFactionIcon(player.faction_id)} alt={player.faction_id} />
|
||||||
<a href="/avatar/{player.id}" on:click={() => handleClick(player)}>{player.name}</a>
|
<a href="/avatar/{player.id}">{player.name}</a>
|
||||||
</td>
|
</td>
|
||||||
<td>{calculateRank(player.bep)}</td>
|
<td>{calculateBr(player.bep)}</td>
|
||||||
<td>{calculateCrRank(player.cep)}</td>
|
<td>{calculateCr(player.cep)}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
@ -233,14 +155,38 @@
|
||||||
<td>{$index + 1}</td>
|
<td>{$index + 1}</td>
|
||||||
<td>
|
<td>
|
||||||
<img height="24" src={getFactionIcon(killer.faction_id)} alt={killer.faction_id} />
|
<img height="24" src={getFactionIcon(killer.faction_id)} alt={killer.faction_id} />
|
||||||
<a href="/avatar/{killer.killer_id}" on:click={() => handleKillClick(killer)}>{killer.name}</a>
|
<a href="/avatar/{killer.killer_id}">{killer.name}</a>
|
||||||
</td>
|
</td>
|
||||||
<td>{killer.count}</td>
|
<td>{killer.count}</td>
|
||||||
<td>{calculateRank(killer.bep)}</td>
|
<td>{calculateBr(killer.bep)}</td>
|
||||||
<td>{calculateCrRank(killer.cep)}</td>
|
<td>{calculateCr(killer.cep)}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="tab-pane" id="top" role="tabpanel" aria-labelledby="top-tab">
|
||||||
|
<table class="table table-sm table-dark table-responsive-md table-striped table-hover">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<th>#</th>
|
||||||
|
<th>Date</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Kills</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each dateKills as player, $index}
|
||||||
|
<tr>
|
||||||
|
<td>{$index + 1}</td>
|
||||||
|
<td>{player.f_kill_date}</td>
|
||||||
|
<td>
|
||||||
|
<img height="24" src={getFactionIcon(player.faction_id)} alt={player.faction_id} />
|
||||||
|
<a href="/avatar/{player.killer_id}">{player.name}</a>
|
||||||
|
</td>
|
||||||
|
<td>{player.kill_count}</td>
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
BIN
public/img/faces/10.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/11.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/110.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/116.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/117.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/118.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/119.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/12.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/120.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/121.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/122.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/img/faces/123.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/124.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/125.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/126.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/13.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/132.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/133.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/134.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/135.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/136.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/137.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/138.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/img/faces/139.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/14.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/140.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/141.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/142.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/148.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/149.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/15.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/150.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/151.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/152.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/153.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/154.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/img/faces/155.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/156.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/157.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/158.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/16.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/img/faces/164.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/165.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/166.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/167.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/168.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/169.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/17.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/170.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/img/faces/171.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/172.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/173.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/174.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/18.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/19.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/20.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/21.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/216.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/img/faces/217.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/img/faces/218.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/img/faces/219.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/img/faces/22.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/220.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/img/faces/221.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/img/faces/222.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/img/faces/223.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/img/faces/224.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/225.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/23.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/232.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/233.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/234.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/235.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/236.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/237.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/238.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/239.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
public/img/faces/24.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/240.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/img/faces/241.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
public/img/faces/248.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/img/faces/249.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/25.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/faces/250.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/251.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/252.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/253.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/254.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/img/faces/255.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
public/img/faces/256.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/img/faces/257.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/img/faces/26.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/faces/264.png
Normal file
|
After Width: | Height: | Size: 18 KiB |