From 4e0948a90ca9d97387e95472f590d8a94fcea254 Mon Sep 17 00:00:00 2001 From: "Ryan Scheel (Havvy)" Date: Fri, 2 Oct 2015 04:19:46 +0200 Subject: [PATCH] WIP --- apps/gald/lib/event_queue.ex | 53 ++++++++++++ apps/gald/lib/player.ex | 103 ++++++++++++++++------- apps/gald/lib/race.ex | 94 +++++++++++++-------- apps/gald/lib/rounds.ex | 33 ++++++++ apps/gald/lib/screen.ex | 28 ++++++ apps/gald/lib/snapshot.ex | 2 +- apps/gald/lib/status.ex | 25 ------ apps/gald/lib/turn.ex | 49 +++++++++++ apps/gald/test/config_test.exs | 1 + apps/gald/test/full_game_test.exs | 64 ++++++++++++++ apps/gald/test/gald_test.exs | 24 +++--- apps/gald/test/player_test.exs | 9 +- apps/gald/test/snapshot_test.exs | 29 ++++--- apps/gald_site/web/static/js/util/map.js | 11 +++ 14 files changed, 406 insertions(+), 119 deletions(-) create mode 100644 apps/gald/lib/event_queue.ex create mode 100644 apps/gald/lib/rounds.ex create mode 100644 apps/gald/lib/screen.ex delete mode 100644 apps/gald/lib/status.ex create mode 100644 apps/gald/lib/turn.ex create mode 100644 apps/gald/test/full_game_test.exs create mode 100644 apps/gald_site/web/static/js/util/map.js diff --git a/apps/gald/lib/event_queue.ex b/apps/gald/lib/event_queue.ex new file mode 100644 index 0000000..f5a4912 --- /dev/null +++ b/apps/gald/lib/event_queue.ex @@ -0,0 +1,53 @@ +defmodule EventQueue.Handler do + use GenEvent + + def init(event_queue) do + {:ok, event_queue} + end + + def handle_event(event, event_queue) do + IO.inspect(event) + GenServer.cast(event_queue, {:event, event}) + {:ok, event_queue} + end +end + +defmodule EventQueue do + @empty_queue :queue.new() + + use GenServer + + def start_link(event_manager) do + {:ok, self} = GenServer.start_link(__MODULE__, :no_args) + GenEvent.add_handler(event_manager, EventQueue.Handler, self) + {:ok, self} + end + + def init(:no_args) do + {:ok, {@empty_queue, nil}} + end + + def handle_cast({:event, event}, {queue, nil}) do + {:noreply, {:queue.in(event, queue)}} + end + def handle_cast({:event, event}, {@empty_queue, from}) do + GenServer.reply(from, event) + {:noreply, {@empty_queue, nil}} + end + + def handle_cast(:stop, _state) do + {:stop, :normal, nil} + end + + def handle_call(:next, from, {@empty_queue, nil}) do + {:noreply, {@empty_queue, from}} + end + def handle_call(:next, _from, {queue, nil}) do + {{:value, event}, queue} = :queue.out(queue) + {:reply, event, queue} + end + + def terminate(:normal, _state), do: :ok + + def terminate({:function_clause, _error}, _state), do: :ok +end \ No newline at end of file diff --git a/apps/gald/lib/player.ex b/apps/gald/lib/player.ex index 26fea4d..9f42680 100644 --- a/apps/gald/lib/player.ex +++ b/apps/gald/lib/player.ex @@ -1,50 +1,89 @@ -# defmodule Gald.Player do -# use Supervisor - -# # Client -# @spec start_link(String.t) :: Supervisor.on_start -# def start_link(name) do -# Supervisor.start_link(__MODULE__, name) -# end - -# # Server -# def init(_name) do -# children = [] -# supervise(children, strategy: :one_for_all) -# end -# end - -defmodule Gald.Player do +defmodule Gald.Players do use GenServer # Client - def start_link(name) do - GenServer.start_link(__MODULE__, name) + def start_link(race_out) do + GenServer.start_link(__MODULE__, race_out) end + def new_player(players, name) do + GenServer.call(players, {:new_player, name}) + end + + def names(players), do: GenServer.call(players, :names) + def turn_order_deciding_data(players), do: GenServer.call(players, :turndata) + # Server - def init(name) do - {:ok, name} + def init(race_out) do + {:ok, sup} = Supervisor.start_link([Supervisor.Spec.worker(Gald.Player, [])], strategy: :simple_one_for_one) + dict = %{} + join_ix = 0 + {:ok, {sup, dict, race_out, join_ix}} + end + + def handle_call({:new_player, name}, _from, {sup, dict, race_out, join_ix}) do + if Map.has_key?(dict, name) do + {:error, :duplicate_name} + else + {:ok, player} = Supervisor.start_child(sup, [name]) + GenEvent.notify(race_out, {:new_player, name}) + dict = Map.put(dict, name, %{pid: player, join_ix: join_ix}) + join_ix = join_ix + 1 + {:reply, {:ok, player}, {sup, dict, race_out, join_ix}} + end + end + + def handle_call(:names, _from, state = {_sup, dict, _race_out, _join_ix}) do + names = dict + |> Enum.sort_by(fn ({_k, %{join_ix: join_ix}}) -> join_ix end) + |> Enum.map(fn ({k, _v}) -> k end) + |> Enum.into([]) + + {:reply, names, state} + end + + def handle_call(:turndata, _from, state = {_sup, dict, _race_out, _join_ix}) do + res = dict + |> Enum.map(fn ({k, %{join_ix: join_ix}}) -> {k, %{join_ix: join_ix}} end) + |> Enum.into(%{}) + + {:reply, res, state} end end -defmodule Gald.Player.Supervisor do - use Supervisor +defmodule Gald.Player do + use GenServer # Client - @spec start_link() :: Supervisor.on_start - def start_link() do - Supervisor.start_link(__MODULE__, []) + def start_link(name) do + GenServer.start_link(__MODULE__, name) end - @spec add_player(pid, String.t) :: Supervisor.on_start - def add_player(players, name) do - Supervisor.start_child(players, [name]) + def io(player) do + player_in = GenServer.call(player, {:get, :in}) + player_out = GenServer.call(player, {:get, :out}) + {:ok, player_in, player_out} end + def name(player), do: GenServer.call(player, {:get, :name}) + # Server - def init([]) do - child = [supervisor(Gald.Player, [])] - supervise(child, strategy: :simple_one_for_one) + def init(name) do + # TODO(Havvy): Make this an addressable supervision tree. + {:ok, player_in} = GenServer.start_link(Gald.Player.In, []) + {:ok, player_out} = GenEvent.start_link([]) + {:ok, %{ + name: name, + in: player_in, + out: player_out + }} + end + + def handle_call({:get, component}, _from, state) do + {:reply, state[component], state} end +end + +defmodule Gald.Player.In do + use GenServer end \ No newline at end of file diff --git a/apps/gald/lib/race.ex b/apps/gald/lib/race.ex index 8bc4150..868bfa7 100644 --- a/apps/gald/lib/race.ex +++ b/apps/gald/lib/race.ex @@ -1,21 +1,23 @@ defmodule Gald.Race do + # TODO(Havvy): Change to a :get_fsm? use GenServer @type snapshot :: {Gald.Status.t, any} @opaque t :: pid # Client - @spec start_link(%Gald.Config{}) :: {:ok, t} + @spec start_link(%Gald.Config{}) :: {:ok, t, GenEvent.t} def start_link(config) do - GenServer.start_link(__MODULE__, config) + {:ok, race} = GenServer.start_link(__MODULE__, config) + {:ok, race, race_out(race)} end @spec snapshot(t) :: snapshot def snapshot(race), do: GenServer.call(race, {:snapshot}) - def add_player(race, name), do: GenServer.call(race, {:add_player, name}) + def new_player(race, name), do: GenServer.call(race, {:new_player, name}) - def start_game(race), do: GenServer.cast(race, {:start_game}) + def begin(race), do: GenServer.cast(race, {:begin}) @spec move_player(t, any, integer) :: non_neg_integer def move_player(race, player, space_change) do @@ -30,38 +32,45 @@ defmodule Gald.Race do def is_over(race), do: GenServer.call(race, {:is_over}) @spec config(t) :: %Gald.Config{} - def config(race), do: GenServer.call(race, {:config}) + def config(race), do: GenServer.call(race, {:get, :config}) @spec get_name(t) :: String.t def get_name(race), do: config(race).name + defp race_out(race), do: GenServer.call(race, {:get, :out}) + # Server def init(config) do import Supervisor.Spec - {:ok, slave} = Supervisor.start_link([], strategy: :one_for_one) - {:ok, status} = Supervisor.start_child(slave, worker(Gald.Status, [])) - {:ok, player_sup} = Supervisor.start_child(slave, supervisor(Gald.Player.Supervisor, [])) + {:ok, sup} = Supervisor.start_link([], strategy: :one_for_all) + {:ok, out} = Supervisor.start_child(sup, worker(GenEvent, [])) + {:ok, players} = Supervisor.start_child(sup, worker(Gald.Players, [out])) {:ok, %{config: config, - slave: slave, - status: status, - player_sup: player_sup, - players: HashDict.new(), - map: :unstarted}} + sup: sup, + status: :lobby, + out: out, + players: players, + map: :unstarted, + rounds: :unstarted, + turn: :unstarted}} + end + + def handle_call({:get, component}, _from, state) do + {:reply, state[component], state} end - def handle_call({:add_player, name}, _from, state) do - case Gald.Status.get_status(state.status) do - :lobby -> - if Dict.has_key?(state.players, name) do - {:reply, {:error, :duplicate_name}, state} - else - {:ok, player} = Gald.Player.Supervisor.add_player(state.player_sup, name) - {:reply, :ok, Dict.update!(state, :players, &Dict.put(&1, name, player))} - end - _ -> - {:reply, {:error, :already_started}, state} + def handle_call({:new_player, name}, _from, state) do + if state.status == :lobby do + case Gald.Players.new_player(state.players, name) do + {:ok, player} -> + {:reply, Gald.Player.io(player), state} + {:error, reason} -> + {:reply, {:error, reason}, state} + end + else + {:reply, {:error, :already_started}, state} end end @@ -73,14 +82,14 @@ defmodule Gald.Race do Gald.Map.move_player(state.map, player, space_change) if Gald.Map.is_over(state.map) do - Gald.Status.end_game(state.status) + state = Dict.update!(state, :status, fn (:play) -> :over end) end {:reply, Gald.Map.get_player_location(state.map, player), state} end def handle_call({:snapshot}, _from, state) do - {:reply, Gald.Snapshot.new(Gald.Status.get_status(state.status), state), state} + {:reply, Gald.Snapshot.new(state.status, state), state} end def handle_call({:get_player_location, player}, _from, state) do @@ -89,21 +98,38 @@ defmodule Gald.Race do def handle_call({:config}, _from, state), do: {:reply, state.config, state} - def handle_cast({:start_game}, state) do + def handle_cast({:begin}, state) do import Supervisor.Spec - map_dict = %{players: player_list(state.players), + IO.puts("Beginning the world.") + # Determine Turn Order + rounds_config = %{ + players: Gald.Players.turn_order_deciding_data(state.players), + race_out: state.out, + supervisor: state.sup + } + rounds_spec = worker(Gald.Rounds, [rounds_config]) + {:ok, rounds} = Supervisor.start_child(state.sup, rounds_spec) + + IO.puts("Rounds created.") + + # Start the Map + map_dict = %{players: Gald.Players.names(state.players), end_space: state.config.end_space} map_spec = worker(Gald.Map, [map_dict]) - {:ok, map} = Supervisor.start_child(state.slave, map_spec) + {:ok, map} = Supervisor.start_child(state.sup, map_spec) - Gald.Status.start_game(state.status) + IO.puts("Map created.") - {:noreply, %{state | map: map}} - end + state = %{state | map: map, rounds: rounds, status: :play} + snapshot = Gald.Snapshot.new(state.status, state) + IO.inspect("Sending out snapshot!") + GenEvent.notify(state.out, {:begin, snapshot}) - # TODO(Havvy): Have a Player manager thing that can give this for us. - def player_list(players), do: Enum.into(Dict.keys(players), HashSet.new()) + Gald.Rounds.begin(rounds) + + {:noreply, state} + end # TODO(Havvy): Have a way to terminate a race. end diff --git a/apps/gald/lib/rounds.ex b/apps/gald/lib/rounds.ex new file mode 100644 index 0000000..2dfcb3d --- /dev/null +++ b/apps/gald/lib/rounds.ex @@ -0,0 +1,33 @@ +defmodule Gald.Rounds do + use GenServer + + # Client + def start_link(config) do + GenServer.start_link(__MODULE__, config) + end + + def begin(rounds), do: GenServer.cast(rounds, :begin) + + # Server + def init(%{players: players, race_out: race_out, supervisor: sup}) do + # TODO(Havvy): Should the order be passed to the Players actor? + order = players + |> Enum.sort_by(fn ({_k, %{join_ix: join_ix}}) -> join_ix end) + |> Enum.map(fn ({k, _v}) -> k end) + |> Enum.into([]) + + {:ok, %{ + race_out: race_out, + sup: sup, + order: order, + round: 1, + round_order: order + }} + end + + def handle_cast(:begin, state = %{race_out: race_out}) do + GenEvent.notify(race_out, {:round_start, 1}) + + {:noreply, state} + end +end \ No newline at end of file diff --git a/apps/gald/lib/screen.ex b/apps/gald/lib/screen.ex new file mode 100644 index 0000000..a9f4306 --- /dev/null +++ b/apps/gald/lib/screen.ex @@ -0,0 +1,28 @@ +defmodule Gald.Screen.DiceMove do + @moduledoc """ + The structure for a screen for a request for a dice movement. + + * who: `{:player, player_name}` + * roll: `{:d, dice_count, dice_size}` + + The `roll` is used to decide which dice images to show to the player. + """ + defstruct who: nil, roll: nil +end + +defmodule Gald.Screen.DiceMoveResult do + @moduledoc """ + The structue for a screen showing the result of rolling dice + for movement. + + * who: `{:player, player_name}` + * roll: `{{:d, 6}, [positive_integer]}` + * to: `{relative, absolute} - e.g., rolling a total of 10 from space 15 gives `{10, 25}`. + + The `roll` is used to decide which dice images to show to the player. + + The `to` is used for the textual description of how the move happened. + """ + + defstruct who: nil, to: nil, roll: nil +end \ No newline at end of file diff --git a/apps/gald/lib/snapshot.ex b/apps/gald/lib/snapshot.ex index bf7758e..1f1991d 100644 --- a/apps/gald/lib/snapshot.ex +++ b/apps/gald/lib/snapshot.ex @@ -27,7 +27,7 @@ defmodule Gald.Snapshot do def new(:lobby, state) do %{status: :lobby, data: %Gald.Snapshot.Lobby{ config: state.config, - players: Gald.Race.player_list(state.players) + players: Gald.Players.names(state.players) }} end diff --git a/apps/gald/lib/status.ex b/apps/gald/lib/status.ex deleted file mode 100644 index 4e4ecfc..0000000 --- a/apps/gald/lib/status.ex +++ /dev/null @@ -1,25 +0,0 @@ -defmodule Gald.Status do - @type t :: :lobby | :play | :over - - @spec start_link() :: Agent.on_start - @spec start_link(any) :: Agent.on_start - def start_link(_opts \\ []) do - Agent.start_link(fn () -> :lobby end) - end - - # TODO(Havvy): If player count is 0, say no. - @spec start_game(pid) :: :ok - def start_game(status), do: Agent.update(status, &into_play/1) - - @spec end_game(pid) :: :ok - def end_game(status), do: Agent.update(status, &into_over/1) - - @spec get_status(pid) :: t - def get_status(status), do: Agent.get(status, &(&1)) - - defp into_play(:lobby), do: :play - defp into_play(other), do: other - - defp into_over(:play), do: :over - defp into_over(other), do: other -end \ No newline at end of file diff --git a/apps/gald/lib/turn.ex b/apps/gald/lib/turn.ex new file mode 100644 index 0000000..fff6d67 --- /dev/null +++ b/apps/gald/lib/turn.ex @@ -0,0 +1,49 @@ +defmodule Gald.Turn do + @behaviour :gen_fsm + + # Client + def start_link(config) do + :gen_fsm.start_link(nil, __MODULE__, config, []) + end + + # Server + def init(config = %{player: player, race_out: race_out}) do + player_name = Gald.Player.name(player) + GenEvent.notify(race_out, {:turn_start, player_name}) + + GenEvent.notify(race_out, %Gald.Screen.DiceMove{ + who: player_name, + roll: {:d, 2, 6} + }) + + {:ok, :dice_roll, {config, %Gald.Screen.DiceMove{ + who: player_name, + roll: {:d, 2, 6} + }}} + end + + def dice_roll(:confirm, {config, dice_move}) do + raise "unimplemented" + end + + def handle_info(_, _state_name, state) do + {:stop, :unexpected_message, state} + end + + def handle_sync_event(_, _from, state_name, state) do + reply = state_name + {:reply, reply, state_name, state} + end + + def handle_event(_, _state_Name, state) do + {:stop, :unexecpted_event, state} + end + + def terminate(_reason, _state_name, _state) do + :ok + end + + def code_change(_old_vsn, state_name, state, _extra) do + {:ok, state_name, state} + end +end \ No newline at end of file diff --git a/apps/gald/test/config_test.exs b/apps/gald/test/config_test.exs index 724e434..159cea8 100644 --- a/apps/gald/test/config_test.exs +++ b/apps/gald/test/config_test.exs @@ -1,6 +1,7 @@ defmodule Gald.RaceConfigTest do use ExUnit.Case, async: true + @tag :skip test "Getting the name" do {:ok, game} = Gald.new_race(%Gald.Config{name: "Test Race"}) assert "Test Race" = Gald.Race.get_name(game) diff --git a/apps/gald/test/full_game_test.exs b/apps/gald/test/full_game_test.exs new file mode 100644 index 0000000..db62b1b --- /dev/null +++ b/apps/gald/test/full_game_test.exs @@ -0,0 +1,64 @@ +defmodule Gald.TwoPlayerRaceTo25Test do + use ExUnit.Case, async: true + + @p1 "alice" + @p2 "bob" + @config %Gald.Config{end_space: 25} + + # @tag :skip + test "two players racing to space 25" do + {:ok, race, race_out} = Gald.Race.start_link(@config) + {:ok, race_out} = EventQueue.start_link(race_out) + + {:ok, p1_in, _p1_out} = Gald.Race.new_player(race, @p1) + assert {:new_player, @p1} = next_event(race_out) + + {:ok, p2_in, _p2_out} = Gald.Race.new_player(race, @p2) + assert {:new_player, @p2} = next_event(race_out) + + Gald.Race.begin(race) + assert {:begin, %{status: :play, data: %Gald.Snapshot.Play{}}} = next_event(race_out) + + round(1, race_out, @p1, p1_in, @p2, p2_in) + round(2, race_out, @p1, p2_in, @p2, p2_in) + + assert {:round_start, 3} = next_event(race_out) + turn(race_out, @p1, p1_in, 3) + + assert {:end, %Gald.Snapshot.Over{}} = next_event(race_out) + + GenServer.call(race_out, :stop) + end + + defp next_event(race_out) do + GenServer.call(race_out, :next) + end + + defp round(n, race_out, p1_name, p1_in, p2_name, p2_in) do + assert {:round_start, 1} = next_event(race_out) + turn(race_out, p1_name, p1_in, n) + turn(race_out, p2_name, p2_in, n) + end + + defp turn(race_out, name, player_in, round) do + assert {:turn_start, name} = next_event(race_out) + + assert {:screen, %Gald.Screen.DiceMove{ + who: {:player, name}, + roll: {:d, 2, 6} + }} = next_event(race_out) + + Gald.Player.In.confirm(player_in) + + end_space = round * 10 + assert {:move, %Gald.Screen.DiceMoveResult{ + who: {:player, ^name}, + to: {10, ^end_space}, + roll: {{:d, 6}, [5, 5]} + }} = next_event(race_out) + + Gald.Player.In.confirm(player_in) + + # TODO(Havvy): Event things here. + end +end \ No newline at end of file diff --git a/apps/gald/test/gald_test.exs b/apps/gald/test/gald_test.exs index 9b1067c..ab0c12c 100644 --- a/apps/gald/test/gald_test.exs +++ b/apps/gald/test/gald_test.exs @@ -5,10 +5,11 @@ defmodule Gald.RaceTest do @p2 "bob" @config %Gald.Config{end_space: 25} + @tag :skip test "race of one player going to space 25" do {:ok, race} = Gald.new_race(@config) - :ok = Gald.Race.add_player(race, @p1) - Gald.Race.start_game(race) + Gald.Race.new_player(race, @p1) + Gald.Race.begin(race) 10 = Gald.Race.move_player(race, @p1, 10) 20 = Gald.Race.move_player(race, @p1, 10) assert Gald.Race.is_over(race) == false @@ -16,11 +17,12 @@ defmodule Gald.RaceTest do assert Gald.Race.is_over(race) == true end + @tag :skip test "race of two players going to space 25" do {:ok, race} = Gald.new_race(@config) - :ok = Gald.Race.add_player(race, @p1) - :ok = Gald.Race.add_player(race, @p2) - Gald.Race.start_game(race) + Gald.Race.new_player(race, @p1) + Gald.Race.new_player(race, @p2) + Gald.Race.begin(race) 10 = Gald.Race.move_player(race, @p1, 10) 10 = Gald.Race.move_player(race, @p2, 10) 20 = Gald.Race.move_player(race, @p1, 10) @@ -30,22 +32,24 @@ defmodule Gald.RaceTest do assert Gald.Race.is_over(race) == true end + @tag :skip test "disallowing of players joining after race started" do {:ok, race} = Gald.new_race(@config) # A game needs at least one player. - :ok = Gald.Race.add_player(race, @p1) + Gald.Race.new_player(race, @p1) - Gald.Race.start_game(race) + Gald.Race.begin(race) - assert {:error, :already_started} == Gald.Race.add_player(race, @p2) + assert {:error, :already_started} == Gald.Race.new_player(race, @p2) end + @tag :skip test "disallowing of players joining with the same name" do {:ok, race} = Gald.new_race(@config) - :ok = Gald.Race.add_player(race, @p1) + Gald.Race.new_player(race, @p1) - assert {:error, :duplicate_name} = Gald.Race.add_player(race, @p1) + assert {:error, :duplicate_name} = Gald.Race.new_player(race, @p1) end end \ No newline at end of file diff --git a/apps/gald/test/player_test.exs b/apps/gald/test/player_test.exs index 98e9bed..ef94aad 100644 --- a/apps/gald/test/player_test.exs +++ b/apps/gald/test/player_test.exs @@ -1,9 +1,12 @@ defmodule Gald.PlayerTest do use ExUnit.Case, async: true - alias Gald.Player.Supervisor, as: PSupervisor + alias Gald.Players, as: Players + + @p1 "alice" test "Creation of a player" do - {:ok, psup} = PSupervisor.start_link() - {:ok, _player} = PSupervisor.add_player(psup, "alice") + {:ok, race_out} = GenEvent.start_link() + {:ok, psup} = Players.start_link(race_out) + {:ok, _p1} = Players.new_player(psup, @p1) end end \ No newline at end of file diff --git a/apps/gald/test/snapshot_test.exs b/apps/gald/test/snapshot_test.exs index fd78881..18f14a8 100644 --- a/apps/gald/test/snapshot_test.exs +++ b/apps/gald/test/snapshot_test.exs @@ -12,37 +12,38 @@ defmodule Gald.SnapshotTest do assert %{status: :lobby, data: %Gald.Snapshot.Lobby{ config: @config, - players: into_set([]) + players: [] }} == snapshot end test "snapshot of a lobby with only one player" do {:ok, race} = Gald.new_race(@config) - :ok = Gald.Race.add_player(race, @p1) + Gald.Race.new_player(race, @p1) snapshot = Gald.Race.snapshot(race) assert %{status: :lobby, data: %Gald.Snapshot.Lobby{ config: @config, - players: into_set([@p1]) + players: [@p1] }} == snapshot end test "snapshot of a lobby with two players" do {:ok, race} = Gald.new_race(@config) - :ok = Gald.Race.add_player(race, @p1) - :ok = Gald.Race.add_player(race, @p2) + Gald.Race.new_player(race, @p1) + Gald.Race.new_player(race, @p2) snapshot = Gald.Race.snapshot(race) assert %{status: :lobby, data: %Gald.Snapshot.Lobby{ config: @config, - players: into_set([@p1, @p2]) + players: [@p1, @p2] }} == snapshot end + @tag :skip test "snapshot of a race with a single player that has not started" do {:ok, race} = Gald.new_race(@config) - :ok = Gald.Race.add_player(race, @p1) - Gald.Race.start_game(race) + Gald.Race.new_player(race, @p1) + Gald.Race.begin(race) snapshot = Gald.Race.snapshot(race) assert %{status: :play, data: %Gald.Snapshot.Play{ @@ -51,10 +52,11 @@ defmodule Gald.SnapshotTest do }} == snapshot end + @tag :skip test "snapshot of a race with a single player who has moved to space 10" do {:ok, race} = Gald.new_race(@config) - :ok = Gald.Race.add_player(race, @p1) - Gald.Race.start_game(race) + Gald.Race.new_player(race, @p1) + Gald.Race.begin(race) Gald.Race.move_player(race, @p1, 10) snapshot = Gald.Race.snapshot(race) @@ -64,10 +66,11 @@ defmodule Gald.SnapshotTest do }} == snapshot end + @tag :skip test "snapshot of a race that has ended" do {:ok, race} = Gald.new_race(@config_short_race) - :ok = Gald.Race.add_player(race, @p1) - Gald.Race.start_game(race) + Gald.Race.new_player(race, @p1) + Gald.Race.begin(race) Gald.Race.move_player(race, @p1, 30) snapshot = Gald.Race.snapshot(race) @@ -76,6 +79,4 @@ defmodule Gald.SnapshotTest do players: %{@p1 => %{space: 30}} }} == snapshot end - - defp into_set(list), do: Enum.into(list, HashSet.new()) end \ No newline at end of file diff --git a/apps/gald_site/web/static/js/util/map.js b/apps/gald_site/web/static/js/util/map.js new file mode 100644 index 0000000..3723ad9 --- /dev/null +++ b/apps/gald_site/web/static/js/util/map.js @@ -0,0 +1,11 @@ +export default function Map (object) { + let map = new (window.Map)(); + + if (object !== undefined) { + Object.keys(object).forEach(function (key) { + map.set(key, object[key]); + }); + } + + return map; +}; \ No newline at end of file