117 lines
3.2 KiB
Elixir
117 lines
3.2 KiB
Elixir
defmodule CobblemonUi.CobblemonFS.Pokemon do
|
|
@moduledoc """
|
|
Normalizes raw NBT Pokémon compound data into a structured map.
|
|
"""
|
|
|
|
@stat_keys ~w(hp attack defence special_attack special_defence speed)
|
|
@stat_display_keys %{
|
|
"hp" => :hp,
|
|
"attack" => :attack,
|
|
"defence" => :defense,
|
|
"special_attack" => :special_attack,
|
|
"special_defence" => :special_defense,
|
|
"speed" => :speed
|
|
}
|
|
|
|
@doc """
|
|
Normalizes a raw NBT compound map representing a single Pokémon
|
|
into the standardized format.
|
|
|
|
Returns `nil` if the input is `nil` (empty slot).
|
|
"""
|
|
@spec normalize(map() | nil) :: map() | nil
|
|
def normalize(nil), do: nil
|
|
|
|
def normalize(raw) when is_map(raw) do
|
|
%{
|
|
species: strip_namespace(get_string(raw, "Species")),
|
|
level: get_int(raw, "Level"),
|
|
form: get_string(raw, "FormId", "default"),
|
|
shiny: get_boolean(raw, "Shiny"),
|
|
nature: strip_namespace(get_string(raw, "Nature")),
|
|
gender: downcase(get_string(raw, "Gender")),
|
|
experience: get_int(raw, "Experience"),
|
|
friendship: get_int(raw, "Friendship"),
|
|
ability: extract_ability(Map.get(raw, "Ability")),
|
|
ivs: normalize_stats(nested_get(raw, ["IVs", "Base"])),
|
|
evs: normalize_stats(Map.get(raw, "EVs")),
|
|
moves: normalize_moves(Map.get(raw, "MoveSet"))
|
|
}
|
|
end
|
|
|
|
defp normalize_stats(nil), do: nil
|
|
|
|
defp normalize_stats(stats) when is_map(stats) do
|
|
Map.new(@stat_keys, fn key ->
|
|
# Stats may be keyed with "cobblemon:" namespace prefix
|
|
val = Map.get(stats, "cobblemon:#{key}", Map.get(stats, key, 0))
|
|
display_key = Map.get(@stat_display_keys, key, String.to_atom(key))
|
|
{display_key, val}
|
|
end)
|
|
end
|
|
|
|
defp normalize_moves(nil), do: []
|
|
|
|
defp normalize_moves(moves) when is_list(moves) do
|
|
Enum.map(moves, fn
|
|
move when is_map(move) ->
|
|
get_string(move, "MoveName") || get_string(move, "id")
|
|
|
|
move when is_binary(move) ->
|
|
move
|
|
|
|
_ ->
|
|
nil
|
|
end)
|
|
|> Enum.reject(&is_nil/1)
|
|
end
|
|
|
|
defp normalize_moves(_), do: []
|
|
|
|
defp get_string(map, key, default \\ nil) do
|
|
case Map.get(map, key) do
|
|
val when is_binary(val) -> val
|
|
_ -> default
|
|
end
|
|
end
|
|
|
|
defp get_int(map, key, default \\ nil) do
|
|
case Map.get(map, key) do
|
|
val when is_integer(val) -> val
|
|
_ -> default
|
|
end
|
|
end
|
|
|
|
defp get_boolean(map, key) do
|
|
case Map.get(map, key) do
|
|
1 -> true
|
|
0 -> false
|
|
true -> true
|
|
false -> false
|
|
_ -> false
|
|
end
|
|
end
|
|
|
|
defp strip_namespace(nil), do: nil
|
|
|
|
defp strip_namespace(val) when is_binary(val) do
|
|
case String.split(val, ":", parts: 2) do
|
|
[_ns, name] -> name
|
|
_ -> val
|
|
end
|
|
end
|
|
|
|
defp downcase(nil), do: nil
|
|
defp downcase(val) when is_binary(val), do: String.downcase(val)
|
|
|
|
defp extract_ability(nil), do: nil
|
|
defp extract_ability(%{"AbilityName" => name}) when is_binary(name), do: name
|
|
defp extract_ability(val) when is_binary(val), do: val
|
|
defp extract_ability(_), do: nil
|
|
|
|
defp nested_get(map, []), do: map
|
|
defp nested_get(nil, _keys), do: nil
|
|
defp nested_get(map, [key | rest]) when is_map(map), do: nested_get(Map.get(map, key), rest)
|
|
defp nested_get(_map, _keys), do: nil
|
|
end
|