core/converters/lesson.converter.ts
core/converters/lesson.converter.ts is a file in Bane's Lab Content. 99 lines of code and 27 definitions.
import { ARCH_FACE, FACE_SEPARATOR, LEX_FACE } from "@govlab/constants";
import type { Contract, Principle } from "@govlab/context";
import type { Faces, IncompleteSeed, LessonSeed, SeedField, SeedReport } from "#types/lesson.types";
import { SEED_FIELDS, SEED_LEVELS, VERIFY_STAGE } from "#configuration/constants/seed.constants";
const SOURCE = "algorithms";
const LABEL_JOINER = ", ";
type SourcedField = "failureMode" | "problem" | "validation";
const kernelOf = function kernelOf(contracts: readonly Contract[], domain: string): Contract | null {
return contracts.find((contract) => contract.domain === domain && contract.derivationMap !== undefined) ?? null;
};
const validationOf = function validationOf(faces: Faces, kernel: Contract | null): string | null {
const entry = kernel?.derivationMap?.find((mapped) => mapped.stage === VERIFY_STAGE);
if (entry === undefined) {
return null;
}
const record = faces.algo.get(entry.record);
return record === null || record.invariant.length === 0 ? null : record.invariant;
};
const causesOf = function causesOf(faces: Faces, meta: Contract, kernel: Contract | null): string[] {
const refs = [meta, ...(kernel ? [kernel] : []), ...meta.composes.flatMap((id) => faces.algo.get(id) ?? [])]
.map((contract) => contract.principleRef)
.filter((ref): ref is string => typeof ref === "string");
const names = new Set(refs.flatMap((ref) => faces.arch.get(ref)?.name ?? []));
return [...names].sort((a, b) => a.localeCompare(b));
};
const governingOf = function governingOf(faces: Faces, meta: Contract): Principle | null {
return typeof meta.principleRef === "string" ? faces.arch.get(meta.principleRef) : null;
};
const textOrNull = function textOrNull(value: string | undefined): string | null {
return value === undefined || value.trim().length === 0 ? null : value;
};
const ARCH_PREFIX = ARCH_FACE + FACE_SEPARATOR;
const LEX_PREFIX = LEX_FACE + FACE_SEPARATOR;
const violationTextOf = function violationTextOf(faces: Faces, ref: string): string | undefined {
if (ref.startsWith(ARCH_PREFIX)) {
return faces.arch.get(ref.slice(ARCH_PREFIX.length))?.formed_by;
}
return ref.startsWith(LEX_PREFIX) ? faces.lex.get(ref.slice(LEX_PREFIX.length))?.definition : undefined;
};
const formationOf = function formationOf(faces: Faces, governing: Principle | null): string | undefined {
if (governing === null || governing.formed_by !== undefined) {
return governing?.formed_by;
}
return (governing.violated_by ?? []).map((ref) => violationTextOf(faces, ref)).find((text) => text !== undefined);
};
const kernelSeedOf = function kernelSeedOf(faces: Faces, kernel: Contract): Pick<LessonSeed, SourcedField> {
const before = kernel.exemplar?.before ?? null;
return { failureMode: before, problem: before, validation: validationOf(faces, kernel) };
};
const clusterSeedOf = function clusterSeedOf(
faces: Faces,
governing: Principle | null,
): Pick<LessonSeed, SourcedField> {
return {
failureMode: textOrNull(governing?.exemplar?.before),
problem: textOrNull(formationOf(faces, governing)),
validation: textOrNull(governing?.detected_by.join(LABEL_JOINER)),
};
};
const seedOf = function seedOf(faces: Faces, meta: Contract, kernel: Contract | null): LessonSeed {
return {
application: meta.flow,
boundary: null,
cause: causesOf(faces, meta, kernel),
decision: meta.intent,
domain: meta.domain,
id: meta.id,
level: SEED_LEVELS[SOURCE],
principle: meta.invariant,
source: SOURCE,
...(kernel ? kernelSeedOf(faces, kernel) : clusterSeedOf(faces, governingOf(faces, meta))),
};
};
const FIELD_ABSENT: Readonly<Record<SeedField, (seed: LessonSeed) => boolean>> = {
cause: (seed) => seed.cause.length === 0,
principle: (seed) => seed.principle.length === 0,
problem: (seed) => seed.problem === null,
validation: (seed) => seed.validation === null,
};
export const missingFieldsOf = function missingFieldsOf(seed: LessonSeed): string[] {
return SEED_FIELDS[seed.source].filter((field) => FIELD_ABSENT[field](seed));
};
export const reportOf = function reportOf(seeds: readonly LessonSeed[]): SeedReport {
const incomplete: IncompleteSeed[] = [];
for (const seed of seeds) {
const missing = missingFieldsOf(seed);
if (missing.length > 0) {
incomplete.push({ id: seed.id, missing });
}
}
return { incomplete, seeds };
};
export const algoSeeds = function algoSeeds(faces: Faces): LessonSeed[] {
const contracts = faces.algo.all();
return faces.algo
.query({ meta: true })
.map((meta) => seedOf(faces, meta, kernelOf(contracts, meta.domain)))
.sort((a, b) => a.id.localeCompare(b.id));
};