# `GenogramMaker`

Build family genograms as plain Elixir data, then render them to
[Graphviz DOT](https://graphviz.org) or [Mermaid](https://mermaid.js.org).

A genogram is a family diagram: people (with sex and vital status), the unions
between them (marriage, divorce, cohabitation, …) with their children, and the
emotional bonds that connect individuals (close, conflict, cutoff, …). Describe
one with a small pipeline-friendly API and turn it into diagram source you can
render with Graphviz or drop straight into Markdown.

    GenogramMaker.new()
    |> GenogramMaker.add_person("ego", :female, name: "Ada", proband: true)
    |> GenogramMaker.add_person("dad", :male, name: "John", birth: 1948, death: 2009)
    |> GenogramMaker.add_person("mom", :female, name: "Mary", birth: 1950)
    |> GenogramMaker.add_union("dad", "mom", type: :marriage, children: ["ego"])
    |> GenogramMaker.add_bond("dad", "ego", :conflict)
    |> GenogramMaker.to_dot()

Standard genogram conventions are applied on render: males are squares, females
circles and unknown-sex people diamonds; deceased people are shaded and the
proband gets a double outline. Partners and their children are linked through a
union point, and emotional bonds are drawn as non-structural coloured lines so
they never distort the generational layout.

People referenced by a union or bond are created automatically (with unknown
sex) if they have not been added yet, so the pipeline above stays compact.

Maintained by the team behind [AutoGenogram](https://autogenogram.com), an AI
genogram maker and analyzer; this library is the code-first companion for
generating genogram source programmatically.

# `id`

```elixir
@type id() :: String.t() | atom()
```

An id for a person; atoms and other terms are coerced to strings.

# `t`

```elixir
@type t() :: %GenogramMaker{
  bonds: [GenogramMaker.Bond.t()],
  people: [GenogramMaker.Person.t()],
  title: String.t() | nil,
  unions: [GenogramMaker.Union.t()]
}
```

# `add_bond`

```elixir
@spec add_bond(t(), id(), id(), GenogramMaker.Bond.type()) :: t()
```

Add an emotional bond between two people.

`type` must be one of `:close`, `:distant`, `:conflict`, `:hostile`, `:cutoff`,
`:fused`. People that do not exist yet are created automatically with unknown sex.

# `add_person`

```elixir
@spec add_person(t(), id(), GenogramMaker.Person.sex(), keyword()) :: t()
```

Add a person, or update them if the `id` already exists.

`sex` must be one of `:male`, `:female`, `:unknown`.

Options:

  * `:name` — display name (defaults to the id on render).
  * `:birth` / `:death` — years shown under the name.
  * `:deceased` — defaults to `true` when `:death` is given, otherwise `false`.
  * `:proband` — mark the index person (double outline). Defaults to `false`.
  * `:note` — free-form note stored on the struct.

# `add_union`

```elixir
@spec add_union(t(), id(), id(), keyword()) :: t()
```

Add a union between two partners.

Options:

  * `:type` — one of `:marriage` (default), `:divorce`, `:separation`,
    `:cohabitation`, `:engagement`.
  * `:children` — list of child ids descending from the union.

Partners and children that do not exist yet are created automatically with
unknown sex.

# `key_map`

```elixir
@spec key_map(t()) :: %{optional(String.t()) =&gt; String.t()}
```

Map each person id to its render key (`"p0"`, `"p1"`, …) in insertion order.

Used by the renderers; exposed for callers writing their own.

# `new`

```elixir
@spec new(keyword()) :: t()
```

Create an empty genogram.

Options:

  * `:title` — optional diagram title (rendered as a graph label in DOT output).

# `to_dot`

```elixir
@spec to_dot(t()) :: String.t()
```

Render the genogram as [Graphviz DOT](https://graphviz.org) source.

# `to_mermaid`

```elixir
@spec to_mermaid(t()) :: String.t()
```

Render the genogram as [Mermaid](https://mermaid.js.org) flowchart source.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
