defmodule Microwaveprop.Pskr.RecalibrationRun do @moduledoc """ One execution of the PSKR-driven recalibration analysis. A row is written every time `Pskr.Recalibrator.run/0` fires (weekly via `Workers.PskrRecalibrationWorker`). The status field separates an actually-completed analysis from runs that bailed early because the corpus was too thin to produce useful bins. Status values: * `"completed"` — analysis ran and `pskr_feature_bins` rows were written for at least one (band, feature) * `"skipped_insufficient_data"` — corpus had < threshold samples, no bins emitted * `"failed"` — exception during analysis (notes carries reason) """ use Ecto.Schema import Ecto.Changeset @primary_key {:id, :binary_id, autogenerate: true} @foreign_key_type :binary_id schema "pskr_recalibration_runs" do field :run_at, :utc_datetime field :status, :string field :sample_count, :integer, default: 0 field :band_count, :integer, default: 0 field :earliest_sample, :utc_datetime field :latest_sample, :utc_datetime field :avg_spots_per_sample, :float field :notes, :string has_many :feature_bins, Microwaveprop.Pskr.FeatureBin, foreign_key: :run_id timestamps(type: :utc_datetime) end @type t :: %__MODULE__{} @cast_fields ~w(run_at status sample_count band_count earliest_sample latest_sample avg_spots_per_sample notes)a @required_fields ~w(run_at status)a @spec changeset(t(), map()) :: Ecto.Changeset.t() def changeset(record, attrs) do record |> cast(attrs, @cast_fields) |> validate_required(@required_fields) |> validate_inclusion(:status, ~w(completed skipped_insufficient_data failed)) end end