import { enhance } from "@zenstackhq/runtime"; import { drinkTypeToColor, random_rgba } from "~/utils/color"; import timeAgo from "~/utils/datetime"; import { db } from "~/utils/db.server"; import { randomRange } from "~/utils/random"; export async function generateMonthChartData(){ const dbe = enhance(db); // Get the previous month in dates var dates = []; const now = Date.now(); const subtracter = (1000 * 60 * 60 * 24); for(let i = 0; i <= 30; i++){ let date = now - (subtracter * i); dates.push(new Date(date)); } dates.reverse(); // Generate labels const labels = dates.map((date)=> timeAgo(date)); // History of specific drink const containersWithHistory = await dbe.container.findMany({ orderBy: [{drink: {type: "asc"}}, {checkouts: {_count: "desc"}}], include: {drink: true, checkouts: {orderBy: {checkoutAt: "asc"}, where: {checkoutAt: {gte: dates[0]}}}} }) var datasets : any = []; for(let container of containersWithHistory){ if(container.checkouts.length == 0) continue; var history = container.checkouts; var totalInventory = container.inventory; // Generate arrays of data var checkouts = []; var inventoryAfter = []; var lastInventoryAfter = history.length > 0 ? history[0].inventoryAfter + 1 : 0; var previousCheckoutInventoryAfter = history.length > 0 ? history[0].inventoryAfter : 0; var lastChange = 0; var previousLastChange = 0; for(let i = 0; i <= dates.length - 1; i++){ let startDate = dates[i]; let endDate = dates[i+1]; let totalCheckouts = 0; for(let entry of history){ if(entry.checkoutAt > startDate && entry.checkoutAt < endDate){ totalCheckouts++; lastInventoryAfter = entry.inventoryAfter; lastChange = i; } } // There was inventory added if((lastInventoryAfter + totalCheckouts) > previousCheckoutInventoryAfter){ if(i > 0 && checkouts[i-1] > 0){ // Special case, there were also checkouts the previous day, do nothing } else if(i > 0) { let index = randomRange(previousLastChange + 1, i - 1); for(let j = index; j <= i - 1; j++){ inventoryAfter[j] = lastInventoryAfter + totalCheckouts; } } } previousCheckoutInventoryAfter = lastInventoryAfter; previousLastChange = lastChange; checkouts[i] = totalCheckouts; inventoryAfter[i] = lastInventoryAfter; } // Force the remaining inventory left values after the last checkout to be equal to // the actual remaining inventory let index = randomRange(lastChange + 1, dates.length - 1); for(let i = index; i <= dates.length - 1; i++){ inventoryAfter[i] = totalInventory; } let color = drinkTypeToColor(container.drink.type); datasets.push({ type: 'bar', label: 'Checkouts ' + container.drink.name, data: checkouts, borderColor: color, backgroundColor: color, }); } const data = { labels, datasets: datasets }; return data; } export async function generate24HChartData(){ const dbe = enhance(db); // Get the previous month in hours var hours = []; const now = Date.now(); const subtracter = (1000 * 60 * 60); for(let i = 0; i <= 24; i++){ let date = now - (subtracter * i); hours.push(new Date(date)); } hours.reverse(); // Generate labels const labels = hours.map((date)=> timeAgo(date)); // History of specific drink const containersWithHistory = await dbe.container.findMany({ orderBy: [{drink: {type: "asc"}}, {checkouts: {_count: "desc"}}], include: {drink: true, checkouts: {orderBy: {checkoutAt: "asc"}, where: {checkoutAt: {gte: hours[0]}}}} }) var datasets : any = []; for(let container of containersWithHistory){ if(container.checkouts.length == 0) continue; var history = container.checkouts; var totalInventory = container.inventory; // Generate arrays of data var checkouts = []; var inventoryAfter = []; var lastInventoryAfter = history.length > 0 ? history[0].inventoryAfter + 1 : 0; var previousCheckoutInventoryAfter = history.length > 0 ? history[0].inventoryAfter : 0; var lastChange = 0; var previousLastChange = 0; for(let i = 0; i <= hours.length - 1; i++){ let startDate = hours[i]; let endDate = hours[i+1]; let totalCheckouts = 0; for(let entry of history){ if(entry.checkoutAt > startDate && entry.checkoutAt < endDate){ totalCheckouts++; lastInventoryAfter = entry.inventoryAfter; lastChange = i; } } // There was inventory added if((lastInventoryAfter + totalCheckouts) > previousCheckoutInventoryAfter){ if(i > 0 && checkouts[i-1] > 0){ // Special case, there were also checkouts the previous day, do nothing } else if(i > 0) { let index = randomRange(previousLastChange + 1, i - 1); for(let j = index; j <= i - 1; j++){ inventoryAfter[j] = lastInventoryAfter + totalCheckouts; } } } previousCheckoutInventoryAfter = lastInventoryAfter; previousLastChange = lastChange; checkouts[i] = totalCheckouts; inventoryAfter[i] = lastInventoryAfter; } // Force the remaining inventory left values after the last checkout to be equal to // the actual remaining inventory let index = randomRange(lastChange + 1, hours.length - 1); for(let i = index; i <= hours.length - 1; i++){ inventoryAfter[i] = totalInventory; } let color = drinkTypeToColor(container.drink.type); datasets.push({ type: 'bar', label: 'Checkouts ' + container.drink.name, data: checkouts, borderColor: color, backgroundColor: color, }); } const data = { labels, datasets: datasets }; return data; }