-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
35 changed files
with
592 additions
and
310 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { | ||
SportsEsports, PlayCircleFilled, Undo, | ||
} from '@mui/icons-material'; | ||
import { Button } from '@mui/material'; | ||
import { Mode } from '../store/GameModes'; | ||
|
||
interface GameToolbarProps { | ||
mode: Mode, | ||
onRestart: () => void; | ||
onChangeMode: () => void; | ||
onRollback: () => void; | ||
} | ||
|
||
export default function GameToolbar({ | ||
mode, onRestart, onChangeMode, onRollback, | ||
}:GameToolbarProps) { | ||
return ( | ||
<> | ||
<Button | ||
color="inherit" | ||
startIcon={<SportsEsports />} | ||
onClick={onChangeMode} | ||
> | ||
{mode === Mode.Ball8 ? '14/1 endlos' : '8/9/10 Ball'} | ||
</Button> | ||
<Button | ||
color="inherit" | ||
startIcon={<PlayCircleFilled />} | ||
onClick={onRestart} | ||
> | ||
Neues Spiel | ||
</Button> | ||
<Button | ||
color="inherit" | ||
startIcon={<Undo />} | ||
onClick={onRollback} | ||
> | ||
Rückgängig | ||
</Button> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { | ||
State as State8, Action as Action8, initialState as initial8State, reducer as reducer8, | ||
} from './GameState'; | ||
import { | ||
State as State14, Action as Action14, initialState as initial14state, reducer as reducer14, | ||
} from './GameState14'; | ||
|
||
export enum Mode { | ||
Ball8 = 'BALL8', | ||
Straight = 'STRAIGHT', | ||
} | ||
|
||
export type State = State8 | State14; | ||
|
||
export type Action = Action8 | Action14; | ||
|
||
export const getInitialState = (mode: Mode) => { | ||
switch (mode) { | ||
case Mode.Ball8: return initial8State; | ||
case Mode.Straight: return initial14state; | ||
default: throw Error(`Unkown Mode '${mode}'`); | ||
} | ||
}; | ||
|
||
export const reducer = (mode: Mode, state: State, action: Action) => { | ||
switch (mode) { | ||
case Mode.Ball8: return reducer8(state as State8, action as Action8); | ||
case Mode.Straight: return reducer14(state as State14, action as Action14); | ||
default: throw Error(`Unkown Mode '${mode}'`); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import { | ||
createContext, ReactNode, useCallback, useContext, useEffect, useMemo, useState, | ||
} from 'react'; | ||
import { useCollectionData } from 'react-firebase-hooks/firestore'; | ||
import { | ||
collection, doc, query, where, updateDoc, limit, | ||
} from 'firebase/firestore'; | ||
import { useAuth } from './AuthProvider'; | ||
import { db } from './Firebase'; | ||
import { | ||
Mode, State, Action, getInitialState, reducer, | ||
} from './GameModes'; | ||
|
||
interface GameState { | ||
mode?: Mode; | ||
state: State; | ||
startNewGame: (mode: Mode) => void; | ||
updateState: (action: Action) => void; | ||
} | ||
|
||
const GameContext = createContext<GameState | undefined>(undefined); | ||
|
||
export function useGame() { | ||
const value = useContext(GameContext); | ||
if (value === undefined) throw new Error('Expected games context value to be set.'); | ||
return value; | ||
} | ||
|
||
interface GameProviderProps { | ||
children: ReactNode; | ||
} | ||
export default function GameProvider({ children }: GameProviderProps) { | ||
const { clubId, tableId } = useAuth(); | ||
const [mode, setMode] = useState<Mode>(Mode.Ball8); | ||
const [state, setState] = useState<State>(getInitialState(mode)); | ||
|
||
const clubRef = clubId ? doc(db, `clubs/${clubId}`) : null; | ||
const tableRef = clubId && tableId ? doc(db, `clubs/${clubId}/tables/${tableId}`) : null; | ||
const q = clubRef && tableRef | ||
? query(collection(db, 'games'), where('club', '==', clubRef), where('table', '==', tableRef), limit(1)) | ||
: null; | ||
const [gameData, gameDataLoading, gameDataError, snapshot] = useCollectionData(q); | ||
const gameRef = snapshot ? snapshot.docs[0].ref : null; | ||
useEffect(() => { if (gameDataError) throw gameDataError; }, [gameDataError]); | ||
|
||
// Sync behaviour: | ||
// - no online state available | ||
// - just use local state | ||
// - start new game | ||
// - online state available | ||
// - local changes -> push to firestore | ||
// - changes in firestore (e.g. from other client) -> apply to local | ||
const onlineSync = gameRef && !gameDataError && !gameDataLoading | ||
&& gameData?.at(0) && gameData.at(0)?.mode; | ||
useEffect(() => { | ||
if (onlineSync) { | ||
setMode(gameData?.at(0)?.mode); | ||
setState(gameData?.at(0)?.state); | ||
} | ||
}, [gameData, onlineSync]); | ||
|
||
const startNewGame = useCallback(async (newMode: Mode) => { | ||
setMode(newMode); | ||
setState(getInitialState(newMode)); | ||
if (onlineSync) { | ||
await updateDoc(gameRef, { mode: newMode, state: getInitialState(newMode) }); | ||
} | ||
}, [gameRef, onlineSync]); | ||
|
||
const updateState = useCallback(async (action: Action) => { | ||
const newState = reducer(mode, state, action); | ||
setState(newState); | ||
if (onlineSync) { | ||
await updateDoc(gameRef, { state: newState }); | ||
} | ||
}, [mode, state, setState, gameRef, onlineSync]); | ||
|
||
const value = useMemo(() => ({ | ||
mode, state, startNewGame, updateState, | ||
}), [mode, state, startNewGame, updateState]); | ||
|
||
return ( | ||
<GameContext.Provider value={value}> | ||
{children} | ||
</GameContext.Provider> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
export default function isDevelopment() { | ||
export function isDevelopmentEnv() { | ||
return process.env.NODE_ENV === 'development'; | ||
} | ||
export function isTestEnv() { | ||
return process.env.NODE_ENV === 'test'; | ||
} |
Oops, something went wrong.