diff --git a/.tool-versions b/.tool-versions index 8220f1c5b..e4f68f147 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ -elixir 1.14.0-otp-25 +elixir 1.14.1-otp-25 erlang 25.1.1 diff --git a/exercises/creature_spawner.livemd b/exercises/creature_spawner.livemd index d1117f68b..52fb25eef 100644 --- a/exercises/creature_spawner.livemd +++ b/exercises/creature_spawner.livemd @@ -102,6 +102,8 @@ Implement the `Monster` process as documented below. ```elixir defmodule Monster do use GenServer + @enforce_keys [:health] + defstruct @enforce_keys @doc """ Start the `Monster` process. @@ -110,9 +112,11 @@ defmodule Monster do iex> {:ok, pid} = Monster.start_link([]) """ + + # BrookQuestion - The Start signature options is killing me "name: opts[:name]" + # Sesame Street it for me please def start_link(opts) do - # IO.inspect/2 to observe when a `Monster` process starts. - IO.inspect(opts, label: "Monster Started") + GenServer.start_link(__MODULE__, opts, name: opts[:name]) end @doc """ @@ -128,6 +132,7 @@ defmodule Monster do %{health: 70} """ def attack(monster_pid, amount) do + GenServer.cast(monster_pid, {:attack, amount}) end @doc """ @@ -140,6 +145,7 @@ defmodule Monster do 100 """ def health(monster_pid) do + GenServer.call(monster_pid, :health) end @doc """ @@ -153,7 +159,8 @@ defmodule Monster do %{health: 100} """ @impl true - def init(_opts) do + def init(opts) do + {:ok, %{health: 100}} end @doc """ @@ -174,8 +181,26 @@ defmodule Monster do """ @impl true def handle_cast({:attack, damage}, state) do + new_health = state.health - damage + + if new_health <= 0 do + raise "dying!" + else + {:noreply, %{state | health: new_health}} + end end + # BrookQuestion - Why is my implementation not working? I don't get it: + + # case state.health - damage do + # 0 -> + # raise("Morir! Morir!") + + # true -> + # new_state = Map.replace(state, :health, state.health - damage) + # {:noreply, new_state} + # end + @doc """ Callback function to retrieve the current health of a monster. @@ -187,10 +212,21 @@ defmodule Monster do """ @impl true def handle_call(:health, _from, state) do + {:reply, state.health, state} end end ``` +```elixir +# {:ok, pid} = GenServer.start_link(Monster, []) +# GenServer.call(pid, :health) +``` + +```elixir +# GenServer.cast(pid, {:attack, 20}) +# :sys.get_state(pid) +``` + ## Supervisor Create three named `Monster` processes under a single supervisor. When one `Monster` process dies after its health reaches zero, another should be restarted in it's place. @@ -240,7 +276,22 @@ Supervisor.start_link(children, strategy: :one_for_one) Enter your solution below. ```elixir +children = [ + %{ + id: :Monster1, + start: {Monster, :start_link, [[name: :monster1]]} + }, + %{ + id: :Monster2, + start: {Monster, :start_link, [[name: :monster2]]} + }, + %{ + id: :Monster3, + start: {Monster, :start_link, [[name: :monster3]]} + } +] +{:ok, supervisor_pid} = Supervisor.start_link(children, strategy: :one_for_one) ``` Call `Monster.attack/1` on your monster processes to ensure they are restarted. @@ -256,7 +307,7 @@ Monster.attack(:monster1, 110) ```elixir - +# Monster.attack(:monster1, 110) ``` ## Bonus: Hero @@ -297,9 +348,26 @@ end ```elixir +#BrookQuestion: in which instances we choose Process.send instead of GenServer.call? + + +defp schedule_attack() do + Process.send_after(self(), :attack_monsters, 1000) + end + + def handle_info(:attack_monsters, state) do + Supervisor.which_children(:rpg_supervisor) + |> Enum.each(fn + {_name, pid, :worker, [Monster]} -> Monster.attack(pid, Enum.random(1..10)) + _ -> :ok + end) ``` +```elixir +Hero.start_link(supervisor_pid) +``` + Start the `Hero` process with three other `Monster` processes in the same supervisor. Make the supervisor a named supervisor so you can find all of its child processes with [Supervisor.which_children/1](https://hexdocs.pm/elixir/Supervisor.html#which_children/1).
diff --git a/exercises/dominoes.livemd b/exercises/dominoes.livemd index 3edf82345..bbf8b197d 100644 --- a/exercises/dominoes.livemd +++ b/exercises/dominoes.livemd @@ -95,7 +95,24 @@ Supervisor.start_link(children, strategy: :rest_for_one) Keep in mind, if you have already started a named process, the supervisor might crash when you attempt to start it again. Re-evaluate the cell after the livebook crashes to resolve this issue. ```elixir +# BrookQuestion Can we go over the start signature thingy again? +children = [ + %{ + id: :domino1, + start: {Domino, :start_link, [[name: :domino1]]} + }, + %{ + id: :domino2, + start: {Domino, :start_link, [[name: :domino2]]} + }, + %{ + id: :domino3, + start: {Domino, :start_link, [[name: :domino3]]} + } +] + +{:ok, supervisor_pid} = Supervisor.start_link(children, strategy: :rest_for_one) ``` Send your dominos messages to ensure they are crashing in the correct order. They will log a message that demonstrates the `Domino.start_link/1` function was called again. @@ -114,7 +131,7 @@ Process.send(:domino_name, :fall, []) Test sending each `Domino` process a message individually. ```elixir - +Process.send(:domino2, :fall, []) ``` ## Commit Your Progress diff --git a/exercises/supervised_stack.livemd b/exercises/supervised_stack.livemd index e19aa51d7..16a2866da 100644 --- a/exercises/supervised_stack.livemd +++ b/exercises/supervised_stack.livemd @@ -22,6 +22,14 @@ We've made a slight modification to the `Stack` process by adding a `start_link/ defmodule Stack do use GenServer + # BrookQuestion - This is how I first tried + # children = [%{id: :stack, start: {__MODULE__, :start_link, []}}] + # Supervisor.start_link(children, strategy: :one_for_one) + # I think I am not grasping the start signature. Guidance, please? + + # BrookQuestion - I also do not fully understand the solution cell + # Is that supposed to be all part of the module, or part of it is to be called from outside? + def start_link(opts) do GenServer.start_link(__MODULE__, [], name: __MODULE__) end @@ -102,7 +110,11 @@ children = [ Keep in mind, if you have already started a supervisor with the `Stack` process, your livebook may crash. You can resolve this issue by simply re-running the cell below to start the supervisor again. ```elixir +children = [ + {Stack, []} +] +{:ok, supervisor_pid} = Supervisor.start_link(children, strategy: :one_for_one) ``` You should be able to send a `:pop` message to the `Stack` process and the [Supervisor](https://hexdocs.pm/elixir/Supervisor.html) will restart the `Stack` process. @@ -110,7 +122,7 @@ You should be able to send a `:pop` message to the `Stack` process and the [Supe Uncomment and evaluate the code below to test your supervisor. ```elixir -# GenServer.call(Stack, :pop) +GenServer.call(Stack, :pop) ``` ## Commit Your Progress