All files / src/pages/flowsheet-page/economics/comparison-panel/model comparisonTableModel.ts

100% Statements 29/29
71.42% Branches 10/14
100% Functions 9/9
100% Lines 27/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124                                            7x             14x 16x     12x   2x 2x 2x 2x       7x 15x                 1170x           7x 15x   7x 7x   77x         151x   14x 14x                               18x   8x             30x             30x             30x       30x         148x 60x    
import type { ComparisonPayload } from "@/api/apiStore.gen";
import { formatPercentageDifference } from "../comparisonFormatters";
import {
  type ComparisonTone,
  deltaToneForDirection,
} from "./comparisonStatusPresentation";
 
export type ComparisonRow = ComparisonPayload["rows"][number];
export type ComparisonStudy = ComparisonPayload["studies"][number];
export type ComparisonValue = ComparisonRow["values"][number];
 
export type ComparisonSummaryItem = {
  key: string;
  label: string;
  value: string;
  tone: ComparisonTone;
  status?: string;
};
 
export function comparisonFinancialRows(
  comparison: ComparisonPayload,
): ComparisonRow[] {
  return comparison.rows;
}
 
/** Present the selected baseline as the first study column without changing the saved study order. */
export function comparisonStudiesWithBaselineFirst(
  comparison: ComparisonPayload,
): ComparisonStudy[] {
  const baselineIndex = comparison.studies.findIndex(
    (study) => study.id === comparison.baseline_study_id,
  );
  if (baselineIndex <= 0) {
    return comparison.studies;
  }
  const ordered = [...comparison.studies];
  const [baselineStudy] = ordered.splice(baselineIndex, 1);
  ordered.unshift(baselineStudy);
  return ordered;
}
 
export function comparisonStudyCount(comparison: ComparisonPayload) {
  return comparison.studies.filter(
    (study) => study.id !== comparison.baseline_study_id,
  ).length;
}
 
/** Keep comparison study cell lookup shared between cell styling and cell content. */
export function comparisonValueForStudy(
  row: ComparisonRow,
  studyId: number | null,
): ComparisonValue | undefined {
  return row.values.find((rowValue) => rowValue.study_id === studyId);
}
 
export function comparisonSummaryItems(
  comparison: ComparisonPayload,
): ComparisonSummaryItem[] {
  const studyNames = new Map(
    comparison.studies.map((study) => [study.id, study.name] as const),
  );
  const targetStudyCount = comparisonStudyCount(comparison);
  return comparison.rows
    .flatMap((row) =>
      row.values.flatMap((value) => {
        if (
          value.study_id === comparison.baseline_study_id ||
          value.percentage_difference == null
        ) {
          return [];
        }
        const parsed = Number(value.percentage_difference);
        return Number.isFinite(parsed)
          ? [
              {
                key: `${row.row_key}-${value.study_id}`,
                label:
                  targetStudyCount > 1
                    ? `${row.label} - ${studyNames.get(value.study_id) ?? "Study"}`
                    : row.label,
                value: formatPercentageDifference(value.percentage_difference),
                magnitude: Math.abs(parsed),
                tone: deltaToneForDirection(row.comparison_direction, parsed),
              },
            ]
          : [];
      }),
    )
    .sort((left, right) => right.magnitude - left.magnitude)
    .slice(0, 2)
    .map(({ key, label, value, tone }) => ({ key, label, value, tone }));
}
 
export function studyHeaderTitle(
  study: ComparisonStudy,
  comparison: ComparisonPayload,
) {
  return duplicateStudyNames(comparison) ? study.flowsheet_name : study.name;
}
 
export function studyHeaderSubtitle(
  study: ComparisonStudy,
  comparison: ComparisonPayload,
) {
  return duplicateStudyNames(comparison) ? "" : study.flowsheet_name;
}
 
export function studyHeaderMeta(
  study: ComparisonStudy,
  comparison: ComparisonPayload,
) {
  const parts = [
    studyHeaderSubtitle(study, comparison),
    study.id === comparison.baseline_study_id ? "Baseline" : "",
  ].filter(Boolean);
  return parts.join(" - ");
}
 
/** Force subtitles to carry flowsheet context when names alone are ambiguous. */
export function duplicateStudyNames(comparison: ComparisonPayload) {
  const names = comparison.studies.map((study) => study.name);
  return new Set(names).size < names.length;
}