setTime($resetHour, 0, 0); if ($now < $todayReset) { $start = $todayReset->modify('-1 day'); $end = $todayReset; } else { $start = $todayReset; $end = $todayReset->modify('+1 day'); } $secondsTotal = max(1, $end->getTimestamp() - $start->getTimestamp()); $secondsElapsed = max( 0, min($secondsTotal, $now->getTimestamp() - $start->getTimestamp()) ); $secondsRemaining = $secondsTotal - $secondsElapsed; return [ 'now' => $now, 'start' => $start, 'end' => $end, 'secondsElapsed' => $secondsElapsed, 'secondsRemaining' => $secondsRemaining, 'hoursElapsed' => $secondsElapsed / 3600, 'hoursRemaining' => $secondsRemaining / 3600, 'hoursTotal' => $secondsTotal / 3600, ]; } function buildResult( float $targetTons, float $alreadyGround, float $projectedRest, float $hoursRemaining ): array { $neededTonnage = max(0.0, $targetTons - $alreadyGround); $requiredRate = $hoursRemaining > 0 ? $neededTonnage / $hoursRemaining : 0.0; $projectedRest = max(0.0, $projectedRest); $projectedRate = $hoursRemaining > 0 ? $projectedRest / $hoursRemaining : 0.0; $projectedTotal = $alreadyGround + $projectedRest; $projectedShortfall = max(0.0, $targetTons - $projectedTotal); $deltaRate = max(0.0, $requiredRate - $projectedRate); return [ 'targetTons' => $targetTons, 'alreadyGround' => $alreadyGround, 'projectedRest' => $projectedRest, 'hoursRemaining' => $hoursRemaining, 'neededTonnage' => $neededTonnage, 'projectedTotal' => $projectedTotal, 'projectedShortfall' => $projectedShortfall, 'requiredRate' => $requiredRate, 'projectedRate' => $projectedRate, 'deltaRate' => $deltaRate, ]; } $liveGroundTons = null; if (isset($value['CANETOT'], $value['W TONS GROUND'])) { $liveGroundTons = (float) $value['CANETOT'] + (float) $value['W TONS GROUND']; } $defaultGround = $liveGroundTons ?? 0.0; $projectedTotal = null; $projectedIncludePath = __DIR__ . '/../../includes/millprojected60min.php'; if (is_file($projectedIncludePath)) { // Reuse the existing include by buffering its echoed total and keeping its relative paths intact. $previousCwd = getcwd(); $includeDir = dirname($projectedIncludePath); if ($includeDir !== false && is_dir($includeDir)) { chdir($includeDir); } ob_start(); include $projectedIncludePath; $projectedRaw = trim(ob_get_clean()); if ($previousCwd !== false && is_dir($previousCwd)) { chdir($previousCwd); } if ($projectedRaw !== '' && is_numeric($projectedRaw)) { $projectedTotal = (float) $projectedRaw; } } $defaultProjectedCarry = 0.0; if ($projectedTotal !== null) { $alreadyGroundForCarry = $liveGroundTons ?? 0.0; $defaultProjectedCarry = max(0.0, $projectedTotal - $alreadyGroundForCarry); } $formInput = [ 'target' => sanitizeTarget($_POST['target'] ?? 22000), 'ground' => sanitizeFloat( array_key_exists('ground', $_POST) ? $_POST['ground'] : $defaultGround, $defaultGround ), 'projected' => sanitizeFloat( array_key_exists('projected', $_POST) ? $_POST['projected'] : $defaultProjectedCarry, $defaultProjectedCarry ), ]; $window = calculateWindow($appTimeZone, $dailyResetHour); $result = buildResult( $formInput['target'], $formInput['ground'], $formInput['projected'], $window['hoursRemaining'] ); $targetDeadlineLabel = $window['end']->format('g:i A T'); require __DIR__ . '/../../includes/layout/header.php'; ?>
Enter today's ground tonnage, your current projection, and the target to see the tons-per-hour required by .
Calculations assume the 24-hour window resets at 5:00 a.m. Central. Required rate uses the remaining hours ( h). Projected shortfall compares the target against the current ground tonnage plus the forecast carry at today's pace.