137 lines
4.4 KiB
TypeScript
137 lines
4.4 KiB
TypeScript
import { FeedSackColumnConfig } from '../types/counting.ts';
|
|
|
|
export function getFeedSackColumnType(cameraName: string): 'inbound' | 'usage' | 'outbound' {
|
|
if (cameraName.includes('karung_masuk')) return 'inbound';
|
|
if (cameraName.includes('karung_keluar')) return 'outbound';
|
|
return 'usage';
|
|
}
|
|
|
|
export function inferKandangIdFromCameraName(cameraName: string): number | null {
|
|
const match = cameraName.toLowerCase().match(/^kandang_(\d+)_/);
|
|
if (!match) {
|
|
return null;
|
|
}
|
|
|
|
const parsed = Number(match[1]);
|
|
return Number.isFinite(parsed) ? parsed : null;
|
|
}
|
|
|
|
export function normalizeFeedSackColumnConfig(column: FeedSackColumnConfig): FeedSackColumnConfig {
|
|
const rawKandangId: unknown = (column as { kandangId?: unknown }).kandangId;
|
|
let kandangId: number | null = null;
|
|
|
|
if (typeof rawKandangId === 'number' && Number.isFinite(rawKandangId)) {
|
|
kandangId = rawKandangId;
|
|
} else if (typeof rawKandangId === 'string' && rawKandangId.trim().length > 0) {
|
|
const parsed = Number(rawKandangId);
|
|
kandangId = Number.isFinite(parsed) ? parsed : null;
|
|
} else if (rawKandangId === undefined) {
|
|
kandangId = inferKandangIdFromCameraName(column.cameraName);
|
|
}
|
|
|
|
return {
|
|
...column,
|
|
type: column.type || getFeedSackColumnType(column.cameraName),
|
|
kandangId,
|
|
};
|
|
}
|
|
|
|
export function normalizeFeedSackColumnConfigs(
|
|
columns: FeedSackColumnConfig[]
|
|
): FeedSackColumnConfig[] {
|
|
return columns.map(normalizeFeedSackColumnConfig);
|
|
}
|
|
|
|
type FeedSackColumnType = 'inbound' | 'usage' | 'outbound';
|
|
|
|
function columnsOfType(
|
|
columns: FeedSackColumnConfig[],
|
|
type: FeedSackColumnType
|
|
): FeedSackColumnConfig[] {
|
|
return columns.filter(
|
|
(column) => (column.type || getFeedSackColumnType(column.cameraName)) === type
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Cameras of one type mapped to a kandang. Returns [] when mapping fails —
|
|
* never all cameras (report must not silently become all-kandang).
|
|
*/
|
|
export function getCameraNamesForKandang(
|
|
columns: FeedSackColumnConfig[],
|
|
type: FeedSackColumnType,
|
|
kandangId?: number | null,
|
|
kandangName?: string | null
|
|
): string[] {
|
|
const typed = columnsOfType(columns, type);
|
|
|
|
if (kandangId !== null && kandangId !== undefined) {
|
|
const mappedCameras = typed
|
|
.filter((column) => column.kandangId === kandangId)
|
|
.map((column) => column.cameraName);
|
|
if (mappedCameras.length > 0) return mappedCameras;
|
|
|
|
const inferredCameras = typed
|
|
.filter((column) => inferKandangIdFromCameraName(column.cameraName) === kandangId)
|
|
.map((column) => column.cameraName);
|
|
if (inferredCameras.length > 0) return inferredCameras;
|
|
}
|
|
|
|
if (kandangName) {
|
|
const kandangNameLower = kandangName.toLowerCase();
|
|
const kandangPrefix = kandangNameLower.replace(/\s+/g, '_');
|
|
|
|
if (kandangNameLower.includes('atas')) {
|
|
const atasCameras = typed
|
|
.filter(
|
|
(column) =>
|
|
column.cameraName.toLowerCase().includes('atas') ||
|
|
column.cameraName.toLowerCase().includes('kiri')
|
|
)
|
|
.map((column) => column.cameraName);
|
|
if (atasCameras.length > 0) return atasCameras;
|
|
}
|
|
|
|
if (kandangNameLower.includes('bawah')) {
|
|
const bawahCameras = typed
|
|
.filter(
|
|
(column) =>
|
|
column.cameraName.toLowerCase().includes('bawah') ||
|
|
column.cameraName.toLowerCase().includes('kanan')
|
|
)
|
|
.map((column) => column.cameraName);
|
|
if (bawahCameras.length > 0) return bawahCameras;
|
|
}
|
|
|
|
const prefixedCameras = typed
|
|
.filter((column) => column.cameraName.toLowerCase().startsWith(kandangPrefix))
|
|
.map((column) => column.cameraName);
|
|
if (prefixedCameras.length > 0) return prefixedCameras;
|
|
}
|
|
|
|
return [];
|
|
}
|
|
|
|
export function getInboundCameraNamesForKandang(
|
|
columns: FeedSackColumnConfig[],
|
|
kandangId?: number | null,
|
|
kandangName?: string | null
|
|
): string[] {
|
|
return getCameraNamesForKandang(columns, 'inbound', kandangId, kandangName);
|
|
}
|
|
|
|
export function getUsageCameraNamesForKandang(
|
|
columns: FeedSackColumnConfig[],
|
|
kandangId?: number | null,
|
|
kandangName?: string | null
|
|
): string[] {
|
|
const mapped = getCameraNamesForKandang(columns, 'usage', kandangId, kandangName);
|
|
if (mapped.length > 0) return mapped;
|
|
return getCombinedUsageCameraNames(columns);
|
|
}
|
|
|
|
/** All usage cameras (left + right / atas + bawah). Production feed use is combined. */
|
|
export function getCombinedUsageCameraNames(columns: FeedSackColumnConfig[]): string[] {
|
|
return columnsOfType(columns, 'usage').map((column) => column.cameraName);
|
|
}
|