# domain/converters/loop.converter.ts

> 148 lines of code and 21 definitions.

Tree: Site tree
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/tree#file-domain-converters-loop-converter-ts
Source text: https://banes-lab.com/assets/sources/source.4f21ec324954db788417580afd4f122c87ec32d96271f668220fe09b7c5bad84.generated.txt

## Definitions

- `loopSection` (lexical_declaration, line 96, exported)
- `substrateDiagram` (lexical_declaration, line 111)
- `loopDiagram` (lexical_declaration, line 63)
- `substrateSection` (lexical_declaration, line 136, exported)
- `transitionLine` (lexical_declaration, line 53)
- `stageSubsection` (lexical_declaration, line 69)
- `transitionRow` (lexical_declaration, line 80)
- `substrateSubsection` (lexical_declaration, line 125)
- `HEADER` (lexical_declaration, line 44)
- `HEADER_WIDE` (lexical_declaration, line 45)
- `SOLID` (lexical_declaration, line 46)
- `DOTTED` (lexical_declaration, line 47)
- `LABEL_OPEN` (lexical_declaration, line 48)
- `LABEL_CLOSE` (lexical_declaration, line 49)
- `GATE_KIND` (lexical_declaration, line 50)
- `REFUTE_KIND` (lexical_declaration, line 51)
- `{ derivationLoop }` (lexical_declaration, line 97, exported)
- `nodes` (lexical_declaration, line 113)
- `edges` (lexical_declaration, line 114)
- `next` (lexical_declaration, line 115)
- `{ substrate }` (lexical_declaration, line 137, exported)

## Uses

