Skip to content

Commit

Permalink
Classic weapon stats component & admin settings
Browse files Browse the repository at this point in the history
  • Loading branch information
scottadkin committed Feb 9, 2025
1 parent 7884f6b commit c64557a
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 6 deletions.
91 changes: 91 additions & 0 deletions src/app/UI/Match/ClassicWeaponStats.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
"use client"
import Header from "../Header";
import Tabs from "../Tabs";
import { useState, useEffect } from "react";
import InteractiveTable from "../InteractiveTable";
import { ignore0, getPlayer, getTeamColorClass } from "@/app/lib/generic.mjs";
import PlayerLink from "../PlayerLink";

function renderTable(selectedWeapon, data, players, totalTeams){


const headers = {
"player": {"title": "Player"},
"kills": {"title": "Kills"},
"deaths": {"title": "Deaths"},
"shots": {"title": "Shots"},
"hits": {"title": "Hits"},
"acc": {"title": "Accuracy"},
"damage": {"title": "Damage"},
};

const rows = [];

for(let i = 0; i < data.length; i++){

const d = data[i];

if(d.weapon_id != selectedWeapon) continue;

const p = getPlayer(players, d.player_id);

rows.push({
"player": {"value": p.name.toLowerCase(),
"displayValue": <PlayerLink id={d.player_id} country={p.country} bNewTab={true}>{p.name}</PlayerLink>,
"className": `text-left ${(totalTeams > 1) ? getTeamColorClass(p.team) : ""}`},
"kills": {"value": d.kills, "displayValue": ignore0(d.kills)},
"deaths": {"value": d.deaths, "displayValue": ignore0(d.deaths)},
"shots": {"value": d.shots, "displayValue": ignore0(d.shots)},
"hits": {"value": d.hits, "displayValue": ignore0(d.hits)},
"acc": {"value": d.accuracy, "displayValue": `${d.accuracy.toFixed(2)}%`},
"damage": {"value": d.damage, "displayValue": ignore0(d.damage)},
});
}
return <InteractiveTable width={3} headers={headers} rows={rows}/>
}

