Skip to content

Commit

Permalink
merge: Pull request #78 from ShrimpCryptid/feature/hide-player-info
Browse files Browse the repository at this point in the history
fix: Unknown player roles are removed from player list
  • Loading branch information
ShrimpCryptid committed Aug 26, 2023
2 parents 282dfde + ce3aefa commit ecd0045
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 60 deletions.
2 changes: 1 addition & 1 deletion backend/src/main/java/game/SecretHitlerGame.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public class SecretHitlerGame implements Serializable {
// The last president and chancellor that were successfully voted into office.
private String lastPresident;
private String lastChancellor;
private Policy.Type lastEnactedPolicy;
private Policy.Type lastEnactedPolicy = Policy.Type.FASCIST;

private String currentPresident;
private String currentChancellor;
Expand Down
2 changes: 1 addition & 1 deletion backend/src/main/java/server/SecretHitlerServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ private static void onWebSocketMessage(WsMessageContext ctx) {
break;

case COMMAND_GET_STATE: // Requests the updated state of the game.
lobby.updateUser(ctx);
lobby.updateUser(ctx, name);
break;

case COMMAND_NOMINATE_CHANCELLOR: // params: PARAM_TARGET (String)
Expand Down
81 changes: 55 additions & 26 deletions backend/src/main/java/server/util/GameToJSONConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import game.GameState;
import game.SecretHitlerGame;
import game.datastructures.Identity;
import game.datastructures.Player;
import game.datastructures.Policy;
import org.json.JSONObject;
Expand All @@ -14,34 +15,50 @@
public class GameToJSONConverter {
/**
* Creates a JSON object from a SecretHitlerGame that represents its state.
*
* @param game the SecretHitlerGame to convert.
* @param name the name of the user to create JSON content for. This is used
* to determine what player identity information to send to the
* user.
* @throws NullPointerException if {@code game} is null.
* @return a JSONObject with the following properties:
* - {@code state}: the state of the game.
* - {@code player-order}: an array of names representing the order of the players in the game.
* - {@code state}: the state of the game.
* - {@code player-order}: an array of names representing the order of
* the players in the game.
*
* - {@code players}: a JSONObject map, with keys that are a player's {@code username}.
* Each {@code username} key maps to an object with the properties {@code id} (String),
* {@code alive} (boolean), and {@code investigated} (boolean), to represent the player.
* The identity is either this.HITLER, this.FASCIST, or this.LIBERAL.
* Ex: {"player1":{"alive": true, "investigated": false, "id": "LIBERAL"}}.
* - {@code players}: a JSONObject map, with keys that are a player's
* {@code username}.
* Each {@code username} key maps to an object with the properties
* {@code id} (String),
* {@code alive} (boolean), and {@code investigated} (boolean), to
* represent the player.
* The identity is either this.HITLER, this.FASCIST, or this.LIBERAL.
* Ex: {"player1":{"alive": true, "investigated": false, "id":
* "LIBERAL"}}.
*
* - {@code president}: the username of the current president.
* - {@code chancellor}: the username of the current chancellor (can be null).
* - {@code last-president}: The username of the last president that presided over a legislative session.
* - {@code last-chancellor}: The username of the last chancellor that presided over a legislative session.
* - {@code draw-size}: The size of the draw deck.
* - {@code discard-size}: The size of the discard deck.
* - {@code fascist-policies}: The number of passed fascist policies.
* - {@code liberal-policies}: The number of passed liberal policies.:
* - {@code user-votes}: A map from each user to their vote from the last chancellor nomination.
* - {@code president-choices}: The choices for the president during the legislative session (only if in
* game state LEGISLATIVE_PRESIDENT).
* - {@code chancellor-choices}: The choices for the chancellor during the legislative session (only if in
* game state LEGISLATIVE_CHANCELLOR).
* - {@code veto-occurred}: Set to true if a veto has already taken place on this legislative session.
* - {@code president}: the username of the current president.
* - {@code chancellor}: the username of the current chancellor (can be
* null).
* - {@code last-president}: The username of the last president that
* presided over a legislative session.
* - {@code last-chancellor}: The username of the last chancellor that
* presided over a legislative session.
* - {@code draw-size}: The size of the draw deck.
* - {@code discard-size}: The size of the discard deck.
* - {@code fascist-policies}: The number of passed fascist policies.
* - {@code liberal-policies}: The number of passed liberal policies.:
* - {@code user-votes}: A map from each user to their vote from the
* last chancellor nomination.
* - {@code president-choices}: The choices for the president during the
* legislative session (only if in
* game state LEGISLATIVE_PRESIDENT).
* - {@code chancellor-choices}: The choices for the chancellor during
* the legislative session (only if in
* game state LEGISLATIVE_CHANCELLOR).
* - {@code veto-occurred}: Set to true if a veto has already taken
* place on this legislative session.
*/
public static JSONObject convert(SecretHitlerGame game) {
public static JSONObject convert(SecretHitlerGame game, String userName) {
if (game == null) {
throw new NullPointerException();
}
Expand All @@ -51,14 +68,22 @@ public static JSONObject convert(SecretHitlerGame game) {
String[] playerOrder = new String[game.getPlayerList().size()];
List<Player> playerList = game.getPlayerList();

// Players should only be shown all roles under specific circumstances.
Identity role = game.getPlayer(userName).getIdentity();
boolean showAllRoles = game.hasGameFinished() || role == Identity.FASCIST
|| (role == Identity.HITLER && game.getPlayerList().size() <= 6);

for (int i = 0; i < playerList.size(); i++) {
JSONObject playerObj = new JSONObject();
Player player = playerList.get(i);

playerObj.put("alive", player.isAlive());

String id = player.getIdentity().toString();
playerObj.put("id", id);
// Only include player role for self or under specific rules
if (player.getUsername().equals(userName) || showAllRoles) {
String id = player.getIdentity().toString();
playerObj.put("id", id);
}
playerObj.put("investigated", player.hasBeenInvestigated());

playerData.put(player.getUsername(), playerObj);
Expand All @@ -79,6 +104,8 @@ public static JSONObject convert(SecretHitlerGame game) {
out.put("election-tracker", game.getElectionTracker());
out.put("election-tracker-advanced", game.didElectionTrackerAdvance());

out.put("last-policy", game.getLastEnactedPolicy().toString().toUpperCase());

out.put("draw-size", game.getDrawSize());
out.put("discard-size", game.getDiscardSize());
out.put("fascist-policies", game.getNumFascistPolicies());
Expand All @@ -101,13 +128,15 @@ public static JSONObject convert(SecretHitlerGame game) {

/**
* Converts a list of policies into a string array.
*
* @param list the list of policies.
* @return a string array with the same length as the list, where each index is either "FASCIST" or "LIBERAL"
* @return a string array with the same length as the list, where each index is
* either "FASCIST" or "LIBERAL"
* according to the type of the Policy at that index in the list.
*/
public static String[] convertPolicyListToStringArray(List<Policy> list) {
String[] out = new String[list.size()];
for(int i = 0; i < list.size(); i++) {
for (int i = 0; i < list.size(); i++) {
out[i] = list.get(i).getType().toString();
}
return out;
Expand Down
9 changes: 5 additions & 4 deletions backend/src/main/java/server/util/Lobby.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentSkipListSet;
Expand Down Expand Up @@ -291,8 +292,8 @@ synchronized public int getUserCount() {
* updates all connected CpuPlayers after a set amount of time.
*/
synchronized public void updateAllUsers() {
for (WsContext ws : userToUsername.keySet()) {
updateUser(ws);
for (Entry<WsContext, String> entry : userToUsername.entrySet()) {
updateUser(entry.getKey(), entry.getValue());
}

// Check if the game ended.
Expand Down Expand Up @@ -365,10 +366,10 @@ public void run() {
* SecretHitlerGame is sent
* to the specified WsContext. ({@code GameToJSONConverter.convert()})
*/
synchronized public void updateUser(WsContext ctx) {
synchronized public void updateUser(WsContext ctx, String userName) {
JSONObject message;
if (isInGame()) {
message = GameToJSONConverter.convert(game); // sends the game state
message = GameToJSONConverter.convert(game, userName); // sends the game state
message.put(SecretHitlerServer.PARAM_PACKET_TYPE, SecretHitlerServer.PACKET_GAME_STATE);
} else {
message = new JSONObject();
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import {
PARAM_ELEC_TRACKER_ADVANCED,
COMMAND_END_TERM,
PARAM_LAST_STATE,
PARAM_LAST_POLICY,
STATE_PP_PEEK,
PLAYER_IS_ALIVE,
PARAM_TARGET,
Expand Down Expand Up @@ -921,7 +922,7 @@ class App extends Component {
this.queueAlert((
<PolicyEnactedAlert
hideAlert={this.hideAlertAndFinish}
policyType={liberalChanged ? LIBERAL : FASCIST}/>
policyType={newState[PARAM_LAST_POLICY]}/>
));
}

Expand Down
1 change: 1 addition & 0 deletions frontend/src/GlobalDefinitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,5 +118,6 @@ export const PARAM_DISCARD_DECK = "discard-size";
export const PARAM_PRESIDENT_CHOICES = "president-choices";
export const PARAM_CHANCELLOR_CHOICES = "chancellor-choices";
export const PARAM_TARGET = "target-user";
export const PARAM_LAST_POLICY = "last-policy";
export const PARAM_DID_VETO_OCCUR = "veto-occurred";
// </editor-fold>
65 changes: 38 additions & 27 deletions frontend/src/util/PolicyDisplay.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,48 @@
import React, {Component} from 'react';
import React, { Component } from "react";
import PropTypes from "prop-types";
import './PolicyDisplay.css';
import {LIBERAL} from "../GlobalDefinitions";
import "./PolicyDisplay.css";
import { LIBERAL } from "../GlobalDefinitions";
import LiberalPolicy from "../assets/policy-liberal.png";
import FascistPolicy from "../assets/policy-fascist.png";

class PolicyDisplay extends Component {
render() {
return (
<div id={"legislative-policy-container"}>
{this.props.policies.map((value, index) => {
let policyName = value === LIBERAL ? "liberal" : "fascist";
return (
<img
id={"legislative-policy"}
className={this.props.allowSelection ? "selectable " + (index === this.props.selection ? " selected" : ""):""}
onClick={() => this.props.onClick(index)}
disabled={!this.props.allowSelection}
src={value === LIBERAL ? LiberalPolicy : FascistPolicy} // Toggles fascist/liberal policy
alt={"A " + policyName + " policy." + (this.props.allowSelection ? " Click to select." : "")}
/>
);
} )}
</div>
);
}
render() {
return (
<div id={"legislative-policy-container"}>
{this.props.policies.map((value, index) => {
let policyName = value === LIBERAL ? "liberal" : "fascist";
return (
<img
id={"legislative-policy"}
key={index}
className={
this.props.allowSelection
? "selectable " +
(index === this.props.selection ? " selected" : "")
: ""
}
onClick={() => this.props.onClick(index)}
disabled={!this.props.allowSelection}
src={value === LIBERAL ? LiberalPolicy : FascistPolicy} // Toggles fascist/liberal policy
alt={
"A " +
policyName +
" policy." +
(this.props.allowSelection ? " Click to select." : "")
}
/>
);
})}
</div>
);
}
}

PolicyDisplay.propTypes = {
policies: PropTypes.array.isRequired,
onClick: PropTypes.func, // If undefined, the policies cannot be selected.
selection: PropTypes.number,
allowSelection: PropTypes.bool,
policies: PropTypes.array.isRequired,
onClick: PropTypes.func, // If undefined, the policies cannot be selected.
selection: PropTypes.number,
allowSelection: PropTypes.bool,
};

export default PolicyDisplay;
export default PolicyDisplay;

0 comments on commit ecd0045

Please sign in to comment.