209 lines
6.2 KiB
TypeScript
209 lines
6.2 KiB
TypeScript
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;
|
|
} |