From efb56934eb9333fb19e515432c5f03f47e5aa3cf Mon Sep 17 00:00:00 2001 From: Carl Worth <cworth@cworth.org> Date: Tue, 9 Jun 2020 07:59:41 -0700 Subject: [PATCH] Add a button to advance from prompt voting to playing the actual game Once a majority of the players have voted a new button appears (for everyone) that when pressed tells the server that it's time to start the game. Then, when the client receives a "start" event from the server with the prompt the server chose, the client replaces the entire interface with a form for entering the responses to the prompt. The submit button for that form is currently inert. --- empathy/empathy.css | 2 +- empathy/empathy.jsx | 105 ++++++++++++++++++++++++++++++++++++++++++++ style.css | 6 +++ 3 files changed, 112 insertions(+), 1 deletion(-) diff --git a/empathy/empathy.css b/empathy/empathy.css index d553597..ef88072 100644 --- a/empathy/empathy.css +++ b/empathy/empathy.css @@ -6,7 +6,7 @@ border-radius: 25px; font-size: 200%; padding: 1em; - margin-top: 0.25em; + margin-bottom: 0.25em; } .vote-choices { diff --git a/empathy/empathy.jsx b/empathy/empathy.jsx index 110b330..0771bbe 100644 --- a/empathy/empathy.jsx +++ b/empathy/empathy.jsx @@ -58,6 +58,8 @@ events.addEventListener("game-state", event => { for (let prompt of state.prompts) { window.game.add_or_update_prompt(prompt); } + + window.game.set_active_prompt(state.active_prompt); }); events.addEventListener("prompt", event => { @@ -66,6 +68,12 @@ events.addEventListener("prompt", event => { window.game.add_or_update_prompt(prompt); }); +events.addEventListener("start", event => { + const prompt = JSON.parse(event.data); + + window.game.set_active_prompt(prompt); +}); + /********************************************************* * Game and supporting classes * *********************************************************/ @@ -249,6 +257,86 @@ const PromptOptions = React.memo(props => { ); }); +const LetsPlay = React.memo(props => { + + function handle_click(prompt_id) { + fetch_post_json + } + + const quorum = Math.round((props.num_players + 1) / 2); + const max_votes = props.prompts.reduce( + (max_so_far, v) => Math.max(max_so_far, v.votes.length), 0); + + if (max_votes < quorum) + return null; + + const candidates = props.prompts.filter(p => p.votes.length >= quorum); + const index = Math.floor(Math.random() * candidates.length); + const winner = candidates[index]; + + return ( + <div className="lets-play"> + <h2>Let's Play</h2> + <p> + That should be enough voting. If you're not waiting for any + other players to join, then let's start. + </p> + <button + className="lets-play" + onClick={() => fetch_post_json(`start/${winner.id}`) } + > + Start Game + </button> + </div> + ); +}); + +const ActivePrompt = React.memo(props => { + + function handle_submit(event) { + + /* Prevent the default page-changing form-submission behavior. */ + event.preventDefault(); + } + + return ( + <div className="active-prompt"> + <h2>The Game of Empathy</h2> + <p> + Remember, you're trying to match your answers with + what the other players submit. + Give {props.prompt.items} responses for the following prompt: + </p> + <h2>{props.prompt.prompt}</h2> + <form onSubmit={handle_submit}> + {Array(props.prompt.items).fill(null).map((whocares,i) => { + return ( + <div + key={i} + className="form-field large"> + <input + type="text" + name={`response_${i}`} + required + autoComplete="off" + /> + </div> + ); + })} + + <div + key="submit-button" + className="form-field large"> + <button type="submit"> + Send + </button> + </div> + + </form> + </div> + ); +}); + class Game extends React.PureComponent { constructor(props) { super(props); @@ -298,9 +386,21 @@ class Game extends React.PureComponent { }); } + set_active_prompt(prompt) { + this.setState({ + active_prompt: prompt + }); + } + render() { const state = this.state; + if (state.active_prompt) { + return <ActivePrompt + prompt={state.active_prompt} + />; + } + return [ <GameInfo key="game-info" @@ -320,6 +420,11 @@ class Game extends React.PureComponent { <PromptOptions key="prompts" prompts={state.prompts} + />, + <LetsPlay + key="lets-play" + num_players={1+state.other_players.length} + prompts={state.prompts} /> ]; } diff --git a/style.css b/style.css index b4d5b1b..c8d6c86 100644 --- a/style.css +++ b/style.css @@ -51,6 +51,7 @@ body { h1,h2 { color: var(--text-fg-color); font-weight: bold; + margin-top: 0.5em; } h1 { @@ -215,6 +216,11 @@ form { grid-column-gap: 1em; } +.form-field { + margin-top: 0.25em; + margin-bottom: 0.25em; +} + .form-field.small.left,.form-field.medium.left { grid-column-start: 1; } -- 2.45.2