Skip to content

Commit a40d068

Browse files
refactor vote calculator, run mix format, address comments
1 parent f6d72d2 commit a40d068

File tree

13 files changed

+122
-68
lines changed

13 files changed

+122
-68
lines changed

config/cards.exs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ config :pointing_party,
1515
Update the application to save an individual's vote and the final card points to the database.
1616
"""
1717
},
18-
1918
%{
2019
title: "Add Guardian dependency",
2120
description: """
@@ -34,5 +33,5 @@ config :pointing_party,
3433
description: """
3534
Update our existing authentication flow to use the newly created Auth module.
3635
"""
37-
},
36+
}
3837
]

lib/pointing_party/account.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ defmodule PointingParty.Account do
1111

1212
def create(attrs) do
1313
changeset = changeset(%Account{}, attrs)
14+
1415
if changeset.valid? do
1516
account = apply_changes(changeset)
1617
{:ok, account}

lib/pointing_party/vote_calculator.ex

Lines changed: 59 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
defmodule PointingParty.VoteCalculator do
2-
32
def calculate_votes(users) do
43
case winning_vote(users) do
54
top_two when is_list(top_two) -> {"tie", top_two}
@@ -8,30 +7,64 @@ defmodule PointingParty.VoteCalculator do
87
end
98

109
def winning_vote(users) do
11-
votes = Enum.map(users, fn {_username, %{metas: [%{points: points}]}} -> points end)
12-
calculated_votes = Enum.reduce(votes, %{}, fn vote, acc ->
13-
acc
14-
|> Map.get_and_update(vote, &({&1, (&1 || 0) + 1}))
15-
|> elem(1)
16-
end)
17-
total_votes = length(votes)
18-
19-
majority_share = total_votes / 2 |> Float.floor()
20-
majority = Enum.reduce_while(calculated_votes, nil, fn {point, vote_count}, _acc ->
21-
if vote_count == total_votes or rem(vote_count, total_votes) > majority_share do
22-
{:halt, point}
23-
else
24-
{:cont, nil}
25-
end
26-
end)
27-
28-
if is_nil(majority) do
29-
calculated_votes
30-
|> Enum.sort_by(&elem(&1, 1))
31-
|> Enum.take(2)
32-
|> Enum.map(&elem(&1, 0))
33-
else
34-
majority
35-
end
10+
initial_score_card()
11+
|> get_points(users)
12+
|> calculate_vote_ratios()
13+
|> calculate_majority()
14+
|> handle_tie()
15+
end
16+
17+
def initial_score_card do
18+
%{votes: nil, calculated_votes: nil, majority: nil}
19+
end
20+
21+
defp get_points(score_card, users) do
22+
votes =
23+
users
24+
|> Enum.map(fn {_username, %{metas: [%{points: points}]}} ->
25+
points
26+
end)
27+
28+
update_score_card(score_card, :votes, votes)
29+
end
30+
31+
defp calculate_vote_ratios(%{votes: votes} = score_card) do
32+
calculated_votes =
33+
Enum.reduce(votes, %{}, fn vote, acc ->
34+
acc
35+
|> Map.get_and_update(vote, &{&1, (&1 || 0) + 1})
36+
|> elem(1)
37+
end)
38+
39+
update_score_card(score_card, :calculated_votes, calculated_votes)
40+
end
41+
42+
defp calculate_majority(score_card) do
43+
total_votes = length(score_card.votes)
44+
majority_share = (total_votes / 2) |> Float.floor()
45+
46+
majority =
47+
Enum.reduce_while(score_card.calculated_votes, nil, fn {point, vote_count}, _acc ->
48+
if vote_count == total_votes or rem(vote_count, total_votes) > majority_share do
49+
{:halt, point}
50+
else
51+
{:cont, nil}
52+
end
53+
end)
54+
55+
update_score_card(score_card, :majority, majority)
56+
end
57+
58+
defp handle_tie(%{majority: nil, calculated_votes: calculated_votes}) do
59+
calculated_votes
60+
|> Enum.sort_by(&elem(&1, 1))
61+
|> Enum.take(2)
62+
|> Enum.map(&elem(&1, 0))
63+
end
64+
65+
defp handle_tie(%{majority: majority}), do: majority
66+
67+
defp update_score_card(score_card, key, value) do
68+
Map.put(score_card, key, value)
3669
end
3770
end
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
defmodule PointingPartyWeb.Presence do
2-
use Phoenix.Presence, otp_app: :pointing_party,
3-
pubsub_server: PointingParty.PubSub
2+
use Phoenix.Presence,
3+
otp_app: :pointing_party,
4+
pubsub_server: PointingParty.PubSub
45
end

lib/pointing_party_web/channels/room_channel.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ defmodule PointingPartyWeb.RoomChannel do
1919
end
2020

2121
def handle_in("user_estimated", %{"points" => points}, socket) do
22-
Presence.update(socket, socket.assigns.username, &(Map.put(&1, :points, points)))
22+
Presence.update(socket, socket.assigns.username, &Map.put(&1, :points, points))
2323

2424
if everyone_voted?(socket) do
2525
finalize_voting(socket)
@@ -62,6 +62,7 @@ defmodule PointingPartyWeb.RoomChannel do
6262
end
6363

6464
defp initialize_state(%{assigns: %{cards: _cards}} = socket), do: socket
65+
6566
defp initialize_state(socket) do
6667
[first | cards] = Card.cards()
6768

lib/pointing_party_web/controllers/session_controller.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ defmodule PointingPartyWeb.SessionController do
1515
|> put_session(:username, username)
1616
|> redirect(to: "/cards")
1717
|> halt()
18+
1819
{:error, changeset} ->
1920
render(conn, "new.html", changeset: changeset)
2021
end
2122
end
2223

2324
def delete(conn, _params) do
24-
clear_session(conn)
25-
|> redirect(to: "/login") |> halt()
25+
clear_session(conn) |> redirect(to: "/login") |> halt()
2626
end
2727
end

lib/pointing_party_web/plugs/auth.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ defmodule PointingPartyWeb.Plugs.Auth do
1212
end
1313

1414
defp authenticate(conn) do
15-
get_session(conn, :username)
15+
get_session(conn, :username)
1616
end
1717
end

priv/repo/migrations/20190708014847_create_cards.exs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@ defmodule PointingParty.Repo.Migrations.CreateCards do
33

44
def change do
55
create table(:cards) do
6-
add :title, :string
7-
add :description, :string
6+
add(:title, :string)
7+
add(:description, :string)
88

99
timestamps()
1010
end
11-
1211
end
1312
end

priv/repo/migrations/20190714140153_add_points_to_cards.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ defmodule PointingParty.Repo.Migrations.AddPointsToCards do
33

44
def change do
55
alter table("cards") do
6-
add :points, :integer, default: 0
6+
add(:points, :integer, default: 0)
77
end
88
end
99
end

priv/repo/seeds.exs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
# We recommend using the bang functions (`insert!`, `update!`
1111
# and so on) as they will fail if something goes wrong.
1212

13-
1413
alias PointingParty.{Card, Repo}
1514

1615
cards = [
@@ -21,7 +20,7 @@ cards = [
2120
%{title: "Fifth card", description: "This is a description of the fifth card."},
2221
%{title: "Sixth card", description: "This is a description of the sixth card."},
2322
%{title: "Seventh card", description: "This is a description of the seventh card."},
24-
%{title: "Eighth card", description: "This is a description of the eighth card."},
23+
%{title: "Eighth card", description: "This is a description of the eighth card."}
2524
]
2625

2726
Enum.each(cards, fn card ->

0 commit comments

Comments
 (0)