import { AFTER_TITLE, AXIS_LABEL, BEFORE_TITLE, COMPOSED_BY_LABEL, COMPOSES_LABEL, DERIVATION_LABEL, DERIVED_BY_LABEL, DETECTS_LABEL, DOMAIN_CAPTION, DOMAIN_INTRO, FLOW_ARROW, FLOW_TITLE, FORCES_LABEL, GROUNDED_BY_LABEL, GROUNDS_LABEL, INTENT_LABEL, INVARIANT_LABEL, LAYER_LABEL, MATH_TYPE_LABEL, META_LABEL, PRINCIPLE_LABEL, PRODUCTIONS_TITLE, PRODUCTION_ARROW, STAGE_LABEL, YIELDS_LABEL, } from "#configuration/strings/ontology.strings"; import { ALGO_ANCHOR, ALGO_DOMAIN_ANCHOR } from "#core/ids/ontology.ids"; import { BNF_LANGUAGE, TEXT_LANGUAGE } from "#configuration/constants/code.constants"; import type { ContractDomainView, ContractView } from "#types/ontology.types"; import type { Section, Subsection } from "#types/document.types"; import { chips, codeOf, diagram, edgeLine, exemplarBlocks, glossary, labelled, linkList, linkOf, linkRow, linked, localId, node, row, text, } from "#domain/converters/ontology.converter"; import { ALGO_FACE } from "@govlab/constants"; import type { Block } from "#types/block.types"; import { DOMAIN_SECTION_ICON } from "#configuration/icons/ontology.icons"; const HEADER = "flowchart LR"; const SOLID = " --> "; const LINE_END = "\n"; const coordinates = function coordinates(contract: ContractView): Block { return chips([ linked(STAGE_LABEL, contract.stage), linked(AXIS_LABEL, contract.axis), linked(MATH_TYPE_LABEL, contract.mathType), labelled(YIELDS_LABEL, contract.yields), linked(LAYER_LABEL, contract.layer), contract.meta ? META_LABEL : null, ]); }; const joins = function joins(contract: ContractView): Block { return glossary([ row(COMPOSES_LABEL, linkList(contract.composes)), ...linkRow(COMPOSED_BY_LABEL, contract.composedBy), ...linkRow(DERIVED_BY_LABEL, contract.derivedBy), row(FORCES_LABEL, linkList(contract.force)), ...linkRow(PRINCIPLE_LABEL, contract.principle === null ? [] : [contract.principle]), row(GROUNDS_LABEL, linkList(contract.grounds)), ...linkRow(GROUNDED_BY_LABEL, contract.groundedBy), ...linkRow(DETECTS_LABEL, contract.detects), ]); }; const derivation = function derivation(contract: ContractView): readonly Block[] { if (contract.derivationMap.length === 0) { return []; } return [ text(DERIVATION_LABEL), glossary(contract.derivationMap.map((step) => row(step.stage.label, linkOf(step.record)))), ]; }; const productions = function productions(contract: ContractView): readonly Block[] { if (contract.productions.length === 0) { return []; } const lines = contract.productions.map((production) => production.lhs + PRODUCTION_ARROW + production.rhs); return [codeOf(PRODUCTIONS_TITLE, lines.join(LINE_END), BNF_LANGUAGE)]; }; const flow = function flow(contract: ContractView): readonly Block[] { return contract.flow.length === 0 ? [] : [codeOf(FLOW_TITLE, contract.flow.join(FLOW_ARROW), TEXT_LANGUAGE)]; }; const contractSubsection = function contractSubsection(contract: ContractView): Subsection { return { blocks: [ coordinates(contract), glossary([row(INTENT_LABEL, contract.intent), row(INVARIANT_LABEL, contract.invariant)]), ...flow(contract), ...productions(contract), joins(contract), ...derivation(contract), ...exemplarBlocks(contract.exemplar, BEFORE_TITLE, AFTER_TITLE), ], id: ALGO_ANCHOR + contract.id, title: contract.title, }; }; const domainDiagram = function domainDiagram(group: ContractDomainView): string { const members = new Set(group.contracts.map((contract) => contract.id)); const nodes = group.contracts.map((contract) => node(contract.id, contract.title)); const edges = group.contracts.flatMap((contract) => [...contract.composes, ...contract.derivationMap.map((step) => step.record)].flatMap((target) => { const id = localId(target, ALGO_FACE, members); return id === null || id === contract.id ? [] : [edgeLine(contract.id, SOLID, id)]; }), ); return diagram(HEADER, [...nodes, ...new Set(edges)]); }; const domainSection = function domainSection(group: ContractDomainView): Section { return { blocks: [{ caption: DOMAIN_CAPTION, kind: "mermaid", text: domainDiagram(group) }], icon: DOMAIN_SECTION_ICON, id: ALGO_DOMAIN_ANCHOR + group.id, intro: DOMAIN_INTRO, subsections: group.contracts.map(contractSubsection), title: group.domain, }; }; export const contractSections = function contractSections(groups: readonly ContractDomainView[]): readonly Section[] { return groups.map(domainSection); };