Skip to content

Instantly share code, notes, and snippets.

@dedeco

dedeco/poll.ex

Created Feb 23, 2020
Embed
What would you like to do?
Poll in Elixir
defmodule Poll do
defstruct candidates: []
#Public API
def start_link() do
poll = %Poll{}
spawn_link(Poll, :run, [poll])
end
def exit(pid) when is_pid(pid) do
send(pid, :exit)
end
def add_candidate(pid, name) when is_pid(pid) do
send(pid, {:add_candidate, name})
end
def vote(pid, name) when is_pid(pid) do
send(pid, {:vote, name})
end
#Implemented Functions
def add_candidate(poll, name) do
candidate = Candidate.new(name)
#candidates = poll.candidates ++ [candidate]
candidates = [candidate | poll.candidates]
%{poll | candidates: candidates}
end
def vote(poll, name) do
candidates = Enum.map(poll.candidates, &increment_vote(&1, name))
Map.put(poll, :candidates, candidates)
end
def candidates(pid) when is_pid(pid) do
send(pid, {:candidates, self()})
receive do
{^pid, poll} -> poll.candidates
end
end
def new(candidates \\ []) do
%Poll{candidates: candidates}
end
defp increment_vote(candidate, name) when is_binary(name) do
increment_vote(candidate, candidate.name == name)
end
defp increment_vote(candidate, _can_increment=false), do: candidate
defp increment_vote(candidate, _can_increment=true) do
Map.update!(candidate, :votes, &(&1 +1))
end
def run(:quit), do: :quit
def run(poll) do
receive do
msg ->
#IO.inspect(msg, label: "Message")
handle(msg, poll)
end
#|> IO.inspect(label: "Poll")
|> run()
end
def handle({:add_candidate, name}, poll) do
poll |>
Poll.add_candidate(name)
end
def handle({:vote, name}, poll) do
poll |>
Poll.vote(name)
end
def handle({:candidates, pid}, poll) do
send(pid, {self(), poll})
poll
end
def handle(:exit, _poll) do
run(:quit)
end
def handle(msg, poll) do
IO.inspect(msg, label: "Unknown Msg")
poll
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment