Skip to content

Commit

Permalink
code review changes - xebow.ex
Browse files Browse the repository at this point in the history
Changes state into a struct and improves the config update function
  • Loading branch information
Jesse Van Volkinburg committed Jul 30, 2020
1 parent de998ce commit c887e52
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 36 deletions.
124 changes: 89 additions & 35 deletions lib/xebow.ex
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,31 @@ defmodule Xebow do
@spec layout() :: Layout.t()
def layout, do: @layout

@type animations :: [Animation.t()]
@type animation_params :: %{String.t() => atom | number | String.t()}

defmodule State do
@moduledoc false
defstruct [:current_animation, :next_list, :previous_list]
end

use GenServer

# Client Implementations:

@doc """
Starts the Xebow application, which manages initialization of animations, as well
as switching between active animations. It also maintains animation config state
and persists it in memory between animation changes.
"""
@spec start_link([]) :: GenServer.on_start()
def start_link([]) do
GenServer.start_link(__MODULE__, Animation.types(), name: __MODULE__)
end

@doc """
Gets the current animation configuration. This retrievs current values, which
allows for changes to be made with `update_animation_config/2`
Gets the animation configuration. This retrievs current values, which allows for
changes to be made with `update_animation_config/1`
"""
@spec get_animation_config() :: {Animation.Config.t(), keyword(Animation.Config.t())}
def get_animation_config do
Expand All @@ -77,11 +90,12 @@ defmodule Xebow do
end

@doc """
Updates the animation configuration for the current animation
Updates the configuration for the current animation
"""
@spec update_animation_config(Animation.t()) :: :ok | :error
def update_animation_config(animation_with_config) do
GenServer.call(__MODULE__, {:update_animation_config, animation_with_config})
@spec update_animation_config(animation_params) ::
:ok
def update_animation_config(params) do
GenServer.cast(__MODULE__, {:update_animation_config, params})
end

# Server Implementations:
Expand All @@ -92,53 +106,93 @@ defmodule Xebow do
types
|> Enum.map(&initialize_animation/1)

[current | _] = active_animations
current = hd(active_animations)
Engine.set_animation(current)
state = {active_animations, []}

{:ok, state}
end
state = %State{
current_animation: current,
next_list: active_animations,
previous_list: []
}

@impl GenServer
def handle_call(:get_animation_config, _caller, state) do
{[current | _rest], _previous} = state
{:reply, Animation.get_config(current), state}
{:ok, state}
end

@impl GenServer
def handle_call({:update_animation_config, animation_with_config}, _caller, state) do
{[_current | rest], previous} = state
{:reply, :ok, {[animation_with_config | rest], previous}}
def handle_call(:get_animation_config, _from, state) do
{:reply, Animation.get_config(state.current_animation), state}
end

@impl GenServer
def handle_cast(:next_animation, state) do
case state do
{[current | []], previous} ->
remaining_next = Enum.reverse([current | previous])
Engine.set_animation(hd(remaining_next))
{:noreply, {remaining_next, []}}

{[current | remaining_next], previous} ->
Engine.set_animation(hd(remaining_next))
{:noreply, {remaining_next, [current | previous]}}
case state.next_list do
[] ->
[new_current | next_list] = Enum.reverse([state.current_animation | state.previous_list])
Engine.set_animation(new_current)

state = %{
state
| current_animation: new_current,
next_list: next_list,
previous_list: []
}

{:noreply, state}

[new_current | next_list] ->
Engine.set_animation(new_current)

state = %{
state
| current_animation: new_current,
next_list: next_list,
previous_list: [state.current_animation | state.previous_list]
}

{:noreply, state}
end
end

@impl GenServer
def handle_cast(:previous_animation, state) do
case state do
{remaining_next, []} ->
[next | remaining_previous] = Enum.reverse(remaining_next)
Engine.set_animation(next)
{:noreply, {[next], remaining_previous}}

{remaining_next, [next | remaining_previous]} ->
Engine.set_animation(next)
{:noreply, {[next | remaining_next], remaining_previous}}
case state.previous_list do
[] ->
[new_current | previous_list] = Enum.reverse([state.current_animation | state.next_list])
Engine.set_animation(new_current)

state = %{
state
| current_animation: new_current,
next_list: [],
previous_list: previous_list
}

{:noreply, state}

[new_current | previous_list] ->
Engine.set_animation(new_current)

state = %{
state
| current_animation: new_current,
next_list: [state.current_animation | state.next_list],
previous_list: previous_list
}

{:noreply, state}
end
end

@impl GenServer
def handle_cast({:update_animation_config, params}, state) do
updated_animation = Animation.update_config(state.current_animation, params)
Engine.set_animation(updated_animation)

state = %{state | current_animation: updated_animation}

{:noreply, state}
end

defp initialize_animation(animation_type) do
Animation.new(animation_type, @leds)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/xebow_web/live/matrix_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ defmodule XebowWeb.MatrixLive do
def handle_event("update_config", %{"_target" => [field_str]} = params, socket) do
value = Map.fetch!(params, field_str)

Engine.update_animation_config(%{field_str => value})
Xebow.update_animation_config(%{field_str => value})

{:noreply, socket}
end
Expand Down

0 comments on commit c887e52

Please sign in to comment.