From b8c911f28ebbc557ca628fec34d399f91b211c19 Mon Sep 17 00:00:00 2001 From: Administrator Date: Thu, 13 Feb 2025 20:54:22 -0500 Subject: [PATCH] updated functionality --- asc/src/context/ScoreContext.js | 232 +++++++++++++++----------------- 1 file changed, 108 insertions(+), 124 deletions(-) diff --git a/asc/src/context/ScoreContext.js b/asc/src/context/ScoreContext.js index 047c2e8..9eba00e 100644 --- a/asc/src/context/ScoreContext.js +++ b/asc/src/context/ScoreContext.js @@ -1,6 +1,7 @@ // src/context/ScoreContext.js import React, { createContext, useContext, useReducer, useEffect } from 'react'; +// Define action types export const ACTIONS = { ADD_ARROW: 'ADD_ARROW', START_NEW_ROUND: 'START_NEW_ROUND', @@ -11,116 +12,7 @@ export const ACTIONS = { UPDATE_HANDICAP: 'UPDATE_HANDICAP' }; -// Reducer function -const scoreReducer = (state, action) => { - let newState; - - switch (action.type) { - case ACTIONS.ADD_ARROW: - const { roundIndex, score, isBullseye } = action.payload; - const updatedRounds = [...state.currentGame.rounds]; - - if (!updatedRounds[roundIndex]) { - updatedRounds[roundIndex] = { arrows: [], total: 0, bullseyes: 0 }; - } - - updatedRounds[roundIndex] = { - ...updatedRounds[roundIndex], - arrows: [...updatedRounds[roundIndex].arrows, score], - total: updatedRounds[roundIndex].total + score, - bullseyes: updatedRounds[roundIndex].bullseyes + (isBullseye ? 1 : 0), - }; - - const totalScore = updatedRounds.reduce((sum, round) => sum + round.total, 0); - const totalBullseyes = updatedRounds.reduce((sum, round) => sum + round.bullseyes, 0); - - newState = { - ...state, - currentGame: { - ...state.currentGame, - rounds: updatedRounds, - totalScore, - totalBullseyes, - }, - }; - break; - - case ACTIONS.START_NEW_ROUND: - // If there's a current game, save it to history - const gamesHistory = state.currentGame.gameType ? - [...state.games, state.currentGame] : - state.games; - - newState = { - games: gamesHistory, - currentGame: { - gameType: action.payload.gameType, - rounds: [], - totalScore: 0, - totalBullseyes: 0, - dateStarted: new Date().toISOString(), - }, - }; - break; - - case ACTIONS.RESET_GAME: - newState = initialState; - break; - - case ACTIONS.LOAD_SAVED_GAME: - newState = action.payload; - break; - - default: - return state; - } - - // Save to localStorage after every state change - localStorage.setItem('archeryScores', JSON.stringify(newState)); - return newState; -}; - -// Create context -const ScoreContext = createContext(); - -// Context provider component -export const ScoreProvider = ({ children }) => { - // Load state from localStorage on initial render - const [state, dispatch] = useReducer(scoreReducer, initialState, () => { - try { - const localData = localStorage.getItem('archeryScores'); - if (localData) { - const parsedData = JSON.parse(localData); - // Verify the data structure - if (parsedData.currentGame && parsedData.games) { - return parsedData; - } - } - } catch (error) { - console.error('Error loading saved game:', error); - } - return initialState; - }); - - return ( - - {children} - - ); -}; - -// Custom hook for using the score context -export const useScore = () => { - const context = useContext(ScoreContext); - if (!context) { - throw new Error('useScore must be used within a ScoreProvider'); - } - return context; -}; - -// src/context/ScoreContext.js -// ... (keeping existing imports and initial setup) - +// Initial state structure const initialState = { currentGame: { id: null, @@ -146,24 +38,71 @@ const initialState = { }, }; -// Handicap calculation function (basic version - can be adjusted based on your league's rules) +// Handicap calculation function const calculateHandicap = (scores) => { if (scores.length < 3) return null; - - // Take the average of the last 3 scores + const lastThree = scores.slice(-3); const average = lastThree.reduce((sum, game) => sum + game.totalScore, 0) / 3; - - // Example handicap calculation (adjust formula as needed) + const maxPossibleScore = scores[0].gameType === '450' ? 450 : 300; const handicap = Math.round((maxPossibleScore - average) * 0.8); - - return Math.max(0, Math.min(100, handicap)); // Cap between 0 and 100 + + return Math.max(0, Math.min(100, handicap)); }; +// Reducer function const scoreReducer = (state, action) => { switch (action.type) { - case ACTIONS.START_NEW_GAME: + case ACTIONS.ADD_ARROW: { + const { roundIndex, score, isBullseye } = action.payload; + const updatedRounds = [...state.currentGame.rounds]; + + if (!updatedRounds[roundIndex]) { + updatedRounds[roundIndex] = { arrows: [], total: 0, bullseyes: 0 }; + } + + updatedRounds[roundIndex] = { + ...updatedRounds[roundIndex], + arrows: [...updatedRounds[roundIndex].arrows, score], + total: updatedRounds[roundIndex].total + score, + bullseyes: updatedRounds[roundIndex].bullseyes + (isBullseye ? 1 : 0), + }; + + const totalScore = updatedRounds.reduce((sum, round) => sum + round.total, 0); + const totalBullseyes = updatedRounds.reduce((sum, round) => sum + round.bullseyes, 0); + + return { + ...state, + currentGame: { + ...state.currentGame, + rounds: updatedRounds, + totalScore, + totalBullseyes, + }, + }; + } + + case ACTIONS.START_NEW_ROUND: { + const gamesHistory = state.currentGame.gameType ? + [...state.games, state.currentGame] : + state.games; + + return { + ...state, + games: gamesHistory, + currentGame: { + ...state.currentGame, + gameType: action.payload.gameType, + rounds: [], + totalScore: 0, + totalBullseyes: 0, + dateStarted: new Date().toISOString(), + }, + }; + } + + case ACTIONS.START_NEW_GAME: { const { gameType, category } = action.payload; return { ...state, @@ -175,19 +114,19 @@ const scoreReducer = (state, action) => { dateStarted: new Date().toISOString(), }, }; + } - case ACTIONS.SAVE_GAME: + case ACTIONS.SAVE_GAME: { const completedGame = { ...state.currentGame, dateCompleted: new Date().toISOString(), }; - // Calculate handicap for league games if (completedGame.category === 'league') { const relevantGames = [...state.games.league, completedGame] .filter(game => game.gameType === completedGame.gameType) .sort((a, b) => new Date(b.dateCompleted) - new Date(a.dateCompleted)); - + completedGame.handicap = calculateHandicap(relevantGames); } @@ -199,7 +138,6 @@ const scoreReducer = (state, action) => { ], }; - // Update statistics const updateAverages = (games, type, category) => { const relevantGames = games.filter(game => game.gameType === type); return relevantGames.length > 0 @@ -227,12 +165,58 @@ const scoreReducer = (state, action) => { games: newGames, statistics: newStatistics, }; + } - // ... (existing cases) + case ACTIONS.RESET_GAME: + return initialState; + + case ACTIONS.LOAD_SAVED_GAME: + return action.payload; default: return state; } }; -// ... (rest of the context implementation) +// Create context +const ScoreContext = createContext(); + +// Context provider component +export const ScoreProvider = ({ children }) => { + const [state, dispatch] = useReducer(scoreReducer, initialState, () => { + try { + const localData = localStorage.getItem('archeryScores'); + if (localData) { + const parsedData = JSON.parse(localData); + if (parsedData.currentGame && parsedData.games) { + return parsedData; + } + } + } catch (error) { + console.error('Error loading saved game:', error); + } + return initialState; + }); + + // Save to localStorage after every state change + useEffect(() => { + localStorage.setItem('archeryScores', JSON.stringify(state)); + }, [state]); + + return ( + + {children} + + ); +}; + +// Custom hook for using the score context +export const useScore = () => { + const context = useContext(ScoreContext); + if (!context) { + throw new Error('useScore must be used within a ScoreProvider'); + } + return context; +}; + +export default ScoreContext;