This commit captures work from multiple sessions building the statistics system and frontend component library. Backend - Phase 3.5: Statistics System - Box score statistics with materialized views - Play stat calculator for real-time updates - Stat view refresher service - Alembic migration for materialized views - Test coverage: 41 new tests (all passing) Frontend - Phase F1: Foundation - Composables: useGameState, useGameActions, useWebSocket - Type definitions and interfaces - Store setup with Pinia Frontend - Phase F2: Game Display - ScoreBoard, GameBoard, CurrentSituation, PlayByPlay components - Demo page at /demo Frontend - Phase F3: Decision Inputs - DefensiveSetup, OffensiveApproach, StolenBaseInputs components - DecisionPanel orchestration - Demo page at /demo-decisions - Test coverage: 213 tests passing Frontend - Phase F4: Dice & Manual Outcome - DiceRoller component - ManualOutcomeEntry with validation - PlayResult display - GameplayPanel orchestration - Demo page at /demo-gameplay - Test coverage: 119 tests passing Frontend - Phase F5: Substitutions - PinchHitterSelector, DefensiveReplacementSelector, PitchingChangeSelector - SubstitutionPanel with tab navigation - Demo page at /demo-substitutions - Test coverage: 114 tests passing Documentation: - PHASE_3_5_HANDOFF.md - Statistics system handoff - PHASE_F2_COMPLETE.md - Game display completion - Frontend phase planning docs - NEXT_SESSION.md updated for Phase F6 Configuration: - Package updates (Nuxt 4 fixes) - Tailwind config enhancements - Game store updates Test Status: - Backend: 731/731 passing (100%) - Frontend: 446/446 passing (100%) - Total: 1,177 tests passing Next Phase: F6 - Integration (wire all components into game page) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
88 lines
2.6 KiB
JavaScript
88 lines
2.6 KiB
JavaScript
/* eslint-disable */
|
|
var jumpToCode = (function init() {
|
|
// Classes of code we would like to highlight in the file view
|
|
var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
|
|
|
|
// Elements to highlight in the file listing view
|
|
var fileListingElements = ['td.pct.low'];
|
|
|
|
// We don't want to select elements that are direct descendants of another match
|
|
var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
|
|
|
|
// Selector that finds elements on the page to which we can jump
|
|
var selector =
|
|
fileListingElements.join(', ') +
|
|
', ' +
|
|
notSelector +
|
|
missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
|
|
|
|
// The NodeList of matching elements
|
|
var missingCoverageElements = document.querySelectorAll(selector);
|
|
|
|
var currentIndex;
|
|
|
|
function toggleClass(index) {
|
|
missingCoverageElements
|
|
.item(currentIndex)
|
|
.classList.remove('highlighted');
|
|
missingCoverageElements.item(index).classList.add('highlighted');
|
|
}
|
|
|
|
function makeCurrent(index) {
|
|
toggleClass(index);
|
|
currentIndex = index;
|
|
missingCoverageElements.item(index).scrollIntoView({
|
|
behavior: 'smooth',
|
|
block: 'center',
|
|
inline: 'center'
|
|
});
|
|
}
|
|
|
|
function goToPrevious() {
|
|
var nextIndex = 0;
|
|
if (typeof currentIndex !== 'number' || currentIndex === 0) {
|
|
nextIndex = missingCoverageElements.length - 1;
|
|
} else if (missingCoverageElements.length > 1) {
|
|
nextIndex = currentIndex - 1;
|
|
}
|
|
|
|
makeCurrent(nextIndex);
|
|
}
|
|
|
|
function goToNext() {
|
|
var nextIndex = 0;
|
|
|
|
if (
|
|
typeof currentIndex === 'number' &&
|
|
currentIndex < missingCoverageElements.length - 1
|
|
) {
|
|
nextIndex = currentIndex + 1;
|
|
}
|
|
|
|
makeCurrent(nextIndex);
|
|
}
|
|
|
|
return function jump(event) {
|
|
if (
|
|
document.getElementById('fileSearch') === document.activeElement &&
|
|
document.activeElement != null
|
|
) {
|
|
// if we're currently focused on the search input, we don't want to navigate
|
|
return;
|
|
}
|
|
|
|
switch (event.which) {
|
|
case 78: // n
|
|
case 74: // j
|
|
goToNext();
|
|
break;
|
|
case 66: // b
|
|
case 75: // k
|
|
case 80: // p
|
|
goToPrevious();
|
|
break;
|
|
}
|
|
};
|
|
})();
|
|
window.addEventListener('keydown', jumpToCode);
|