Improved infrastructure for step five
This commit is contained in:
parent
542ffbc826
commit
7e20cac9c1
|
|
@ -1,9 +1,25 @@
|
||||||
defmodule ZombieSurvivor.Game do
|
defmodule ZombieSurvivor.Game do
|
||||||
alias ZombieSurvivor.{Game, Survivor}
|
alias ZombieSurvivor.{Game, Survivor}
|
||||||
|
|
||||||
@type t :: %__MODULE__{survivors: %{String.t() => Survivor.t()}}
|
defmodule State do
|
||||||
|
alias __MODULE__, as: Game
|
||||||
|
|
||||||
defstruct survivors: %{}
|
@type t :: %__MODULE__{
|
||||||
|
survivors: %{String.t() => Survivor.t()},
|
||||||
|
history: [String.t()]
|
||||||
|
}
|
||||||
|
@type history_type ::
|
||||||
|
:start
|
||||||
|
| :new_survivor
|
||||||
|
| :new_equipment
|
||||||
|
| :wounded
|
||||||
|
| :death
|
||||||
|
| :levelup
|
||||||
|
| :game_levelup
|
||||||
|
| :end
|
||||||
|
@type history :: {history_type, any}
|
||||||
|
|
||||||
|
defstruct survivors: %{}, history: []
|
||||||
|
|
||||||
@spec new() :: Game.t()
|
@spec new() :: Game.t()
|
||||||
def new(), do: %Game{}
|
def new(), do: %Game{}
|
||||||
|
|
@ -36,3 +52,47 @@ defmodule ZombieSurvivor.Game do
|
||||||
|> ZombieSurvivor.level()
|
|> ZombieSurvivor.level()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
use GenServer
|
||||||
|
|
||||||
|
def new, do: start_link()
|
||||||
|
|
||||||
|
def add_survivor(pid, survivor), do: GenServer.cast(pid, {:add_survivor, survivor})
|
||||||
|
def ended?(pid), do: GenServer.call(pid, :ended?)
|
||||||
|
def history(pid), do: GenServer.call(pid, :history)
|
||||||
|
def level(pid), do: GenServer.call(pid, :level)
|
||||||
|
def survivors(pid), do: GenServer.call(pid, :survivors)
|
||||||
|
|
||||||
|
## Server callbacks
|
||||||
|
|
||||||
|
def start_link(opts \\ []) do
|
||||||
|
GenServer.start_link(__MODULE__, :ok, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl GenServer
|
||||||
|
def init(:ok) do
|
||||||
|
{:ok, State.new()}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl GenServer
|
||||||
|
def handle_call(:ended?, _from, state) do
|
||||||
|
{:reply, State.ended?(state), state}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_call(:history, _from, state) do
|
||||||
|
{:reply, state.history, state}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_call(:level, _from, state) do
|
||||||
|
{:reply, State.level(state), state}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_call(:survivors, _from, state) do
|
||||||
|
{:reply, state.survivors, state}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl GenServer
|
||||||
|
def handle_cast({:add_survivor, survivor}, state) do
|
||||||
|
{:noreply, State.add_survivor(state, survivor)}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
||||||
|
|
@ -7,124 +7,102 @@ defmodule GameTest do
|
||||||
@new_survivor Survivor.new(name: "Zombait")
|
@new_survivor Survivor.new(name: "Zombait")
|
||||||
@dead_survivor Survivor.new(name: "Deadman", wounds: 2)
|
@dead_survivor Survivor.new(name: "Deadman", wounds: 2)
|
||||||
|
|
||||||
describe "new/0 starts a game" do
|
setup do
|
||||||
test "that has 0 survivors" do
|
game = start_supervised!(Game)
|
||||||
assert Map.size(Game.new().survivors) == 0
|
%{game: game}
|
||||||
end
|
end
|
||||||
|
|
||||||
test "that's at level blue" do
|
describe "new/0 starts a game" do
|
||||||
assert Game.level(Game.new()) == :blue
|
test "that has 0 survivors", %{game: game} do
|
||||||
|
assert Map.size(Game.survivors(game)) == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
test "that's at level blue", %{game: game} do
|
||||||
|
assert Game.level(game) == :blue
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "add_survivor/1" do
|
describe "add_survivor/1" do
|
||||||
test "adds a survivor to a game" do
|
test "adds a survivor to a game", %{game: game} do
|
||||||
g =
|
Game.add_survivor(game, @new_survivor)
|
||||||
Game.new()
|
|
||||||
|> Game.add_survivor(@new_survivor)
|
|
||||||
|
|
||||||
assert Map.size(g.survivors) == 1
|
assert Map.size(Game.survivors(game)) == 1
|
||||||
|
|
||||||
g =
|
Game.add_survivor(game, %{@new_survivor | name: "Larry"})
|
||||||
g
|
|
||||||
|> Game.add_survivor(%{@new_survivor | name: "Larry"})
|
|
||||||
|
|
||||||
assert Map.size(g.survivors) == 2
|
assert Map.size(Game.survivors(game)) == 2
|
||||||
end
|
end
|
||||||
|
|
||||||
test "ensures that two survivors with the same name can't exist" do
|
test "ensures that two survivors with the same name can't exist", %{game: game} do
|
||||||
g =
|
game
|
||||||
Game.new()
|
|
||||||
|> Game.add_survivor(@new_survivor)
|
|> Game.add_survivor(@new_survivor)
|
||||||
|> Game.add_survivor(@new_survivor)
|
|> Game.add_survivor(@new_survivor)
|
||||||
|
|
||||||
assert Map.size(g.survivors) == 1
|
assert Map.size(Game.survivors(game)) == 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "ended?/1" do
|
describe "ended?/1" do
|
||||||
test "returns true if all its survivors are dead" do
|
test "returns true if all its survivors are dead", %{game: game} do
|
||||||
# TODO: Property test, add many dead survivors
|
# TODO: Property test, add many dead survivors
|
||||||
g =
|
game
|
||||||
Game.new()
|
|
||||||
|> Game.add_survivor(@dead_survivor)
|
|> Game.add_survivor(@dead_survivor)
|
||||||
|
|
||||||
assert Game.ended?(g)
|
assert Game.ended?(game)
|
||||||
|
|
||||||
g =
|
game
|
||||||
g
|
|
||||||
|> Game.add_survivor(%{@dead_survivor | name: "Zambee"})
|
|> Game.add_survivor(%{@dead_survivor | name: "Zambee"})
|
||||||
|
|
||||||
assert Game.ended?(g)
|
assert Game.ended?(game)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns false if at least one survivor is alive" do
|
test "returns false if at least one survivor is alive", %{game: game} do
|
||||||
g =
|
game
|
||||||
Game.new()
|
|
||||||
|> Game.add_survivor(@new_survivor)
|
|> Game.add_survivor(@new_survivor)
|
||||||
|> Game.add_survivor(@dead_survivor)
|
|> Game.add_survivor(@dead_survivor)
|
||||||
|
|
||||||
refute Game.ended?(g)
|
refute Game.ended?(game)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns false if no survivors joined" do
|
test "returns false if no survivors joined", %{game: game} do
|
||||||
g = Game.new()
|
refute Game.ended?(game)
|
||||||
|
|
||||||
refute Game.ended?(g)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "level/1" do
|
describe "level/1" do
|
||||||
test "returns the level of the highest levelled survivor" do
|
test "returns the level of the highest levelled survivor", %{game: game} do
|
||||||
g =
|
Game.add_survivor(game, @new_survivor)
|
||||||
Game.new()
|
|
||||||
|> Game.add_survivor(@new_survivor)
|
|
||||||
|
|
||||||
assert Game.level(g) == :blue
|
assert Game.level(game) == :blue
|
||||||
|
|
||||||
g =
|
Game.add_survivor(game, Survivor.new(name: "Eric", experience: 10))
|
||||||
g
|
|
||||||
|> Game.add_survivor(Survivor.new(name: "Eric", experience: 10))
|
|
||||||
|
|
||||||
assert Game.level(g) == :yellow
|
assert Game.level(game) == :yellow
|
||||||
|
|
||||||
g =
|
Game.add_survivor(game, Survivor.new(name: "Jack", experience: 20))
|
||||||
g
|
|
||||||
|> Game.add_survivor(Survivor.new(name: "Jack", experience: 20))
|
|
||||||
|
|
||||||
assert Game.level(g) == :orange
|
assert Game.level(game) == :orange
|
||||||
|
Game.add_survivor(game, Survivor.new(name: "Liru", experience: 1_000_000))
|
||||||
|
|
||||||
g =
|
assert Game.level(game) == :red
|
||||||
g
|
|
||||||
|> Game.add_survivor(Survivor.new(name: "Liru", experience: 1_000_000))
|
|
||||||
|
|
||||||
assert Game.level(g) == :red
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns the level of the highest levelled living survivor" do
|
test "returns the level of the highest levelled living survivor", %{game: game} do
|
||||||
g =
|
Game.add_survivor(game, @new_survivor)
|
||||||
Game.new()
|
|
||||||
|> Game.add_survivor(@new_survivor)
|
|
||||||
|
|
||||||
assert Game.level(g) == :blue
|
assert Game.level(game) == :blue
|
||||||
|
|
||||||
g =
|
Game.add_survivor(game, Survivor.new(name: "Eric", experience: 10))
|
||||||
g
|
|
||||||
|> Game.add_survivor(Survivor.new(name: "Eric", experience: 10))
|
|
||||||
|
|
||||||
assert Game.level(g) == :yellow
|
assert Game.level(game) == :yellow
|
||||||
|
|
||||||
g =
|
Game.add_survivor(game, %{@dead_survivor | name: "Jack", experience: 20})
|
||||||
g
|
|
||||||
|> Game.add_survivor(Survivor.new(name: "Jack", experience: 20, wounds: 2))
|
|
||||||
|
|
||||||
assert Game.level(g) == :yellow
|
assert Game.level(game) == :yellow
|
||||||
|
|
||||||
g =
|
Game.add_survivor(game, %{@dead_survivor | name: "Fake Liru", experience: 1_000_000})
|
||||||
g
|
|
||||||
|> Game.add_survivor(Survivor.new(name: "Liru", experience: 1_000_000, wounds: 2))
|
|
||||||
|
|
||||||
assert Game.level(g) == :yellow
|
assert Game.level(game) == :yellow
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue