Files
dashboard/utils/reportFcrEef.ts
T

70 lines
2.3 KiB
TypeScript

import type { DashboardReportEefRow, DashboardReportFcrRow } from '../types/dashboardReport.ts';
type ScalesKpiRow = {
food_total?: number;
iot_weight?: number;
chicken_life?: number;
harvest_weight_total?: number;
iot_fcr?: number;
chicken_life_percentage?: number;
iot_average_harvest_bw?: number;
iot_average_day_weight?: number;
iot_eef?: number;
};
const toValidRatio = (value: number | undefined): number | null =>
value !== undefined && value > 0 ? value : null;
const toNullableNumber = (value: number | undefined | null): number | null =>
value !== undefined && value !== null ? value : null;
const isKpiMap = (value: unknown): value is Record<string, ScalesKpiRow> =>
!!value && typeof value === 'object' && !Array.isArray(value);
const kpiDaysInRange = (
kpi: unknown,
upToDay: number
): Array<[number, ScalesKpiRow]> => {
if (!isKpiMap(kpi)) return [];
return Object.entries(kpi)
.map(([dayKey, row]) => [Number(dayKey), row || {}] as [number, ScalesKpiRow])
.filter(([day]) => Number.isFinite(day) && day >= 0 && day <= upToDay)
.sort((a, b) => a[0] - b[0]);
};
export function mapKpiToFcrRows(kpi: unknown, upToDay: number): DashboardReportFcrRow[] {
return kpiDaysInRange(kpi, upToDay).map(([day, row]) => ({
day,
feedTotal: row.food_total ?? 0,
iotWeight: toNullableNumber(row.iot_weight),
chickenLife: row.chicken_life ?? 0,
harvestWeightTotal: row.harvest_weight_total ?? 0,
iotFcr: toValidRatio(row.iot_fcr),
}));
}
export function mapKpiToEefRows(kpi: unknown, upToDay: number): DashboardReportEefRow[] {
return kpiDaysInRange(kpi, upToDay).map(([day, row]) => ({
day,
chickenLifePercentage: toNullableNumber(row.chicken_life_percentage),
iotAverageHarvestBw: toNullableNumber(row.iot_average_harvest_bw),
iotAverageDayWeight: toNullableNumber(row.iot_average_day_weight),
iotFcr: toValidRatio(row.iot_fcr),
iotEef: toValidRatio(row.iot_eef),
}));
}
export function latestValidRatio<T>(
rows: T[] | null | undefined,
key: keyof T
): number | null {
if (!rows?.length) return null;
for (let i = rows.length - 1; i >= 0; i--) {
const value = rows[i]?.[key];
if (typeof value === 'number' && Number.isFinite(value) && value > 0) {
return value;
}
}
return null;
}