1
0
James Ketrenos 99f0971873 Lots of fixes for volcano and other features
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
2022-06-18 12:30:26 -07:00

199 lines
6.1 KiB
JavaScript

import React, { useState, useEffect, useContext, useRef, useMemo, useCallback } from "react";
import equal from "fast-deep-equal";
import Paper from '@material-ui/core/Paper';
import Button from '@material-ui/core/Button';
import "./Winner.css";
import {Resource} from './Resource.js';
import {PlayerColor} from './PlayerColor.js';
import { GlobalContext } from "./GlobalContext.js";
const Winner = ({ winnerDismissed, setWinnerDismissed }) => {
const { ws } = useContext(GlobalContext);
const [winner, setWinner] = useState(undefined);
const [state, setState] = useState(undefined);
const fields = useMemo(() => [
'winner', 'state'
], []);
const onWsMessage = (event) => {
const data = JSON.parse(event.data);
switch (data.type) {
case 'game-update':
console.log(`winner - game update`, data.update);
if ('winner' in data.update && !equal(data.update.winner, winner)) {
setWinner(data.update.winner);
}
if ('state' in data.update && data.update.state !== state) {
if (data.update.state !== 'winner') {
setWinner(undefined);
}
setWinnerDismissed(false);
setState(data.update.state);
}
break;
default:
break;
}
};
const refWsMessage = useRef(onWsMessage);
useEffect(() => { refWsMessage.current = onWsMessage; });
useEffect(() => {
if (!ws) { return; }
const cbMessage = e => refWsMessage.current(e);
ws.addEventListener('message', cbMessage);
return () => {
ws.removeEventListener('message', cbMessage);
}
}, [ws, refWsMessage]);
useEffect(() => {
if (!ws) { return; }
ws.send(JSON.stringify({
type: 'get',
fields
}));
}, [ws, fields]);
const quitClicked = useCallback((event) => {
if (!winnerDismissed) {
setWinnerDismissed(true);
ws.send(JSON.stringify({
type: 'goto-lobby'
}));
}
}, [ws, winnerDismissed, setWinnerDismissed]);
if (!winner || winnerDismissed) {
return <></>;
}
let losers = [];
for (let key in winner.players) {
if (key === winner.color || winner.players[key].status === 'Not active') {
continue;
}
losers.push(winner.players[key]);
}
const turnCount = Math.floor(winner.turns / (losers.length + 1));
losers = losers.map(player => {
const averageSeconds = Math.floor(player.totalTime / turnCount / 1000),
average = `${Math.floor(averageSeconds / 60)}m:${averageSeconds % 60}s`;
return <div key={player.color}>
<PlayerColor color={player.color}/> {player.name} finished with {player.points} victory points.
{ Number(player.potential) !== 0 && <>They had <b>{player.potential}</b> unplayed Victory Point card(s).</> }
Their average turn time was {average}.
</div>;
});
let robber;
let max = 0;
let playerStolen = {};
const stats = winner.stolen;
for (let player in stats) {
if (player === 'total' || player === 'player') {
continue;
}
if (player === 'robber') {
robber = <></>;
for (let type in stats.robber.stole) {
if (type === 'total') {
continue;
}
const count = stats.robber.stole[type];
robber = <>{robber}
<Resource label={true} type={type} count={count} disabled/>
</>;
}
robber = <div>
Throughout the game, the robber blocked <b>{stats.robber.stole.total}
</b> resources:
<div className="ThiefStole">{robber}</div></div>;
continue;
}
if ( stats[player].stolen.total < max) {
continue;
}
if (stats[player].stolen.total > max) {
max = stats[player].stolen.total;
playerStolen = {
robber: stats[player].stolen.robber,
player: stats[player].stolen.player,
element: <></>
};
}
let stolen;
for (let type in stats[player].stolen) {
if ([ 'total', 'robber', 'player' ].indexOf(type) !== -1) {
continue;
}
if (!stolen) {
stolen = <></>;
}
const count = stats[player].stolen[type];
stolen = <>{stolen}
<Resource label={true} type={type} count={count} disabled/>
</>;
}
if (stolen) {
playerStolen.element = <div key={player}>
<PlayerColor color={player}/> {winner.players[player].name}
<div className="PlayerStolen">{stolen}</div>
</div>;
}
}
if (!robber) {
robber = <div>The robber never blocked any resources from anyone!</div>;
}
const averageSeconds = Math.floor(winner.totalTime / turnCount / 1000),
average = `${Math.floor(averageSeconds / 60)}m:${averageSeconds % 60}s`;
const seconds = winner.elapsedTime / 1000,
h = Math.floor(seconds / (60 * 60)),
m = Math.floor((seconds % (60 * 60)) / 60),
s = Math.floor((seconds % (60 * 60)) % 60);
const totalTime = `${h}h:${m}m:${s}s`;
let vpType = ['market', 'university', 'library', 'palace'];
vpType = vpType[Math.floor(vpType.length * Math.random())];
return (
<div className="Winner">
<Paper>
<div className="Title">{winner.name} has won with {winner.points} victory points!</div>
<div style={{display: 'flex', flexDirection: 'row'}}>
<Resource type={`vp-${vpType}`} disabled count={1}/>
<div className="Description">
<div>Congratulations, <b>{winner.name}</b>!</div>
<div>
<PlayerColor color={winner.color}/> {winner.name} won the game
with <b>{winner.points}</b> Victory Points after {turnCount} game turns.
{ Number(winner.potential) !== 0 && <>They had <b>{winner.potential}</b> unplayed Victory Point card(s).</>}
Their average turn time was {average}.
</div>
{ losers }
<div>The game took {totalTime}.</div>
{ robber }
{ max !== 0 && <>
<div>The robber stole {playerStolen.robber} and other players
stole {playerStolen.player} resources from:</div>
<div className="PlayerStolenList">
{ playerStolen.element }
</div>
</> }
</div>
</div>
<Button onClick={quitClicked}>Go back to Lobby</Button>
</Paper>
</div>
);
};
export { Winner };