94 lines
3.2 KiB
TypeScript
94 lines
3.2 KiB
TypeScript
import {
|
|
FeedScheduleRecommendation,
|
|
FeedingEvent,
|
|
ConsumptionPatternPoint,
|
|
ScheduleInfluencingFactors,
|
|
} from '../types';
|
|
import { initialUsers, initialRoles } from './accessManagementData.ts';
|
|
|
|
const operatorRoleId = initialRoles.find((r) => r.name === 'Operator')?.id;
|
|
const operators = operatorRoleId ? initialUsers.filter((u) => u.roleId === operatorRoleId) : [];
|
|
|
|
export const initialFeedSchedule: FeedScheduleRecommendation = {
|
|
nextFeedingTime: new Date(Date.now() + 2 * 60 * 60 * 1000), // in 2 hours
|
|
lastFeedingTime: new Date(Date.now() - 3 * 60 * 60 * 1000), // 3 hours ago
|
|
reason: 'Jadwal dimundurkan untuk menghindari stres panas akibat suhu tinggi pada siang hari.',
|
|
};
|
|
|
|
export const initialFeedingEvents: FeedingEvent[] = (() => {
|
|
const events: FeedingEvent[] = [];
|
|
const now = new Date();
|
|
const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
|
|
|
|
for (let day = 0; day < 30; day++) {
|
|
const currentDate = new Date(startOfMonth);
|
|
currentDate.setDate(startOfMonth.getDate() + day);
|
|
|
|
// Add 4 feeding events per day at different times
|
|
const feedingTimes = [8, 12, 16, 20];
|
|
feedingTimes.forEach((hour, index) => {
|
|
const eventTime = new Date(currentDate);
|
|
eventTime.setHours(hour, 0, 0, 0);
|
|
|
|
if (eventTime > new Date(now.getTime() + 3 * 24 * 60 * 60 * 1000)) {
|
|
return; // Don't generate events too far in the future
|
|
}
|
|
|
|
let status: 'completed' | 'upcoming' | 'skipped' = 'upcoming';
|
|
if (eventTime < now) {
|
|
status = Math.random() < 0.05 ? 'skipped' : 'completed';
|
|
}
|
|
|
|
const type: 'AI Recommended' | 'Manual' = Math.random() < 0.3 ? 'AI Recommended' : 'Manual';
|
|
|
|
const operator = operators[Math.floor(Math.random() * operators.length)] ?? {
|
|
id: 'user-3',
|
|
name: 'Siti Aminah',
|
|
};
|
|
const quantityKg = 250 + Math.floor(Math.random() * 100);
|
|
|
|
events.push({
|
|
id: `event-${day}-${index}`,
|
|
time: eventTime,
|
|
type: status === 'skipped' ? 'Skipped' : type,
|
|
status,
|
|
operatorId: operator.id,
|
|
operatorName: operator.name,
|
|
feedType: 'CP 511 Bravo',
|
|
quantityKg: quantityKg,
|
|
quantitySacks: Math.round(quantityKg / 50),
|
|
});
|
|
});
|
|
}
|
|
|
|
// Ensure the next upcoming event matches the recommendation
|
|
const nextUpcoming = events.find((e) => e.status === 'upcoming');
|
|
if (nextUpcoming) {
|
|
nextUpcoming.time = initialFeedSchedule.nextFeedingTime;
|
|
nextUpcoming.type = 'AI Recommended';
|
|
}
|
|
|
|
return events;
|
|
})();
|
|
|
|
export const initialConsumptionPattern: ConsumptionPatternPoint[] = Array.from(
|
|
{ length: 24 },
|
|
(_, i) => {
|
|
const isFeedingHour = [8, 12, 16, 20].includes(i);
|
|
const predicted = 1 + Math.sin((i - 6) / 4) * 3 + (isFeedingHour ? 5 : 0) + Math.random();
|
|
const actual = i < new Date().getHours() ? predicted - 0.5 + Math.random() * 1.5 : null;
|
|
|
|
return {
|
|
hour: i,
|
|
predicted: Math.max(0, predicted),
|
|
actual: actual ? Math.max(0, actual) : null,
|
|
};
|
|
}
|
|
);
|
|
|
|
export const initialScheduleFactors: ScheduleInfluencingFactors = {
|
|
temperature: { value: 31.8, unit: '°C', status: 'warning' },
|
|
humidity: { value: 78, unit: '%', status: 'warning' },
|
|
activityLevel: { value: 65, unit: '%', status: 'ok' },
|
|
};
|