Current section
Files
Jump to
Current section
Files
lib/rule_system/rule_module.ex
defmodule ExTTRPGDev.RuleSystem.RuleModule do
@moduledoc """
Represents the parsed contents of a rule system's `module.toml` manifest.
"""
defmodule ConceptType do
@moduledoc "A declared concept type within a rule system module."
defstruct [:id, :name]
end
defmodule CharacterChoice do
@moduledoc """
A top-level concept selection a character must make during creation,
e.g. choosing a race or class.
"""
defstruct [:concept_type, required: true]
end
defstruct [
:name,
:slug,
:version,
:family,
:series,
:publisher,
:concept_types,
character_building_choices: []
]
@required_keys ["name", "slug", "version"]
@doc """
Builds a RuleModule struct from a decoded TOML map.
Returns `{:ok, %RuleModule{}}` on success or `{:error, reason}` on failure.
"""
def from_map(%{"module" => module_map} = map) do
missing = Enum.find(@required_keys, fn key -> not Map.has_key?(module_map, key) end)
if missing do
{:error, {:missing_required_key, missing}}
else
concept_types =
map
|> Map.get("concept_type", [])
|> Enum.map(fn et -> %ConceptType{id: et["id"], name: et["name"]} end)
{:ok,
%__MODULE__{
name: module_map["name"],
slug: module_map["slug"],
version: module_map["version"],
family: module_map["family"],
series: module_map["series"],
publisher: module_map["publisher"],
concept_types: concept_types
}}
end
end
def from_map(_), do: {:error, {:missing_required_key, "module"}}
@doc """
Returns a MapSet of declared concept type id strings.
"""
def concept_type_ids(%__MODULE__{concept_types: concept_types}) do
concept_types
|> Enum.map(& &1.id)
|> MapSet.new()
end
end