diff --git a/client/src/Winner.css b/client/src/Winner.css index 605fa35..760897e 100644 --- a/client/src/Winner.css +++ b/client/src/Winner.css @@ -80,3 +80,19 @@ text-align: center; line-height: 1.5rem; } + +.Winner .ThiefStole { + +} + +.Winner .PlayerStolen { + display: flex; + align-items: center; + +} + +.Winner .PlayerStolenList { + display: flex; + flex-wrap: wrap; + flex-direction: row; +} \ No newline at end of file diff --git a/client/src/Winner.js b/client/src/Winner.js index ccba456..8a8436d 100644 --- a/client/src/Winner.js +++ b/client/src/Winner.js @@ -88,24 +88,60 @@ const Winner = ({ winnerDismissed, setWinnerDismissed }) => { ; }); - let robber = <>; + let robber; + let max = 0; - if (winner.robberStole) { - let stolen = <>; - for (let type in winner.stolen) { - const resource = winner.stolen[type]; - if (typeof resource === 'object') { /* player colors are also in 'game.stolen' */ + let playerStolen = []; + const stats = winner.stolen; + for (let player in stats) { + if (player === 'robber') { + robber = <>; + for (let type in stats.robber.stole) { + if (type === 'total') { + continue; + } + const count = stats.robber.stole[type]; + robber = <>{robber} + + ; + } + robber =
+ Throughout the game, the robber stole {stats.robber.stole.total} + resources: +
{robber}
; + continue; + } + + if (stats[player].stolen.total < max) { + continue; + } + if (stats[player].stolen.total > max) { + max = stats[player].stolen.total; + playerStolen = []; + } + + let stolen; + for (let type in stats[player].stolen) { + if (type === 'total') { continue; } + if (!stolen) { + stolen = <>; + } + const count = stats[player].stolen[type]; stolen = <>{stolen} - + ; } - robber =
- Throughout the game, the robber stole {winner.robberStole} resources: -
{stolen}
-
; - } else { + if (stolen) { + playerStolen.push(
+ {winner.players[player].name} +
{stolen}
+
); + } + } + + if (!robber) { robber =
The robber never stole any resources from anyone!
; } @@ -138,6 +174,12 @@ const Winner = ({ winnerDismissed, setWinnerDismissed }) => { { losers }
The game took {totalTime}.
{ robber } + { max !== 0 && <> +
Player{ playerStolen.length === 1 ? '' : 's'} that had the most ({max}) resources stolen by the thief or other players:
+
+ { playerStolen } +
+ } diff --git a/server/routes/games.js b/server/routes/games.js index 1c1876a..8b2eaeb 100755 --- a/server/routes/games.js +++ b/server/routes/games.js @@ -285,14 +285,15 @@ const distributeResources = (game, roll) => { tiles.forEach(tile => { let shuffle = game.tileOrder[tile.index]; const resource = game.tiles[shuffle]; - console.log(tile.index, resource); layout.tiles[tile.index].corners.forEach(cornerIndex => { const active = game.placements.corners[cornerIndex]; if (active && active.color) { + const count = active.type === 'settlement' ? 1 : 2; if (!tile.robber) { - receives[active.color][resource.type] += active.type === 'settlement' ? 1 : 2; + receives[active.color][resource.type] += count; } else { - receives.robber[resource.type] += active.type === 'settlement' ? 1 : 2; + trackTheft(game, active.color, robber, resource.type, count); + receives.robber[resource.type] += count; } } }) @@ -316,7 +317,7 @@ const distributeResources = (game, roll) => { session.player.resources += entry[type]; message.push(`${entry[type]} ${type}`); } else { - robberSteal(game, color, type, entry[type]); + robber.push(`${entry[type]} ${type}`); } } @@ -510,6 +511,7 @@ const loadGame = async (id) => { console.log(`${info}: Creating backup of games/${id}`); await writeFile(`games/${id}.bk`, JSON.stringify(game)); } catch (error) { + console.log(`Load or parse error from games/${id}:`, error); console.log(`Attempting to load backup from games/${id}.bk`); game = await readFile(`games/${id}.bk`) .catch(() => { @@ -518,7 +520,7 @@ const loadGame = async (id) => { if (game) { try { game = JSON.parse(game); - console.log(`Restoring backup to games/${id}`); + console.log(`Saving backup to games/${id}`); await writeFile(`games/${id}`, JSON.stringify(game, null, 2)); } catch (error) { console.error(error); @@ -2055,6 +2057,8 @@ const stealResource = (game, session, color) => { session.player.resources++; game.turn.actions = []; game.turn.limits = {}; + trackTheft(game, victim.color, session.color, type, 1); + addChatMessage(game, session, `${session.name} randomly stole 1 ${type} from ` + `${victim.name}.`); @@ -3320,7 +3324,6 @@ const calculatePoints = (game, update) => { console.log(`${info}: ${message}`); update.winner = Object.assign({}, player, { state: 'winner', - robberStole: game.robberStole, stolen: game.stolen, chat: game.chat, turns: game.turns, @@ -3944,22 +3947,71 @@ const getFilteredGameForPlayer = (game, session) => { }); } -const robberSteal = (game, color, type, count) => { - if (!game.stolen) { - game.stolen = {}; +/* Example: +"stolen": { + "robber": { + "stole": { + "total": 5, + "wheat": 2, + "wood": 1, + "sheep": 2 + } + }, + "O": { + "stolen": { + "total": 2, + "wheat": 2 + }, + "stole": { + "total": 2, + "brick": 2 + } + }, + "W": { + "stolen": { + "total": 4, + "brick": 2, + "wood": 1, + "sheep": 2 + }, + "stole": { + "total": 3, + "brick": 2, + "wheat": 1 + } } - if (!(color in game.stolen)) { - game.stolen[color] = {}; +} +*/ +const trackTheft = (game, from, to, type, count) => { + const stats = game.stolen; + + /* Initialize the stole / stolen structures */ + [ to, from ].forEach(player => { + if (!(player in stats)) { + stats[player] = { + stole: { /* the resources this player stole */ + total: 0 + }, + stolen: { /* the resources stolen from this player */ + total: 0 + } + }; + } + }); + + /* Initialize 'type' field in structures */ + if (!(type in stats[from].stole)) { + games.stolen[from].stole[type] = 0; } - if (!(type in game.stolen)) { - game.stolen[type] = 0; + if (!(type in stats[to].stole)) { + games.stole[to].stolen[type] = 0; } - if (!(type in game.stolen[color])) { - game.stolen[color][type] = 0; - } - game.robberStole = game.robberStole += count; - game.stolen[type] += count; - game.stolen[color][type] += count; + + /* Update counts */ + stats[from].stolen.total += count; + stats[from].stolen[type] += count; + stats[to].stole.total += count; + stats[to].stole[type] += count; } const resetGame = (game) => { @@ -3986,8 +4038,12 @@ const resetGame = (game) => { tileOrder: game.tileOrder, signature: game.signature, players: game.players, - stolen: {}, - robberStole: 0, + stolen: { + robber: { + stole: 0 + }, + total: 0 + }, longestRoad: '', longestRoadLength: 0, largestArmy: '',