api specs
This commit is contained in:
297
phoenix/lib/shooting_event_phx/domain/settings.ex
Normal file
297
phoenix/lib/shooting_event_phx/domain/settings.ex
Normal file
@@ -0,0 +1,297 @@
|
||||
defmodule ShootingEventPhx.Domain.Settings do
|
||||
@moduledoc false
|
||||
import Ecto.Query
|
||||
alias ShootingEventPhx.Repo
|
||||
alias ShootingEventPhx.Domain.AppSetting
|
||||
|
||||
@setting_view_proof_in_view "view_proof_in_view"
|
||||
@setting_live_active_view "live_active_view"
|
||||
@setting_live_show_group_live "live_show_group_live"
|
||||
@setting_live_group_display_mode "live_group_display_mode"
|
||||
@setting_live_group_fixed_code "live_group_fixed_code"
|
||||
@setting_live_show_prelim_tie "live_show_prelim_tie"
|
||||
@setting_live_show_prelim_overall "live_show_prelim_overall"
|
||||
@setting_live_show_final_groups "live_show_final_groups"
|
||||
@setting_live_final_display_mode "live_final_display_mode"
|
||||
@setting_live_final_fixed_group "live_final_fixed_group"
|
||||
@setting_live_show_final_tie "live_show_final_tie"
|
||||
@setting_live_show_podium "live_show_podium"
|
||||
@setting_live_rotation_interval "live_rotation_interval_sec"
|
||||
@setting_live_rotation_players "live_rotation_player_count"
|
||||
|
||||
@allowed_live_views MapSet.new([
|
||||
"group_live",
|
||||
"prelim_tie",
|
||||
"prelim_overall",
|
||||
"final_groups",
|
||||
"final_tie",
|
||||
"podium"
|
||||
])
|
||||
|
||||
def default_live_mode do
|
||||
%{
|
||||
"activeView" => "group_live",
|
||||
"showGroupLive" => true,
|
||||
"groupDisplayMode" => "rotate",
|
||||
"groupFixedCode" => "",
|
||||
"showPrelimTie" => true,
|
||||
"showPrelimOverall" => true,
|
||||
"showFinalGroups" => true,
|
||||
"finalDisplayMode" => "rotate",
|
||||
"finalFixedGroup" => 1,
|
||||
"showFinalTie" => true,
|
||||
"showPodium" => true,
|
||||
"rotationIntervalSec" => 5,
|
||||
"rotationPlayerCount" => 12
|
||||
}
|
||||
end
|
||||
|
||||
def read_settings do
|
||||
all =
|
||||
Repo.all(from s in AppSetting, select: {s.key, s.value})
|
||||
|> Map.new()
|
||||
|
||||
live = default_live_mode()
|
||||
|
||||
live =
|
||||
live
|
||||
|> Map.put("showGroupLive", setting_bool(Map.get(all, @setting_live_show_group_live, "1")))
|
||||
|> Map.put(
|
||||
"activeView",
|
||||
normalize_live_active_view(
|
||||
Map.get(all, @setting_live_active_view, live["activeView"]),
|
||||
live["activeView"]
|
||||
)
|
||||
)
|
||||
|> Map.put(
|
||||
"groupDisplayMode",
|
||||
normalize_display_mode(
|
||||
Map.get(all, @setting_live_group_display_mode, live["groupDisplayMode"]),
|
||||
live["groupDisplayMode"]
|
||||
)
|
||||
)
|
||||
|> Map.put(
|
||||
"groupFixedCode",
|
||||
String.upcase(String.trim(Map.get(all, @setting_live_group_fixed_code, "")))
|
||||
)
|
||||
|> Map.put("showPrelimTie", setting_bool(Map.get(all, @setting_live_show_prelim_tie, "1")))
|
||||
|> Map.put(
|
||||
"showPrelimOverall",
|
||||
setting_bool(Map.get(all, @setting_live_show_prelim_overall, "1"))
|
||||
)
|
||||
|> Map.put(
|
||||
"showFinalGroups",
|
||||
setting_bool(Map.get(all, @setting_live_show_final_groups, "1"))
|
||||
)
|
||||
|> Map.put(
|
||||
"finalDisplayMode",
|
||||
normalize_display_mode(
|
||||
Map.get(all, @setting_live_final_display_mode, live["finalDisplayMode"]),
|
||||
live["finalDisplayMode"]
|
||||
)
|
||||
)
|
||||
|> Map.put(
|
||||
"finalFixedGroup",
|
||||
normalize_final_fixed_group(Map.get(all, @setting_live_final_fixed_group, "1"), 1)
|
||||
)
|
||||
|> Map.put("showFinalTie", setting_bool(Map.get(all, @setting_live_show_final_tie, "1")))
|
||||
|> Map.put("showPodium", setting_bool(Map.get(all, @setting_live_show_podium, "1")))
|
||||
|> Map.put(
|
||||
"rotationIntervalSec",
|
||||
normalize_rotation_interval(Map.get(all, @setting_live_rotation_interval, "5"), 5)
|
||||
)
|
||||
|> Map.put(
|
||||
"rotationPlayerCount",
|
||||
normalize_rotation_player_count(Map.get(all, @setting_live_rotation_players, "12"), 12)
|
||||
)
|
||||
|
||||
%{
|
||||
"viewProofInView" => setting_bool(Map.get(all, @setting_view_proof_in_view, "0")),
|
||||
"liveMode" => live
|
||||
}
|
||||
end
|
||||
|
||||
def update_settings(%{} = req) do
|
||||
has_update =
|
||||
Map.has_key?(req, "viewProofInView") or
|
||||
Map.has_key?(req, :viewProofInView) or
|
||||
Map.has_key?(req, "liveMode") or
|
||||
Map.has_key?(req, :liveMode)
|
||||
|
||||
if not has_update do
|
||||
{:error, "at least one settings field is required"}
|
||||
else
|
||||
Repo.transaction(fn ->
|
||||
req
|
||||
|> get_value("viewProofInView")
|
||||
|> maybe_upsert(@setting_view_proof_in_view)
|
||||
|
||||
live_patch = get_value(req, "liveMode")
|
||||
if is_map(live_patch), do: persist_live_patch(live_patch)
|
||||
end)
|
||||
|> case do
|
||||
{:ok, _} -> :ok
|
||||
{:error, %Ecto.ConstraintError{} = e} -> {:error, Exception.message(e)}
|
||||
{:error, reason} when is_binary(reason) -> {:error, reason}
|
||||
{:error, reason} -> {:error, inspect(reason)}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp persist_live_patch(patch) do
|
||||
patch
|
||||
|> get_value("activeView")
|
||||
|> maybe_upsert(@setting_live_active_view, fn v ->
|
||||
normalize_live_active_view(v, "group_live")
|
||||
end)
|
||||
|
||||
patch
|
||||
|> get_value("showGroupLive")
|
||||
|> maybe_upsert(@setting_live_show_group_live)
|
||||
|
||||
patch
|
||||
|> get_value("groupDisplayMode")
|
||||
|> maybe_upsert(@setting_live_group_display_mode, fn v ->
|
||||
normalize_display_mode(v, "rotate")
|
||||
end)
|
||||
|
||||
patch
|
||||
|> get_value("groupFixedCode")
|
||||
|> maybe_upsert(@setting_live_group_fixed_code, fn v ->
|
||||
v |> to_string() |> String.trim() |> String.upcase()
|
||||
end)
|
||||
|
||||
patch
|
||||
|> get_value("showPrelimTie")
|
||||
|> maybe_upsert(@setting_live_show_prelim_tie)
|
||||
|
||||
patch
|
||||
|> get_value("showPrelimOverall")
|
||||
|> maybe_upsert(@setting_live_show_prelim_overall)
|
||||
|
||||
patch
|
||||
|> get_value("showFinalGroups")
|
||||
|> maybe_upsert(@setting_live_show_final_groups)
|
||||
|
||||
patch
|
||||
|> get_value("finalDisplayMode")
|
||||
|> maybe_upsert(@setting_live_final_display_mode, fn v ->
|
||||
normalize_display_mode(v, "rotate")
|
||||
end)
|
||||
|
||||
patch
|
||||
|> get_value("finalFixedGroup")
|
||||
|> maybe_upsert(@setting_live_final_fixed_group, fn v -> normalize_final_fixed_group(v, 1) end)
|
||||
|
||||
patch
|
||||
|> get_value("showFinalTie")
|
||||
|> maybe_upsert(@setting_live_show_final_tie)
|
||||
|
||||
patch
|
||||
|> get_value("showPodium")
|
||||
|> maybe_upsert(@setting_live_show_podium)
|
||||
|
||||
patch
|
||||
|> get_value("rotationIntervalSec")
|
||||
|> maybe_upsert(@setting_live_rotation_interval, fn v -> normalize_rotation_interval(v, 5) end)
|
||||
|
||||
patch
|
||||
|> get_value("rotationPlayerCount")
|
||||
|> maybe_upsert(@setting_live_rotation_players, fn v ->
|
||||
normalize_rotation_player_count(v, 12)
|
||||
end)
|
||||
end
|
||||
|
||||
defp maybe_upsert(nil, _key), do: :ok
|
||||
|
||||
defp maybe_upsert(value, key) do
|
||||
normalized = setting_string(value)
|
||||
|
||||
Repo.insert!(
|
||||
%AppSetting{key: key, value: normalized},
|
||||
on_conflict: [set: [value: normalized, updated_at: DateTime.utc_now()]],
|
||||
conflict_target: :key
|
||||
)
|
||||
end
|
||||
|
||||
defp maybe_upsert(nil, _key, _fun), do: :ok
|
||||
|
||||
defp maybe_upsert(value, key, normalize_fun) do
|
||||
normalized = value |> normalize_fun.() |> setting_string()
|
||||
maybe_upsert(normalized, key)
|
||||
end
|
||||
|
||||
defp get_value(map, key) when is_map(map) do
|
||||
cond do
|
||||
Map.has_key?(map, key) -> Map.get(map, key)
|
||||
Map.has_key?(map, String.to_atom(key)) -> Map.get(map, String.to_atom(key))
|
||||
true -> nil
|
||||
end
|
||||
end
|
||||
|
||||
defp setting_bool(value) do
|
||||
case value |> to_string() |> String.trim() |> String.downcase() do
|
||||
"1" -> true
|
||||
"true" -> true
|
||||
"yes" -> true
|
||||
"on" -> true
|
||||
_ -> false
|
||||
end
|
||||
end
|
||||
|
||||
defp setting_string(v) when is_boolean(v), do: if(v, do: "1", else: "0")
|
||||
defp setting_string(v) when is_integer(v), do: Integer.to_string(v)
|
||||
defp setting_string(v), do: v |> to_string()
|
||||
|
||||
defp normalize_display_mode(value, fallback) do
|
||||
case value |> to_string() |> String.trim() |> String.downcase() do
|
||||
"fixed" -> "fixed"
|
||||
"rotate" -> "rotate"
|
||||
_ -> if(String.downcase(to_string(fallback)) == "fixed", do: "fixed", else: "rotate")
|
||||
end
|
||||
end
|
||||
|
||||
defp normalize_final_fixed_group(value, fallback) do
|
||||
parsed =
|
||||
case Integer.parse(to_string(value)) do
|
||||
{v, _} -> v
|
||||
_ -> fallback
|
||||
end
|
||||
|
||||
if parsed == 2, do: 2, else: 1
|
||||
end
|
||||
|
||||
defp normalize_rotation_interval(value, fallback) do
|
||||
parsed =
|
||||
case Integer.parse(to_string(value)) do
|
||||
{v, _} -> v
|
||||
_ -> fallback
|
||||
end
|
||||
|
||||
parsed |> max(3) |> min(30)
|
||||
end
|
||||
|
||||
defp normalize_rotation_player_count(value, fallback) do
|
||||
parsed =
|
||||
case Integer.parse(to_string(value)) do
|
||||
{v, _} -> v
|
||||
_ -> fallback
|
||||
end
|
||||
|
||||
parsed |> max(3) |> min(40)
|
||||
end
|
||||
|
||||
defp normalize_live_active_view(value, fallback) do
|
||||
normalized =
|
||||
value
|
||||
|> to_string()
|
||||
|> String.trim()
|
||||
|> String.downcase()
|
||||
|
||||
cond do
|
||||
MapSet.member?(@allowed_live_views, normalized) -> normalized
|
||||
MapSet.member?(@allowed_live_views, to_string(fallback)) -> fallback
|
||||
true -> "group_live"
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user