<!
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Professional Cricket Stats Tracker</title>
<script src="[Link]
<style>
:root {
--primary-color: #1a73e8; --secondary-color: #5f6368; --bg-color:
#f1f3f4;
--text-color: #202124; --light-grey: #dadce0; --white: #ffffff;
--danger-color: #d93025; --success-color: #1e8e3e; --warning-color:
#ff9800;
}
body {
font-family: "Google Sans", -apple-system, BlinkMacSystemFont, "Segoe
UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background-color: var(--bg-color); color: var(--text-color);
line-height: 1.6; margin: 0; transition: background-color 0.3s, color
0.3s;
}
.header { background-color: var(--white); padding: 0 2rem; box-shadow: 0
2px 4px rgba(0,0,0,0.1); position: sticky; top: 0; z-index: 100; transition:
background-color 0.3s; }
.container { max-width: 1300px; margin: 0 auto; padding: 2rem; }
.card { background-color: var(--white); border-radius: 8px; box-shadow: 0
1px 2px 0 rgba(60,64,67,.3), 0 2px 6px 2px rgba(60,64,67,.15); padding: 1.5rem
2rem; margin-bottom: 2rem; transition: background-color 0.3s; }
h1, h2, h3 { color: var(--secondary-color); border-bottom: 1px solid var(--
light-grey); padding-bottom: 10px; margin-top: 0; transition: color 0.3s, border-
color 0.3s; }
h1 { text-align: center; border-bottom: none; margin: 1rem 0 2rem 0; color:
#3c4043; }
h3 { margin-top: 2rem; }
table { width: 100%; border-collapse: collapse; margin-top: 1rem; table-
layout: auto; }
th, td { border: 1px solid var(--light-grey); padding: 12px; text-align:
center; vertical-align: middle; transition: border-color 0.3s; }
td:first-child { text-align: left; }
thead th { background-color: #e9ecef; color: var(--secondary-color); font-
weight: 600; transition: background-color 0.3s, color 0.3s; }
tbody tr:nth-child(even) { background-color: #f8f9fa; }
.form-grid { display: grid; grid-template-columns: repeat(auto-fit,
minmax(200px, 1fr)); gap: 1rem; }
input, select, button { width: 100%; padding: 12px; border-radius: 5px;
border: 1px solid #ced4da; box-sizing: border-box; font-size: 1rem; }
button { color: var(--white); background-color: var(--primary-color);
border: none; cursor: pointer; font-weight: 600; transition: background-color 0.2s,
box-shadow 0.2s; }
.tab-nav { display: flex; flex-wrap: nowrap; overflow-x: auto; border-
bottom: 1px solid var(--light-grey); margin: 0 auto; max-width: 1300px; }
.tab-button { background: none; border: none; color: var(--secondary-
color); padding: 1rem 1.5rem; font-size: 1.1rem; font-weight: 500; cursor: pointer;
border-bottom: 3px solid transparent; margin-bottom: -1px; white-space: nowrap; }
.[Link] { color: var(--primary-color); border-bottom-color:
var(--primary-color); font-weight: 600; }
.tab-pane { display: none; } .[Link] { display: block; }
.settings-actions { display: flex; flex-direction: column; gap: 1rem; max-
width: 400px; margin-top: 1.5rem;}
.stats-header { display: flex; align-items: center; gap: 1.5rem; flex-wrap:
wrap; }
.stats-header img, #playerListTable img { width: 80px; height: 80px;
border-radius: 50%; object-fit: cover; background-color: var(--light-grey); }
.player-bio { display: flex; flex-direction: column; }
.player-bio p { margin: 2px 0; font-size: 0.9rem; }
.stats-filter, .h2h-filters-container { margin: 1.5rem 0; display: flex;
flex-wrap: wrap; gap: 1.5rem; align-items: center; }
.stats-filter > div, .h2h-filters > div { display: flex; gap: 0.5rem;
align-items: center;}
.stats-filter label, .h2h-filters label { font-weight: bold; }
.stats-tables-grid { display: grid; grid-template-columns: repeat(auto-fit,
minmax(350px, 1fr)); gap: 1rem; }
/* Redesigned Performance Row */
.performance-row { border: 1px solid var(--light-grey); border-radius: 8px;
padding: 1rem; margin-top: 1rem; }
.performance-row-header { display: flex; align-items: center; gap: 1rem;
border-bottom: 1px solid var(--light-grey); padding-bottom: 1rem; margin-bottom:
1rem; }
.performance-row-header select { flex-grow: 1; }
.perf-stats-grid { display: grid; grid-template-columns: repeat(auto-fit,
minmax(250px, 1fr)); gap: 1.5rem; }
.perf-group h4 { margin: 0 0 0.5rem 0; font-size: 1rem; color: var(--
primary-color); border-bottom: none; }
.perf-group .input-pair { display: grid; grid-template-columns: 80px 1fr;
gap: 0.5rem; align-items: center; margin-bottom: 0.5rem;}
.perf-group .input-pair label { font-size: 0.85rem; text-align: right; }
.dnb-group { display: flex; align-items: center; justify-content: center;
gap: 0.5rem; }
.dnb-group label { font-size: 0.8rem; }
/* Dark Mode */
[Link]-mode { --bg-color: #202124; --text-color: #e8eaed; --secondary-
color: #bdc1c6; --light-grey: #3c4043; --white: #28292d; }
[Link]-mode thead th { background-color: #3c4043; }
[Link]-mode tbody tr:nth-child(even) { background-color: #2a2a2a; }
[Link]-mode input, [Link]-mode select { background-color: #3c4043;
border-color: #5f6368; color: var(--text-color); }
</style>
</head>
<body>
<header class="header">
<nav class="tab-nav">
<button class="tab-button active" data-tab="home">Home</button>
<button class="tab-button" data-tab="log-match">Log Match</button>
<button class="tab-button" data-tab="h2h-stats">H2H Stats</button>
<button class="tab-button" data-tab="match-history">Match
History</button>
<button class="tab-button" data-tab="settings">Settings</button>
</nav>
</header>
<main class="container">
<div id="home" class="tab-pane active"><div class="card"><h2>Player
Roster</h2><form id="addPlayerForm" class="form-grid"><input type="text"
id="playerName" placeholder="Player Name" required><input type="date"
id="playerDob" title="Date of Birth"><input type="text" id="playerRole"
placeholder="Playing Role"><input type="text" id="battingStyle"
placeholder="Batting Style"><input type="text" id="bowlingStyle"
placeholder="Bowling Style"><input type="url" id="playerAvatar" placeholder="Avatar
Image URL"></form><button type="submit" form="addPlayerForm" class="btn-success"
style="margin-top: 1rem;">Add Player</button><table
id="playerListTable"><thead><tr><th>Avatar</th><th>Name</th><th>Role</
th><th>Actions</th></tr></thead><tbody></tbody></table></div></div>
<div id="log-match" class="tab-pane"><div class="card"><h2>Log a New
Match</h2><form id="logMatchForm"><div class="form-grid"><input type="date"
id="matchDate" required><input type="text" id="matchOpponent" placeholder="Opponent
Name"><select id="matchFormat" required><option value="">-- Select Format
--</option><option value="Test">Test</option><option
value="ODI">ODI</option><option value="T20">T20</option><option value="10 Overs">10
Overs</option><option value="5 Overs">5 Overs</option><option
value="Other">Other</option></select><select id="manOfTheMatch"><option value="">--
Man of the Match --</option></select></div><h3 style="margin-top:2rem">Player
Performances</h3><div id="performanceEntries"></div><button type="button"
id="addPerformanceBtn" style="margin-top:1rem">Add Player
Performance</button><button type="submit" class="btn-success" style="margin-
top:1rem;float:right">Save Match</button></form></div></div>
<div id="h2h-stats" class="tab-pane"><div class="card"><h3>Select Players
and Filters for Comparison</h3><div class="h2h-filters-container"><div class="h2h-
filters"><div><label>Player A:</label><select
id="h2hPlayerA"></select></div><div><label>Player B:</label><select
id="h2hPlayerB"></select></div></div><div class="h2h-
filters"><div><label>Format:</label><select
id="h2hFormatFilter"></select></div><div><label>Year:</label><select
id="h2hYearFilter"></select></div></div></div><button id="compareBtn"
style="margin-top:1rem; max-width: 200px;">Compare Careers</button><div
id="h2hResults" style="margin-top: 2rem;"></div></div></div>
<div id="match-history" class="tab-pane"><div class="card"><h2>Match
History</h2><table
id="matchHistoryTable"><thead><tr><th>Date</th><th>Format</th><th>Opponent</
th><th>Players</th><th>MOTM</th><th>Actions</th></tr></thead><tbody></tbody></
table></div></div>
<div id="settings" class="tab-pane"><div
class="card"><h2>Settings</h2><h3>Data Management</h3><div class="settings-
actions"><button id="exportDataBtn" class="btn-warning">Export Data</button><button
id="importDataBtn" class="btn-warning">Import Data</button><input type="file"
id="importFile" accept=".json" style="display:none"></div><h3 style="margin-top:
2rem;">Appearance</h3><div class="settings-actions"><button
id="darkModeToggle">Toggle Dark Mode</button></div><h3 style="margin-top:
2rem;">Archive (Trash)</h3><p>Items here are deleted permanently after 3
days.</p><table id="archiveTable"><thead><tr><th>Item</th><th>Type</th><th>Deleted
On</th><th>Actions</th></tr></thead><tbody></tbody></table></div></div>
<div id="career-stats" class="tab-pane">
<div class="card">
<div class="stats-header">
<img id="statsAvatar"
src="[Link]
g" alt="Player Avatar">
<div>
<h2 id="statsPlayerName" style="border-bottom:none; margin:
0;"></h2>
<div class="player-bio">
<p id="statsPlayerAge"></p><p id="statsPlayerRole"></p>
<p id="statsPlayerBatting"></p><p
id="statsPlayerBowling"></p>
</div>
</div>
</div>
<div class="stats-filter">
<div><label for="formatFilter">Format:</label><select
id="formatFilter"></select></div>
<div><label for="yearFilter">Year:</label><select
id="yearFilter"></select></div>
</div>
<h3>Batting</h3>
<table><thead><tr><th>M</th><th>I</th><th>NO</th><th>Runs</th><th>HS</th><th>Avg</
th><th>BF</th><th>SR</th></tr></thead>
<tbody><tr><td id="c_m_bat">-</td><td id="c_i_bat">-</td><td
id="c_no">-</td><td id="c_runs">-</td><td id="c_hs">-</td><td
id="c_avg_bat">-</td><td id="c_bf">-</td><td
id="c_sr_bat">-</td></tr></tbody></table>
<div class="stats-tables-grid">
<div><h3>Milestones &
Awards</h3><table><thead><tr><th>100s</th><th>50s</th><th>5W</th><th>MOTM</th></
tr></thead><tbody><tr><td id="c_100s">-</td><td id="c_50s">-</td><td
id="c_5w">-</td><td id="c_motm">-</td></tr></tbody></table></div>
<div><h3>Fielding</h3><table><thead><tr><th>Catches</th><th>Stumpings</th><th>Run
Outs</th></tr></thead><tbody><tr><td id="c_ct">-</td><td id="c_st">-</td><td
id="c_ro">-</td></tr></tbody></table></div>
</div>
<h3>Bowling</h3>
<table><thead><tr><th>M</th><th>I</th><th>Overs</th><th>Balls</th><th>Runs</
th><th>Wkts</th><th>BBI</th><th>Avg</th><th>Econ</th><th>SR</th></tr></thead>
<tbody><tr><td id="c_m_bowl">-</td><td id="c_i_bowl">-</td><td
id="c_overs">-</td><td id="c_balls_bowl">-</td><td id="c_runs_con">-</td><td
id="c_wkts">-</td><td id="c_bbi">-</td><td id="c_avg_bowl">-</td><td id="c_econ">-
</td><td id="c_sr_bowl">-</td></tr></tbody></table>
<h3 style="margin-top: 2rem;">Runs per Innings Chart</h3>
<canvas id="runsChart"></canvas>
</div>
</div>
</main>
<script>
[Link]('DOMContentLoaded', () => {
// --- DOM Elements ---
const tabNav = [Link]('.tab-nav');
const tabPanes = [Link]('.tab-pane');
const addPlayerForm = [Link]('addPlayerForm');
const playerListTableBody = [Link]('#playerListTable tbody');
const logMatchForm = [Link]('logMatchForm');
const addPerformanceBtn = [Link]('addPerformanceBtn');
const performanceEntries = [Link]('performanceEntries');
const manOfTheMatchSelect = [Link]('manOfTheMatch');
const formatFilterSelect = [Link]('formatFilter');
const yearFilterSelect = [Link]('yearFilter');
const matchHistoryTableBody = [Link]('#matchHistoryTable
tbody');
const archiveTableBody = [Link]('#archiveTable tbody');
const exportDataBtn = [Link]('exportDataBtn');
const importDataBtn = [Link]('importDataBtn');
const importFile = [Link]('importFile');
const darkModeToggle = [Link]('darkModeToggle');
const h2hPlayerASelect = [Link]('h2hPlayerA');
const h2hPlayerBSelect = [Link]('h2hPlayerB');
const h2hFormatFilter = [Link]('h2hFormatFilter');
const h2hYearFilter = [Link]('h2hYearFilter');
const compareBtn = [Link]('compareBtn');
const h2hResultsDiv = [Link]('h2hResults');
const runsChartCanvas = [Link]('runsChart');
let runsChart;
// --- App State ---
let db = { players: [], matches: [], trash: [] };
let currentStatsPlayerId = null;
// --- INITIALIZATION ---
loadData();
if ([Link]('darkMode') === 'enabled')
[Link]('dark-mode');
// --- EVENT LISTENERS ---
[Link]('click', handleTabSwitch);
[Link]('submit', handleAddPlayer);
[Link]('click', handlePlayerListClick);
[Link]('click', addPerformanceRow);
[Link]('submit', handleLogMatch);
[Link]('change', handleFilterChange);
[Link]('change', handleFilterChange);
[Link]('click', handleMatchHistoryClick);
[Link]('click', handleArchiveClick);
[Link]('click', exportData);
[Link]('click', () => [Link]());
[Link]('change', importData);
[Link]('click', toggleDarkMode);
[Link]('click', displayH2HStats);
// --- TAB SWITCHING ---
function switchTab(targetTabId) {
if (targetTabId === 'h2h-stats') populateH2HDropdowns();
if (targetTabId === 'log-match') {
populateMOTMSelect();
if ([Link]('.performance-row').length ===
0) addPerformanceRow();
}
[Link](pane => [Link]('active'));
[Link](targetTabId)?.[Link]('active');
[Link]('.tab-button').forEach(btn =>
[Link]('active'));
const targetButton = [Link](`[data-tab='${targetTabId}']`);
if (targetButton) [Link]('active');
}
function handleTabSwitch(e) {
const tabButton = [Link]('.tab-button');
if (!tabButton) return;
switchTab([Link]);
}
// --- DARK MODE ---
function toggleDarkMode() {
[Link]('dark-mode');
[Link]('darkMode', [Link]('dark-
mode') ? 'enabled' : 'disabled');
}
// --- DATA HANDLING ---
function saveData() { [Link]('cricketAppDb', [Link](db));
}
function loadData() {
const storedDb = [Link]('cricketAppDb');
if (storedDb) db = [Link](storedDb);
if (![Link]) [Link] = [];
purgeOldTrash();
renderAll();
}
function renderAll() {
renderPlayerList();
renderMatchHistory();
renderArchive();
updateAllPlayerDropdowns();
}
function exportData() {
if ([Link] === 0 && [Link] === 0) return alert("No
data to export.");
const dataStr = [Link](db, null, 2);
const dataBlob = new Blob([dataStr], {type: "application/json"});
const url = [Link](dataBlob);
const link = [Link]('a');
[Link] = url;
[Link] = `cricket_stats_backup_${new
Date().toISOString().slice(0,10)}.json`;
[Link]();
[Link](url);
}
function importData(event) {
const file = [Link][0]; if (!file) return;
const reader = new FileReader();
[Link] = function(e) {
try {
const importedDb = [Link]([Link]);
if (importedDb && [Link]([Link]) &&
[Link]([Link])) {
if (confirm("This will overwrite all current data. Are you
sure?")) {
db = importedDb;
if(![Link]) [Link] = [];
saveData();
renderAll();
switchTab('home');
alert("Data imported successfully!");
}
} else { alert("Invalid data file format."); }
} catch (error) { alert("Error reading file."); }
};
[Link](file);
[Link] = '';
}
// --- PLAYER MANAGEMENT ---
function handleAddPlayer(e) {
[Link]();
[Link]({
id: [Link](), name:
[Link]('playerName').[Link]() || 'Unnamed Player',
role: [Link]('playerRole').[Link](),
battingStyle: [Link]('battingStyle').[Link](),
bowlingStyle: [Link]('bowlingStyle').[Link](),
avatarUrl: [Link]('playerAvatar').[Link](),
dob: [Link]('#playerDob').value
});
saveData();
renderPlayerList();
[Link]();
updateAllPlayerDropdowns();
}
function renderPlayerList() {
[Link] = '';
const defaultAvatar =
'[Link]
[Link](player => {
const row = [Link]('tr');
[Link] = `<td><img src="${[Link] || defaultAvatar}"
alt="Avatar"></td>
<td>${[Link]}</td><td>${[Link] || '-'}</td>
<td><button class="btn-small" data-player-id="${[Link]}" data-
action="view-stats">View Stats</button>
<button class="btn-small btn-danger" data-player-id="$
{[Link]}" data-action="delete-player">Delete</button></td>`;
[Link](row);
});
}
function handlePlayerListClick(e) {
const targetButton = [Link]('button');
if (!targetButton) return;
const { action, playerId } = [Link];
if (action === 'view-stats') openStatsPage(parseInt(playerId));
else if (action === 'delete-player') if (confirm('Are you sure? This will
move the player to the Archive.')) deleteToArchive('player', parseInt(playerId));
}
function updateAllPlayerDropdowns() {
populateH2HDropdowns();
populateMOTMSelect();
}
// --- MATCH LOGGING & HISTORY ---
function populateMOTMSelect() {
const currentSelection = [Link];
[Link] = '<option value="">-- Man of the Match
--</option>';
[Link](player => {
[Link] += `<option value="${[Link]}">$
{[Link]}</option>`;
});
[Link] = currentSelection;
}
function addPerformanceRow() {
if ([Link] === 0) {
if ([Link] === 0) alert('Add a player on
the "Home" tab first.');
return;
}
const row = [Link]('div');
[Link] = 'performance-row';
const playerOptions = [Link](p => `<option value="${[Link]}">$
{[Link]}</option>`).join('');
[Link] = `<div class="performance-row-header"><select data-
field="playerId">${playerOptions}</select></div>
<div class="perf-stats-grid">
<div class="perf-group"><h4>Batting</h4>
<div class="input-pair"><label>Did Not Bat:</label><input
type="checkbox" data-field="dnbBat"></div>
<div class="input-pair"><label>Runs:</label><input
type="number" min="0" placeholder="R" data-field="runs"></div>
<div class="input-pair"><label>Balls:</label><input
type="number" min="0" placeholder="B" data-field="balls"></div>
<div class="input-pair"><label>4s:</label><input type="number"
min="0" placeholder="4s" data-field="fours"></div>
<div class="input-pair"><label>6s:</label><input type="number"
min="0" placeholder="6s" data-field="sixes"></div>
<div class="input-pair"><label>Out?</label><select data-
field="out"><option value="yes">Yes</option><option
value="no">No</option></select></div>
</div>
<div class="perf-group"><h4>Bowling</h4>
<div class="input-pair"><label>Did Not Bowl:</label><input
type="checkbox" data-field="dnbBowl"></div>
<div class="input-pair"><label>Overs:</label><input type="text"
placeholder="e.g. 4.0" data-field="overs"></div>
<div class="input-pair"><label>Runs Con:</label><input
type="number" min="0" placeholder="R" data-field="runsCon"></div>
<div class="input-pair"><label>Wickets:</label><input
type="number" min="0" placeholder="W" data-field="wkts"></div>
</div>
<div class="perf-group"><h4>Fielding</h4>
<div class="input-pair"><label>Catches:</label><input
type="number" min="0" placeholder="Ct" data-field="catches"></div>
<div class="input-pair"><label>Stumpings:</label><input
type="number" min="0" placeholder="St" data-field="stumpings"></div>
<div class="input-pair"><label>Run Outs:</label><input
type="number" min="0" placeholder="RO" data-field="runOuts"></div>
</div>
</div>`;
[Link](row);
}
function handleLogMatch(e) {
[Link]();
const performances = [];
[Link]('.performance-row').forEach(row => {
const performanceData = {};
[Link]('[data-field]').forEach(input => {
const field = [Link];
if ([Link] === 'checkbox') performanceData[field] =
[Link];
else if ([Link] === 'number' || [Link] ===
'playerId') performanceData[field] = parseInt([Link]) || 0;
else performanceData[field] = [Link];
});
[Link](performanceData);
});
if ([Link] === 0) return alert('A match needs at least one
performance.');
[Link]({
id: [Link](), date: [Link]('matchDate').value,
format: [Link]('matchFormat').value,
opponent: [Link]('matchOpponent').[Link](),
motmPlayerId: parseInt([Link]) || null,
performances: performances
});
saveData();
[Link]();
[Link] = '';
addPerformanceRow();
alert('Match logged successfully!');
renderMatchHistory();
}
function renderMatchHistory() {
[Link] = '';
[...[Link]].reverse().forEach(match => {
const playerNames = [Link](p => [Link](pl =>
[Link] === [Link])?.name || 'N/A').join(', ');
const motm = [Link](pl => [Link] === [Link])?.name
|| '-';
const row = [Link]('tr');
[Link] = `<td>${[Link]}</td><td>${[Link]}</td><td>$
{[Link] || '-'}</td><td>${playerNames}</td><td>${motm}</td>
<td><button class="btn-small btn-danger" data-match-id="$
{[Link]}" data-action="delete-match">Delete</button></td>`;
[Link](row);
});
}
function handleMatchHistoryClick(e) {
const targetButton = [Link]('button');
if (!targetButton) return;
if([Link] === 'delete-match') {
const matchId = parseInt([Link]);
if (confirm('Are you sure? This will move the match to the Archive.'))
deleteToArchive('match', matchId);
}
}
// --- H2H STATS ---
function populateH2HDropdowns() {
const createOptions = (select) => {
const currentVal = [Link];
[Link] = `<option value="">-- Select Player --</option>`;
[Link](p => { [Link] += `<option value="$
{[Link]}">${[Link]}</option>`; });
[Link] = currentVal;
};
populateOptions(h2hFormatFilter, new Set([Link](m => [Link])),
'All Formats');
populateOptions(h2hYearFilter, new Set([Link](m => [Link] ? new
Date([Link]).getFullYear() : null)), 'All Years', true);
createOptions(h2hPlayerASelect);
createOptions(h2hPlayerBSelect);
}
function displayH2HStats() {
const pA_id = parseInt([Link]);
const pB_id = parseInt([Link]);
if (!pA_id || !pB_id || pA_id === pB_id) return [Link] =
'<p>Please select two different players.</p>';
const filters = { format: [Link], year:
[Link] };
const statsA = getPlayerStats(pA_id, filters);
const statsB = getPlayerStats(pB_id, filters);
const playerA = [Link](p => [Link] === pA_id);
const playerB = [Link](p => [Link] === pB_id);
const generateRow = (label, valA, valB) => `<tr><td>${label}</td><td>$
{valA}</td><td>${valB}</td></tr>`;
[Link] = `<h3>Comparison: ${[Link]} vs $
{[Link]} (${[Link] || 'All Formats'}, ${[Link] || 'All
Years'})</h3>
<h4>Batting & Fielding</h4><table><thead><tr><th>Stat</th><th>$
{[Link]}</th><th>${[Link]}</th></tr></thead><tbody>
${generateRow('Matches',[Link],[Link])}
${generateRow('Innings',[Link],[Link])}
${generateRow('Not Outs',[Link],[Link])}
${generateRow('Runs',[Link],[Link])}
${generateRow('High Score',[Link],[Link])}
${generateRow('Average',[Link],[Link])}
${generateRow('Balls Faced',[Link],[Link])}
${generateRow('Strike Rate',[Link],[Link])}
${generateRow('100s / 50s', `${[Link]}/${[Link]}`, `$
{[Link]}/${[Link]}`)}
${generateRow('4s / 6s', `${[Link]}/${[Link]}`, `$
{[Link]}/${[Link]}`)}
${generateRow('Catches',[Link],[Link])}
${generateRow('Stumpings',[Link],[Link])}
${generateRow('Run Outs',[Link],[Link])}
${generateRow('MOTM Awards',[Link],[Link])}
</tbody></table>
<h4>Bowling</h4><table><thead><tr><th>Stat</th><th>${[Link]}</
th><th>${[Link]}</th></tr></thead><tbody>
${generateRow('Innings',[Link],[Link])}
${generateRow('Overs',[Link],[Link])}
${generateRow('Wickets',[Link],[Link])}
${generateRow('Best Bowling',[Link],[Link])}
${generateRow('Average',[Link],[Link])}
${generateRow('Economy',[Link],[Link])}
${generateRow('Strike Rate',[Link],[Link])}
${generateRow('5 Wicket
Hauls',[Link],[Link])}
</tbody></table>`;
}
// --- STATS DISPLAY & CALCULATION ---
function getPlayerStats(playerId, filters) {
let performances = [Link](match => [Link](p
=> [Link] === playerId).map(p => ({ ...p, date: [Link], format:
[Link], opponent: [Link], motmPlayerId: [Link] })));
if ([Link] && [Link] !== 'Overall') performances =
[Link](p => [Link] === [Link]);
if ([Link] && [Link] !== 'All') performances =
[Link](p => [Link] && new Date([Link]).getFullYear() == [Link]);
let stats = { matches: new Set([Link](p => [Link] +
[Link])).size, inningsBat: 0, notOuts: 0, runs: 0, highestScore: 0, ballsFaced:
0, hundreds: 0, fifties: 0, fours: 0, sixes: 0, inningsBowl: 0, ballsBowled: 0,
runsConceded: 0, wickets: 0, bestBBIWickets: 0, bestBBIRuns: Infinity,
fiveWicketHauls: 0, catches: 0, stumpings: 0, runOuts: 0, motm: 0 };
[Link](p => {
if (![Link]) { [Link]++; if ([Link] === 'no') [Link]+
+; }
if (![Link] && [Link]) [Link]++;
if([Link] === playerId) [Link]++;
[Link] += [Link] || 0; [Link] += [Link] || 0;
[Link] += [Link] || 0; [Link] += [Link] || 0;
if (([Link] || 0) > [Link]) [Link] = [Link] ||
0;
if (([Link] || 0) >= 100) [Link]++; else if (([Link] || 0) >=
50) [Link]++;
const [oversInt, partial] = ([Link] || '0.0').split('.').map(Number);
[Link] += (oversInt || 0) * 6 + (partial || 0);
[Link] += [Link] || 0; [Link] += [Link] || 0;
if (([Link] || 0) > [Link] || (([Link] || 0) ===
[Link] && ([Link] || 0) < [Link])) {
[Link] = [Link] || 0; [Link] = [Link]
|| 0;
}
if (([Link] || 0) >= 5) [Link]++;
[Link] += [Link] || 0; [Link] += [Link] || 0;
[Link] += [Link] || 0;
});
const timesOut = [Link] - [Link];
[Link] = timesOut > 0 ? ([Link] / timesOut).toFixed(2) : '∞';
[Link] = [Link] > 0 ? ([Link] / [Link] *
100).toFixed(2) : '0.00';
[Link] = [Link]([Link] / 6) + '.' + ([Link]
% 6);
[Link] = [Link] > 0 ? ([Link] /
[Link]).toFixed(2) : '–';
[Link] = [Link] > 0 ? ([Link] /
([Link] / 6)).toFixed(2) : '0.00';
[Link] = [Link] > 0 ? ([Link] /
[Link]).toFixed(2) : '–';
[Link] = [Link] === Infinity ? '-' : `$
{[Link]}/${[Link]}`;
return stats;
}
function openStatsPage(playerId) {
// This is the primary fix for the "View Stats" button.
// It now reliably activates the correct pane and deactivates others.
currentStatsPlayerId = playerId;
[Link](pane => [Link]('active'));
[Link]('.tab-button').forEach(btn =>
[Link]('active'));
[Link]('career-stats').[Link]('active');
const playerMatches = [Link](m => [Link](p =>
[Link] === playerId));
populateOptions(formatFilterSelect, new Set([Link](m =>
[Link])), 'Overall Career');
populateOptions(yearFilterSelect, new Set([Link](m => [Link] ?
new Date([Link]).getFullYear() : null)), 'All Years', true);
calculateAndDisplayStats(playerId, 'Overall', 'All');
}
function handleFilterChange() { if (currentStatsPlayerId)
calculateAndDisplayStats(currentStatsPlayerId, [Link],
[Link]); }
function calculateAndDisplayStats(playerId, formatFilter, yearFilter) {
const player = [Link](p => [Link] === playerId); if (!player)
return;
const stats = getPlayerStats(playerId, { format: formatFilter, year:
yearFilter });
const getAge = dobString => {
if (!dobString) return 'N/A';
const dob = new Date(dobString);
if (isNaN([Link]())) return 'N/A';
const ageDifMs = [Link]() - [Link]();
const ageDate = new Date(ageDifMs);
return `${[Link]([Link]() - 1970)} years old`;
};
[Link]('statsPlayerName').textContent = [Link];
[Link]('statsPlayerAge').textContent = `Age: $
{getAge([Link])}`;
[Link]('statsPlayerRole').textContent = `Role: $
{[Link] || 'N/A'}`;
[Link]('statsPlayerBatting').textContent = `Batting: $
{[Link] || 'N/A'}`;
[Link]('statsPlayerBowling').textContent = `Bowling: $
{[Link] || 'N/A'}`;
[Link]('statsAvatar').src = [Link] ||
'[Link]
const setStat = (id, val) => {
const el = [Link](id);
if (el) [Link] = val;
};
setStat('c_m_bat', [Link]); setStat('c_i_bat', [Link]);
setStat('c_no', [Link]);
setStat('c_runs', [Link]); setStat('c_hs', [Link]);
setStat('c_avg_bat', [Link]);
setStat('c_bf', [Link]); setStat('c_sr_bat', [Link]);
setStat('c_100s', [Link]); setStat('c_50s', [Link]);
setStat('c_5w', [Link]); setStat('c_motm', [Link]);
setStat('c_ct', [Link]); setStat('c_st', [Link]);
setStat('c_ro', [Link]);
setStat('c_m_bowl', [Link]); setStat('c_i_bowl', [Link]);
setStat('c_overs', [Link]);
setStat('c_balls_bowl', [Link]); setStat('c_runs_con',
[Link]);
setStat('c_wkts', [Link]); setStat('c_bbi', [Link]);
setStat('c_avg_bowl', [Link]);
setStat('c_econ', [Link]); setStat('c_sr_bowl', [Link]);
if (runsChart) [Link]();
const battingPerformances = [Link](m => [Link](p
=> [Link] === playerId && ![Link]));
runsChart = new Chart([Link]('2d'), {
type: 'line', data: {
labels: [Link]((p, i) => `Innings ${i+1}`),
datasets: [{ label: 'Runs per Innings', data:
[Link](p => [Link]), backgroundColor: 'rgba(26, 115, 232, 0.2)',
borderColor: 'rgba(26, 115, 232, 1)', borderWidth: 2, tension: 0.1 }]
}, options: { scales: { y: { beginAtZero: true } } }
});
}
// --- ARCHIVE ---
function purgeOldTrash() {
const threeDaysAgo = [Link]() - 3 * 24 * 60 * 60 * 1000;
if ([Link] > 0) {
[Link] = [Link](item => new Date([Link]).getTime() >
threeDaysAgo);
saveData();
}
}
function renderArchive() {
[Link] = '';
[...[Link]].reverse().forEach(item => {
const row = [Link]('tr');
const itemName = [Link] === 'player' ? [Link] : `Match on $
{[Link]}`;
[Link] = `<td>${itemName}</td><td>${[Link]}</td><td>${new
Date([Link]).toLocaleString()}</td>
<td><button class="btn-small btn-success" data-item-id="$
{[Link]}" data-item-type="${[Link]}"
data-action="restore">Restore</button>
<button class="btn-small btn-danger" data-item-id="${[Link]}"
data-item-type="${[Link]}" data-action="delete-perm">Delete
Permanently</button></td>`;
[Link](row);
});
}
function deleteToArchive(type, id) {
let itemIndex = -1, itemToMove = null;
if (type === 'player') {
itemIndex = [Link](p => [Link] === id);
if (itemIndex > -1) [itemToMove] = [Link](itemIndex, 1);
} else if (type === 'match') {
itemIndex = [Link](m => [Link] === id);
if (itemIndex > -1) [itemToMove] = [Link](itemIndex, 1);
}
if(itemToMove) {
[Link]({ type: type, data: itemToMove, deletedOn: new
Date().toISOString() });
saveData();
renderAll();
}
}
function handleArchiveClick(e) {
const targetButton = [Link]('button');
if (!targetButton) return;
const { action, itemId, itemType } = [Link];
const id = parseInt(itemId);
const itemIndex = [Link](i => [Link] === id && [Link] ===
itemType);
if (itemIndex === -1) return;
if (action === 'restore') {
const [item] = [Link](itemIndex, 1);
delete [Link];
if ([Link] === 'player') [Link]([Link]);
else if ([Link] === 'match') [Link]([Link]);
saveData();
renderAll();
// This is the fix for the stats update bug.
if (currentStatsPlayerId) {
calculateAndDisplayStats(currentStatsPlayerId,
[Link], [Link]);
}
} else if (action === 'delete-perm') {
if (confirm('This cannot be undone. Are you sure?')) {
[Link](itemIndex, 1);
saveData();
renderAll();
}
}
}
// --- UTILITY ---
function populateOptions(selectElement, itemSet, defaultOptionText, sortDesc =
false) {
const currentVal = [Link];
const defaultAllValue = [Link]('All') ? 'All' : '';
[Link] = `<option value="${defaultAllValue}">$
{defaultOptionText}</option>`;
let items = [...itemSet].filter(Boolean);
if (sortDesc) [Link]((a,b) => b-a); else [Link]();
[Link](item => { [Link] += `<option value="$
{item}">${item}</option>`; });
[Link] = currentVal;
}
});
</script>
</body>
</html>