query('SELECT * FROM filaments')->fetchAll(); $cur = config()['currency']; // Filament with no recorded price is valued at a flat DEFAULT_VALUE per full // spool; the remaining value scales that (or the real price) by how much is // left. spool_pct() caps at 100, so an over-full spool never exceeds its value. const DEFAULT_VALUE = 20.0; $totalSpools = count($rows); $remainingG = 0.0; // grams still on the spools $originalG = 0.0; // grams originally purchased (nominal) $remainingValue = 0.0; // $ worth of filament still on the spools $purchaseValue = 0.0; // $ actually recorded as paid $pricedCount = 0; // spools with a recorded price $fullCount = 0; // spools still at (or above) 100% $brands = []; // lower-cased brand => true $colors = []; // color-name (or hex) key => true $materials = []; // type => remaining grams foreach ($rows as $r) { $orig = (float)($r['original_g'] ?? 0); if ($orig <= 0) { $orig = 1000.0; } $rem = max(0.0, (float)$r['remaining_g']); $originalG += $orig; $remainingG += $rem; $hasPrice = $r['cost'] !== null && $r['cost'] !== ''; if ($hasPrice) { $purchaseValue += (float)$r['cost']; $pricedCount++; } $spoolValue = $hasPrice ? (float)$r['cost'] : DEFAULT_VALUE; $remainingValue += $spoolValue * min(1.0, $rem / $orig); $brand = trim((string)$r['brand']); if ($brand !== '') { $brands[mb_strtolower($brand)] = true; } // Group colors by name when the spool has one, otherwise by hex, so unnamed // spools of the same shade still collapse to a single "color". $name = trim((string)($r['color_name'] ?? '')); $hex = mb_strtolower(trim((string)($r['color_hex'] ?? ''))); if ($name !== '') { $colors['n:' . mb_strtolower($name)] = true; } elseif ($hex !== '') { $colors['h:' . $hex] = true; } $type = trim((string)$r['type']); if ($type !== '') { $materials[$type] = ($materials[$type] ?? 0) + $rem; } if (spool_pct($r) >= 100) { $fullCount++; } } $inUseCount = $totalSpools - $fullCount; arsort($materials); $money = fn(float $v): string => $cur . number_format($v, 2); $kg = fn(float $g): string => number_format($g / 1000, 2) . ' kg'; $grams = fn(float $g): string => number_format(round($g)) . ' g'; // kg for a kilo or more, grams below — reads better across the range. $amt = fn(float $g): string => $g >= 1000 ? number_format($g / 1000, 2) . ' kg' : number_format(round($g)) . ' g'; page_header('Stats'); ?>
No filaments yet — add your first spool.
Share of your remaining filament by weight.
$g): $pct = $remainingG > 0 ? round(100 * $g / $remainingG) : 0; ?>