This commit is contained in:
NotARoomba 2026-03-03 14:35:40 -05:00
parent e6473c91ac
commit 78f1caab59
2 changed files with 21 additions and 36 deletions

View file

@ -195,10 +195,11 @@ admin.get("/stats", async ({ headers, status }) => {
: 0; : 0;
// Max dollar cost from shop fulfillment (all luck_win orders regardless of fulfillment) // Max dollar cost from shop fulfillment (all luck_win orders regardless of fulfillment)
const [luckWinOrders, consolationCount] = await Promise.all([ const [luckWinOrders, consolationOrders] = await Promise.all([
db db
.select({ .select({
itemPrice: shopItemsTable.price, itemPrice: shopItemsTable.price,
totalPrice: shopOrdersTable.totalPrice,
}) })
.from(shopOrdersTable) .from(shopOrdersTable)
.innerJoin( .innerJoin(
@ -207,7 +208,10 @@ admin.get("/stats", async ({ headers, status }) => {
) )
.where(eq(shopOrdersTable.orderType, "luck_win")), .where(eq(shopOrdersTable.orderType, "luck_win")),
db db
.select({ count: sql<number>`count(*)` }) .select({
count: sql<number>`count(*)`,
totalScraps: sql<number>`COALESCE(SUM(${shopOrdersTable.totalPrice}), 0)`,
})
.from(shopOrdersTable) .from(shopOrdersTable)
.where(eq(shopOrdersTable.orderType, "consolation")), .where(eq(shopOrdersTable.orderType, "consolation")),
]); ]);
@ -216,11 +220,22 @@ admin.get("/stats", async ({ headers, status }) => {
(sum, o) => sum + o.itemPrice / SCRAPS_PER_DOLLAR, (sum, o) => sum + o.itemPrice / SCRAPS_PER_DOLLAR,
0, 0,
); );
const consolationDollarCost = Number(consolationCount[0]?.count || 0) * 2; const consolationCount = consolationOrders[0];
const consolationDollarCost = Number(consolationCount?.count || 0) * 2;
const totalRealCost = luckWinDollarCost + consolationDollarCost; const totalRealCost = luckWinDollarCost + consolationDollarCost;
// Derive hours from the scraps spent on luck_win + consolation orders
const luckWinTotalScraps = luckWinOrders.reduce(
(sum, o) => sum + o.totalPrice,
0,
);
const consolationTotalScraps = Number(consolationCount?.totalScraps || 0);
const scrapsPerHour = SCRAPS_PER_DOLLAR * (DOLLARS_PER_HOUR ?? 4);
const fulfillmentHours =
(luckWinTotalScraps + consolationTotalScraps) / scrapsPerHour;
const realCostPerHour = const realCostPerHour =
roundedTotalHours > 0 fulfillmentHours > 0
? Math.round((totalRealCost / roundedTotalHours) * 100) / 100 ? Math.round((totalRealCost / fulfillmentHours) * 100) / 100
: 0; : 0;
// Actual fulfillment cost (only fulfilled orders + upgrades consumed on fulfilled wins) // Actual fulfillment cost (only fulfilled orders + upgrades consumed on fulfilled wins)
@ -320,7 +335,7 @@ admin.get("/stats", async ({ headers, status }) => {
luckWinItemsCost: Math.round(luckWinDollarCost * 100) / 100, luckWinItemsCost: Math.round(luckWinDollarCost * 100) / 100,
luckWinCount: luckWinOrders.length, luckWinCount: luckWinOrders.length,
consolationShippingCost: Math.round(consolationDollarCost * 100) / 100, consolationShippingCost: Math.round(consolationDollarCost * 100) / 100,
consolationCount: Number(consolationCount[0]?.count || 0), consolationCount: Number(consolationCount?.count || 0),
totalRealCost: Math.round(totalRealCost * 100) / 100, totalRealCost: Math.round(totalRealCost * 100) / 100,
realCostPerHour, realCostPerHour,
}, },
@ -337,8 +352,6 @@ admin.get("/stats", async ({ headers, status }) => {
fulfilledUpgradeCost: Math.round(fulfilledUpgradeDollarCost * 100) / 100, fulfilledUpgradeCost: Math.round(fulfilledUpgradeDollarCost * 100) / 100,
totalActualCost: Math.round(totalActualCost * 100) / 100, totalActualCost: Math.round(totalActualCost * 100) / 100,
actualCostPerHour, actualCostPerHour,
remainingBudget:
Math.round((hcbBalanceCents / 100 - totalActualCost) * 100) / 100,
}, },
}; };
}); });

View file

@ -62,7 +62,6 @@
fulfilledUpgradeCost: number; fulfilledUpgradeCost: number;
totalActualCost: number; totalActualCost: number;
actualCostPerHour: number; actualCostPerHour: number;
remainingBudget: number;
} }
interface Stats { interface Stats {
@ -625,33 +624,6 @@
</div> </div>
</div> </div>
<div
class="flex items-center gap-4 rounded-2xl border-4 p-6 {stats.shopActualCost
.remainingBudget >= 0
? 'border-green-500 bg-green-50'
: 'border-red-500 bg-red-50'}"
>
<div
class="flex h-16 w-16 items-center justify-center rounded-full text-white {stats
.shopActualCost.remainingBudget >= 0
? 'bg-green-600'
: 'bg-red-600'}"
>
<DollarSign size={32} />
</div>
<div>
<p class="text-sm font-bold text-gray-500">remaining budget</p>
<p
class="text-4xl font-bold {stats.shopActualCost.remainingBudget >= 0
? 'text-green-700'
: 'text-red-700'}"
>
${stats.shopActualCost.remainingBudget.toFixed(2)}
</p>
<p class="text-xs text-gray-400">hcb balance actual fulfillment cost</p>
</div>
</div>
<div class="flex items-center gap-4 rounded-2xl border-4 border-red-500 bg-red-50 p-6"> <div class="flex items-center gap-4 rounded-2xl border-4 border-red-500 bg-red-50 p-6">
<div <div
class="flex h-16 w-16 items-center justify-center rounded-full bg-red-600 text-white" class="flex h-16 w-16 items-center justify-center rounded-full bg-red-600 text-white"