defmodule Polymarket.Schemas.Series do @moduledoc """ A series an `Event` belongs to, as returned by the Gamma API (e.g. nested in `GET /events/keyset`). A series groups recurring events together (e.g. all "NBA" games). The Gamma API delivers its keys in `camelCase`; `from_attrs/1` normalises them to the `snake_case` fields below. Field coverage follows the Gamma OpenAPI `Series` schema; the nested relational objects (`events`, `tags`, `categories`, `collections`, `chats`) are intentionally omitted as they are not returned when a series is nested inside an event. """ use TypedEctoSchema alias Polymarket.JsonUtil alias Polymarket.Schemas.Coerce @primary_key false @derive Jason.Encoder typed_embedded_schema do # Identity / description field(:id, :string) field(:ticker, :string) field(:slug, :string) field(:title, :string) field(:description, :string) field(:series_type, :string) field(:recurrence, :string) field(:layout, :string) field(:image, :string) field(:icon, :string) # Spec types `competitive` as a string here, unlike on `Market`/`Event`. field(:competitive, :string) field(:created_by, :string) field(:updated_by, :string) # Status flags field(:active, :boolean) field(:closed, :boolean) field(:archived, :boolean) field(:new, :boolean) field(:featured, :boolean) field(:restricted, :boolean) field(:comments_enabled, :boolean) field(:requires_translation, :boolean) # Counts / volume / liquidity field(:comment_count, :integer) field(:liquidity, :float) field(:volume, :float) field(:volume24hr, :float) # Dates field(:start_date, :utc_datetime_usec) field(:published_at, :utc_datetime_usec) field(:created_at, :utc_datetime_usec) field(:updated_at, :utc_datetime_usec) end @doc """ Builds a `Series` from the raw (JSON-decoded) Gamma attributes. Keys may be in `camelCase` (atom or string); they are normalised to the `snake_case` fields and each value is coerced to its field type. """ @spec from_attrs(map()) :: {:ok, t()} def from_attrs(attrs) do attrs = JsonUtil.snake_case_keys(attrs) {:ok, %__MODULE__{ id: attrs["id"], ticker: attrs["ticker"], slug: attrs["slug"], title: attrs["title"], description: attrs["description"], series_type: attrs["series_type"], recurrence: attrs["recurrence"], layout: attrs["layout"], image: attrs["image"], icon: attrs["icon"], competitive: attrs["competitive"], created_by: attrs["created_by"], updated_by: attrs["updated_by"], active: attrs["active"], closed: attrs["closed"], archived: attrs["archived"], new: attrs["new"], featured: attrs["featured"], restricted: attrs["restricted"], comments_enabled: attrs["comments_enabled"], requires_translation: attrs["requires_translation"], comment_count: Coerce.to_int(attrs["comment_count"]), liquidity: Coerce.to_float(attrs["liquidity"]), volume: Coerce.to_float(attrs["volume"]), volume24hr: Coerce.to_float(attrs["volume24hr"]), start_date: Coerce.to_datetime(attrs["start_date"]), published_at: Coerce.to_datetime(attrs["published_at"]), created_at: Coerce.to_datetime(attrs["created_at"]), updated_at: Coerce.to_datetime(attrs["updated_at"]) }} end end