Skip to content

Commit b27703f

Browse files
starting state with tests
1 parent 9d23d94 commit b27703f

File tree

7 files changed

+4025
-95
lines changed

7 files changed

+4025
-95
lines changed

assets/js/socket.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import { Socket, Presence } from 'phoenix'
2+
import updateUsers from './users'
3+
24
const socket = new Socket('/socket', {params: {username: window.pointingParty.username}})
35
socket.connect()
46

57
let driving = false;
68

9+
// connect to Presence here
10+
// set up your syncDiff function using updateUsers as a callback
11+
712
const startButton = document.querySelector('.start-button')
813
startButton.addEventListener('click', e => {
914
driving = true;

assets/js/users.js

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,33 @@
11
import { forEach, isNil, map, none } from 'ramda'
22

3+
const usersElem = document.querySelector('.users')
4+
35
const updateUsers = presence => {
4-
const usersElem = document.querySelector('.users')
56
usersElem.innerHTML = ''
67

7-
const users = presence.list(listBy)
8-
forEach(addUser(usersElem))(users)
9-
10-
if (allHaveEstimated(users)) {
11-
forEach(showPoints(usersElem))(users)
8+
// let user = list presences with the help of a listBy function
9+
for(let i = 0; i < users.length; i++) {
10+
addUser(users[i])
1211
}
12+
13+
// implement a feature that
14+
// 1. checks if all fo the users in the present list have voted, i.e. have points values that are not nil
15+
// 2. displays the user's vote next to their name if so
1316
}
1417

15-
const listBy = (username, { metas: [{ points }, ..._rest]}) => ({ username, points })
18+
const listBy = (username, { metas: [{ points }, ..._rest]}) => {
19+
// build out the listBy function so that it returns a list of users
20+
// where each user looks like this:
21+
// {username: username, points: points}
22+
}
1623

1724
const showPoints = usersElem => ({userId, points}) => {
1825
const userElem = document.querySelector(`.${userId}.user-estimate`)
1926
userElem.innerHTML = points
2027
}
2128

22-
// const addUser = usersElem => ({userId, points}) => {
23-
// const userElem = document.createElement('dt')
24-
// userElem.appendChild(document.createTextNode(userId))
25-
// userElem.setAttribute('class', 'col-8')
26-
//
27-
// const estimateElem = document.createElement('dd')
28-
// estimateElem.setAttribute('class', `${userId} user-estimate col-4`)
29-
//
30-
// usersElem.appendChild(userElem)
31-
// usersElem.appendChild(estimateElem)
32-
// }
33-
34-
const allHaveEstimated = users => {
35-
const pointsCollection = map(({ points }) => points)(users)
36-
37-
return none(isNil)(pointsCollection)
38-
}
39-
4029
function addUser(user) {
41-
document.createElement('dt')
30+
const userElem = document.createElement('dt')
4231
userElem.appendChild(document.createTextNode(user.username))
4332
userElem.setAttribute('class', 'col-8')
4433

Lines changed: 8 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,42 @@
11
defmodule PointingPartyWeb.RoomChannel do
22
use PointingPartyWeb, :channel
33

4-
alias PointingParty.Card
5-
alias PointingPartyWeb.Presence
6-
alias PointingParty.VoteCalculator
7-
84
def join("room:lobby", _payload, socket) do
95
send(self(), :after_join)
106

117
{:ok, socket}
128
end
139

1410
def handle_info(:after_join, socket) do
15-
push(socket, "presence_state", Presence.list(socket))
16-
{:ok, _} = Presence.track(socket, socket.assigns.username, %{})
17-
11+
# handle Presence listing and tracking here
1812
{:noreply, socket}
1913
end
2014

2115
def handle_in("user_estimated", %{"points" => points}, socket) do
22-
Presence.update(socket, socket.assigns.username, &(Map.put(&1, :points, points)))
23-
24-
if everyone_voted?(socket) do
25-
finalize_voting(socket)
26-
end
27-
16+
# update votes for user presence
17+
# calculate votes if everyone voted with the help of the VoteCalculator
18+
# broadcast the 'winner'/'tie' event with a payload of %{points: points}
2819
{:noreply, socket}
2920
end
3021

3122
def handle_in("finalized_points", %{"points" => points}, socket) do
32-
updated_socket = save_vote_next_card(points, socket)
33-
broadcast!(updated_socket, "new_card", %{card: current_card(updated_socket)})
34-
{:reply, :ok, updated_socket}
23+
# update state by setting the current card to the next card
24+
# broadcast the "new_card" message with a payload of %{card: new_current_card}
25+
{:reply, :ok, socket}
3526
end
3627

3728
def handle_in("start_pointing", _params, socket) do
3829
updated_socket = initialize_state(socket)
39-
broadcast!(updated_socket, "new_card", %{card: current_card(updated_socket)})
30+
# broadcast the "new_card" message with a payload of %{card: current_card}
4031
{:reply, :ok, updated_socket}
4132
end
4233

43-
intercept ["new_card"]
44-
45-
def handle_out("new_card", payload, socket) do
46-
Presence.update(socket, socket.assigns.username, &(Map.put(&1, :points, nil)))
47-
push(socket, "new_card", payload)
48-
{:noreply, socket}
49-
end
50-
51-
52-
defp current_card(socket) do
53-
socket.assigns
54-
|> Map.get(:current)
55-
|> Map.from_struct()
56-
|> Map.drop([:__meta__])
57-
end
58-
59-
defp everyone_voted?(socket) do
60-
socket
61-
|> Presence.list()
62-
|> Enum.map(fn {_username, %{metas: [metas]}} -> Map.get(metas, :points) end)
63-
|> Enum.all?(&(not is_nil(&1)))
64-
end
65-
66-
defp finalize_voting(socket) do
67-
current_users = Presence.list(socket)
68-
69-
{event, points} = VoteCalculator.calculate_votes(current_users)
70-
broadcast!(socket, event, %{points: points})
71-
end
72-
7334
defp initialize_state(%{assigns: %{cards: _cards}} = socket), do: socket
7435
defp initialize_state(socket) do
7536
[first | cards] = Card.cards()
7637

7738
socket
78-
|> assign(:points, Card.points_range())
7939
|> assign(:unvoted, cards)
8040
|> assign(:current, first)
8141
end
82-
83-
defp save_vote_next_card(points, socket) do
84-
latest_card =
85-
socket.assigns
86-
|> Map.get(:current)
87-
|> Map.put(:points, points)
88-
89-
{next, remaining} =
90-
socket.assigns
91-
|> Map.get(:unvoted)
92-
|> List.pop_at(0)
93-
94-
socket
95-
|> assign(:unvoted, remaining)
96-
|> assign(:current, next)
97-
|> assign(:voted, [latest_card | socket.assigns[:voted]])
98-
end
9942
end

lib/pointing_party_web/channels/user_socket.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ defmodule PointingPartyWeb.UserSocket do
1515
#
1616
# See `Phoenix.Token` documentation for examples in
1717
# performing token verification on connect.
18-
def connect(%{"username" => username}, socket, _connect_info) do
19-
{:ok, assign(socket, :username, username)}
18+
def connect(_params, socket, _connect_info) do
19+
{:ok, socket}
2020
end
2121

2222
# Socket id's are topics that allow you to identify all sockets for a given user:

mix.exs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ defmodule PointingParty.MixProject do
88
elixir: "~> 1.5",
99
elixirc_paths: elixirc_paths(Mix.env()),
1010
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
11-
elixirc_options: [warnings_as_errors: true],
1211
start_permanent: Mix.env() == :prod,
1312
deps: deps()
1413
]

priv/static/js/app.js

Lines changed: 3972 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
defmodule PointingParty.VoteCalculatorTest do
2+
use ExUnit.Case, async: true
3+
4+
@users_with_winner %{
5+
"sean" => %{metas: [%{points: 1}]},
6+
"michael" => %{metas: [%{points: 3}]},
7+
"sophie" => %{metas: [%{points: 3}]}
8+
}
9+
10+
@users_with_tie %{
11+
"sean" => %{metas: [%{points: 1}]},
12+
"michael" => %{metas: [%{points: 2}]},
13+
"sophie" => %{metas: [%{points: 3}]}
14+
}
15+
16+
test "calculate_votes/1 calculates when there is a winner" do
17+
{"winner", 3} = PointingParty.VoteCalculator.calculate_votes(@users_with_winner)
18+
end
19+
20+
test "calculate_votes/1 calculates when there is a tie" do
21+
{"tie", [1,2]} = PointingParty.VoteCalculator.calculate_votes(@users_with_tie)
22+
end
23+
end

0 commit comments

Comments
 (0)