add statistics

This commit is contained in:
Torben Haack
2024-11-04 12:11:36 +01:00
parent 2e396c7cf2
commit cddd8c1814
15 changed files with 924 additions and 164 deletions

View File

@ -0,0 +1,54 @@
import type { printJobs } from "@/server/db/schema";
import type { InferResultType } from "@/utils/drizzle";
import type { InferSelectModel } from "drizzle-orm";
export interface PrinterErrorRate {
printerId: string;
name: string;
errorRate: number; // Error rate as a percentage (0-100)
}
/**
* Calculates the error rate for print jobs aggregated by printer as a percentage.
*
* @param pJobs - Array of print job objects.
* @returns An array of PrinterErrorRate objects, each containing the printer ID and its error rate.
*/
export function calculatePrinterErrorRate(
pJobs: InferResultType<"printJobs", { printer: true }>[],
): PrinterErrorRate[] {
if (pJobs.length === 0) {
return []; // No jobs, no data.
}
const printers = pJobs.map((job) => job.printer);
// Group jobs by printer ID
const jobsByPrinter: Record<string, InferSelectModel<typeof printJobs>[]> = pJobs.reduce(
(acc, job) => {
if (!acc[job.printerId]) {
acc[job.printerId] = [];
}
acc[job.printerId].push(job);
return acc;
},
{} as Record<string, InferSelectModel<typeof printJobs>[]>,
);
// Calculate the error rate for each printer
const printerErrorRates: PrinterErrorRate[] = Object.entries(jobsByPrinter).map(([printerId, jobs]) => {
const totalJobs = jobs.length;
const abortedJobsCount = jobs.filter((job) => job.aborted).length;
const errorRate = (abortedJobsCount / totalJobs) * 100;
const printer = printers.find((printer) => printer.id === printerId);
const printerName = printer ? printer.name : "Unbekannter Drucker";
return {
printerId,
name: printerName,
errorRate: Number.parseFloat(errorRate.toFixed(2)), // Rounded to two decimal places
};
});
return printerErrorRates;
}

View File

@ -0,0 +1,49 @@
import type { printJobs, printers } from "@/server/db/schema";
import { endOfMonth, startOfMonth } from "date-fns";
import type { InferSelectModel } from "drizzle-orm";
interface PrinterIdleTime {
printerId: string;
printerName: string;
averageIdleTime: number; // in minutes
}
/**
* Calculates the average idle time for each printer within the current month.
*
* @param printJobs - Array of print job objects.
* @param printers - Array of printer objects.
* @returns An array of PrinterIdleTime objects with average idle times.
*/
export function calculatePrinterIdleTime(
pJobs: InferSelectModel<typeof printJobs>[],
p: InferSelectModel<typeof printers>[],
): PrinterIdleTime[] {
const now = new Date();
const startOfThisMonth = startOfMonth(now);
const endOfThisMonth = endOfMonth(now);
const totalMinutesInMonth = (endOfThisMonth.getTime() - startOfThisMonth.getTime()) / (1000 * 60);
const usedTimePerPrinter: Record<string, number> = pJobs.reduce(
(acc, job) => {
const jobStart = new Date(job.startAt);
if (jobStart >= startOfThisMonth && jobStart <= endOfThisMonth) {
acc[job.printerId] = (acc[job.printerId] || 0) + job.durationInMinutes;
}
return acc;
},
{} as Record<string, number>,
);
return p.map((printer) => {
const usedTime = usedTimePerPrinter[printer.id] || 0;
const idleTime = totalMinutesInMonth - usedTime;
const averageIdleTime = idleTime < 0 ? 0 : idleTime; // Ensure no negative idle time
return {
printerId: printer.id,
printerName: printer.name,
averageIdleTime,
};
});
}

View File

@ -0,0 +1,30 @@
import type { InferResultType } from "@/utils/drizzle";
export function calculatePrinterUtilization(jobs: InferResultType<"printJobs", { printer: true }>[]) {
const printers = jobs.reduce<Record<string, string>>((acc, job) => {
acc[job.printerId] = job.printer.name;
return acc;
}, {});
const usedTimePerPrinter: Record<string, number> = jobs.reduce(
(acc, job) => {
acc[job.printer.id] = (acc[job.printer.id] || 0) + job.durationInMinutes;
return acc;
},
{} as Record<string, number>,
);
const totalTimeInMinutes = 60 * 70 * 4; // 60 Minutes * 70h * 4 Weeks
const printerUtilizationPercentage = Object.keys(usedTimePerPrinter).map((printerId) => {
const usedTime = usedTimePerPrinter[printerId];
return {
printerId,
name: printers[printerId],
utilizationPercentage: usedTime / totalTimeInMinutes,
};
});
return printerUtilizationPercentage;
}

View File

@ -0,0 +1,49 @@
import type { printJobs } from "@/server/db/schema";
import { endOfDay, endOfMonth, endOfWeek, startOfDay, startOfMonth, startOfWeek } from "date-fns";
import type { InferSelectModel } from "drizzle-orm";
interface PrintVolumes {
today: number;
thisWeek: number;
thisMonth: number;
}
/**
* Calculates the number of print jobs for today, this week, and this month.
*
* @param printJobs - Array of print job objects.
* @returns An object with counts of print jobs for today, this week, and this month.
*/
export function calculatePrintVolumes(pJobs: InferSelectModel<typeof printJobs>[]): PrintVolumes {
const now = new Date();
// Define time ranges
const timeRanges = {
today: { start: startOfDay(now), end: endOfDay(now) },
thisWeek: { start: startOfWeek(now), end: endOfWeek(now) },
thisMonth: { start: startOfMonth(now), end: endOfMonth(now) },
};
// Initialize counts
const volumes: PrintVolumes = {
today: 0,
thisWeek: 0,
thisMonth: 0,
};
// Iterate over print jobs and count based on time ranges
for (const job of pJobs) {
const jobStart = new Date(job.startAt);
if (jobStart >= timeRanges.today.start && jobStart <= timeRanges.today.end) {
volumes.today += 1;
}
if (jobStart >= timeRanges.thisWeek.start && jobStart <= timeRanges.thisWeek.end) {
volumes.thisWeek += 1;
}
if (jobStart >= timeRanges.thisMonth.start && jobStart <= timeRanges.thisMonth.end) {
volumes.thisMonth += 1;
}
}
return volumes;
}