defmodule CobblemonUi.CobblemonFS.Pokemon do @moduledoc """ Normalizes raw NBT Pokémon compound data into a structured map. """ @stat_keys ~w(hp attack defense special_attack special_defense 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: get_string(raw, "species"), level: get_int(raw, "level"), form: get_string(raw, "form", "default"), shiny: get_boolean(raw, "shiny"), nature: get_string(raw, "nature"), gender: get_string(raw, "gender"), experience: get_int(raw, "experience"), friendship: get_int(raw, "friendship"), ability: get_string(raw, "ability"), ivs: normalize_stats(Map.get(raw, "ivs")), evs: normalize_stats(Map.get(raw, "evs")), moves: normalize_moves(Map.get(raw, "moves")) } end defp normalize_stats(nil), do: nil defp normalize_stats(stats) when is_map(stats) do Map.new(@stat_keys, fn key -> {String.to_atom(key), get_int(stats, key, 0)} 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, "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 end