defmodule Band do use GenServer @delay 750 def start_link(role, skill) do GenServer.start_link(__MODULE__, [role, skill], []) end @impl true def init([role, skill]) do Process.flag(:trap_exit, true) time_to_play = :rand.uniform(3000) name = pick_name() str_role = Atom.to_string(role) IO.inspect("Musician #{name}, playing the #{str_role} entered room") state = %{ name: name, role: role, skill: skill } {:ok, state, time_to_play} end @impl true def handle_call(:stop, _from, state) do {:stop, :normal, :ok, state} end def handle_call(_message, _from, state) do {:noreply, state, @delay} end @impl true def handle_cast(_message, state) do {:noreply, state, @delay} end @impl true def handle_info(:timeout, %{name: name, skill: :good} = state) do IO.inspect("#{name} produced sound!") {:noreply, state, @delay} end def handle_info(:timeout, %{name: name, skill: :bad} = state) do case :rand.uniform(5) do 1 -> IO.inspect("#{name} played a false note!") {:stop, :bad_note, state} _ -> IO.inspect("#{name} produced sound!") {:noreply, state, @delay} end end def handle_info(_message, state) do {:noreply, state, @delay} end @impl true def terminate(:normal, state) do IO.inspect("#{state.name} left the room (#{state.role})") end def terminate(:bad_note, state) do IO.inspect("#{state.name} kicked. (#{state.role})") end def terminate(:shutdown, _state) do IO.inspect("The manager is mad and fired the whole band! ") end def terminate(_reason, state) do IO.inspect("#{state.name} has been kicked (#{state.role}) ") end def pick_name() do Enum.random(firstnames()) <> " " <> Enum.random(lastnames()) end def firstnames do [ "Valerie", "Arnold", "Carlos", "Dorothy", "Keesha", "Phoebe", "Ralphie", "Tim", "Wanda", "Janet" ] end def lastnames() do [ "Frizzle", "Perlstein", "Ramon", "Ann", "Franklin", "Terese", "Tennelli", "Jamal", "Li", "Perlstein" ] end def stop(pid, _role) do GenServer.call(pid, :stop) end end