diff --git a/lib/elixir_koans.ex b/lib/elixir_koans.ex index 891e3dd..904967a 100644 --- a/lib/elixir_koans.ex +++ b/lib/elixir_koans.ex @@ -6,7 +6,8 @@ defmodule ElixirKoans do import Supervisor.Spec children = [ - worker(Display, []) + worker(Display, []), + worker(Tracker, []) ] opts = [strategy: :one_for_one, name: ElixirKoans.Supervisor] diff --git a/lib/meditate.ex b/lib/meditate.ex index 971e0eb..ba529f5 100644 --- a/lib/meditate.ex +++ b/lib/meditate.ex @@ -17,11 +17,13 @@ defmodule Mix.Tasks.Meditate do Display.disable_clear() end - Options.initial_koan + modules = Options.initial_koan |> ok? |> Runner.modules_to_run - |> Tracker.start - |> Runner.run + + Tracker.set_total(modules) + + Runner.run(modules) if Tracker.complete? do Display.congratulate diff --git a/lib/tracker.ex b/lib/tracker.ex index 111fc2a..f555b4e 100644 --- a/lib/tracker.ex +++ b/lib/tracker.ex @@ -1,22 +1,27 @@ defmodule Tracker do - def start(modules) do - total = modules - |> Enum.flat_map(&(&1.all_koans)) - |> Enum.count + alias __MODULE__ - Agent.start_link(fn -> %{total: total, - koans: MapSet.new(), - visited_modules: MapSet.new()} end, name: __MODULE__) - modules + defstruct total: 0, koans: MapSet.new(), visited_modules: MapSet.new() + + def start_link do + Agent.start_link(fn -> %Tracker{} end, name: __MODULE__) end - defp get(), do: Agent.get(__MODULE__, &(&1)) + def set_total(modules) do + total = modules + |> Enum.flat_map(&(&1.all_koans)) + |> Enum.count + + Agent.update(__MODULE__, fn _ -> %Tracker{total: total} end) + end def completed(module, koan) do - Agent.update(__MODULE__, fn(%{koans: completed, visited_modules: modules} = all) -> - %{ all | koans: MapSet.put(completed, koan), - visited_modules: MapSet.put(modules, module)} - end) + Agent.update(__MODULE__, &mark_koan_completed(&1, module, koan)) + end + + defp mark_koan_completed(state, module, koan) do + %{state | koans: MapSet.put(state.koans, koan), + visited_modules: MapSet.put(state.visited_modules, module)} end def visited do @@ -28,14 +33,13 @@ defmodule Tracker do total == completed end - def summarize, do: get() |> summarize() - defp summarize(%{total: total, - koans: completed, - visited_modules: modules}) do + def summarize do + state = Agent.get(__MODULE__, &(&1)) + %{ - total: total, - current: MapSet.size(completed), - visited_modules: MapSet.to_list(modules) + total: state.total, + current: MapSet.size(state.koans), + visited_modules: MapSet.to_list(state.visited_modules) } end end diff --git a/test/tracker_test.exs b/test/tracker_test.exs index 8c74be7..c758f76 100644 --- a/test/tracker_test.exs +++ b/test/tracker_test.exs @@ -4,25 +4,25 @@ defmodule TrackerTest do @sample_modules [SampleKoan, PassingKoan] test "can start" do - Tracker.start(@sample_modules) + Tracker.set_total(@sample_modules) assert Tracker.summarize == %{total: 2, current: 0, visited_modules: []} end test "can be notified of completed koans" do - Tracker.start(@sample_modules) + Tracker.set_total(@sample_modules) Tracker.completed(SampleKoan, :"Hi there") assert Tracker.summarize == %{total: 2, current: 1, visited_modules: [SampleKoan]} end test "multiple comletions of the same koan count only once" do - Tracker.start(@sample_modules) + Tracker.set_total(@sample_modules) Tracker.completed(SampleKoan, :"Hi there") Tracker.completed(SampleKoan, :"Hi there") assert Tracker.summarize == %{total: 2, current: 1, visited_modules: [SampleKoan]} end test "knows when koans are not complete" do - Tracker.start(@sample_modules) + Tracker.set_total(@sample_modules) refute Tracker.complete? end end