fix analytics
This commit is contained in:
parent
6b5be5696d
commit
fb7ca4c523
@ -3,21 +3,34 @@ import type { InferResultType } from "@/utils/drizzle";
|
|||||||
type UsagePerDay = {
|
type UsagePerDay = {
|
||||||
day: number; // 0 (Sunday) to 6 (Saturday)
|
day: number; // 0 (Sunday) to 6 (Saturday)
|
||||||
usageMinutes: number;
|
usageMinutes: number;
|
||||||
dataPoints: number;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function aggregateUsageByDay(jobs: InferResultType<"printJobs">[]): UsagePerDay[] {
|
function aggregateUsageByDay(jobs: InferResultType<"printJobs">[]): {
|
||||||
|
usageData: UsagePerDay[];
|
||||||
|
earliestDate: Date;
|
||||||
|
latestDate: Date;
|
||||||
|
} {
|
||||||
const usagePerDayMap = new Map<number, number>();
|
const usagePerDayMap = new Map<number, number>();
|
||||||
const usagePerDayDatapointsMap = new Map<number, number>();
|
|
||||||
|
let earliestDate: Date | null = null;
|
||||||
|
let latestDate: Date | null = null;
|
||||||
|
|
||||||
for (const job of jobs) {
|
for (const job of jobs) {
|
||||||
let remainingDuration = job.durationInMinutes;
|
let remainingDuration = job.durationInMinutes;
|
||||||
const currentStart = new Date(job.startAt);
|
const currentStart = new Date(job.startAt);
|
||||||
|
|
||||||
|
// Update earliest and latest dates
|
||||||
|
if (!earliestDate || currentStart < earliestDate) {
|
||||||
|
earliestDate = new Date(currentStart);
|
||||||
|
}
|
||||||
|
const jobEnd = new Date(currentStart);
|
||||||
|
jobEnd.setMinutes(jobEnd.getMinutes() + job.durationInMinutes);
|
||||||
|
if (!latestDate || jobEnd > latestDate) {
|
||||||
|
latestDate = new Date(jobEnd);
|
||||||
|
}
|
||||||
|
|
||||||
while (remainingDuration > 0) {
|
while (remainingDuration > 0) {
|
||||||
const day = currentStart.getDay();
|
const day = currentStart.getDay();
|
||||||
const dataPoints = usagePerDayDatapointsMap.get(day) || 0;
|
|
||||||
usagePerDayDatapointsMap.set(day, dataPoints + 1);
|
|
||||||
|
|
||||||
// Calculate minutes remaining in the current day
|
// Calculate minutes remaining in the current day
|
||||||
const minutesRemainingInDay = (24 - currentStart.getHours()) * 60 - currentStart.getMinutes();
|
const minutesRemainingInDay = (24 - currentStart.getHours()) * 60 - currentStart.getMinutes();
|
||||||
@ -37,17 +50,43 @@ function aggregateUsageByDay(jobs: InferResultType<"printJobs">[]): UsagePerDay[
|
|||||||
const usageData: UsagePerDay[] = Array.from({ length: 7 }, (_, day) => ({
|
const usageData: UsagePerDay[] = Array.from({ length: 7 }, (_, day) => ({
|
||||||
day,
|
day,
|
||||||
usageMinutes: usagePerDayMap.get(day) || 0,
|
usageMinutes: usagePerDayMap.get(day) || 0,
|
||||||
dataPoints: usagePerDayDatapointsMap.get(day) || 0,
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return usageData;
|
if (earliestDate === null) {
|
||||||
|
earliestDate = new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (latestDate === null) {
|
||||||
|
latestDate = new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
return { usageData, earliestDate: earliestDate, latestDate: latestDate };
|
||||||
|
}
|
||||||
|
|
||||||
|
function countWeekdays(startDate: Date, endDate: Date): number[] {
|
||||||
|
const countPerDay = Array(7).fill(0);
|
||||||
|
const currentDate = new Date(startDate);
|
||||||
|
currentDate.setHours(0, 0, 0, 0); // Ensure starting at midnight
|
||||||
|
endDate.setHours(0, 0, 0, 0); // Ensure ending at midnight
|
||||||
|
|
||||||
|
while (currentDate <= endDate) {
|
||||||
|
const day = currentDate.getDay();
|
||||||
|
countPerDay[day]++;
|
||||||
|
currentDate.setDate(currentDate.getDate() + 1);
|
||||||
|
}
|
||||||
|
return countPerDay;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function forecastPrinterUsage(jobs: InferResultType<"printJobs">[]): number[] {
|
export function forecastPrinterUsage(jobs: InferResultType<"printJobs">[]): number[] {
|
||||||
const usageData = aggregateUsageByDay(jobs);
|
const { usageData, earliestDate, latestDate } = aggregateUsageByDay(jobs);
|
||||||
|
|
||||||
|
// Count the number of times each weekday occurs in the data period
|
||||||
|
const weekdaysCount = countWeekdays(earliestDate, latestDate);
|
||||||
|
|
||||||
const forecasts: number[] = [];
|
const forecasts: number[] = [];
|
||||||
for (const data of usageData) {
|
for (const data of usageData) {
|
||||||
let usagePrediction = data.usageMinutes / data.dataPoints;
|
const dayCount = weekdaysCount[data.day];
|
||||||
|
let usagePrediction = data.usageMinutes / dayCount;
|
||||||
if (Number.isNaN(usagePrediction)) {
|
if (Number.isNaN(usagePrediction)) {
|
||||||
usagePrediction = 0;
|
usagePrediction = 0;
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,13 @@ interface PrintVolumes {
|
|||||||
export function calculatePrintVolumes(pJobs: InferSelectModel<typeof printJobs>[]): PrintVolumes {
|
export function calculatePrintVolumes(pJobs: InferSelectModel<typeof printJobs>[]): PrintVolumes {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
||||||
// Define time ranges
|
// Define time ranges with week starting on Monday
|
||||||
const timeRanges = {
|
const timeRanges = {
|
||||||
today: { start: startOfDay(now), end: endOfDay(now) },
|
today: { start: startOfDay(now), end: endOfDay(now) },
|
||||||
thisWeek: { start: startOfWeek(now), end: endOfWeek(now) },
|
thisWeek: {
|
||||||
|
start: startOfWeek(now, { weekStartsOn: 1 }),
|
||||||
|
end: endOfWeek(now, { weekStartsOn: 1 }),
|
||||||
|
},
|
||||||
thisMonth: { start: startOfMonth(now), end: endOfMonth(now) },
|
thisMonth: { start: startOfMonth(now), end: endOfMonth(now) },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user