87 lines
2.3 KiB
TypeScript
87 lines
2.3 KiB
TypeScript
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 | undefined>): 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),
|
|
};
|
|
}
|