import type { DashboardReportCountingRow, DashboardReportFeedInRow, DashboardReportFeedUseRow, } from '../types/dashboardReport.ts'; import { sackAccuracy } from './reportAccuracy.ts'; export const REPORT_TOTAL_LABEL = 'Total'; const isPresentNumber = (value: number | null | undefined): value is number => typeof value === 'number' && Number.isFinite(value); function sumPresent(values: Array): number | null { let total = 0; let any = false; for (const value of values) { if (!isPresentNumber(value)) continue; total += value; any = true; } return any ? total : null; } export interface CountingTotalsRow { label: string; countBefore: number | null; mortality: number | null; harvest: number | null; harvestWeight: number | null; countAfter: number | null; iotCount: number | null; accuracy: number | null; } export interface FeedInTotalsRow { label: string; manualIn: number | null; iotIn: number | null; accuracy: number | null; } export interface FeedUseTotalsRow { label: string; manualUse: number | null; iotUse: number | null; accuracy: number | null; } export function countingTotals(rows: DashboardReportCountingRow[]): CountingTotalsRow | null { if (!rows.length) return null; const first = rows[0]; return { label: REPORT_TOTAL_LABEL, countBefore: first?.countBefore ?? null, mortality: sumPresent(rows.map((row) => row.mortality)), harvest: sumPresent(rows.map((row) => row.harvest)), harvestWeight: sumPresent(rows.map((row) => row.harvestWeight)), countAfter: null, iotCount: null, accuracy: null, }; } export function feedInTotals(rows: DashboardReportFeedInRow[]): FeedInTotalsRow | null { if (!rows.length) return null; const manualIn = sumPresent(rows.map((row) => row.manualIn)); const iotIn = sumPresent(rows.map((row) => row.iotIn)); return { label: REPORT_TOTAL_LABEL, manualIn, iotIn, accuracy: sackAccuracy(manualIn, iotIn), }; } export function feedUseTotals(rows: DashboardReportFeedUseRow[]): FeedUseTotalsRow | null { if (!rows.length) return null; const manualUse = sumPresent(rows.map((row) => row.manualUse)); const iotUse = sumPresent(rows.map((row) => row.iotUse)); return { label: REPORT_TOTAL_LABEL, manualUse, iotUse, accuracy: sackAccuracy(manualUse, iotUse), }; }