Refactor game state management and enhance scoring logic
- Added `handleHit` function to handle various hit types (single, double, triple, home run). - Refactored `handleBall`, `handleOut`, and `handlePitch` to return `scoredRunners` and update scores accordingly. - Updated history management to include both `gameState` and `lineupState`. - Improved scoreboard rendering to reflect updated scoring structure and base occupation styles. - Enhanced navigation button styling for active lineup tab. - Fixed UI to dynamically display scored runners and adjusted base styling in `GameStateDisplay`.
This commit is contained in:
94
src/App.js
94
src/App.js
@@ -52,17 +52,18 @@ const handleBall = (prevState) => {
|
||||
let newState = {...prevState}
|
||||
let message = `Ball ${newBalls}.`
|
||||
var endsAtBat = false
|
||||
var scoredRunners = []
|
||||
if (newBalls === 4) {
|
||||
// Walk (advance batter to 1st base)
|
||||
const advanceResult = advanceRunners(newState, [1,0,0,0]);
|
||||
newState = { ...newState, ...resetCount(advanceResult.newState)};
|
||||
endsAtBat = true
|
||||
console.log(advanceResult)
|
||||
scoredRunners = advanceResult.scoredRunners
|
||||
message = [message, "Walk!", advanceResult.message].join(' ')
|
||||
} else {
|
||||
newState.count.balls = newBalls;
|
||||
}
|
||||
return { newState, message, endsAtBat };
|
||||
return { newState, message, scoredRunners, endsAtBat };
|
||||
};
|
||||
|
||||
// Handle outs
|
||||
@@ -78,11 +79,43 @@ const handleOut = (prevState) => {
|
||||
message = [message, switchInningResult.message].join(" ")
|
||||
} else {
|
||||
message += "."
|
||||
newState = { ...newState, outs: newOuts}
|
||||
newState.outs = newOuts
|
||||
}
|
||||
return {newState, message, endsAtBat: true};
|
||||
};
|
||||
|
||||
const handleHit = (prevState, hit_type) => {
|
||||
var newState = {...prevState}
|
||||
var message = `${hit_type}!`
|
||||
var basesToAdvance
|
||||
var endsAtBat = false
|
||||
var scoredRunners = []
|
||||
switch (hit_type) {
|
||||
case "single":
|
||||
basesToAdvance = [1,1,1,1];
|
||||
break;
|
||||
case "double":
|
||||
basesToAdvance = [2,2,2,1];
|
||||
break;
|
||||
case "triple":
|
||||
basesToAdvance = [3,2,2,1];
|
||||
break;
|
||||
case "home run":
|
||||
basesToAdvance = [4,3,2,1];
|
||||
break;
|
||||
default:
|
||||
console.warn("Unknown pitch type:", hit_type);
|
||||
return; // Exit if pitch is not recognized
|
||||
}
|
||||
|
||||
const advancedResult = advanceRunners(newState, basesToAdvance);
|
||||
newState = { ...newState, ...resetCount(advancedResult.newState)};
|
||||
endsAtBat = true
|
||||
scoredRunners = advancedResult.scoredRunners
|
||||
message = [message, advancedResult.message].join(' ')
|
||||
return { newState, message, scoredRunners, endsAtBat };
|
||||
}
|
||||
|
||||
const resetCount = (prevState) => {
|
||||
return {...prevState, count:{strikes: 0, balls: 0}}
|
||||
}
|
||||
@@ -279,7 +312,9 @@ function App() {
|
||||
// Function to handle play input
|
||||
const handlePitch = (pitch) => {
|
||||
// Save current state to history before modifying it
|
||||
setHistory((prevHistory) => [...prevHistory, { ...gameState }]);
|
||||
console.dir(gameState)
|
||||
setHistory((prevHistory) => [...prevHistory, { gameState:{...gameState}, lineupState:{...lineupState}}]);
|
||||
console.dir(history)
|
||||
// const currentBatter = getCurrentBatter();
|
||||
const lineup = getActiveLineup();
|
||||
const currentIndex = getCurrentBatterIndex();
|
||||
@@ -289,7 +324,7 @@ function App() {
|
||||
let pitchResultState = {...gameState}
|
||||
pitchResultState.currentBatter = currentBatter
|
||||
var endsAtBat
|
||||
var scoredRunners
|
||||
var scoredRunners = []
|
||||
if (pitch === "strike") {
|
||||
const result = handleStrike(pitchResultState)
|
||||
const {newState, message} = result
|
||||
@@ -306,6 +341,7 @@ function App() {
|
||||
const result = handleBall(pitchResultState)
|
||||
const {newState, message} = result
|
||||
endsAtBat = result.endsAtBat
|
||||
scoredRunners= result.scoredRunners
|
||||
gameLogMessageArray.push(message)
|
||||
pitchResultState = { ...pitchResultState, ...newState };
|
||||
} else if (pitch === "out") {
|
||||
@@ -314,31 +350,32 @@ function App() {
|
||||
endsAtBat = result.endsAtBat
|
||||
gameLogMessageArray.push(message)
|
||||
pitchResultState = { ...pitchResultState, ...newState };
|
||||
} else if (pitch === "hit") {
|
||||
const result = advanceRunners(pitchResultState, [1,0,0,0]);
|
||||
} else if (
|
||||
pitch === "single" ||
|
||||
pitch === "double" ||
|
||||
pitch === "triple" ||
|
||||
pitch === "home run"
|
||||
) {
|
||||
const result = handleHit(pitchResultState, pitch)
|
||||
const {newState, message} = result
|
||||
gameLogMessageArray.push(message)
|
||||
scoredRunners = result.scoredRunners
|
||||
pitchResultState = {...pitchResultState, ...newState}
|
||||
endsAtBat = result.endsAtBat
|
||||
scoredRunners= result.scoredRunners
|
||||
gameLogMessageArray.push(message)
|
||||
pitchResultState = { ...pitchResultState, ...newState };
|
||||
|
||||
} else {
|
||||
console.warn("Unknown play:", pitch); // Optional: Handle unexpected values
|
||||
}
|
||||
if (gameState.isTopHalf){
|
||||
pitchResultState.score.away += scoredRunners.length
|
||||
} else {
|
||||
pitchResultState.score.home += scoredRunners.length
|
||||
}
|
||||
addToGameLog([...gameLogMessageArray].join(' '))
|
||||
setGameState(pitchResultState)
|
||||
if (endsAtBat){advanceLineup(gameState, lineupState, setLineupState)}
|
||||
addToGameLog([...gameLogMessageArray].join(' '))
|
||||
};
|
||||
|
||||
const scoreRunner = (scoringRunner) => {
|
||||
setGameState((prevState)=>{
|
||||
const homeScore = gameState.isTopHalf ? prevState.homeScore : prevState.homeScore + 1
|
||||
const awayScore = gameState.isTopHalf ? prevState.awayScore + 1 : prevState.awayScore
|
||||
const activeLineup = getActiveLineup();
|
||||
const currentBatter = activeLineup[getCurrentBatterIndex()];
|
||||
return {...prevState, homeScore, awayScore}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
const endGame = () => {
|
||||
setGameState((prevState)=>({...prevState, isFinal: true}))
|
||||
}
|
||||
@@ -351,10 +388,13 @@ function App() {
|
||||
|
||||
// Undo the last action
|
||||
const handleUndo = () => {
|
||||
console.dir(history)
|
||||
if (history.length > 0) {
|
||||
const lastState = history[history.length - 1];
|
||||
const {gameState, lineupState} = history[history.length - 1];
|
||||
const latestGameLog = gameLog[gameLog.length-1]
|
||||
setGameState(lastState); // Revert to the last state
|
||||
setGameState(gameState); // Revert to the last state
|
||||
setLineupState(lineupState); // Revert to the last state
|
||||
|
||||
setHistory((prevHistory) => prevHistory.slice(0, -1)); // Remove the last history entry
|
||||
setGameLog((prevGamelong) => prevGamelong.slice(0, -1)); // Remove the last history entry
|
||||
}
|
||||
@@ -405,9 +445,9 @@ function App() {
|
||||
<button className="play foul" onClick={() => handlePitch("foul")} disabled={gameState.isFinal}>Foul</button>
|
||||
<button className="play out" onClick={() => handlePitch("out")} disabled={gameState.isFinal}>Out</button>
|
||||
|
||||
<Button className="play hit" onClick={() => handlePitch("hit")}>1</Button>
|
||||
<Button className="play hit" onClick={() => handlePitch("hit")}>2</Button>
|
||||
<Button className="play hit" onClick={() => handlePitch("hit")}>3</Button>
|
||||
<Button className="play hit" onClick={() => handlePitch("single")}>1</Button>
|
||||
<Button className="play hit" onClick={() => handlePitch("double")}>2</Button>
|
||||
<Button className="play hit" onClick={() => handlePitch("triple")}>3</Button>
|
||||
|
||||
</section>
|
||||
<section>
|
||||
|
||||
@@ -96,4 +96,12 @@ body {
|
||||
}
|
||||
border: none;
|
||||
}
|
||||
.lineups.nav {
|
||||
.nav-item button[role=tab][aria-selected=true]{
|
||||
font-weight: 900;
|
||||
&:before, &:after{
|
||||
content: "*";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ function Inning({inning, isTopHalf}){
|
||||
)
|
||||
}
|
||||
|
||||
function GameStateDisplay({inning, bases, isTopHalf, outs, count, awayScore, homeScore, isFinal }){
|
||||
function GameStateDisplay({inning, bases, isTopHalf, outs, count, score, isFinal }){
|
||||
return (
|
||||
<div className="gameState">
|
||||
<header>Scoreboard</header>
|
||||
@@ -24,9 +24,9 @@ function GameStateDisplay({inning, bases, isTopHalf, outs, count, awayScore, ho
|
||||
<Col>{count.balls}-{count.strikes}</Col>
|
||||
<Col>{outs} outs</Col>
|
||||
<Col>
|
||||
<FontAwesomeIcon icon={fa1} className={`base ${bases[0] ? "occupied" : ""}`}></FontAwesomeIcon>
|
||||
<FontAwesomeIcon icon={fa2} className={`base ${bases[1] ? "occupied" : ""}`}></FontAwesomeIcon>
|
||||
<FontAwesomeIcon icon={fa3} className={`base ${bases[2] ? "occupied" : ""}`}></FontAwesomeIcon>
|
||||
<FontAwesomeIcon icon={fa1} className={`base ${bases[0] ? `occupied ${bases[0]}` : ""}`}></FontAwesomeIcon>
|
||||
<FontAwesomeIcon icon={fa2} className={`base ${bases[1] ? `occupied ${bases[1]}` : ""}`}></FontAwesomeIcon>
|
||||
<FontAwesomeIcon icon={fa3} className={`base ${bases[2] ? `occupied ${bases[2]}` : ""}`}></FontAwesomeIcon>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
@@ -35,8 +35,8 @@ function GameStateDisplay({inning, bases, isTopHalf, outs, count, awayScore, ho
|
||||
)}
|
||||
<strong>{isFinal ? "FINAL!" : ""}</strong>
|
||||
<Row>
|
||||
<Col><strong> Away Score: </strong> {awayScore}</Col>
|
||||
<Col><strong> Home Score: </strong> {homeScore}</Col>
|
||||
<Col><strong> Away Score: </strong> {score.away}</Col>
|
||||
<Col><strong> Home Score: </strong> {score.home}</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
|
||||
7
src/utils/inningUtils.js
Normal file
7
src/utils/inningUtils.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const encodeInning = (inningNumber, isTopHalf) =>
|
||||
inningNumber * 10 + (isTopHalf ? 1 : 2);
|
||||
|
||||
const decodeInning = (inningInt) => ({
|
||||
inningNumber: Math.floor(inningInt / 10),
|
||||
isTopHalf: inningInt % 10 === 1,
|
||||
});
|
||||
Reference in New Issue
Block a user