Merge pull request #30 from jhalitaksoy/feature/game-model
Feature/game model
This commit is contained in:
commit
2ea22f5303
@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
MancalaGame,
|
|
||||||
GameStep,
|
GameStep,
|
||||||
HistoryItem,
|
HistoryItem,
|
||||||
GAME_STEP_GAME_MOVE,
|
GAME_STEP_GAME_MOVE,
|
||||||
@ -7,11 +6,13 @@ import {
|
|||||||
GAME_STEP_BOARD_CLEARED,
|
GAME_STEP_BOARD_CLEARED,
|
||||||
GAME_STEP_LAST_STONE_IN_BANK,
|
GAME_STEP_LAST_STONE_IN_BANK,
|
||||||
GAME_STEP_DOUBLE_STONE_IN_PIT,
|
GAME_STEP_DOUBLE_STONE_IN_PIT,
|
||||||
|
MancalaGame,
|
||||||
} from "mancala.js";
|
} from "mancala.js";
|
||||||
import { v4 } from "uuid";
|
import { v4 } from "uuid";
|
||||||
import { Context } from "../context/context";
|
import { Context } from "../context/context";
|
||||||
import BoardViewModelFactory from "../factory/BoardViewModelFactory";
|
import BoardViewModelFactory from "../factory/BoardViewModelFactory";
|
||||||
import { PitViewModelFactory } from "../factory/PitViewModelFactory";
|
import { PitViewModelFactory } from "../factory/PitViewModelFactory";
|
||||||
|
import { Game } from "../models/Game";
|
||||||
import { getColorByBrightness } from "../util/ColorUtil";
|
import { getColorByBrightness } from "../util/ColorUtil";
|
||||||
import BoardViewModel from "../viewmodel/BoardViewModel";
|
import BoardViewModel from "../viewmodel/BoardViewModel";
|
||||||
|
|
||||||
@ -19,8 +20,8 @@ const animationUpdateInterval = 300;
|
|||||||
|
|
||||||
export default class PitAnimator {
|
export default class PitAnimator {
|
||||||
context: Context;
|
context: Context;
|
||||||
game: MancalaGame | undefined;
|
game: Game | undefined;
|
||||||
oldGame: MancalaGame | undefined;
|
oldGame: Game | undefined;
|
||||||
currentIntervalID: number;
|
currentIntervalID: number;
|
||||||
onBoardViewModelUpdate: (boardViewModel: BoardViewModel) => void;
|
onBoardViewModelUpdate: (boardViewModel: BoardViewModel) => void;
|
||||||
boardViewModel: BoardViewModel | undefined;
|
boardViewModel: BoardViewModel | undefined;
|
||||||
@ -36,13 +37,17 @@ export default class PitAnimator {
|
|||||||
this.onBoardViewModelUpdate = onBoardViewModelUpdate;
|
this.onBoardViewModelUpdate = onBoardViewModelUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setNewGame(game: MancalaGame) {
|
get mancalaGame(): MancalaGame | undefined {
|
||||||
|
return this.game?.mancalaGame;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setNewGame(game: Game) {
|
||||||
this.reset();
|
this.reset();
|
||||||
this.game = game;
|
this.game = game;
|
||||||
this.onBoardViewModelUpdate?.(this.getBoardViewModelFromGame(this.game));
|
this.onBoardViewModelUpdate?.(this.getBoardViewModelFromGame(this.game));
|
||||||
}
|
}
|
||||||
|
|
||||||
public setUpdatedGame(game: MancalaGame) {
|
public setUpdatedGame(game: Game) {
|
||||||
this.resetAnimationState();
|
this.resetAnimationState();
|
||||||
if (!this.game) {
|
if (!this.game) {
|
||||||
this.setNewGame(game);
|
this.setNewGame(game);
|
||||||
@ -55,8 +60,8 @@ export default class PitAnimator {
|
|||||||
|
|
||||||
onGameMoveAnimationStart() {
|
onGameMoveAnimationStart() {
|
||||||
this.stopCurrentAnimation();
|
this.stopCurrentAnimation();
|
||||||
if (this.game && this.oldGame && this.game.history.length > 0) {
|
if (this.game && this.oldGame && this.mancalaGame && this.mancalaGame?.history.length > 0) {
|
||||||
const lastHistoryItem = this.game.history[this.game.history.length - 1];
|
const lastHistoryItem = this.mancalaGame.history[this.mancalaGame.history.length - 1];
|
||||||
if (lastHistoryItem.gameSteps.length > 0) {
|
if (lastHistoryItem.gameSteps.length > 0) {
|
||||||
this.animationIndex = 0;
|
this.animationIndex = 0;
|
||||||
this.currentHistoryItem = lastHistoryItem;
|
this.currentHistoryItem = lastHistoryItem;
|
||||||
@ -68,13 +73,13 @@ export default class PitAnimator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onAnimate() {
|
onAnimate() {
|
||||||
if (!this.currentHistoryItem || !this.game || !this.oldBoardViewModel) return;
|
if (!this.currentHistoryItem || !this.game || !this.oldBoardViewModel || !this.mancalaGame) return;
|
||||||
if (this.animationIndex === this.currentHistoryItem.gameSteps.length) {
|
if (this.animationIndex === this.currentHistoryItem.gameSteps.length) {
|
||||||
this.clearCurrentInterval();
|
this.clearCurrentInterval();
|
||||||
this.onBoardViewModelUpdate?.(this.getBoardViewModelFromGame(this.game));
|
this.onBoardViewModelUpdate?.(this.getBoardViewModelFromGame(this.game));
|
||||||
} else {
|
} else {
|
||||||
const gameStep = this.currentHistoryItem.gameSteps[this.animationIndex];
|
const gameStep = this.currentHistoryItem.gameSteps[this.animationIndex];
|
||||||
const index = this.game.board.getPitIndexCircularly(gameStep.index);
|
const index = this.mancalaGame.board.getPitIndexCircularly(gameStep.index);
|
||||||
this.animatePit(index, this.oldBoardViewModel, gameStep);
|
this.animatePit(index, this.oldBoardViewModel, gameStep);
|
||||||
this.onBoardViewModelUpdate?.(this.oldBoardViewModel);
|
this.onBoardViewModelUpdate?.(this.oldBoardViewModel);
|
||||||
}
|
}
|
||||||
@ -92,7 +97,7 @@ export default class PitAnimator {
|
|||||||
boardViewModel: BoardViewModel,
|
boardViewModel: BoardViewModel,
|
||||||
gameStep: GameStep
|
gameStep: GameStep
|
||||||
) {
|
) {
|
||||||
if (!this.currentHistoryItem || !this.game) return;
|
if (!this.currentHistoryItem || !this.game || !this.mancalaGame) return;
|
||||||
const pitViewModel = boardViewModel.pits[index];
|
const pitViewModel = boardViewModel.pits[index];
|
||||||
if (this.animationIndex === 0) {
|
if (this.animationIndex === 0) {
|
||||||
//This is one stone move case, TODO: beautify it later
|
//This is one stone move case, TODO: beautify it later
|
||||||
@ -112,7 +117,7 @@ export default class PitAnimator {
|
|||||||
} else if (gameStep.type === GAME_STEP_LAST_STONE_IN_EMPTY_PIT) {
|
} else if (gameStep.type === GAME_STEP_LAST_STONE_IN_EMPTY_PIT) {
|
||||||
pitViewModel.pitColor = theme.pitGetRivalStonePitAnimateColor;
|
pitViewModel.pitColor = theme.pitGetRivalStonePitAnimateColor;
|
||||||
pitViewModel.stoneCount = 0;
|
pitViewModel.stoneCount = 0;
|
||||||
const oppositeIndex = this.game.board.getPitIndexCircularly(
|
const oppositeIndex = this.mancalaGame.board.getPitIndexCircularly(
|
||||||
gameStep.data.oppositeIndex
|
gameStep.data.oppositeIndex
|
||||||
);
|
);
|
||||||
const oppositePitViewModel = boardViewModel.pits[oppositeIndex];
|
const oppositePitViewModel = boardViewModel.pits[oppositeIndex];
|
||||||
@ -122,13 +127,13 @@ export default class PitAnimator {
|
|||||||
pitViewModel.pitColor = theme.pitLastStoneInBankPitAnimateColor;
|
pitViewModel.pitColor = theme.pitLastStoneInBankPitAnimateColor;
|
||||||
} else if (gameStep.type === GAME_STEP_BOARD_CLEARED) {
|
} else if (gameStep.type === GAME_STEP_BOARD_CLEARED) {
|
||||||
for (const index of gameStep.data.pitIndexesThatHasStone) {
|
for (const index of gameStep.data.pitIndexesThatHasStone) {
|
||||||
const oppositeIndex = this.game.board.getPitIndexCircularly(index);
|
const oppositeIndex = this.mancalaGame.board.getPitIndexCircularly(index);
|
||||||
const oppositePitViewModel = boardViewModel.pits[oppositeIndex];
|
const oppositePitViewModel = boardViewModel.pits[oppositeIndex];
|
||||||
oppositePitViewModel.pitColor = theme.pitGetRivalStonePitAnimateColor;
|
oppositePitViewModel.pitColor = theme.pitGetRivalStonePitAnimateColor;
|
||||||
oppositePitViewModel.stoneCount = 0;
|
oppositePitViewModel.stoneCount = 0;
|
||||||
}
|
}
|
||||||
} else if (gameStep.type === GAME_STEP_DOUBLE_STONE_IN_PIT) {
|
} else if (gameStep.type === GAME_STEP_DOUBLE_STONE_IN_PIT) {
|
||||||
const _index = this.game.board.getPitIndexCircularly(index);
|
const _index = this.mancalaGame.board.getPitIndexCircularly(index);
|
||||||
const pitViewModel = boardViewModel.pits[_index];
|
const pitViewModel = boardViewModel.pits[_index];
|
||||||
pitViewModel.pitColor = theme.pitGetRivalStonePitAnimateColor;
|
pitViewModel.pitColor = theme.pitGetRivalStonePitAnimateColor;
|
||||||
pitViewModel.stoneCount = 0;
|
pitViewModel.stoneCount = 0;
|
||||||
@ -164,13 +169,13 @@ export default class PitAnimator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public getBoardViewModelFromGame(game: MancalaGame): BoardViewModel {
|
public getBoardViewModelFromGame(game: Game): BoardViewModel {
|
||||||
const pitViewModels = this.createPitViewModelsFromGame(game);
|
const pitViewModels = this.createPitViewModelsFromGame(game);
|
||||||
return BoardViewModelFactory.create(v4(), pitViewModels);
|
return BoardViewModelFactory.create(v4(), pitViewModels);
|
||||||
}
|
}
|
||||||
|
|
||||||
private createPitViewModelsFromGame(game: MancalaGame) {
|
private createPitViewModelsFromGame(game: Game) {
|
||||||
return game.board.pits.map((pit) => {
|
return game.mancalaGame.board.pits.map((pit) => {
|
||||||
const theme = this.context.themeManager.theme;
|
const theme = this.context.themeManager.theme;
|
||||||
const stoneCount = pit.stoneCount;
|
const stoneCount = pit.stoneCount;
|
||||||
const stoneColor = theme.stoneColor;
|
const stoneColor = theme.stoneColor;
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import { MancalaGame } from "mancala.js";
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { FunctionComponent } from "react";
|
import { FunctionComponent } from "react";
|
||||||
import { Context } from "../context/context";
|
import { Context } from "../context/context";
|
||||||
|
import { Game } from "../models/Game";
|
||||||
import { getColorByBrightness } from "../util/ColorUtil";
|
import { getColorByBrightness } from "../util/ColorUtil";
|
||||||
import CircularPanel from "./CircularPanel";
|
import CircularPanel from "./CircularPanel";
|
||||||
|
|
||||||
function getInfoPanelTextByGameState(params: {
|
function getInfoPanelTextByGameState(params: {
|
||||||
context: Context;
|
context: Context;
|
||||||
game?: MancalaGame;
|
game?: Game;
|
||||||
crashMessage?: string;
|
crashMessage?: string;
|
||||||
userKey?: string;
|
userKey?: string;
|
||||||
userKeyWhoLeave?: string;
|
userKeyWhoLeave?: string;
|
||||||
@ -27,10 +27,10 @@ function getInfoPanelTextByGameState(params: {
|
|||||||
message = context.texts.YouLeftTheGame;
|
message = context.texts.YouLeftTheGame;
|
||||||
}
|
}
|
||||||
return message;
|
return message;
|
||||||
} else if (game?.state == "ended") {
|
} else if (game?.mancalaGame.state == "ended") {
|
||||||
const wonPlayer = game.getWonPlayerId();
|
const wonPlayer = game.mancalaGame.getWonPlayerId();
|
||||||
let whoWon =
|
let whoWon =
|
||||||
game.getWonPlayerId() === userKey
|
game.mancalaGame.getWonPlayerId() === userKey
|
||||||
? context.texts.YouWon
|
? context.texts.YouWon
|
||||||
: context.texts.YouLost;
|
: context.texts.YouLost;
|
||||||
if (!wonPlayer) {
|
if (!wonPlayer) {
|
||||||
@ -39,7 +39,7 @@ function getInfoPanelTextByGameState(params: {
|
|||||||
return context.texts.GameEnded + " " + whoWon;
|
return context.texts.GameEnded + " " + whoWon;
|
||||||
} else {
|
} else {
|
||||||
if (game) {
|
if (game) {
|
||||||
return userKey ? game.checkIsPlayerTurn(userKey)
|
return userKey ? game.mancalaGame.checkIsPlayerTurn(userKey)
|
||||||
? context.texts.YourTurn
|
? context.texts.YourTurn
|
||||||
: context.texts.OpponentTurn : undefined;
|
: context.texts.OpponentTurn : undefined;
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ function getInfoPanelTextByGameState(params: {
|
|||||||
|
|
||||||
const InfoPanel: FunctionComponent<{
|
const InfoPanel: FunctionComponent<{
|
||||||
context: Context;
|
context: Context;
|
||||||
game?: MancalaGame;
|
game?: Game;
|
||||||
crashMessage?: string;
|
crashMessage?: string;
|
||||||
userKey?: string;
|
userKey?: string;
|
||||||
userKeyWhoLeave?: string;
|
userKeyWhoLeave?: string;
|
||||||
@ -65,7 +65,7 @@ const InfoPanel: FunctionComponent<{
|
|||||||
visible
|
visible
|
||||||
}) => {
|
}) => {
|
||||||
if (visible === false) return <></>;
|
if (visible === false) return <></>;
|
||||||
const isUserTurn = userKey ? game?.checkIsPlayerTurn(userKey) : false;
|
const isUserTurn = userKey ? game?.mancalaGame.checkIsPlayerTurn(userKey) : false;
|
||||||
const containerColor = isUserTurn
|
const containerColor = isUserTurn
|
||||||
? context.themeManager.theme.playerTurnColor
|
? context.themeManager.theme.playerTurnColor
|
||||||
: context.themeManager.theme.boardColor;
|
: context.themeManager.theme.boardColor;
|
||||||
|
|||||||
@ -1,43 +1,45 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { MancalaGame, Pit } from "mancala.js";
|
|
||||||
import { FunctionComponent } from "react";
|
import { FunctionComponent } from "react";
|
||||||
import { Context } from "../../context/context";
|
import { Context } from "../../context/context";
|
||||||
import BoardViewModel from "../../viewmodel/BoardViewModel";
|
import BoardViewModel from "../../viewmodel/BoardViewModel";
|
||||||
import PitViewModel from "../../viewmodel/PitViewModel";
|
import PitViewModel from "../../viewmodel/PitViewModel";
|
||||||
import PitView from "./PitView";
|
import PitView from "./PitView";
|
||||||
import StoreView from "./StoreView";
|
import StoreView from "./StoreView";
|
||||||
|
import { Game } from "../../models/Game";
|
||||||
|
import { Pit } from "mancala.js";
|
||||||
|
|
||||||
const BoardView: FunctionComponent<{
|
const BoardView: FunctionComponent<{
|
||||||
game: MancalaGame;
|
game: Game;
|
||||||
context: Context;
|
context: Context;
|
||||||
boardId: string;
|
boardId: string;
|
||||||
boardViewModel: BoardViewModel;
|
boardViewModel: BoardViewModel;
|
||||||
userKey: string;
|
userKey: string;
|
||||||
onPitSelect: (index: number, pit: Pit) => void;
|
onPitSelect: (index: number, pit: Pit) => void;
|
||||||
}> = ({ game, context, boardId, boardViewModel, userKey, onPitSelect: onPitSelect }) => {
|
}> = ({ game, context, boardId, boardViewModel, userKey, onPitSelect: onPitSelect }) => {
|
||||||
|
const mancalaGame = game?.mancalaGame;
|
||||||
const createPitView = (key: any, pitViewModel: PitViewModel, onClick: () => void) => {
|
const createPitView = (key: any, pitViewModel: PitViewModel, onClick: () => void) => {
|
||||||
return <PitView key={key} pitViewModel={pitViewModel} onClick={onClick} />;
|
return <PitView key={key} pitViewModel={pitViewModel} onClick={onClick} />;
|
||||||
};
|
};
|
||||||
const player1Pits = game?.board.player1Pits.map((pit, index) => {
|
const player1Pits = mancalaGame?.board.player1Pits.map((pit, index) => {
|
||||||
const pitViewModel = boardViewModel.pits[pit.index];
|
const pitViewModel = boardViewModel.pits[pit.index];
|
||||||
return createPitView(index, pitViewModel, () => {
|
return createPitView(index, pitViewModel, () => {
|
||||||
if (game.turnPlayerId === game.player1Id && userKey === game.player1Id)
|
if (mancalaGame?.turnPlayerId === mancalaGame?.player1Id && userKey === mancalaGame?.player1Id)
|
||||||
onPitSelect(game.board.player1Pits.indexOf(pit), pit);
|
onPitSelect(mancalaGame?.board.player1Pits.indexOf(pit), pit);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
const player2Pits = game?.board.player2Pits.map((pit, index) => {
|
const player2Pits = mancalaGame?.board.player2Pits.map((pit, index) => {
|
||||||
const pitViewModel = boardViewModel.pits[pit.index];
|
const pitViewModel = boardViewModel.pits[pit.index];
|
||||||
return createPitView(index, pitViewModel, () => {
|
return createPitView(index, pitViewModel, () => {
|
||||||
if (game.turnPlayerId === game.player2Id && userKey === game.player2Id)
|
if (mancalaGame?.turnPlayerId === mancalaGame?.player2Id && userKey === mancalaGame?.player2Id)
|
||||||
onPitSelect(game.board.player2Pits.indexOf(pit), pit);
|
onPitSelect(mancalaGame?.board.player2Pits.indexOf(pit), pit);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
const theme = context.themeManager.theme;
|
const theme = context.themeManager.theme;
|
||||||
const player1BankViewModel =
|
const player1BankViewModel =
|
||||||
boardViewModel.pits[game.board.player1BankIndex()];
|
boardViewModel.pits[mancalaGame?.board.player1BankIndex()];
|
||||||
const player2BankViewModel =
|
const player2BankViewModel =
|
||||||
boardViewModel.pits[game.board.player2BankIndex()];
|
boardViewModel.pits[mancalaGame?.board.player2BankIndex()];
|
||||||
const isPlayer2 = userKey === game?.player2Id;
|
const isPlayer2 = userKey === mancalaGame?.player2Id;
|
||||||
return (
|
return (
|
||||||
<div className="board" style={{ background: theme.boardColor }}>
|
<div className="board" style={{ background: theme.boardColor }}>
|
||||||
<StoreView
|
<StoreView
|
||||||
|
|||||||
13
src/models/Game.ts
Normal file
13
src/models/Game.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { MancalaGame } from "mancala.js";
|
||||||
|
import { UserConnectionInfo } from "./UserConnectionInfo";
|
||||||
|
|
||||||
|
export interface Game {
|
||||||
|
id: string;
|
||||||
|
mancalaGame: MancalaGame;
|
||||||
|
gameUsersConnectionInfo: GameUsersConnectionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GameUsersConnectionInfo {
|
||||||
|
user1ConnectionInfo: UserConnectionInfo;
|
||||||
|
user2ConnectionInfo: UserConnectionInfo;
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { CommonMancalaGame, MancalaGame, Pit } from 'mancala.js';
|
import { MancalaGame, Pit } from 'mancala.js';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { FunctionComponent, useState } from 'react';
|
import { FunctionComponent, useState } from 'react';
|
||||||
import { useNavigate, useParams } from 'react-router';
|
import { useNavigate, useParams } from 'react-router';
|
||||||
@ -23,11 +23,11 @@ import useWindowDimensions from '../hooks/useWindowDimensions';
|
|||||||
import { ConnectionState } from '../models/ConnectionState';
|
import { ConnectionState } from '../models/ConnectionState';
|
||||||
import { GameMove } from '../models/GameMove';
|
import { GameMove } from '../models/GameMove';
|
||||||
import { LoadingState } from '../models/LoadingState';
|
import { LoadingState } from '../models/LoadingState';
|
||||||
import { UserConnectionInfo } from '../models/UserConnectionInfo';
|
|
||||||
import { Theme } from '../theme/Theme';
|
import { Theme } from '../theme/Theme';
|
||||||
import { getColorByBrightness } from '../util/ColorUtil';
|
import { getColorByBrightness } from '../util/ColorUtil';
|
||||||
import BoardViewModel from '../viewmodel/BoardViewModel';
|
import BoardViewModel from '../viewmodel/BoardViewModel';
|
||||||
import Center from '../components/Center';
|
import Center from '../components/Center';
|
||||||
|
import { Game, GameUsersConnectionInfo } from '../models/Game';
|
||||||
|
|
||||||
const GamePage: FunctionComponent<{
|
const GamePage: FunctionComponent<{
|
||||||
context: Context,
|
context: Context,
|
||||||
@ -37,7 +37,7 @@ const GamePage: FunctionComponent<{
|
|||||||
}> = ({ context, userKey, theme, connectionState }) => {
|
}> = ({ context, userKey, theme, connectionState }) => {
|
||||||
let params = useParams<{ gameId: string }>();
|
let params = useParams<{ gameId: string }>();
|
||||||
|
|
||||||
const [game, setGame] = useState<MancalaGame | undefined>(undefined);
|
const [game, setGame] = useState<Game | undefined>(undefined);
|
||||||
|
|
||||||
const [crashMessage, setCrashMessage] = useState<string | undefined>(undefined);
|
const [crashMessage, setCrashMessage] = useState<string | undefined>(undefined);
|
||||||
|
|
||||||
@ -53,20 +53,36 @@ const GamePage: FunctionComponent<{
|
|||||||
// We have to block future actions if there is an ongoing action.
|
// We have to block future actions if there is an ongoing action.
|
||||||
const [hasOngoingAction, setHasOngoingAction] = useState<boolean>(false);
|
const [hasOngoingAction, setHasOngoingAction] = useState<boolean>(false);
|
||||||
|
|
||||||
const [isOpponentOnline, setIsOpponentOnline] = useState<boolean>(false);
|
const [gameUsersConnectionInfo, setGameUsersConnectionInfo] = useState<GameUsersConnectionInfo | undefined>();
|
||||||
|
|
||||||
const { height, width } = useWindowDimensions();
|
const { height, width } = useWindowDimensions();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const [gameLoadingState, setLoadingStateGame] = useState<LoadingState<MancalaGame>>(LoadingState.Unset());
|
const [gameLoadingState, setLoadingStateGame] = useState<LoadingState<Game>>(LoadingState.Unset());
|
||||||
|
|
||||||
const onGameUpdate = (pitAnimator: PitAnimator, message: Object) => {
|
const mancalaGame: MancalaGame | undefined = game?.mancalaGame;
|
||||||
const newGame: CommonMancalaGame = message as CommonMancalaGame;
|
|
||||||
const mancalaGame = MancalaGame.createFromMancalaGame(newGame);
|
const onGameUpdate = (pitAnimator: PitAnimator, newGame: Game) => {
|
||||||
setGame(mancalaGame);
|
setGame(newGame);
|
||||||
pitAnimator.setUpdatedGame(mancalaGame);
|
pitAnimator.setUpdatedGame(newGame);
|
||||||
setHasOngoingAction(false);
|
setHasOngoingAction(false);
|
||||||
|
setGameUsersConnectionInfo(newGame.gameUsersConnectionInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isUserOnline = (userId: string) => {
|
||||||
|
if (!gameUsersConnectionInfo) return false;
|
||||||
|
const user1ConnectionInfo = gameUsersConnectionInfo.user1ConnectionInfo;
|
||||||
|
const user2ConnectionInfo = gameUsersConnectionInfo.user2ConnectionInfo;
|
||||||
|
if (user1ConnectionInfo.userId === userId) return user1ConnectionInfo.isOnline;
|
||||||
|
if (user2ConnectionInfo.userId === userId) return user2ConnectionInfo.isOnline;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onGameUpdateEvent = (pitAnimator: PitAnimator, message: Object) => {
|
||||||
|
const newGame: Game = message as Game;
|
||||||
|
newGame.mancalaGame = MancalaGame.createFromMancalaGame(newGame.mancalaGame);
|
||||||
|
onGameUpdate(pitAnimator, newGame);
|
||||||
}
|
}
|
||||||
const onGameCrashed = (message: any) => {
|
const onGameCrashed = (message: any) => {
|
||||||
const newCrashMessage = message as string;
|
const newCrashMessage = message as string;
|
||||||
@ -80,13 +96,12 @@ const GamePage: FunctionComponent<{
|
|||||||
setHasOngoingAction(false);
|
setHasOngoingAction(false);
|
||||||
};
|
};
|
||||||
const onUserConnectionChange = (message: any) => {
|
const onUserConnectionChange = (message: any) => {
|
||||||
const userConnectionInfo = message as UserConnectionInfo;
|
const gameUsersConnectionInfo = message as GameUsersConnectionInfo;
|
||||||
//todo: change this when implementing watch the game feature
|
setGameUsersConnectionInfo(gameUsersConnectionInfo);
|
||||||
setIsOpponentOnline(userConnectionInfo.isOnline);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const listenMessages = (pitAnimator: PitAnimator) : () => void => {
|
const listenMessages = (pitAnimator: PitAnimator): () => void => {
|
||||||
const _onGameUpdate = (message: object) => onGameUpdate(pitAnimator, message);
|
const _onGameUpdate = (message: object) => onGameUpdateEvent(pitAnimator, message);
|
||||||
context.rtmt.listenMessage(channel_on_game_update, _onGameUpdate);
|
context.rtmt.listenMessage(channel_on_game_update, _onGameUpdate);
|
||||||
context.rtmt.listenMessage(channel_on_game_crashed, onGameCrashed);
|
context.rtmt.listenMessage(channel_on_game_crashed, onGameCrashed);
|
||||||
context.rtmt.listenMessage(channel_on_game_user_leave, onGameUserLeave);
|
context.rtmt.listenMessage(channel_on_game_user_leave, onGameUserLeave);
|
||||||
@ -106,12 +121,13 @@ const GamePage: FunctionComponent<{
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getBoardIndex = (index: number) => {
|
const getBoardIndex = (index: number) => {
|
||||||
if (!game) return -1;
|
if (!game || !mancalaGame) return -1;
|
||||||
if (userKey === game.player2Id) return index + game.board.pits.length / 2;
|
const pitsLenght = mancalaGame.board.pits.length;
|
||||||
|
if (userKey === mancalaGame.player2Id) return index + pitsLenght / 2;
|
||||||
return index;
|
return index;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOpponentId = () => game?.player1Id === userKey ? game?.player2Id : game?.player1Id;
|
const getOpponentId = () => mancalaGame?.player1Id === userKey ? mancalaGame?.player2Id : mancalaGame?.player1Id;
|
||||||
|
|
||||||
const checkHasAnOngoingAction = () => hasOngoingAction;
|
const checkHasAnOngoingAction = () => hasOngoingAction;
|
||||||
|
|
||||||
@ -143,15 +159,13 @@ const GamePage: FunctionComponent<{
|
|||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
let pitAnimator: PitAnimator | undefined;
|
let pitAnimator: PitAnimator | undefined;
|
||||||
let unlistenMessages: ()=>void;
|
let unlistenMessages: () => void;
|
||||||
setLoadingStateGame(LoadingState.Loading())
|
setLoadingStateGame(LoadingState.Loading())
|
||||||
context.gameStore.get(params.gameId!!).then((game) => {
|
context.gameStore.get(params.gameId!!).then((game) => {
|
||||||
if (game) {
|
if (game) {
|
||||||
setGame(game);
|
|
||||||
setHasOngoingAction(false);
|
|
||||||
pitAnimator = new PitAnimator(context, updateBoardViewModel);
|
pitAnimator = new PitAnimator(context, updateBoardViewModel);
|
||||||
pitAnimator.setNewGame(game);
|
|
||||||
setPitAnimator(pitAnimator);
|
setPitAnimator(pitAnimator);
|
||||||
|
onGameUpdate(pitAnimator, game);
|
||||||
unlistenMessages = listenMessages(pitAnimator);
|
unlistenMessages = listenMessages(pitAnimator);
|
||||||
setLoadingStateGame(LoadingState.Loaded({ value: game }))
|
setLoadingStateGame(LoadingState.Loaded({ value: game }))
|
||||||
} else {
|
} else {
|
||||||
@ -169,9 +183,10 @@ const GamePage: FunctionComponent<{
|
|||||||
context.themeManager.theme.textColor,
|
context.themeManager.theme.textColor,
|
||||||
context.themeManager.theme.textLightColor
|
context.themeManager.theme.textLightColor
|
||||||
);
|
);
|
||||||
const renderNewGameBtn = userKeyWhoLeave || !game || (game && game.state == "ended");
|
const renderNewGameBtn = userKeyWhoLeave || !game || (game && game.mancalaGame.state == "ended");
|
||||||
const showBoardView = game && boardViewModel && userKey && true;
|
const showBoardView = game && boardViewModel && userKey && true;
|
||||||
const opponentUser = { id: getOpponentId() || "0", name: "Anonymous", isOnline: isOpponentOnline, isAnonymous: true };
|
const opponentId = getOpponentId();
|
||||||
|
const opponentUser = { id: getOpponentId() || "0", name: "Anonymous", isOnline: opponentId ? isUserOnline(opponentId) : false, isAnonymous: true };
|
||||||
const user = { id: userKey || "1", name: "Anonymous", isOnline: connectionState === "connected", isAnonymous: true };
|
const user = { id: userKey || "1", name: "Anonymous", isOnline: connectionState === "connected", isAnonymous: true };
|
||||||
|
|
||||||
const isMobile = width < 600;
|
const isMobile = width < 600;
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import { CommonMancalaGame, MancalaGame } from "mancala.js";
|
import { CommonMancalaGame, MancalaGame } from "mancala.js";
|
||||||
|
import { Game } from "../models/Game";
|
||||||
import { HttpService } from "../service/HttpService";
|
import { HttpService } from "../service/HttpService";
|
||||||
|
|
||||||
export interface GameStore {
|
export interface GameStore {
|
||||||
get(id: string): Promise<MancalaGame | undefined>;
|
get(id: string): Promise<Game | undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GameStoreImpl implements GameStore {
|
export class GameStoreImpl implements GameStore {
|
||||||
@ -11,11 +12,13 @@ export class GameStoreImpl implements GameStore {
|
|||||||
this.httpService = props.httpService;
|
this.httpService = props.httpService;
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(id: string): Promise<MancalaGame | undefined> {
|
async get(id: string): Promise<Game | undefined> {
|
||||||
try {
|
try {
|
||||||
const response = await this.httpService.get(`/game/${id}`);
|
const response = await this.httpService.get(`/game/${id}`);
|
||||||
const json = await response.json();
|
const json = await response.json();
|
||||||
return MancalaGame.createFromMancalaGame(json as CommonMancalaGame);
|
const game: Game = json as Game;
|
||||||
|
game.mancalaGame = MancalaGame.createFromMancalaGame(game.mancalaGame);
|
||||||
|
return game;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// todo check error
|
// todo check error
|
||||||
Promise.resolve(undefined);
|
Promise.resolve(undefined);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user