marmar-context / web / context / src / logic / checks.ts
checks.ts
Raw
import type { CheckRun, NotChecked } from "../api/types";
import type { Assessment } from "../types";
import { firstName, tierOf } from "./format";

const plural = (n: number, one: string, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;

/** CHK-3: say what the patient's details added; zero is never "safe". */
export function checkHeadline(a: Pick<Assessment, "baseline" | "contextual" | "addedRuleIds">, patientName: string) {
  const name = firstName(patientName);
  const after = a.contextual.findings.length;
  const added = a.addedRuleIds.length;
  if (!after) return { headline: "No findings. This does not mean the prescription is safe.", before: a.baseline.findings.length, after };
  return {
    headline: added
      ? `Personalized to ${name}: ${plural(added, "finding")} the medication list alone did not show.`
      : `${plural(after, "finding")} for clinician review. The medication list alone showed the same.`,
    before: a.baseline.findings.length,
    after,
  };
}

/** Most pressing first (CHK-6). */
export const byTier = <T extends { tier: string }>(findings: T[]) =>
  [...findings].sort((x, y) => tierOf(x.tier).rank - tierOf(y.tier).rank);

/** CHK-3: every result ends with what was not checked. */
export function notCheckedLines(n: NotChecked, rulesReviewed: boolean): string[] {
  return [
    ...n.productsWithoutRules.map((p) => `${p}: recorded, not checked. No rules for this product yet.`),
    ...(n.unconfirmedFacts ? [`${plural(n.unconfirmedFacts, "fact or line", "facts or lines")} not confirmed for this check.`] : []),
    ...(!rulesReviewed || n.rulesAwaitingReview
      ? [`Rules waiting for clinical review${n.rulesAwaitingReview ? `: ${n.rulesAwaitingReview} changes` : ""}. Their findings are shown, labelled as not yet reviewed.`]
      : []),
    ...(n.checkInAnswers ? ["Answers from check-ins: no rule reads them."] : []),
    ...n.other,
  ];
}

/** The newest mark for each finding (FND-3). */
export function latestMarks(check: Pick<CheckRun, "marks">) {
  const out = new Map<string, CheckRun["marks"][number]>();
  for (const m of check.marks) out.set(m.findingId, m);
  return out;
}

export const markLabels = { reviewed: "Reviewed", not_relevant: "Not relevant", problem: "Problem reported" } as const;