- [domain/converters/ontology.converter.ts](https://banes-lab.com/source/tree/domain/converters/ontology.converter.ts.md)

## Used by

- [domain/converters/reason.converter.ts](https://banes-lab.com/source/tree/domain/converters/reason.converter.ts.md)

## Source

```typescript
import {
    AXIS_LABEL,
    CONTRACTS_LABEL,
    FIELD_SEPARATOR,
    FLOW_ARROW,
    GROUNDS_LABEL,
    LAYER_LABEL,
    MATH_TYPE_LABEL,
} from "#configuration/strings/ontology.strings";
import {
    GATE_LABEL,
    LOOP_CAPTION,
    LOOP_INTRO,
    LOOP_SECTION_TITLE,
    MATH_TYPES_LABEL,
    ON_FAIL_LABEL,
    ON_PASS_LABEL,
    RECURSION_LABEL,
    SUBSTRATE_CAPTION,
    SUBSTRATE_INTRO,
    SUBSTRATE_SECTION_TITLE,
    TRANSITIONS_TITLE,
    TRANSITION_LABEL,
} from "#configuration/strings/reason.strings";
import type { LoopStageView, LoopTransitionView, SubstrateNodeView } from "#types/loop.types";
import { REASON_ANCHOR, STAGE_ANCHOR, SUBSTRATE_SECTION_ID } from "#core/ids/ontology.ids";
import type { Section, Subsection } from "#types/document.types";
import {
    chips,
    diagram,
    edgeLine,
    fields,
    glossary,
    labelled,
    linkOf,
    linkRow,
    linked,
    node,
    row,
} from "#domain/converters/ontology.converter";
import { REASON_SECTION_ICON } from "#configuration/icons/ontology.icons";
import type { ReasonView } from "#types/reason.types";

const HEADER = "flowchart TB";
const HEADER_WIDE = "flowchart LR";
const SOLID = " --> ";
const DOTTED = " -.-> ";
const LABEL_OPEN = " -- ";
const LABEL_CLOSE = " --> ";
const GATE_KIND = "gates";
const REFUTE_KIND = "refutes-back";

const transitionLine = function transitionLine(transition: LoopTransitionView): string {
    if (transition.kind === REFUTE_KIND) {
        return edgeLine(transition.from.label, DOTTED, transition.to.label);
    }
    if (transition.kind === GATE_KIND && transition.gate !== null) {
        return edgeLine(transition.from.label, LABEL_OPEN + transition.gate + LABEL_CLOSE, transition.to.label);
    }
    return edgeLine(transition.from.label, SOLID, transition.to.label);
};

const loopDiagram = function loopDiagram(reason: ReasonView): string {
    const { derivationLoop } = reason;
    const nodes = derivationLoop.stages.map((stage) => node(stage.id, stage.id + FIELD_SEPARATOR + stage.axis.label));
    return diagram(HEADER, [...nodes, ...derivationLoop.transitions.map(transitionLine)]);
};

const stageSubsection = function stageSubsection(stage: LoopStageView): Subsection {
    return {
        blocks: [
            chips([linked(AXIS_LABEL, stage.axis)]),
            glossary([...linkRow(CONTRACTS_LABEL, stage.contracts), ...linkRow(GROUNDS_LABEL, stage.edges)]),
        ],
        id: STAGE_ANCHOR + stage.id,
        title: stage.id,
    };
};

const transitionRow = function transitionRow(transition: LoopTransitionView): {
    readonly description: string;
    readonly term: string;
} {
    return row(
        transition.from.label + FLOW_ARROW + transition.to.label,
        fields([
            linkOf(transition.from) + FLOW_ARROW + linkOf(transition.to),
            labelled(TRANSITION_LABEL, transition.kind),
            labelled(GATE_LABEL, transition.gate),
            labelled(ON_PASS_LABEL, transition.onPass),
            labelled(ON_FAIL_LABEL, transition.onFail),
        ]),
    );
};

export const loopSection = function loopSection(reason: ReasonView): Section {
    const { derivationLoop } = reason;
    return {
        blocks: [{ caption: LOOP_CAPTION, kind: "mermaid", text: loopDiagram(reason) }],
        icon: REASON_SECTION_ICON,
        id: REASON_ANCHOR + derivationLoop.anchor,
        intro: LOOP_INTRO,
        subsections: [
            ...derivationLoop.stages.map(stageSubsection),
            { blocks: [glossary(derivationLoop.transitions.map(transitionRow))], title: TRANSITIONS_TITLE },
        ],
        title: LOOP_SECTION_TITLE,
    };
};

const substrateDiagram = function substrateDiagram(reason: ReasonView): string {
    const { substrate } = reason;
    const nodes = substrate.cycle.map((stage) => node(stage.label, stage.label));
    const edges = substrate.cycle.flatMap((stage, index) => {
        const next = substrate.cycle[index + 1];
        return next === undefined ? [] : [edgeLine(stage.label, SOLID, next.label)];
    });
    return diagram(HEADER_WIDE, [
        ...nodes,
        ...edges,
        edgeLine(substrate.recursionFrom.label, DOTTED, substrate.recursionTo.label),
    ]);
};

const substrateSubsection = function substrateSubsection(entry: SubstrateNodeView): Subsection {
    return {
        blocks: [
            chips([linked(LAYER_LABEL, entry.layer), linked(MATH_TYPE_LABEL, entry.mathType)]),
            glossary(linkRow(MATH_TYPES_LABEL, entry.mathTypes)),
        ],
        id: REASON_ANCHOR + entry.anchor,
        title: entry.name,
    };
};

export const substrateSection = function substrateSection(reason: ReasonView): Section {
    const { substrate } = reason;
    return {
        blocks: [
            { caption: SUBSTRATE_CAPTION, kind: "mermaid", text: substrateDiagram(reason) },
            {
                kind: "text",
                text:
                    RECURSION_LABEL +
                    FIELD_SEPARATOR +
                    linkOf(substrate.recursionFrom) +
                    FLOW_ARROW +
                    linkOf(substrate.recursionTo),
            },
        ],
        icon: REASON_SECTION_ICON,
        id: SUBSTRATE_SECTION_ID,
        intro: SUBSTRATE_INTRO,
        subsections: substrate.nodes.map(substrateSubsection),
        title: SUBSTRATE_SECTION_TITLE,
    };
};
```
