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 newState = {...prevState}
|
||||||
let message = `Ball ${newBalls}.`
|
let message = `Ball ${newBalls}.`
|
||||||
var endsAtBat = false
|
var endsAtBat = false
|
||||||
|
var scoredRunners = []
|
||||||
if (newBalls === 4) {
|
if (newBalls === 4) {
|
||||||
// Walk (advance batter to 1st base)
|
// Walk (advance batter to 1st base)
|
||||||
const advanceResult = advanceRunners(newState, [1,0,0,0]);
|
const advanceResult = advanceRunners(newState, [1,0,0,0]);
|
||||||
newState = { ...newState, ...resetCount(advanceResult.newState)};
|
newState = { ...newState, ...resetCount(advanceResult.newState)};
|
||||||
endsAtBat = true
|
endsAtBat = true
|
||||||
console.log(advanceResult)
|
scoredRunners = advanceResult.scoredRunners
|
||||||
message = [message, "Walk!", advanceResult.message].join(' ')
|
message = [message, "Walk!", advanceResult.message].join(' ')
|
||||||
} else {
|
} else {
|
||||||
newState.count.balls = newBalls;
|
newState.count.balls = newBalls;
|
||||||
}
|
}
|
||||||
return { newState, message, endsAtBat };
|
return { newState, message, scoredRunners, endsAtBat };
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle outs
|
// Handle outs
|
||||||
@@ -78,11 +79,43 @@ const handleOut = (prevState) => {
|
|||||||
message = [message, switchInningResult.message].join(" ")
|
message = [message, switchInningResult.message].join(" ")
|
||||||
} else {
|
} else {
|
||||||
message += "."
|
message += "."
|
||||||
newState = { ...newState, outs: newOuts}
|
newState.outs = newOuts
|
||||||
}
|
}
|
||||||
return {newState, message, endsAtBat: true};
|
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) => {
|
const resetCount = (prevState) => {
|
||||||
return {...prevState, count:{strikes: 0, balls: 0}}
|
return {...prevState, count:{strikes: 0, balls: 0}}
|
||||||
}
|
}
|
||||||
@@ -279,7 +312,9 @@ function App() {
|
|||||||
// Function to handle play input
|
// Function to handle play input
|
||||||
const handlePitch = (pitch) => {
|
const handlePitch = (pitch) => {
|
||||||
// Save current state to history before modifying it
|
// 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 currentBatter = getCurrentBatter();
|
||||||
const lineup = getActiveLineup();
|
const lineup = getActiveLineup();
|
||||||
const currentIndex = getCurrentBatterIndex();
|
const currentIndex = getCurrentBatterIndex();
|
||||||
@@ -289,7 +324,7 @@ function App() {
|
|||||||
let pitchResultState = {...gameState}
|
let pitchResultState = {...gameState}
|
||||||
pitchResultState.currentBatter = currentBatter
|
pitchResultState.currentBatter = currentBatter
|
||||||
var endsAtBat
|
var endsAtBat
|
||||||
var scoredRunners
|
var scoredRunners = []
|
||||||
if (pitch === "strike") {
|
if (pitch === "strike") {
|
||||||
const result = handleStrike(pitchResultState)
|
const result = handleStrike(pitchResultState)
|
||||||
const {newState, message} = result
|
const {newState, message} = result
|
||||||
@@ -306,6 +341,7 @@ function App() {
|
|||||||
const result = handleBall(pitchResultState)
|
const result = handleBall(pitchResultState)
|
||||||
const {newState, message} = result
|
const {newState, message} = result
|
||||||
endsAtBat = result.endsAtBat
|
endsAtBat = result.endsAtBat
|
||||||
|
scoredRunners= result.scoredRunners
|
||||||
gameLogMessageArray.push(message)
|
gameLogMessageArray.push(message)
|
||||||
pitchResultState = { ...pitchResultState, ...newState };
|
pitchResultState = { ...pitchResultState, ...newState };
|
||||||
} else if (pitch === "out") {
|
} else if (pitch === "out") {
|
||||||
@@ -314,31 +350,32 @@ function App() {
|
|||||||
endsAtBat = result.endsAtBat
|
endsAtBat = result.endsAtBat
|
||||||
gameLogMessageArray.push(message)
|
gameLogMessageArray.push(message)
|
||||||
pitchResultState = { ...pitchResultState, ...newState };
|
pitchResultState = { ...pitchResultState, ...newState };
|
||||||
} else if (pitch === "hit") {
|
} else if (
|
||||||
const result = advanceRunners(pitchResultState, [1,0,0,0]);
|
pitch === "single" ||
|
||||||
|
pitch === "double" ||
|
||||||
|
pitch === "triple" ||
|
||||||
|
pitch === "home run"
|
||||||
|
) {
|
||||||
|
const result = handleHit(pitchResultState, pitch)
|
||||||
const {newState, message} = result
|
const {newState, message} = result
|
||||||
gameLogMessageArray.push(message)
|
endsAtBat = result.endsAtBat
|
||||||
scoredRunners = result.scoredRunners
|
scoredRunners= result.scoredRunners
|
||||||
pitchResultState = {...pitchResultState, ...newState}
|
gameLogMessageArray.push(message)
|
||||||
|
pitchResultState = { ...pitchResultState, ...newState };
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
console.warn("Unknown play:", pitch); // Optional: Handle unexpected values
|
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)
|
setGameState(pitchResultState)
|
||||||
if (endsAtBat){advanceLineup(gameState, lineupState, setLineupState)}
|
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 = () => {
|
const endGame = () => {
|
||||||
setGameState((prevState)=>({...prevState, isFinal: true}))
|
setGameState((prevState)=>({...prevState, isFinal: true}))
|
||||||
}
|
}
|
||||||
@@ -351,10 +388,13 @@ function App() {
|
|||||||
|
|
||||||
// Undo the last action
|
// Undo the last action
|
||||||
const handleUndo = () => {
|
const handleUndo = () => {
|
||||||
|
console.dir(history)
|
||||||
if (history.length > 0) {
|
if (history.length > 0) {
|
||||||
const lastState = history[history.length - 1];
|
const {gameState, lineupState} = history[history.length - 1];
|
||||||
const latestGameLog = gameLog[gameLog.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
|
setHistory((prevHistory) => prevHistory.slice(0, -1)); // Remove the last history entry
|
||||||
setGameLog((prevGamelong) => prevGamelong.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 foul" onClick={() => handlePitch("foul")} disabled={gameState.isFinal}>Foul</button>
|
||||||
<button className="play out" onClick={() => handlePitch("out")} disabled={gameState.isFinal}>Out</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("single")}>1</Button>
|
||||||
<Button className="play hit" onClick={() => handlePitch("hit")}>2</Button>
|
<Button className="play hit" onClick={() => handlePitch("double")}>2</Button>
|
||||||
<Button className="play hit" onClick={() => handlePitch("hit")}>3</Button>
|
<Button className="play hit" onClick={() => handlePitch("triple")}>3</Button>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
|
|||||||
@@ -96,4 +96,12 @@ body {
|
|||||||
}
|
}
|
||||||
border: none;
|
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 (
|
return (
|
||||||
<div className="gameState">
|
<div className="gameState">
|
||||||
<header>Scoreboard</header>
|
<header>Scoreboard</header>
|
||||||
@@ -24,9 +24,9 @@ function GameStateDisplay({inning, bases, isTopHalf, outs, count, awayScore, ho
|
|||||||
<Col>{count.balls}-{count.strikes}</Col>
|
<Col>{count.balls}-{count.strikes}</Col>
|
||||||
<Col>{outs} outs</Col>
|
<Col>{outs} outs</Col>
|
||||||
<Col>
|
<Col>
|
||||||
<FontAwesomeIcon icon={fa1} className={`base ${bases[0] ? "occupied" : ""}`}></FontAwesomeIcon>
|
<FontAwesomeIcon icon={fa1} className={`base ${bases[0] ? `occupied ${bases[0]}` : ""}`}></FontAwesomeIcon>
|
||||||
<FontAwesomeIcon icon={fa2} className={`base ${bases[1] ? "occupied" : ""}`}></FontAwesomeIcon>
|
<FontAwesomeIcon icon={fa2} className={`base ${bases[1] ? `occupied ${bases[1]}` : ""}`}></FontAwesomeIcon>
|
||||||
<FontAwesomeIcon icon={fa3} className={`base ${bases[2] ? "occupied" : ""}`}></FontAwesomeIcon>
|
<FontAwesomeIcon icon={fa3} className={`base ${bases[2] ? `occupied ${bases[2]}` : ""}`}></FontAwesomeIcon>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
@@ -35,8 +35,8 @@ function GameStateDisplay({inning, bases, isTopHalf, outs, count, awayScore, ho
|
|||||||
)}
|
)}
|
||||||
<strong>{isFinal ? "FINAL!" : ""}</strong>
|
<strong>{isFinal ? "FINAL!" : ""}</strong>
|
||||||
<Row>
|
<Row>
|
||||||
<Col><strong> Away Score: </strong> {awayScore}</Col>
|
<Col><strong> Away Score: </strong> {score.away}</Col>
|
||||||
<Col><strong> Home Score: </strong> {homeScore}</Col>
|
<Col><strong> Home Score: </strong> {score.home}</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</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