export default function ClassicWeaponStats({weaponNames, weaponImages, data, players, totalTeams}){

if(data.length === 0) return null;

const [selectedWeapon, setSelectedWeapon] = useState("0");

const tabOptions = [];

for(const [value, name] of Object.entries(weaponNames)){

if(value === "0") continue;

tabOptions.push({name, value});
}

tabOptions.sort((a, b) =>{

a = a.name.toLowerCase();
b = b.name.toLowerCase();

if(a < b) return -1
if(a > b) return 1;
return 0;

});

const firstTab = (tabOptions.length > 0) ? tabOptions[0].value : "";


useEffect(() =>{

setSelectedWeapon(firstTab);

}, [firstTab]);



return <>
<Header>Classic Weapon Stats</Header>
<Tabs options={tabOptions} selectedValue={selectedWeapon} changeSelected={(value) =>{
setSelectedWeapon(value);
}}/>
{renderTable(selectedWeapon, data, players, totalTeams)}
</>
}
2 changes: 1 addition & 1 deletion src/app/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default async function RootLayout({ children }) {
{children}
<footer>
<a href="https://github.com/scottadkin/node-utstats-lite">Node UTStats Lite Website</a> for the <a href="https://github.com/rxut/UTStatsLite">UTStats Lite Mutator</a><br/>
Website Version 1.6.0 &copy; 2024-2025 Scott Adkin<br/>
Website Version 1.7.0 &copy; 2024-2025 Scott Adkin<br/>
UTStats-lite changes by rX <br/>
UTStats mod was originally created by azazel, AnthraX, and toa, with additions by Skillz, killereye, Enakin, Loki and rork.

Expand Down
3 changes: 2 additions & 1 deletion src/app/lib/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export async function clearAllDataTables(){
"ctf_covers",
"player_map_minute_averages",
"map_weapon_totals",
"map_rankings"
"map_rankings",
"classic_weapon_match_stats"
];


Expand Down
10 changes: 9 additions & 1 deletion src/app/lib/classicWeaponStats.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { bulkInsert } from "./database.mjs";
import { bulkInsert, simpleQuery } from "./database.mjs";

export async function bulkInsertMatchStats(matchId, mapId, gametypeId, playerManager, weaponsManager){

Expand Down Expand Up @@ -30,4 +30,12 @@ export async function bulkInsertMatchStats(matchId, mapId, gametypeId, playerMan
const query = `INSERT INTO nstats_classic_weapon_match_stats (match_id,gametype_id,map_id,player_id,weapon_id,kills,deaths,shots,hits,accuracy,damage) VALUES ?`;

await bulkInsert(query, insertVars);
}


export async function getMatchData(matchId){

const query = `SELECT player_id,weapon_id,kills,deaths,shots,hits,accuracy,damage FROM nstats_classic_weapon_match_stats WHERE match_id=?`;

return await simpleQuery(query, [matchId]);
}
2 changes: 1 addition & 1 deletion src/app/lib/pageLayout.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { simpleQuery } from "./database.mjs";
const DEFAULT_PAGE_LAYOUTS = {
"home": ["Welcome Message", "Social Media", "Recent Matches", "Activity Heatmap", "Most Played Maps", "Most Played Gametypes", "Servers"],
"map": ["Basic Summary", "Activity Heatmap", "Recent Matches", "Rankings", "Weapon Statistics", "Player Top Averages"],
"match": ["Basic Info", "Screenshot", "Frags", "CTF", "CTF Caps", "DOM","Damage Stats", "Weapons", "Items", "Special Events", "Kills", "Pings", "JSON Links"],
"match": ["Basic Info", "Screenshot", "Frags", "CTF", "CTF Caps", "DOM","Damage Stats","Classic Weapon Stats", "Weapons", "Items", "Special Events", "Kills", "Pings", "JSON Links"],
"player": ["Gametype Totals", "CTF", "Special Events", "Weapons", "Rankings", "Items","Activity Heatmap", "Recent Matches"],
"nav": ["Home", "Matches", "Players", "Rankings", "Records", "Maps", "Admin", "Login/Register", "Watchlist"]
};
Expand Down
1 change: 1 addition & 0 deletions src/app/lib/siteSettings.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const DEFAULT_PAGE_SETTINGS = [
{"category": "Match" ,"type": `bool`, "name": "Display CTF Caps", "value": 1},
{"category": "Match" ,"type": `bool`, "name": "Display DOM", "value": 1},
{"category": "Match" ,"type": `bool`, "name": "Display Weapons", "value": 1},
{"category": "Match" ,"type": `bool`, "name": "Display Classic Weapon Stats", "value": 1},
{"category": "Match" ,"type": `bool`, "name": "Display Items", "value": 1},
{"category": "Match" ,"type": `bool`, "name": "Display Special Events", "value": 1},
{"category": "Match" ,"type": `bool`, "name": "Display Kills", "value": 1},
Expand Down
12 changes: 10 additions & 2 deletions src/app/match/[id]/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import DamageStats from "@/app/UI/Match/DamageStats";
import CTFCaps from "@/app/UI/Match/CTFCaps";
import { getSessionInfo } from "@/app/lib/authentication";
import AdminTools from "@/app/UI/Match/AdminTools";
import ClassicWeaponStats from "@/app/UI/Match/ClassicWeaponStats";
import { getMatchData as classicGetMatchData } from "@/app/lib/classicWeaponStats.mjs";

export async function generateMetadata({ params, searchParams }, parent) {
// read route params
Expand Down Expand Up @@ -92,6 +94,8 @@ export default async function MatchPage({params, searchParams}) {

const weaponImages = await getAllWeaponImages();

const classicStats = await classicGetMatchData(matchId);

const pageSettings = await getCategorySettings("Match");
const pageLayout = await getPageLayout("Match");

Expand All @@ -105,10 +109,8 @@ export default async function MatchPage({params, searchParams}) {

const totalTeams = matchData.basic.total_teams;


const elems = [];


elems[pageLayout["Basic Info"]] = (pageSettings["Display Basic Info"] === "1") ? <BasicInfo key="basic" matchData={matchData}/> : null;
elems[pageLayout["Screenshot"]] = (pageSettings["Display Screenshot"] === "1") ? <MatchScreenshot key="sshot" data={matchData}/> : null;
elems[pageLayout["Frags"]] = (pageSettings["Display Frags"] === "1") ? <FragTable key="frags" data={matchData} totalTeams={totalTeams}/> : null;
Expand All @@ -124,8 +126,14 @@ export default async function MatchPage({params, searchParams}) {
elems[pageLayout["JSON Links"]] = (pageSettings["Display JSON Links"] === "1") ? <JSONInfo key="json" matchId={matchId}/> : null;
elems[pageLayout["Damage Stats"]] = (pageSettings["Display Damage Stats"] === "1") ? <DamageStats key="damage" data={matchData.playerData} totalTeams={totalTeams}/> : null;


elems[pageLayout["Classic Weapon Stats"]] = (pageSettings["Display Classic Weapon Stats"] === "1") ? <ClassicWeaponStats key="classic-weapons" weaponNames={matchData.weaponStats.names} weaponImages={weaponImages} data={classicStats} players={matchData.basicPlayers} totalTeams={totalTeams}/> : null;



return (
<main>

{(session !== null) ? <AdminTools matchId={matchId}/> : null}
{elems}
</main>
Expand Down

0 comments on commit c64557a

Please sign in to comment.