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, }; };